diff --git a/app/coffeescripts/ember/quizzes/controllers/quiz/moderate/student_extension_controller.coffee b/app/coffeescripts/ember/quizzes/controllers/quiz/moderate/student_extension_controller.coffee new file mode 100644 index 00000000000..27bde9d50b7 --- /dev/null +++ b/app/coffeescripts/ember/quizzes/controllers/quiz/moderate/student_extension_controller.coffee @@ -0,0 +1,74 @@ +define [ + 'ember' + 'ic-ajax' + 'i18n!quiz_extensions' +], (Em, ajax, I18n) -> + + StudentExtensionsController = Em.ArrayController.extend + needs: ['quiz'] + quiz: Ember.computed.alias('controllers.quiz.model') + extension: Ember.Object.create + + studentExtensionTitle: + I18n.t 'student_extensions', 'Student Extensions' + + extensionsFor: ( -> + if @get("length") == 1 + student = @get("firstObject.name") + I18n.t('extensions_student', 'Extensions for %{student}', student: student) + else + I18n.t('extensions_num_students', 'Extensions for %{num} Students', num: @get('length')) + ).property('@each') + + modalHeight: ( -> + height = 220 + height += 60 if @get('quiz.timeLimit') + height += 60 if !@get('unlimitedAttempts') + height + ).property('quiz.timeLimit', 'unlimitedAttempts') + + unlimitedAttempts: ( -> + @get('quiz.multipleAttemptsAllowed') && @get('quiz.allowedAttempts') == -1 + ).property('quiz.multipleAttemptsAllowed', 'quiz.allowedAttempts') + + quizExtraAttemptsNote: ( -> + I18n.t('everyone_gets_attempts', 'everyone already gets %{num}', num: @get('quiz.allowedAttempts')) + ).property('quiz.allowedAttempts') + + quizExtraTimeNote: ( -> + I18n.t('everyone_gets_time', 'everyone already gets %{num} minutes', num: @get('quiz.timeLimit')) + ).property('quiz.timeLimit') + + # setup the extension object with defaults based on the selected students + setupExtension: ( -> + if @get('length') == 1 + qs = @get("firstObject.quizSubmission") + @set("extension.extraAttempts", qs.get("extraAttempts")) + @set("extension.extraTime", qs.get("extraTime")) + @set("extension.manuallyUnlocked", qs.get("manuallyUnlocked")) + else + allUnlocked = @everyProperty('quizSubmission.manuallyUnlocked', true) + @set("extension.manuallyUnlocked", !!@get('length') && allUnlocked) + ).observes('model') + + actions: + submitStudentExtensions: -> + quizExtensions = @get("model").map (student) => + user_id: student.get("id") + extra_attempts: @get('extension.extraAttempts') + extra_time: @get('extension.extraTime') + manually_unlocked: @get('extension.manuallyUnlocked') + + options = + url: @get("quiz").get('quizExtensionsUrl') + data: JSON.stringify(quiz_extensions: quizExtensions) + type: 'POST' + dataType: 'json' + contentType: 'application/json' + headers: 'Accepts': 'application/vnd.api+json' + + ajax.raw(options).then => + $.flashMessage I18n.t 'extensions_successfully_added', 'Extensions Successfully Added' + @send 'refreshData' + + diff --git a/app/coffeescripts/ember/quizzes/controllers/quiz/moderate_controller.coffee b/app/coffeescripts/ember/quizzes/controllers/quiz/moderate_controller.coffee index c4f2cdb18bd..5fee52f35d7 100644 --- a/app/coffeescripts/ember/quizzes/controllers/quiz/moderate_controller.coffee +++ b/app/coffeescripts/ember/quizzes/controllers/quiz/moderate_controller.coffee @@ -20,91 +20,30 @@ define [ @send('refreshData') Ember.run.later this, @triggerReload, LATER_REFRESH_MS - needs: ['quiz'] + checkedStudents: ( -> + @filterProperty('isChecked', true) + ).property('@each.isChecked') - quiz: Ember.computed.alias('controllers.quiz.model') - - # student extension modal - - selectedStudents: [] - - studentExtensionTitle: - I18n.t 'student_extensions', 'Student Extensions' - - singleSelection: ( -> - @get("selectedStudents.length") == 1 - ).property('selectedStudents') - - extensionsFor: ( -> - if @get("singleSelection") - student = @get("selectedStudents.firstObject.name") - I18n.t('extensions_student', 'Extensions for %{student}', student: student) + allChecked: ( (key, value) -> + if value == undefined + !!@get('length') && @everyProperty('isChecked', true) else - I18n.t('extensions_num_students', 'Extensions for %{num} Students', num: @get('length')) - ).property('selectedStudents') + @setEach('isChecked', value) + ).property('@each.isChecked') - modalHeight: ( -> - height = 220 - height += 60 if @get('quiz.timeLimit') - height += 60 if !@get('unlimitedAttempts') - height - ).property('quiz.timeLimit', 'unlimitedAttempts') + changeExtensionFor: ( -> + I18n.t('change_extension_for', "Change extension for %{num} Students", num: @get("checkedStudents.length")) + ).property('checkedStudents') - unlimitedAttempts: ( -> - @get('quiz.multipleAttemptsAllowed') && @get('quiz.allowedAttempts') == -1 - ).property('quiz.multipleAttemptsAllowed', 'quiz.allowedAttempts') - - quizExtraAttemptsNote: ( -> - I18n.t('everyone_gets_attempts', 'everyone already gets %{num}', num: @get('quiz.allowedAttempts')) - ).property('quiz.allowedAttempts') - - quizExtraTimeNote: ( -> - I18n.t('everyone_gets_time', 'everyone already gets %{num} minutes', num: @get('quiz.timeLimit')) - ).property('quiz.timeLimit') - - extraAttempts: ( -> - if @get("singleSelection") - student = @get("selectedStudents").get("firstObject") - student.get("quizSubmission").get("extraAttempts") - ).property('selectedStudents') - - extraTime: ( -> - if @get("singleSelection") - student = @get("selectedStudents").get("firstObject") - student.get("quizSubmission").get("extraTime") - ).property('selectedStudents') - - manuallyUnlocked: ( -> - if @get("singleSelection") - student = @get("selectedStudents").get("firstObject") - student.get("quizSubmission").get("manuallyUnlocked") - ).property('selectedStudents') - - # /student extension modal + studentsHaveTakenQuiz: ( -> + complete = @filterProperty('quizSubmission.isComplete', true).get("length") + total = @get("length") + I18n.t('students_have_taken', '%{complete} of %{total} students have completed this quiz', complete: complete, total: total) + ).property('@each.quizSubmission.isComplete') actions: refreshData: -> @set('reloading', true) true - # student extension modal - submitStudentExtensions: -> - quizExtensions = @get("selectedStudents").map (student) => - user_id: student.get("id") - extra_attempts: @get('extraAttempts') - extra_time: @get('extraTime') - manually_unlocked: @get('manuallyUnlocked') - - options = - url: @get("quiz").get('quizExtensionsUrl') - data: JSON.stringify(quiz_extensions: quizExtensions) - type: 'POST' - dataType: 'json' - contentType: 'application/json' - headers: 'Accepts': 'application/vnd.api+json' - - ajax.raw(options).then => - $.flashMessage I18n.t 'extensions_successfully_added', 'Extensions Successfully Added' - @send 'refreshData' - QuizModerateController diff --git a/app/coffeescripts/ember/quizzes/routes/quiz_moderate_route.coffee b/app/coffeescripts/ember/quizzes/routes/quiz_moderate_route.coffee index 2d660cb98d9..2b354ef32f6 100644 --- a/app/coffeescripts/ember/quizzes/routes/quiz_moderate_route.coffee +++ b/app/coffeescripts/ember/quizzes/routes/quiz_moderate_route.coffee @@ -53,11 +53,13 @@ define [ @forceReload(quiz) studentExtension: (model) -> - controller = @controllerFor('quiz.moderate') - controller.set('selectedStudents', Em.A([model])) + model = if model.get("length") then model else [model] + controller = @controllerFor('quiz.moderate.student_extension') + controller.set('model', Em.A(model)) @render 'quiz/moderate/student_extension', into: 'application' outlet: 'modal' + controller: controller ModerateRoute diff --git a/app/coffeescripts/ember/quizzes/templates/quiz/moderate.hbs b/app/coffeescripts/ember/quizzes/templates/quiz/moderate.hbs index 10a867aee3a..093ef3d49a5 100644 --- a/app/coffeescripts/ember/quizzes/templates/quiz/moderate.hbs +++ b/app/coffeescripts/ember/quizzes/templates/quiz/moderate.hbs @@ -1,8 +1,16 @@
+
+ {{studentsHaveTakenQuiz}} + {{#if checkedStudents.length}} + + {{changeExtensionFor}} + + {{/if}} +
- + @@ -18,7 +26,8 @@ - + {{#each user in controller itemController='quiz.submission_row'}} - + - +
{{input type='checkbox' checked=headerChecked}}{{input type='checkbox' checked=allChecked}} {{#t 'student'}}Student{{/t}} {{#t 'score'}}Score{{/t}} +   @@ -31,7 +40,7 @@
{{input type='checkbox' checked=selected}}{{input type='checkbox' checked=isChecked}} {{#if hasActiveSubmission}} @@ -57,7 +66,16 @@ {{remainingStatusLabel}}{{remainingAttempts}} {{user.friendlyScore}} + + {{#if quizSubmission.manuallyUnlocked}} + + + {{#t 'manually_unlocked'}}Manually Unlocked{{/t}} + + + {{/if}} + {{#t 'edit'}}Edit{{/t}} diff --git a/app/coffeescripts/ember/quizzes/templates/quiz/moderate/student_extension.hbs b/app/coffeescripts/ember/quizzes/templates/quiz/moderate/student_extension.hbs index 1b48ff6fcba..52bd12dec8e 100644 --- a/app/coffeescripts/ember/quizzes/templates/quiz/moderate/student_extension.hbs +++ b/app/coffeescripts/ember/quizzes/templates/quiz/moderate/student_extension.hbs @@ -14,7 +14,7 @@ {{quizExtraAttemptsNote}} - {{input type="text" id="extra_attempts" value=extraAttempts class="text"}} + {{input type="text" id="extra_attempts" value=extension.extraAttempts class="text"}} {{t 'attempts' 'attempts'}} @@ -27,14 +27,14 @@ {{quizExtraTimeNote}} - {{input type="text" id="extra_time" value=extraTime class="text"}} + {{input type="text" id="extra_time" value=extension.extraTime class="text"}} {{t 'minutes' 'minutes'}} {{/if}}
- {{input type="checkbox" id="manually_unlocked" checked=manuallyUnlocked}} + {{input type="checkbox" id="manually_unlocked" checked=extension.manuallyUnlocked}} diff --git a/app/stylesheets/ember_quizzes/moderate.scss b/app/stylesheets/ember_quizzes/moderate.scss index 5aa030af85b..0176fdaecef 100644 --- a/app/stylesheets/ember_quizzes/moderate.scss +++ b/app/stylesheets/ember_quizzes/moderate.scss @@ -1,3 +1,64 @@ +#quiz-show { + .quiz-moderate { + .have-taken { + float: left; + margin-bottom: 20px; + margin-left: 3px; + } + .change-extensions-for { + float: right; + margin-bottom: 20px; + margin-right: 3px; + } + + #moderate-table { + .check { + width: 12px; + line-height: 1em; + vertical-align: top; + } + .icon-refreshing { + &.inactive { + display:none; + } + position: relative; + left: -2px; + top: -2px; + } + th { + text-align: center; + } + td { + text-align: center; + } + th.name, + td.name { + text-align: left; + } + th.unlocked, + td.unlocked { + padding: 8px 2px; + } + th.edit, + td.edit { + padding: 8px 2px; + } + th a.icon-refresh:before { + font-size: 100%; + } + th a.icon-refresh, + td a.icon-edit { + color: #444; + } + .extra-time { + font-size: 85%; + color: #555; + } + + } + } +} + #student-extension-dialog { h2 { margin: 0 0 1.5em 0; diff --git a/app/stylesheets/ember_quizzes/show.scss b/app/stylesheets/ember_quizzes/show.scss index 21d9415d236..25db16f70df 100644 --- a/app/stylesheets/ember_quizzes/show.scss +++ b/app/stylesheets/ember_quizzes/show.scss @@ -75,7 +75,7 @@ .tabs-content { border-top: 1px solid #CAD0D7; - padding: 55px 35px; + padding: 25px 35px 55px 35px; } table.quiz-table { @@ -168,49 +168,6 @@ } } - //===== Moderate Tab === - - .quiz-moderate { - - #moderate-table { - .check { - width: 12px; - line-height: 1em; - vertical-align: top; - } - .icon-refreshing { - &.inactive { - display:none; - } - position: relative; - left: -2px; - top: -2px; - } - th { - text-align: center; - } - td { - text-align: center; - } - th.name, - td.name { - text-align: left; - } - th a.icon-refresh:before { - font-size: 100%; - } - th a.icon-refresh, - td a.icon-edit { - color: #444; - } - .extra-time { - font-size: 85%; - color: #555; - } - - } - - } // ic-actions overrides @@ -234,6 +191,7 @@ } } + // Dialogs - Put outside the #quiz_show scope because jQueryUI puts // it in the body.