option for LTI title to not squash assignment name
- adds a `preserveExistingAssignmentName` option that LTI 1.3 tools can include in the content item in the Deep Linking response (for `assignment_selection` and `submission_type_selection` placements). When given, the title (if any) given in the content item will not overwrite an existing Assignment name (if already present). - also remove an old feature flag that has been on for a while Test plan: - Have an LTI 1.3 tool with the submission_type_selection placement The placement should have the `require_resource_selection` option enabled - check out my latest LTI 1.3 test tool commit with `Extra arbitrary content item data (JSON object)` field - Test the following situations with the submission_type_selection placement: - assignment name is empty, tool returns a title as usual - title should be set - assignment name is not empty (different from what tool will set), tool returns a title as usual - title should be set (overwritten) - assignment name is not empty, tool returns a title as usual, tool includes '"https://canvas.instructure.com/lti/preserveExistingAssignmentName": true' in the content item in the deep linking response (use new 'Extra arbitrary content item data' field in test tool - title should not be set - assignment name is not empty, tool returns null title (use Extra arbitrary contenbt item data) and null lineItem.label (change/remove label from line item data field) - try those with the assignment_selection placement too - Refresh the page to start afresh and check that when a title is supplied but the preserveExistingAssignmentName is given, the title still shows up on the card UI, and the assignment can be saved refs INTEROP-8700 flag=none Change-Id: I970aaefb58c411fc6b517e440e323ba0380e5136 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/351503 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Steven McGee <steve.mcgee@instructure.com> QA-Review: Steven McGee <steve.mcgee@instructure.com> Product-Review: Alexis Nast <alexis.nast@instructure.com>
This commit is contained in:
parent
cd58810787
commit
76cd6b7e7d
|
@ -392,7 +392,6 @@ class ApplicationController < ActionController::Base
|
|||
scheduled_page_publication
|
||||
send_usage_metrics
|
||||
rce_transform_loaded_content
|
||||
lti_assignment_page_line_items
|
||||
mobile_offline_mode
|
||||
react_discussions_post
|
||||
instui_nav
|
||||
|
|
|
@ -120,6 +120,7 @@
|
|||
<input type="hidden" name="description" id="external_tool_create_description"/>
|
||||
<input type="hidden" name="available" id="external_tool_create_available"/>
|
||||
<input type="hidden" name="submission" id="external_tool_create_submission"/>
|
||||
<input type="hidden" id="external_tool_create_preserve_existing_assignment_name" />
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
|
|
|
@ -39,8 +39,7 @@ assignment_submission_type_card:
|
|||
state: hidden
|
||||
applies_to: SiteAdmin
|
||||
display_name: Allow submission type resource card to be shown in the assignment edit page
|
||||
description: |-
|
||||
When enabled, the new submission type resource card will be shown in the assignment edit page.
|
||||
description: When enabled, the new submission type resource card will be shown in the assignment edit page.
|
||||
environments:
|
||||
development:
|
||||
state: allowed_on
|
||||
|
@ -145,11 +144,6 @@ lti_ags_remove_top_submitted_at:
|
|||
state: allowed_on
|
||||
ci:
|
||||
state: allowed_on
|
||||
lti_assignment_page_line_items:
|
||||
state: hidden
|
||||
display_name: LTI Deep Linking Line Items on Assignment create/edit page
|
||||
description: If enabled, prefills the assignment form with values from deep link messages on the assignment create/edit page.
|
||||
applies_to: RootAccount
|
||||
lti_before_assignment_results:
|
||||
state: hidden
|
||||
display_name: Display LTI placement before assignment description after submitting.
|
||||
|
|
|
@ -143,26 +143,16 @@ as either module items or assignments, based on the presence or absence of the `
|
|||
property.
|
||||
|
||||
#### Assignment Selection Deep Linking
|
||||
|
||||
When a tool is launched from the `assignment_selection` placement, properties
|
||||
from the deep linking response will overwrite existing settings on the
|
||||
assignment create/edit page. However, the following properties in the deep
|
||||
linking response behave uniquely:
|
||||
|
||||
* `lineItem.label` or `title` (corresponding to the assignment name)
|
||||
* `lineItem.scoreMaximum` (corresponding to the assignment's "points possible")
|
||||
* `text` (corresponding to the assignment description body)
|
||||
|
||||
Existing values for these corresponding assignment settings will *not* be
|
||||
overwritten in the following cases:
|
||||
|
||||
* The deep linking response omits one of the properties. Leaving out a property
|
||||
will not erase an existing value.
|
||||
* The feature flag "LTI Deep Linking Line Items on Assignment create/edit page"
|
||||
(`lti_assignment_page_line_items`) is disabled. This flag, enabled by
|
||||
default since August 2023, can be disabled by institution admins. (Note that,
|
||||
if the corresponding assignment settings are empty, the values from the
|
||||
deep linking response are used regardless of the feature flag.)
|
||||
When a tool is launched from the `assignment_selection` placement, any previous
|
||||
LTI parameters (URL, iframe width, etc.) are overwritten with the information
|
||||
in the Deep Linking Response. In addition, if the following properties are
|
||||
present and non-empty in the content item in the Deep Linking Response, they
|
||||
will set the following fields, potentially overwriting user-inputted values:
|
||||
- `text` sets/overwrites the assignment description
|
||||
- `lineItem.scoreMaximum` sets/overwrites the maximum score for the assignment
|
||||
- `lineItem.label` or `title` sets the assignment name, and overwrites unless
|
||||
`"https://canvas.instructure.com/lti/preserveExistingAssignmentName": true`
|
||||
is given in the content item.
|
||||
|
||||
### HTML fragment
|
||||
Full support for required properties.
|
||||
|
|
|
@ -989,10 +989,6 @@ module Lti
|
|||
end
|
||||
|
||||
context "when on the new assignment page" do
|
||||
before do
|
||||
course.root_account.enable_feature! :lti_assignment_page_line_items
|
||||
end
|
||||
|
||||
let(:return_url_params) { super().merge({ placement: "assignment_selection" }) }
|
||||
let(:content_items) do
|
||||
[
|
||||
|
@ -1002,14 +998,6 @@ module Lti
|
|||
]
|
||||
end
|
||||
|
||||
context "when assignment edit page feature flag is disabled" do
|
||||
before do
|
||||
course.root_account.disable_feature! :lti_assignment_page_line_items
|
||||
end
|
||||
|
||||
it_behaves_like "does nothing"
|
||||
end
|
||||
|
||||
it "does not create a new module" do
|
||||
expect { subject }.not_to change { course.context_modules.count }
|
||||
end
|
||||
|
|
|
@ -640,6 +640,7 @@ EditView.prototype.handleAssignmentSelectionSubmit = function (data) {
|
|||
height: data['item[iframe][height]'],
|
||||
},
|
||||
lineItem: tryJsonParse(data['item[line_item]']),
|
||||
'https://canvas.instructure.com/lti/preserveExistingAssignmentName': tryJsonParse(data['item[preserveExistingAssignmentName]']),
|
||||
}
|
||||
this.handleContentItem(contentItem)
|
||||
}
|
||||
|
@ -651,7 +652,6 @@ EditView.prototype.handleAssignmentSelectionSubmit = function (data) {
|
|||
* @param {ResourceLinkContentItem} item
|
||||
*/
|
||||
EditView.prototype.handleContentItem = function (item) {
|
||||
const line_items_enabled = !!window.ENV.FEATURES.lti_assignment_page_line_items
|
||||
this.$externalToolsCustomParams.val(JSON.stringify(item.custom))
|
||||
this.$externalToolsContentType.val(item.type)
|
||||
this.$externalToolsContentId.val(item.id || this.selectedTool?.id)
|
||||
|
@ -661,33 +661,22 @@ EditView.prototype.handleContentItem = function (item) {
|
|||
this.$externalToolsIframeWidth.val(item.iframe?.width)
|
||||
this.$externalToolsIframeHeight.val(item.iframe?.height)
|
||||
|
||||
const line_item = item.lineItem
|
||||
if (line_item) {
|
||||
this.$externalToolsLineItem.val(JSON.stringify(line_item))
|
||||
if (
|
||||
'scoreMaximum' in line_item &&
|
||||
(line_items_enabled || this.$assignmentPointsPossible.val() === '0')
|
||||
) {
|
||||
this.$assignmentPointsPossible.val(line_item.scoreMaximum)
|
||||
}
|
||||
const new_assignment_name = 'label' in line_item ? line_item.label : item.title
|
||||
|
||||
if (new_assignment_name && (line_items_enabled || this.$name.val() === '')) {
|
||||
this.$name.val(new_assignment_name)
|
||||
}
|
||||
} else {
|
||||
const new_assignment_name = item.title
|
||||
if (new_assignment_name && (line_items_enabled || this.$name.val() === '')) {
|
||||
this.$name.val(new_assignment_name)
|
||||
const lineItem = item.lineItem
|
||||
if (lineItem) {
|
||||
this.$externalToolsLineItem.val(JSON.stringify(lineItem))
|
||||
if ('scoreMaximum' in lineItem) {
|
||||
this.$assignmentPointsPossible.val(lineItem.scoreMaximum)
|
||||
}
|
||||
}
|
||||
|
||||
const description = item.text
|
||||
if (description) {
|
||||
const existing_desc = RichContentEditor.callOnRCE(this.$description, 'get_code')
|
||||
if (line_items_enabled || existing_desc === '') {
|
||||
RichContentEditor.callOnRCE(this.$description, 'set_code', description)
|
||||
}
|
||||
const newAssignmentName = (lineItem && 'label' in lineItem) ? lineItem.label : item.title
|
||||
const replaceAssignmentName = !item['https://canvas.instructure.com/lti/preserveExistingAssignmentName']
|
||||
if (newAssignmentName && (replaceAssignmentName || this.$name.val() === '')) {
|
||||
this.$name.val(newAssignmentName)
|
||||
}
|
||||
|
||||
if (item.text) {
|
||||
RichContentEditor.callOnRCE(this.$description, 'set_code', item.text)
|
||||
}
|
||||
|
||||
this.renderAssignmentSubmissionTypeContainer()
|
||||
|
|
|
@ -474,17 +474,36 @@ const lastSubmissionTypeContainerProps = function () {
|
|||
return calls[calls.length - 1].args[1]
|
||||
}
|
||||
|
||||
test('when a submission_type_selection tool chosen and a resource selected: sets selectedTool and title', function () {
|
||||
const view = editViewWithSubmissionTypeSelection()
|
||||
view.$submissionType.val('external_tool_placement_123')
|
||||
view.$submissionType.trigger('change')
|
||||
view.handleContentItem({
|
||||
const makeResourceLinkContentItem = function(overrides={}) {
|
||||
return {
|
||||
type: 'ltiResourceLink',
|
||||
custom: {},
|
||||
url: 'http://example.com',
|
||||
title: 'someResource',
|
||||
lineItem: {},
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
test("when a submission_type_selection sends back title and preserveExistingAssignmentName: shows resource and doesn't overwrite title", function () {
|
||||
const view = editViewWithSubmissionTypeSelection()
|
||||
view.$submissionType.val('external_tool_placement_123')
|
||||
view.$submissionType.trigger('change')
|
||||
view.$('#assignment_name').val('Test Assignment')
|
||||
const contentItem = makeResourceLinkContentItem({
|
||||
'https://canvas.instructure.com/lti/preserveExistingAssignmentName': true
|
||||
})
|
||||
view.handleContentItem(contentItem)
|
||||
|
||||
equal(view.$('#assignment_name').val(), 'Test Assignment')
|
||||
equal(view.$externalToolsTitle.val(), 'someResource')
|
||||
})
|
||||
|
||||
test('when a submission_type_selection tool chosen and a resource selected: sets selectedTool, title, assignment name', function () {
|
||||
const view = editViewWithSubmissionTypeSelection()
|
||||
view.$submissionType.val('external_tool_placement_123')
|
||||
view.$submissionType.trigger('change')
|
||||
view.handleContentItem(makeResourceLinkContentItem())
|
||||
const formData = view.getFormData()
|
||||
|
||||
ok(view.selectedTool.require_resource_selection)
|
||||
|
@ -492,6 +511,7 @@ test('when a submission_type_selection tool chosen and a resource selected: sets
|
|||
|
||||
// Card is shown (props include title):
|
||||
equal(lastSubmissionTypeContainerProps().resource.title, 'someResource')
|
||||
equal(view.$('#assignment_name').val(), 'someResource')
|
||||
})
|
||||
|
||||
test('when a submission_type_selection tool chosen, a resource selected, and the resource removed: keeps selectedTool but clears out title', function () {
|
||||
|
@ -499,13 +519,7 @@ test('when a submission_type_selection tool chosen, a resource selected, and the
|
|||
view.$submissionType.val('external_tool_placement_123')
|
||||
view.$submissionType.trigger('change')
|
||||
|
||||
view.handleContentItem({
|
||||
type: 'ltiResourceLink',
|
||||
custom: {},
|
||||
url: 'http://example.com',
|
||||
title: 'someResourceLinkTitle',
|
||||
lineItem: {},
|
||||
})
|
||||
view.handleContentItem(makeResourceLinkContentItem())
|
||||
view.handleRemoveResource()
|
||||
|
||||
const formData = view.getFormData()
|
||||
|
@ -524,13 +538,7 @@ test('when a submission_type_select tool chosen but changed back to generic "Ext
|
|||
const view = editViewWithSubmissionTypeSelection()
|
||||
view.$submissionType.val('external_tool_placement_123')
|
||||
view.$submissionType.trigger('change')
|
||||
view.handleContentItem({
|
||||
type: 'ltiResourceLink',
|
||||
custom: {},
|
||||
url: 'http://example.com',
|
||||
title: 'someResourceLinkTitle',
|
||||
lineItem: {},
|
||||
})
|
||||
view.handleContentItem(makeResourceLinkContentItem())
|
||||
|
||||
const formData = view.getFormData()
|
||||
ok(view.selectedTool)
|
||||
|
@ -1612,6 +1620,7 @@ QUnit.skip(
|
|||
'item[available]':
|
||||
'{"startDateTime": "2023-04-13T00:00:00.000Z", "endDateTime": "2023-04-14T00:00:00.000Z"}',
|
||||
'item[description]': 'todo_fix_me',
|
||||
'item[preserveExistingAssignmentName]': 'true',
|
||||
}
|
||||
const view = editView()
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ export type ResourceLinkContentItem = {
|
|||
startDateTime?: string
|
||||
endDateTime?: string
|
||||
}
|
||||
['https://canvas.instructure.com/lti/preserveExistingAssignmentName']?: boolean
|
||||
}
|
||||
|
||||
const ltiEndpointParams = (lookupUuid?: string | null | undefined) => {
|
||||
|
|
|
@ -247,6 +247,7 @@ describe('SelectContentDialog: deepLinkingResponseHandler', () => {
|
|||
<input type='text' id='external_tool_create_iframe_width' />
|
||||
<input type='text' id='external_tool_create_iframe_height' />
|
||||
<input type='checkbox' id='external_tool_create_new_tab' />
|
||||
<input type='text' id='external_tool_create_preserve_existing_assignment_name' />
|
||||
<div id='context_external_tools_select'>
|
||||
<span class='domain_message' />
|
||||
<div class='tools'>
|
||||
|
@ -303,6 +304,7 @@ describe('SelectContentDialog: deepLinkingResponseHandler', () => {
|
|||
endDateTime: '2023-04-21T00:00:00.000Z',
|
||||
},
|
||||
text: 'Description text',
|
||||
'https://canvas.instructure.com/lti/preserveExistingAssignmentName': true,
|
||||
}
|
||||
const makeDeepLinkingEvent = (additionalContentItemFields = {}, omitFields = []) => {
|
||||
const omittedContentItem = Object.fromEntries(
|
||||
|
@ -434,6 +436,7 @@ describe('SelectContentDialog: deepLinkingResponseHandler', () => {
|
|||
'{"startDateTime":"2023-04-12T00:00:00.000Z","endDateTime":"2023-04-21T00:00:00.000Z"}'
|
||||
)
|
||||
expect(data['item[description]']).toEqual('Description text')
|
||||
expect(data['item[preserveExistingAssignmentName]']).toEqual('true')
|
||||
})
|
||||
|
||||
it('recover assignment id from context external tool item data if given', async () => {
|
||||
|
|
|
@ -282,6 +282,10 @@ export function handleContentItemResult(
|
|||
setJsonValueIfDefined('#external_tool_create_line_item', result.lineItem)
|
||||
setJsonValueIfDefined('#external_tool_create_submission', result.submission)
|
||||
setJsonValueIfDefined('#external_tool_create_available', result.available)
|
||||
setJsonValueIfDefined(
|
||||
'#external_tool_create_preserve_existing_assignment_name',
|
||||
result['https://canvas.instructure.com/lti/preserveExistingAssignmentName']
|
||||
)
|
||||
if ('text' in result && typeof result.text === 'string') {
|
||||
$('#external_tool_create_description').val(result.text)
|
||||
}
|
||||
|
@ -526,6 +530,9 @@ export function extractContextExternalToolItemData() {
|
|||
'item[description]': $('#external_tool_create_description').val(),
|
||||
'item[submission]': $('#external_tool_create_submission').val(),
|
||||
'item[available]': $('#external_tool_create_available').val(),
|
||||
'item[preserveExistingAssignmentName]': $(
|
||||
'#external_tool_create_preserve_existing_assignment_name'
|
||||
).val(),
|
||||
} as const
|
||||
}
|
||||
|
||||
|
@ -540,6 +547,7 @@ export function resetExternalToolFields() {
|
|||
$('#external_tool_create_assignment_id').val('')
|
||||
$('#external_tool_create_iframe_width').val('')
|
||||
$('#external_tool_create_iframe_height').val('')
|
||||
$('#external_tool_create_preserve_existing_assignment_name').val('')
|
||||
}
|
||||
|
||||
export type SelectContentDialogOptions = {
|
||||
|
|
Loading…
Reference in New Issue