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 == {