Ember Quiz Stats - File Upload & Formula
Render question statistics for those question types similar to Essay. File Upload should include a link to download all submissions too. QuizSerializer was updated to include the submission ZIP download URL. Closes CNVS-12988 TEST PLAN ---- ---- - using your data set from https://gerrit.instructure.com/#/c/35112/ - verify that the score chart renders with the student scores - verify that you get a link to Download All Files for FUpload questions - verify that the "Attempts: x out of Y" reads correctly based on the "responses" field and the total participant count, respectively - tooltips and chart interactivity like that for Essay Change-Id: I4a77631491b169106e2eb677b21c1f30f3ca9440 Reviewed-on: https://gerrit.instructure.com/35113 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Jason Madsen <jmadsen@instructure.com> QA-Review: Caleb Guanzon <cguanzon@instructure.com> Product-Review: Ahmad Amireh <ahmad@instructure.com>
This commit is contained in:
parent
ddcffe00ef
commit
076e541cdb
|
@ -0,0 +1,2 @@
|
||||||
|
define [ './essay_controller' ], (Base) ->
|
||||||
|
Base
|
|
@ -0,0 +1,2 @@
|
||||||
|
define [ './essay_controller' ], (Base) ->
|
||||||
|
Base
|
|
@ -31,7 +31,8 @@ define [
|
||||||
correctMiddleStudentCount: attr()
|
correctMiddleStudentCount: attr()
|
||||||
correctBottomStudentCount: attr()
|
correctBottomStudentCount: attr()
|
||||||
|
|
||||||
speedGraderUrl: Em.computed.alias('quizStatistics.quiz.speedGraderUrl').readOnly()
|
speedGraderUrl: alias('quizStatistics.quiz.speedGraderUrl').readOnly()
|
||||||
|
quizSubmissionsZipUrl: alias('quizStatistics.quiz.quizSubmissionsZipUrl').readOnly()
|
||||||
|
|
||||||
# Helper for calculating the ratio of correct responses for this question.
|
# Helper for calculating the ratio of correct responses for this question.
|
||||||
#
|
#
|
||||||
|
@ -61,6 +62,10 @@ define [
|
||||||
'fill_in_multiple_blanks'
|
'fill_in_multiple_blanks'
|
||||||
when 'essay_question'
|
when 'essay_question'
|
||||||
'essay'
|
'essay'
|
||||||
|
when 'file_upload_question'
|
||||||
|
'file_upload'
|
||||||
|
when 'calculated_question'
|
||||||
|
'calculated'
|
||||||
else
|
else
|
||||||
'generic'
|
'generic'
|
||||||
).property('questionType')
|
).property('questionType')
|
||||||
|
|
|
@ -124,6 +124,7 @@ define [
|
||||||
quizSubmissions: alias('studentQuizSubmissions')
|
quizSubmissions: alias('studentQuizSubmissions')
|
||||||
takeable: attr()
|
takeable: attr()
|
||||||
takeQuizUrl: attr()
|
takeQuizUrl: attr()
|
||||||
|
quizSubmissionsZipUrl: attr()
|
||||||
|
|
||||||
Quiz.SORT_LAST = 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ'
|
Quiz.SORT_LAST = 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<header>
|
||||||
|
{{partial "quiz/statistics/questions/essay/header_contents"}}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{partial "quiz/statistics/questions/essay/charts"}}
|
||||||
|
</div>
|
|
@ -5,19 +5,9 @@
|
||||||
</a>
|
</a>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<span class="question-attempts">{{attemptsLabel}}</span>
|
{{partial "quiz/statistics/questions/essay/header_contents"}}
|
||||||
|
|
||||||
<div class="question-text">
|
|
||||||
{{{questionText}}}
|
|
||||||
</div>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<section class="correct-answer-ratio-section">
|
{{partial "quiz/statistics/questions/essay/charts"}}
|
||||||
{{render "quiz/statistics/questions/multiple_choice/correct_pie" controller}}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="essay-score-chart-section">
|
|
||||||
{{render "quiz/statistics/questions/essay/score_chart" controller}}
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<section class="correct-answer-ratio-section">
|
||||||
|
{{render "quiz/statistics/questions/multiple_choice/correct_pie" controller}}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="essay-score-chart-section">
|
||||||
|
{{render "quiz/statistics/questions/essay/score_chart" controller}}
|
||||||
|
</section>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<span class="question-attempts">{{attemptsLabel}}</span>
|
||||||
|
|
||||||
|
<div class="question-text">
|
||||||
|
{{{questionText}}}
|
||||||
|
</div>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<header>
|
||||||
|
<aside class="pull-right">
|
||||||
|
<a {{bind-attr href=quizSubmissionsZipUrl}} target="_blank">
|
||||||
|
{{t 'download_submissions' 'Download All Files'}}
|
||||||
|
</a>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{{partial "quiz/statistics/questions/essay/header_contents"}}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{partial "quiz/statistics/questions/essay/charts"}}
|
||||||
|
</div>
|
|
@ -0,0 +1,2 @@
|
||||||
|
define [ '../questions_view' ], (Base) ->
|
||||||
|
Base
|
|
@ -1,2 +1,2 @@
|
||||||
define [ '../questions_view' ], (BaseView) ->
|
define [ '../questions_view' ], (Base) ->
|
||||||
BaseView
|
Base
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
define [ '../questions_view' ], (Base) ->
|
||||||
|
Base
|
|
@ -1,2 +1,2 @@
|
||||||
define [ '../questions_view' ], (BaseView) ->
|
define [ '../questions_view' ], (Base) ->
|
||||||
BaseView
|
Base
|
|
@ -1,2 +1,2 @@
|
||||||
define [ '../questions_view' ], (BaseView) ->
|
define [ '../questions_view' ], (Base) ->
|
||||||
BaseView.extend {}
|
Base
|
|
@ -17,7 +17,7 @@ module Quizzes
|
||||||
:require_lockdown_browser_monitor, :lockdown_browser_monitor_data,
|
:require_lockdown_browser_monitor, :lockdown_browser_monitor_data,
|
||||||
:speed_grader_url, :permissions, :quiz_reports_url, :quiz_statistics_url,
|
:speed_grader_url, :permissions, :quiz_reports_url, :quiz_statistics_url,
|
||||||
:message_students_url, :quiz_submission_html_url, :section_count,
|
:message_students_url, :quiz_submission_html_url, :section_count,
|
||||||
:take_quiz_url, :takeable
|
:take_quiz_url, :takeable, :quiz_submissions_zip_url
|
||||||
|
|
||||||
def_delegators :@controller,
|
def_delegators :@controller,
|
||||||
:api_v1_course_assignment_group_url,
|
:api_v1_course_assignment_group_url,
|
||||||
|
@ -29,7 +29,8 @@ module Quizzes
|
||||||
:course_quiz_submission_html_url,
|
:course_quiz_submission_html_url,
|
||||||
:api_v1_course_quiz_submission_users_url,
|
:api_v1_course_quiz_submission_users_url,
|
||||||
:api_v1_course_quiz_submission_users_message_url,
|
:api_v1_course_quiz_submission_users_message_url,
|
||||||
:course_quiz_take_url
|
:course_quiz_take_url,
|
||||||
|
:course_quiz_quiz_submissions_url
|
||||||
|
|
||||||
def_delegators :@object,
|
def_delegators :@object,
|
||||||
:context,
|
:context,
|
||||||
|
@ -145,6 +146,8 @@ module Quizzes
|
||||||
when :submitted_students, :unsubmitted_students then user_may_grade?
|
when :submitted_students, :unsubmitted_students then user_may_grade?
|
||||||
when :quiz_submission then accepts_jsonapi?
|
when :quiz_submission then accepts_jsonapi?
|
||||||
when :quiz_submission_html_url then accepts_jsonapi?
|
when :quiz_submission_html_url then accepts_jsonapi?
|
||||||
|
when :quiz_submissions_zip_url then
|
||||||
|
accepts_jsonapi? && user_may_grade? && has_file_uploads?
|
||||||
else true
|
else true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -211,6 +214,10 @@ module Quizzes
|
||||||
!!(accepts_jsonapi? || stringify_json_ids?)
|
!!(accepts_jsonapi? || stringify_json_ids?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def quiz_submissions_zip_url
|
||||||
|
course_quiz_quiz_submissions_url(quiz.context, quiz.id, zip: 1)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def show_speedgrader?
|
def show_speedgrader?
|
||||||
|
@ -260,5 +267,8 @@ module Quizzes
|
||||||
!!submission_for_current_user
|
!!submission_for_current_user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def has_file_uploads?
|
||||||
|
quiz.has_file_upload_question?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,7 @@ module CanvasQuizStatistics::Analyzers
|
||||||
private
|
private
|
||||||
|
|
||||||
def answer_present?(response)
|
def answer_present?(response)
|
||||||
response.has_key?(:attachment_ids) && response[:attachment_ids].any?
|
(response[:attachment_ids] || []).any?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,6 +12,7 @@ describe CanvasQuizStatistics::Analyzers::FileUpload do
|
||||||
it 'should count students who have uploaded an attachment' do
|
it 'should count students who have uploaded an attachment' do
|
||||||
subject.run([
|
subject.run([
|
||||||
{},
|
{},
|
||||||
|
{ attachment_ids: nil },
|
||||||
{ attachment_ids: [] },
|
{ attachment_ids: [] },
|
||||||
{ attachment_ids: ['1'] }
|
{ attachment_ids: ['1'] }
|
||||||
])[:responses].should == 1
|
])[:responses].should == 1
|
||||||
|
|
|
@ -354,6 +354,35 @@ describe Quizzes::QuizSerializer do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "quiz_submissions_zip_url" do
|
||||||
|
it "includes a url to download all files" do
|
||||||
|
controller.expects(:accepts_jsonapi?).at_least_once.returns true
|
||||||
|
serializer.expects(:user_may_grade?).at_least_once.returns true
|
||||||
|
serializer.expects(:has_file_uploads?).at_least_once.returns true
|
||||||
|
serializer.as_json[:quiz][:quiz_submissions_zip_url].should ==
|
||||||
|
'http://example.com/courses/1/quizzes/1/submissions?zip=1'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't if it's not a JSON-API request" do
|
||||||
|
controller.expects(:accepts_jsonapi?).at_least_once.returns false
|
||||||
|
serializer.expects(:user_may_grade?).at_least_once.returns true
|
||||||
|
serializer.as_json[:quiz].should_not have_key :quiz_submissions_zip_url
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't if the user may not grade" do
|
||||||
|
controller.expects(:accepts_jsonapi?).at_least_once.returns true
|
||||||
|
serializer.expects(:user_may_grade?).at_least_once.returns false
|
||||||
|
serializer.as_json[:quiz].should_not have_key :quiz_submissions_zip_url
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't if the quiz has no file upload questions" do
|
||||||
|
controller.expects(:accepts_jsonapi?).at_least_once.returns true
|
||||||
|
serializer.expects(:user_may_grade?).at_least_once.returns true
|
||||||
|
serializer.expects(:has_file_uploads?).at_least_once.returns false
|
||||||
|
serializer.as_json[:quiz].should_not have_key :quiz_submissions_zip_url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "permissions" do
|
describe "permissions" do
|
||||||
it "serializes permissions" do
|
it "serializes permissions" do
|
||||||
serializer.as_json[:quiz][:permissions].should == {
|
serializer.as_json[:quiz][:permissions].should == {
|
||||||
|
|
Loading…
Reference in New Issue