add total number of students to ember message students dialog
fixes CNVS-13153 test plan: - enable 'new quiz stats' flag - as a teacher - create a quiz - visit the quiz - the menu item for messaging a student has been adjusted to say "Message Students Who..." - click on this option - it should show the list of students who have taken the quiz up to 10 stents. If more than 10 students are available, it should say "and {number} more students" - switching recipients between students who have taken the quiz, and students who have not taken the quiz should work. It should resize the dialog to allow for more room if more students are listed. - entering a message should send successfully - if you attempt to send the message with no message, the modal dialog will close and a warning message will tell you it didn't send Change-Id: I964de663a5b84daaf5a723694e975eaa147505d7 Reviewed-on: https://gerrit.instructure.com/35870 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Jason Madsen <jmadsen@instructure.com> QA-Review: Trevor deHaan <tdehaan@instructure.com> Product-Review: Derek DeVries <ddevries@instructure.com>
This commit is contained in:
parent
abf9d8f0cd
commit
47434d86ae
|
@ -42,6 +42,8 @@ define [
|
|||
position: @get('position')
|
||||
close: => @sendAction('_destroyAction')
|
||||
|
||||
@set("dialog", $el)
|
||||
|
||||
uiDialog = $el
|
||||
.dialog('open')
|
||||
.data('dialog')
|
||||
|
@ -60,6 +62,11 @@ define [
|
|||
|
||||
).on 'didInsertElement'
|
||||
|
||||
adjustDimensions: (->
|
||||
@get('dialog').dialog("option", "height", @get('height'))
|
||||
@get('dialog').dialog("option", "width", @get('width'))
|
||||
).observes('height', 'width')
|
||||
|
||||
_close: ->
|
||||
@$().dialog 'close'
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
define [
|
||||
'ember'
|
||||
'ic-ajax'
|
||||
'i18n!quiz_message_students'
|
||||
], (Ember, ajax, I18n) ->
|
||||
|
||||
{equal} = Ember.computed
|
||||
|
||||
Ember.ArrayController.extend
|
||||
needs: ['quiz']
|
||||
quiz: Ember.computed.alias('controllers.quiz.model')
|
||||
|
||||
title: I18n.t('message_students_who', 'Message Students Who...')
|
||||
|
||||
recipientGroups: (->
|
||||
[
|
||||
Ember.Object.create({
|
||||
id: 'submitted'
|
||||
name: I18n.t('students_who_have_taken_the_quiz', 'Students Who Have Taken the Quiz'),
|
||||
})
|
||||
Ember.Object.create({
|
||||
id: 'unsubmitted'
|
||||
name: I18n.t('student_who_have_not_taken_the_quiz', 'Students Who Have Not Taken the Quiz')
|
||||
})
|
||||
]
|
||||
).property('quiz.submittedStudents', 'quiz.unsubmittedStudents')
|
||||
|
||||
recipients: (->
|
||||
if @get('selectedRecipientGroup') is 'submitted'
|
||||
@get('quiz.submittedStudents')
|
||||
else
|
||||
@get('quiz.unsubmittedStudents')
|
||||
).property('selectedRecipientGroup', 'quiz.submittedStudents', 'quiz.unsubmittedStudents')
|
||||
|
||||
showUnsubmitted: equal 'selectedRecipientGroup', 'unsubmitted'
|
||||
|
||||
noRecipients: equal 'recipients.length', 0
|
||||
|
||||
moreRecipientsLabel: (->
|
||||
if @get('selectedRecipientGroup') is 'submitted'
|
||||
pagination = @store.metadataFor("submittedStudent").pagination
|
||||
shown = @get('quiz.submittedStudents.length')
|
||||
else
|
||||
pagination = @store.metadataFor("unsubmittedStudent").pagination
|
||||
shown = @get('quiz.unsubmittedStudents.length')
|
||||
|
||||
total = if pagination then pagination.count else 0
|
||||
if total > shown
|
||||
I18n.t('and_num_more_students', 'and %{num} more students', num: total - shown)
|
||||
|
||||
).property('selectedRecipientGroup', 'quiz.submittedStudents', 'quiz.unsubmittedStudents')
|
||||
|
||||
# base height + 10px height for every student
|
||||
modalHeight: (->
|
||||
325 + @get('recipients.length') * 10
|
||||
).property('recipients', 'recipients.isFulfilled')
|
||||
|
||||
actions:
|
||||
submit: ->
|
||||
if @get('messageBody')
|
||||
ajax
|
||||
url: @get('quiz.messageStudentsUrl')
|
||||
data: JSON.stringify(
|
||||
conversations: [
|
||||
recipients: @get('selectedRecipientGroup')
|
||||
body: @get('messageBody')
|
||||
]
|
||||
)
|
||||
type: 'POST'
|
||||
dataType: 'json'
|
||||
contentType: 'application/json'
|
||||
Ember.$.flashMessage I18n.t 'message_sent_successfully', 'Message sent successfully'
|
||||
else
|
||||
Ember.$.flashWarning I18n.t 'message_not_sent_because_empty', 'Message not sent because it was left empty'
|
|
@ -6,9 +6,6 @@ define [
|
|||
'compiled/jquery.rails_flash_notifications'
|
||||
], (Ember, I18n, $, env) ->
|
||||
|
||||
{RSVP, K} = Ember
|
||||
{equal} = Ember.computed
|
||||
|
||||
updateAllDates = (field) ->
|
||||
date = new Date()
|
||||
@set field, date
|
||||
|
@ -19,7 +16,7 @@ define [
|
|||
# override.set field, date
|
||||
# override.save()
|
||||
promises.pushObject(@get('model').save())
|
||||
RSVP.all promises
|
||||
Ember.RSVP.all promises
|
||||
|
||||
QuizController = Ember.ObjectController.extend
|
||||
legacyQuizSubmissionVersionsReady: Ember.computed.and('quizSubmissionVersionsHtml', 'didLoadQuizSubmissionVersionsHtml')
|
||||
|
@ -45,6 +42,10 @@ define [
|
|||
@get('published') and @get('takeable') and !@get('lockedForUser')
|
||||
).property('published', 'takeable', 'lockedForUser')
|
||||
|
||||
messageStudentsActive: (->
|
||||
@get('published')
|
||||
).property('published')
|
||||
|
||||
takeOrResumeMessage: (->
|
||||
if @get('quizSubmission.isCompleted')
|
||||
if @get('isSurvey')
|
||||
|
@ -112,34 +113,6 @@ define [
|
|||
I18n.t('time_limit_minutes', "%{limit} minutes", {limit: @get("timeLimit")})
|
||||
).property('timeLimit')
|
||||
|
||||
# message students modal
|
||||
|
||||
recipientGroups: (->
|
||||
[
|
||||
Ember.Object.create({
|
||||
id: 'submitted'
|
||||
name: I18n.t('students_who_have_taken_the_quiz', 'Students Who Have Taken the Quiz'),
|
||||
})
|
||||
Ember.Object.create({
|
||||
id: 'unsubmitted'
|
||||
name: I18n.t('student_who_have_not_taken_the_quiz', 'Students Who Have Not Taken the Quiz')
|
||||
})
|
||||
]
|
||||
).property('submittedStudents', 'unsubmittedStudents')
|
||||
|
||||
recipients: (->
|
||||
if @get('selectedRecipientGroup') is 'submitted'
|
||||
@get('submittedStudents')
|
||||
else
|
||||
@get('unsubmittedStudents')
|
||||
).property('selectedRecipientGroup', 'submittedStudents', 'unsubmittedStudents')
|
||||
|
||||
showUnsubmitted: equal 'selectedRecipientGroup', 'unsubmitted'
|
||||
|
||||
noRecipients: equal 'recipients.length', 0
|
||||
|
||||
# /message students modal
|
||||
|
||||
actions:
|
||||
takeQuiz: ->
|
||||
if @get 'takeQuizActive'
|
||||
|
@ -162,6 +135,12 @@ define [
|
|||
else
|
||||
$.flashWarning I18n.t('there_are_no_submissions_to_grade', 'There are no submissions to grade.')
|
||||
|
||||
messageStudents: ->
|
||||
if !@get('messageStudentsActive')
|
||||
$.flashWarning I18n.t('you_cannot_message_unpublished', 'You can not message students until this quiz is published.')
|
||||
else
|
||||
true
|
||||
|
||||
moderateQuiz: ->
|
||||
window.location = @get 'moderateUrl'
|
||||
|
||||
|
@ -205,26 +184,6 @@ define [
|
|||
model.save().then =>
|
||||
@transitionToRoute 'quizzes'
|
||||
|
||||
# message students modal
|
||||
|
||||
sendMessageToStudents: ->
|
||||
$.ajax
|
||||
url: @get('messageStudentsUrl')
|
||||
data: JSON.stringify(
|
||||
conversations: [
|
||||
recipients: @get('selectedRecipientGroup')
|
||||
body: @get('messageBody')
|
||||
]
|
||||
)
|
||||
type: 'POST'
|
||||
dataType: 'json'
|
||||
contentType: 'application/json'
|
||||
$.flashMessage I18n.t 'message_sent', 'Message Sent'
|
||||
|
||||
# For modal, just do nothing.
|
||||
cancel: K
|
||||
# /message students modal
|
||||
|
||||
# Kind of a gross hack so we can get quiz arrows in...
|
||||
addLegacyJS: (->
|
||||
return unless @get('quizSubmissionHTML.html')
|
||||
|
|
|
@ -137,8 +137,8 @@ define [
|
|||
|
||||
Ember.A(dates.concat(overrides))
|
||||
).property('lockAt', 'unlockAt', 'dueAt', 'sectionCount', 'assignmentOverrides.[]')
|
||||
submittedStudents: hasMany 'user', polymporphic: true, async: true
|
||||
unsubmittedStudents: hasMany 'user', polymorphic: true, async: true
|
||||
submittedStudents: hasMany 'submitted_student', polymporphic: true, async: true
|
||||
unsubmittedStudents: hasMany 'unsubmitted_student', polymorphic: true, async: true
|
||||
messageStudentsUrl: attr()
|
||||
quizExtensionsUrl: attr()
|
||||
quizSubmission: belongsTo 'quiz_submission'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
define [
|
||||
'ember'
|
||||
'ember-data'
|
||||
], (Em, DS, ajax) ->
|
||||
], (Em, DS) ->
|
||||
|
||||
{alias, equal, any} = Em.computed
|
||||
computed = Em.computed
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
define [
|
||||
'ember-data'
|
||||
'./user'
|
||||
], (DS, User) ->
|
||||
|
||||
SubmittedStudent = User.extend()
|
|
@ -0,0 +1,6 @@
|
|||
define [
|
||||
'ember-data'
|
||||
'./user'
|
||||
], (DS, User) ->
|
||||
|
||||
UnsubmittedStudent = User.extend()
|
|
@ -37,6 +37,6 @@ define [
|
|||
outlet: 'modal'
|
||||
|
||||
messageStudents: ->
|
||||
@render 'message_students',
|
||||
@render 'quiz/message_students',
|
||||
into: 'application'
|
||||
outlet: 'modal'
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
define [
|
||||
'ember-data'
|
||||
'./user_serializer'
|
||||
], (DS, UserSerializer) ->
|
||||
|
||||
SubmittedStudentSerializer = UserSerializer.extend
|
||||
typeForRoot: (root) ->
|
||||
return @_super('submitted_students')
|
|
@ -0,0 +1,8 @@
|
|||
define [
|
||||
'ember-data'
|
||||
'./user_serializer'
|
||||
], (DS, UserSerializer) ->
|
||||
|
||||
UnsubmittedStudentSerializer = UserSerializer.extend
|
||||
typeForRoot: (root) ->
|
||||
return @_super('unsubmitted_students')
|
|
@ -1,38 +0,0 @@
|
|||
{{#form-dialog
|
||||
title="Message Students"
|
||||
on-submit="sendMessageToStudents"
|
||||
submit-disabled=noRecipients
|
||||
height=500
|
||||
width=500
|
||||
fix-dialog-buttons=false
|
||||
}}
|
||||
<div id="message-students-dialog">
|
||||
<label for="select-recipient-group">
|
||||
{{#t 'recipients'}}Recipients{{/t}}
|
||||
</label>
|
||||
{{fast-select
|
||||
items=recipientGroups
|
||||
value=selectedRecipientGroup
|
||||
class="input-xlarge"
|
||||
valuePath="id"
|
||||
labelPath="name"
|
||||
id="select-recipient-group"
|
||||
}}
|
||||
|
||||
<div>
|
||||
{{#if recipients.isFulfilled}}
|
||||
{{#each recipients}}
|
||||
<span class="label">{{shortName}}</span>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<img src='/images/ajax-loader-medium-444.gif'/>
|
||||
{{#t 'loading'}}Loading{{/t}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<label for=message-body>
|
||||
Message
|
||||
</label>
|
||||
{{textarea value=messageBody id='message-body'}}
|
||||
</div>
|
||||
{{/form-dialog}}
|
|
@ -58,9 +58,16 @@
|
|||
{{/ic-menu-item}}
|
||||
{{/unless}}
|
||||
|
||||
{{#ic-menu-item on-select="messageStudents" class="js-message-students"}}
|
||||
{{#ic-menu-item on-select="messageStudents" classBinding=":js-message-students messageStudentsActive::disabled"}}
|
||||
<i class="icon-discussion"></i>
|
||||
{{#t 'Message Students'}}Message Students{{/t}}
|
||||
{{#if messageStudentsActive}}
|
||||
{{#t 'message_students_who'}}Message Students Who...{{/t}}
|
||||
{{else}}
|
||||
<span class="disabled">
|
||||
{{#t 'message_students_who'}}Message Students Who...{{/t}}
|
||||
<span class="screenreader-only">{{#t "option_is_disabled"}}this option is disabled{{/t}}</span>
|
||||
</span>
|
||||
{{/if}}
|
||||
{{/ic-menu-item}}
|
||||
|
||||
{{#ic-menu-item on-select="showStudentResults"}}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
{{#form-dialog
|
||||
title=title
|
||||
on-submit="submit"
|
||||
submit-disabled=noRecipients
|
||||
height=modalHeight
|
||||
width=500
|
||||
fix-dialog-buttons=false
|
||||
}}
|
||||
<div class="message-students-who-dialog">
|
||||
<div class="field">
|
||||
<label for="select-recipient-group">
|
||||
{{#t 'recipients'}}Recipients{{/t}}
|
||||
</label>
|
||||
{{fast-select
|
||||
items=recipientGroups
|
||||
value=selectedRecipientGroup
|
||||
class="input-xlarge"
|
||||
valuePath="id"
|
||||
labelPath="name"
|
||||
id="select-recipient-group"
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="recipients">
|
||||
{{#if recipients.isFulfilled}}
|
||||
{{#each recipients}}
|
||||
<span class="label">{{shortName}}</span>
|
||||
{{/each}}
|
||||
<span class="more-label">
|
||||
{{moreRecipientsLabel}}
|
||||
</span>
|
||||
{{else}}
|
||||
<img src='/images/ajax-loader-medium-444.gif'/>
|
||||
{{#t 'loading'}}Loading{{/t}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<label for="message-body">
|
||||
{{#t 'message'}}Message{{/t}}
|
||||
</label>
|
||||
{{textarea value=messageBody id='message-body'}}
|
||||
</div>
|
||||
{{/form-dialog}}
|
|
@ -63,7 +63,7 @@ define [
|
|||
"mobile_url":"http://localhost:3000/courses/1/quizzes/1?force_user=1&persist_headless=1",
|
||||
"message_students_url": "http://localhost:3000/courses/1/quizzes/1/submission_users/message",
|
||||
"question_count":0,
|
||||
"published":false,
|
||||
"published":true,
|
||||
"unpublishable":true,
|
||||
"locked_for_user":false
|
||||
"permissions":
|
||||
|
|
|
@ -249,12 +249,30 @@
|
|||
// Dialogs - Put outside the #quiz_show scope because jQueryUI puts
|
||||
// it in the body.
|
||||
|
||||
#message-students-dialog {
|
||||
.message-students-who-dialog {
|
||||
.field {
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
.recipients {
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
select {
|
||||
margin-bottom: 0;
|
||||
width: 300px;
|
||||
}
|
||||
.label {
|
||||
margin: 2px 0;
|
||||
}
|
||||
.more-label {
|
||||
font-size: 88%;
|
||||
color: #666;
|
||||
}
|
||||
textarea {
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue