From 076e541cdb02bd8b3085f7a30af7391e05147422 Mon Sep 17 00:00:00 2001 From: Ahmad Amireh Date: Mon, 19 May 2014 11:20:50 +0300 Subject: [PATCH] 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 Reviewed-by: Jason Madsen QA-Review: Caleb Guanzon Product-Review: Ahmad Amireh --- .../questions/calculated_controller.coffee | 2 ++ .../questions/file_upload_controller.coffee | 2 ++ .../quizzes/models/question_statistics.coffee | 7 ++++- .../ember/quizzes/models/quiz.coffee | 1 + .../quiz/statistics/questions/calculated.hbs | 7 +++++ .../quiz/statistics/questions/essay.hbs | 14 ++------- .../statistics/questions/essay/_charts.hbs | 7 +++++ .../questions/essay/_header_contents.hbs | 5 ++++ .../quiz/statistics/questions/file_upload.hbs | 13 +++++++++ .../questions/calculated_view.coffee | 2 ++ .../statistics/questions/essay_view.coffee | 4 +-- .../questions/file_upload_view.coffee | 2 ++ .../questions/multiple_choice_view.coffee | 4 +-- .../questions/short_answer_view.coffee | 4 +-- app/serializers/quizzes/quiz_serializer.rb | 14 +++++++-- .../analyzers/file_upload.rb | 2 +- .../analyzers/file_upload_spec.rb | 1 + .../quizzes/quiz_serializer_spec.rb | 29 +++++++++++++++++++ 18 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 app/coffeescripts/ember/quizzes/controllers/quiz/statistics/questions/calculated_controller.coffee create mode 100644 app/coffeescripts/ember/quizzes/controllers/quiz/statistics/questions/file_upload_controller.coffee create mode 100644 app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/calculated.hbs create mode 100644 app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay/_charts.hbs create mode 100644 app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay/_header_contents.hbs create mode 100644 app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/file_upload.hbs create mode 100644 app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/calculated_view.coffee create mode 100644 app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/file_upload_view.coffee diff --git a/app/coffeescripts/ember/quizzes/controllers/quiz/statistics/questions/calculated_controller.coffee b/app/coffeescripts/ember/quizzes/controllers/quiz/statistics/questions/calculated_controller.coffee new file mode 100644 index 00000000000..a64982783a0 --- /dev/null +++ b/app/coffeescripts/ember/quizzes/controllers/quiz/statistics/questions/calculated_controller.coffee @@ -0,0 +1,2 @@ +define [ './essay_controller' ], (Base) -> + Base \ No newline at end of file diff --git a/app/coffeescripts/ember/quizzes/controllers/quiz/statistics/questions/file_upload_controller.coffee b/app/coffeescripts/ember/quizzes/controllers/quiz/statistics/questions/file_upload_controller.coffee new file mode 100644 index 00000000000..a64982783a0 --- /dev/null +++ b/app/coffeescripts/ember/quizzes/controllers/quiz/statistics/questions/file_upload_controller.coffee @@ -0,0 +1,2 @@ +define [ './essay_controller' ], (Base) -> + Base \ No newline at end of file diff --git a/app/coffeescripts/ember/quizzes/models/question_statistics.coffee b/app/coffeescripts/ember/quizzes/models/question_statistics.coffee index 266dbe0543a..95a3b1271d9 100644 --- a/app/coffeescripts/ember/quizzes/models/question_statistics.coffee +++ b/app/coffeescripts/ember/quizzes/models/question_statistics.coffee @@ -31,7 +31,8 @@ define [ correctMiddleStudentCount: 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. # @@ -61,6 +62,10 @@ define [ 'fill_in_multiple_blanks' when 'essay_question' 'essay' + when 'file_upload_question' + 'file_upload' + when 'calculated_question' + 'calculated' else 'generic' ).property('questionType') diff --git a/app/coffeescripts/ember/quizzes/models/quiz.coffee b/app/coffeescripts/ember/quizzes/models/quiz.coffee index 130b7e4f801..bfbb1568c21 100644 --- a/app/coffeescripts/ember/quizzes/models/quiz.coffee +++ b/app/coffeescripts/ember/quizzes/models/quiz.coffee @@ -124,6 +124,7 @@ define [ quizSubmissions: alias('studentQuizSubmissions') takeable: attr() takeQuizUrl: attr() + quizSubmissionsZipUrl: attr() Quiz.SORT_LAST = 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ' diff --git a/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/calculated.hbs b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/calculated.hbs new file mode 100644 index 00000000000..1372df3ffb3 --- /dev/null +++ b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/calculated.hbs @@ -0,0 +1,7 @@ +
+ {{partial "quiz/statistics/questions/essay/header_contents"}} +
+ +
+ {{partial "quiz/statistics/questions/essay/charts"}} +
\ No newline at end of file diff --git a/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay.hbs b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay.hbs index e934c290cea..aa88ff77e3c 100644 --- a/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay.hbs +++ b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay.hbs @@ -5,19 +5,9 @@ - {{attemptsLabel}} - -
- {{{questionText}}} -
+ {{partial "quiz/statistics/questions/essay/header_contents"}}
-
- {{render "quiz/statistics/questions/multiple_choice/correct_pie" controller}} -
- -
- {{render "quiz/statistics/questions/essay/score_chart" controller}} -
+ {{partial "quiz/statistics/questions/essay/charts"}}
\ No newline at end of file diff --git a/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay/_charts.hbs b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay/_charts.hbs new file mode 100644 index 00000000000..94ef45e77b7 --- /dev/null +++ b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay/_charts.hbs @@ -0,0 +1,7 @@ +
+ {{render "quiz/statistics/questions/multiple_choice/correct_pie" controller}} +
+ +
+ {{render "quiz/statistics/questions/essay/score_chart" controller}} +
\ No newline at end of file diff --git a/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay/_header_contents.hbs b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay/_header_contents.hbs new file mode 100644 index 00000000000..638d454fce0 --- /dev/null +++ b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/essay/_header_contents.hbs @@ -0,0 +1,5 @@ +{{attemptsLabel}} + +
+ {{{questionText}}} +
\ No newline at end of file diff --git a/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/file_upload.hbs b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/file_upload.hbs new file mode 100644 index 00000000000..c768f3255ce --- /dev/null +++ b/app/coffeescripts/ember/quizzes/templates/quiz/statistics/questions/file_upload.hbs @@ -0,0 +1,13 @@ +
+ + + {{partial "quiz/statistics/questions/essay/header_contents"}} +
+ +
+ {{partial "quiz/statistics/questions/essay/charts"}} +
\ No newline at end of file diff --git a/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/calculated_view.coffee b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/calculated_view.coffee new file mode 100644 index 00000000000..4a8a54dfc6e --- /dev/null +++ b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/calculated_view.coffee @@ -0,0 +1,2 @@ +define [ '../questions_view' ], (Base) -> + Base diff --git a/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/essay_view.coffee b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/essay_view.coffee index 38b3a2ea50a..4a8a54dfc6e 100644 --- a/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/essay_view.coffee +++ b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/essay_view.coffee @@ -1,2 +1,2 @@ -define [ '../questions_view' ], (BaseView) -> - BaseView +define [ '../questions_view' ], (Base) -> + Base diff --git a/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/file_upload_view.coffee b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/file_upload_view.coffee new file mode 100644 index 00000000000..4a8a54dfc6e --- /dev/null +++ b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/file_upload_view.coffee @@ -0,0 +1,2 @@ +define [ '../questions_view' ], (Base) -> + Base diff --git a/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/multiple_choice_view.coffee b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/multiple_choice_view.coffee index 5380c4defc2..6261025ed99 100644 --- a/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/multiple_choice_view.coffee +++ b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/multiple_choice_view.coffee @@ -1,2 +1,2 @@ -define [ '../questions_view' ], (BaseView) -> - BaseView \ No newline at end of file +define [ '../questions_view' ], (Base) -> + Base \ No newline at end of file diff --git a/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/short_answer_view.coffee b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/short_answer_view.coffee index 8ce21ebf494..6261025ed99 100644 --- a/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/short_answer_view.coffee +++ b/app/coffeescripts/ember/quizzes/views/quiz/statistics/questions/short_answer_view.coffee @@ -1,2 +1,2 @@ -define [ '../questions_view' ], (BaseView) -> - BaseView.extend {} \ No newline at end of file +define [ '../questions_view' ], (Base) -> + Base \ No newline at end of file diff --git a/app/serializers/quizzes/quiz_serializer.rb b/app/serializers/quizzes/quiz_serializer.rb index a3d2f63f611..505746f80ba 100644 --- a/app/serializers/quizzes/quiz_serializer.rb +++ b/app/serializers/quizzes/quiz_serializer.rb @@ -17,7 +17,7 @@ module Quizzes :require_lockdown_browser_monitor, :lockdown_browser_monitor_data, :speed_grader_url, :permissions, :quiz_reports_url, :quiz_statistics_url, :message_students_url, :quiz_submission_html_url, :section_count, - :take_quiz_url, :takeable + :take_quiz_url, :takeable, :quiz_submissions_zip_url def_delegators :@controller, :api_v1_course_assignment_group_url, @@ -29,7 +29,8 @@ module Quizzes :course_quiz_submission_html_url, :api_v1_course_quiz_submission_users_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, :context, @@ -145,6 +146,8 @@ module Quizzes when :submitted_students, :unsubmitted_students then user_may_grade? when :quiz_submission 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 end end @@ -211,6 +214,10 @@ module Quizzes !!(accepts_jsonapi? || stringify_json_ids?) end + def quiz_submissions_zip_url + course_quiz_quiz_submissions_url(quiz.context, quiz.id, zip: 1) + end + private def show_speedgrader? @@ -260,5 +267,8 @@ module Quizzes !!submission_for_current_user end + def has_file_uploads? + quiz.has_file_upload_question? + end end end diff --git a/gems/canvas_quiz_statistics/lib/canvas_quiz_statistics/analyzers/file_upload.rb b/gems/canvas_quiz_statistics/lib/canvas_quiz_statistics/analyzers/file_upload.rb index de715c067e2..972a1c9c5c9 100644 --- a/gems/canvas_quiz_statistics/lib/canvas_quiz_statistics/analyzers/file_upload.rb +++ b/gems/canvas_quiz_statistics/lib/canvas_quiz_statistics/analyzers/file_upload.rb @@ -22,7 +22,7 @@ module CanvasQuizStatistics::Analyzers private def answer_present?(response) - response.has_key?(:attachment_ids) && response[:attachment_ids].any? + (response[:attachment_ids] || []).any? end end end diff --git a/gems/canvas_quiz_statistics/spec/canvas_quiz_statistics/analyzers/file_upload_spec.rb b/gems/canvas_quiz_statistics/spec/canvas_quiz_statistics/analyzers/file_upload_spec.rb index 220242065ea..316edf101a0 100644 --- a/gems/canvas_quiz_statistics/spec/canvas_quiz_statistics/analyzers/file_upload_spec.rb +++ b/gems/canvas_quiz_statistics/spec/canvas_quiz_statistics/analyzers/file_upload_spec.rb @@ -12,6 +12,7 @@ describe CanvasQuizStatistics::Analyzers::FileUpload do it 'should count students who have uploaded an attachment' do subject.run([ {}, + { attachment_ids: nil }, { attachment_ids: [] }, { attachment_ids: ['1'] } ])[:responses].should == 1 diff --git a/spec/serializers/quizzes/quiz_serializer_spec.rb b/spec/serializers/quizzes/quiz_serializer_spec.rb index 842ef237c68..58bf793f3f3 100644 --- a/spec/serializers/quizzes/quiz_serializer_spec.rb +++ b/spec/serializers/quizzes/quiz_serializer_spec.rb @@ -354,6 +354,35 @@ describe Quizzes::QuizSerializer do 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 it "serializes permissions" do serializer.as_json[:quiz][:permissions].should == {