Add LTI launch capability to speedgrader
Closes CNVS-29144 Test Plan: - Add an external tool assignment - Passback a URL type score which matches the launch URL of the tool - Confirm that speedgrading that page launches into the tool Change-Id: Iff3e00ece10c6b4ff891e4af90053c88a677db6a Reviewed-on: https://gerrit.instructure.com/79526 Reviewed-by: Davis McClellan <dmcclellan@instructure.com> Reviewed-by: Cameron Matheson <cameron@instructure.com> Tested-by: Jenkins Reviewed-by: Nathan Mills <nathanm@instructure.com> QA-Review: Michael Hargiss <mhargiss@instructure.com> Product-Review: Jason Sparks <jsparks@instructure.com>
This commit is contained in:
parent
6f038299f4
commit
167b46924a
|
@ -141,6 +141,7 @@ class SubmissionsController < ApplicationController
|
|||
"online_url" => ["url"].freeze,
|
||||
"online_upload" => ["file_ids"].freeze,
|
||||
"media_recording" => ["media_comment_id", "media_comment_type"].freeze,
|
||||
"basic_lti_launch" => ["url"].freeze
|
||||
}.freeze
|
||||
|
||||
# @API Submit an assignment
|
||||
|
@ -158,7 +159,7 @@ class SubmissionsController < ApplicationController
|
|||
# @argument comment[text_comment] [String]
|
||||
# Include a textual comment with the submission.
|
||||
#
|
||||
# @argument submission[submission_type] [Required, String, "online_text_entry"|"online_url"|"online_upload"|"media_recording"]
|
||||
# @argument submission[submission_type] [Required, String, "online_text_entry"|"online_url"|"online_upload"|"media_recording"|"basic_lti_launch"]
|
||||
# The type of submission being made. The assignment submission_types must
|
||||
# include this submission type as an allowed option, or the submission will be rejected with a 400 error.
|
||||
#
|
||||
|
@ -177,7 +178,7 @@ class SubmissionsController < ApplicationController
|
|||
# Submit the assignment as a URL. The URL scheme must be "http" or "https",
|
||||
# no "ftp" or other URL schemes are allowed. If no scheme is given (e.g.
|
||||
# "www.example.com") then "http" will be assumed. Requires a submission_type
|
||||
# of "online_url".
|
||||
# of "online_url" or "basic_lti_launch".
|
||||
#
|
||||
# @argument submission[file_ids][] [Integer]
|
||||
# Submit the assignment as a set of one or more previously uploaded files
|
||||
|
|
|
@ -1321,7 +1321,7 @@ class Assignment < ActiveRecord::Base
|
|||
submitted = case opts[:submission_type]
|
||||
when "online_text_entry"
|
||||
opts[:body].present?
|
||||
when "online_url"
|
||||
when "online_url", "basic_lti_launch"
|
||||
opts[:url].present?
|
||||
when "online_upload"
|
||||
opts[:attachments].size > 0
|
||||
|
|
|
@ -2,7 +2,6 @@ require_relative '../assignment'
|
|||
|
||||
class Assignment
|
||||
class SpeedGrader
|
||||
|
||||
def initialize(assignment, user, avatars: false, grading_role: :grader)
|
||||
@assignment = assignment
|
||||
@user = user
|
||||
|
@ -117,7 +116,7 @@ class Assignment
|
|||
|
||||
res[:submissions] = submissions.map do |sub|
|
||||
json = sub.as_json(:include_root => false,
|
||||
:methods => [:submission_history, :late],
|
||||
:methods => [:submission_history, :late, :external_tool_url],
|
||||
:only => submission_fields
|
||||
).merge("from_enrollment_type" => enrollment_types_by_id[sub.user_id])
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@ module Lti
|
|||
SUBMISSION_TYPES_MAP = {
|
||||
'online_upload' => 'file',
|
||||
'online_url' => 'url',
|
||||
'external_tool' => ['url', 'text']
|
||||
}
|
||||
'external_tool' => ['url', 'text'].freeze,
|
||||
'basic_lti_launch' => 'url'
|
||||
}.freeze
|
||||
|
||||
def initialize(assignment, source_id = nil)
|
||||
@assignment = assignment
|
||||
|
|
|
@ -482,6 +482,13 @@ class Submission < ActiveRecord::Base
|
|||
turnitin_data.select{|_, v| v.is_a?(Hash) && v.key?(:outcome_response)}.any?
|
||||
end
|
||||
|
||||
def external_tool_url
|
||||
if self.submission_type == 'basic_lti_launch'
|
||||
base_url = "#{HostUrl.protocol}://#{HostUrl.default_host}"
|
||||
base_url + "/courses/#{assignment.context.id}/external_tools/retrieve?display=borderless&assignment_id=#{assignment.id}&url=#{URI.encode(url)}"
|
||||
end
|
||||
end
|
||||
|
||||
def touch_graders
|
||||
self.class.connection.after_transaction_commit do
|
||||
if self.assignment && self.user && self.assignment.context.is_a?(Course)
|
||||
|
|
|
@ -124,6 +124,10 @@ module BasicLTI
|
|||
@lti_request && @lti_request.at_css('imsx_POXBody > replaceResultRequest > resultRecord > result > resultData > url').try(:content)
|
||||
end
|
||||
|
||||
def result_data_launch_url
|
||||
@lti_request && @lti_request.at_css('imsx_POXBody > replaceResultRequest > resultRecord > result > resultData > ltiLaunchUrl').try(:content)
|
||||
end
|
||||
|
||||
def to_xml
|
||||
xml = LtiResponse.envelope.dup
|
||||
xml.at_css('imsx_POXHeader imsx_statusInfo imsx_codeMajor').content = code_major
|
||||
|
@ -186,7 +190,7 @@ module BasicLTI
|
|||
|
||||
protected
|
||||
|
||||
def handle_replaceResult(tool, course, assignment, user)
|
||||
def handle_replaceResult(_tool, _course, assignment, user)
|
||||
text_value = self.result_score
|
||||
new_score = Float(text_value) rescue false
|
||||
raw_score = Float(self.result_total_score) rescue false
|
||||
|
@ -196,9 +200,12 @@ module BasicLTI
|
|||
if text = result_data_text
|
||||
submission_hash[:body] = text
|
||||
submission_hash[:submission_type] = 'online_text_entry'
|
||||
elsif url = result_data_url
|
||||
elsif (url = result_data_url)
|
||||
submission_hash[:url] = url
|
||||
submission_hash[:submission_type] = 'online_url'
|
||||
elsif (launch_url = result_data_launch_url)
|
||||
submission_hash[:url] = launch_url
|
||||
submission_hash[:submission_type] = 'basic_lti_launch'
|
||||
end
|
||||
|
||||
old_submission = assignment.submissions.where(user_id: user.id).first
|
||||
|
|
|
@ -1772,13 +1772,11 @@ define([
|
|||
$iframe_holder.show().loadDocPreview($.extend(previewOptions, {
|
||||
crocodoc_session_url: (attachment.provisional_crocodoc_url || attachment.crocodoc_url)
|
||||
}));
|
||||
}
|
||||
else if (attachment && attachment.canvadoc_url) {
|
||||
} else if (attachment && attachment.canvadoc_url) {
|
||||
$iframe_holder.show().loadDocPreview($.extend(previewOptions, {
|
||||
canvadoc_session_url: attachment.canvadoc_url
|
||||
}));
|
||||
}
|
||||
else if ( attachment && ($.isPreviewable(attachment.content_type, 'google')) ) {
|
||||
} else if ( attachment && ($.isPreviewable(attachment.content_type, 'google')) ) {
|
||||
if (!INST.disableCrocodocPreviews) $no_annotation_warning.show();
|
||||
|
||||
var currentStudentIDAsOfAjaxCall = this.currentStudent.id;
|
||||
|
@ -1787,16 +1785,20 @@ define([
|
|||
return(currentStudentIDAsOfAjaxCall == this.currentStudent.id);
|
||||
},this)});
|
||||
$iframe_holder.show().loadDocPreview(previewOptions);
|
||||
}
|
||||
else if (attachment && browserableCssClasses.test(attachment.mime_class)) {
|
||||
var src = unescape($submission_file_hidden.find('.display_name').attr('href'))
|
||||
.replace("{{submissionId}}", this.currentStudent.submission.user_id)
|
||||
.replace("{{attachmentId}}", attachment.id);
|
||||
$iframe_holder.html('<iframe src="'+htmlEscape(src)+'" frameborder="0" id="speedgrader_iframe"></iframe>').show();
|
||||
}
|
||||
else {
|
||||
//load in the iframe preview. if we are viewing a past version of the file pass the version to preview in the url
|
||||
$iframe_holder.html($.raw(
|
||||
} else if (attachment && browserableCssClasses.test(attachment.mime_class)) {
|
||||
var src = unescape($submission_file_hidden.find('.display_name').attr('href'))
|
||||
.replace("{{submissionId}}", this.currentStudent.submission.user_id)
|
||||
.replace("{{attachmentId}}", attachment.id);
|
||||
$iframe_holder.html('<iframe src="'+htmlEscape(src)+'" frameborder="0" id="speedgrader_iframe"></iframe>').show();
|
||||
} else if (this.currentStudent.submission.external_tool_url) {
|
||||
$iframe_holder.html(
|
||||
$.raw('<iframe id="speedgrader_iframe" src="' +
|
||||
htmlEscape(this.currentStudent.submission.external_tool_url) + '" class="tool_launch"></iframe>'
|
||||
)
|
||||
).show();
|
||||
} else {
|
||||
//load in the iframe preview. if we are viewing a past version of the file pass the version to preview in the url
|
||||
$iframe_holder.html($.raw(
|
||||
'<iframe id="speedgrader_iframe" src="' + htmlEscape('/courses/' + jsonData.context_id +
|
||||
'/assignments/' + this.currentStudent.submission.assignment_id +
|
||||
'/submissions/' + this.currentStudent.submission.user_id +
|
||||
|
|
|
@ -253,5 +253,15 @@ describe BasicLTI::BasicOutcomes do
|
|||
expect(submission.submission_type).to eq 'online_upload'
|
||||
end
|
||||
|
||||
it 'accepts LTI launch URLs as a data format with a specific submission type' do
|
||||
xml.at_css('text').replace('<ltiLaunchUrl>http://example.com/launch</ltiLaunchUrl>')
|
||||
request = BasicLTI::BasicOutcomes.process_request(tool, xml)
|
||||
|
||||
expect(request.code_major).to eq 'success'
|
||||
expect(request.handle_request(tool)).to be_truthy
|
||||
submission = assignment.submissions.where(user_id: @user.id).first
|
||||
expect(submission.submission_type).to eq 'basic_lti_launch'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -749,6 +749,21 @@ describe Submission do
|
|||
end
|
||||
end
|
||||
|
||||
context '#external_tool_url' do
|
||||
let(:submission) { Submission.new }
|
||||
let(:lti_submission) { @assignment.submit_homework @user, submission_type: 'basic_lti_launch', url: 'http://www.example.com' }
|
||||
context 'submission_type of "basic_lti_launch"' do
|
||||
it 'returns a url containing the submitted url' do
|
||||
expect(lti_submission.external_tool_url).to include(lti_submission.url)
|
||||
end
|
||||
end
|
||||
context 'submission_type of anything other than "basic_lti_launch"' do
|
||||
it 'returns nothing' do
|
||||
expect(submission.external_tool_url).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "should return the correct quiz_submission_version" do
|
||||
# see redmine #6048
|
||||
|
||||
|
|
Loading…
Reference in New Issue