allow messaging more than 100 students from quizzes

fixes CNVS-39904

conversation create api has a limit of 100 recipients for private
messages, so we need to batch them client side

test plan:
- test using "Message students who" in quizzes with > 100 people
- also test from a group category (other place where this code is
reused)

Change-Id: I387105ca3a9d9245a795cad07c9fb3c576c78478
Reviewed-on: https://gerrit.instructure.com/131385
Tested-by: Jenkins
Reviewed-by: Felix Milea-Ciobanu <fmileaciobanu@instructure.com>
QA-Review: KC Naegle <knaegle@instructure.com>
Product-Review: Simon Williams <simon@instructure.com>
This commit is contained in:
Simon Williams 2017-10-31 12:19:58 -06:00
parent e8787b677f
commit c004ff0367
5 changed files with 91 additions and 8 deletions

View File

@ -18,9 +18,8 @@
define [
'i18n!conversations'
'Backbone'
'underscore'
'jquery'
], (I18n,{Model},_,$) ->
], (I18n, {Model}, $) ->
class Conversation extends Model
@ -37,13 +36,13 @@ define [
NO_RECIPIENTS_ERR = I18n.t('no_recipients_choose_another_group',
'No recipients are in this group. Please choose another group.')
validate: (attrs,options) ->
validate: (attrs, options) ->
errors = {}
if !attrs.body or !$.trim(attrs.body.toString())
errors.body = [ message: BLANK_BODY_ERR ]
if !attrs.recipients || !attrs.recipients.length
errors.recipients = [ message: NO_RECIPIENTS_ERR ]
if _.keys(errors).length
if Object.keys(errors).length
errors
else
undefined

View File

@ -0,0 +1,36 @@
#
# Copyright (C) 2017 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
define [
'jquery'
'lodash'
'compiled/models/Conversation'
], ($, _, Conversation) ->
class ConversationCreator
constructor: (opts) ->
@chunkSize = opts.chunkSize || 100
save: (data, saveOpts) ->
xhrs = _.chunk(data.recipients, @chunkSize).map (chunk) ->
chunkData = Object.assign({}, data, { recipients: chunk })
(new Conversation).save(chunkData, saveOpts)
$.when.apply($, xhrs)
# we can validate the full data set in one go
validate: (attrs, options) ->
(new Conversation).validate(attrs, options)

View File

@ -21,11 +21,11 @@ define [
'compiled/views/DialogFormView'
'jst/messageStudentsDialog'
'jst/EmptyDialogFormWrapper'
'compiled/models/Conversation'
'compiled/models/ConversationCreator'
'jst/_messageStudentsWhoRecipientList'
'underscore'
'compiled/jquery/serializeForm'
], (I18n, $, DialogFormView, template, wrapperTemplate, Conversation, recipientListTemplate, _) ->
], (I18n, $, DialogFormView, template, wrapperTemplate, ConversationCreator, recipientListTemplate, _) ->
class MessageStudentsDialog extends DialogFormView
@ -68,7 +68,7 @@ define [
I18n.t('message_students', 'Message students')
@recipients = @recipientGroups[0].recipients
@model or= new Conversation
@model or= new ConversationCreator(chunkSize: ENV.MAX_GROUP_CONVERSATION_SIZE)
toJSON: =>
json = {}

View File

@ -239,7 +239,8 @@ class Quizzes::QuizzesController < ApplicationController
COURSE_ID: @context.id,
LOCKDOWN_BROWSER: @quiz.require_lockdown_browser?,
QUIZ: quiz_json(@quiz,@context,@current_user,session),
QUIZZES_URL: course_quizzes_url(@context)
QUIZZES_URL: course_quizzes_url(@context),
MAX_GROUP_CONVERSATION_SIZE: Conversation.max_group_conversation_size
}
append_sis_data(hash)
js_env(hash)

View File

@ -0,0 +1,47 @@
#
# Copyright (C) 2013 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
define [
'compiled/models/ConversationCreator'
], (ConversationCreator) ->
QUnit.module "ConversationCreator",
setup: ->
@cc = new ConversationCreator(chunkSize: 2)
@server = sinon.fakeServer.create()
teardown: ->
@server.restore()
respond = (data) ->
test "#validate passes through to Conversation", ->
ok @cc.validate(body: '')
ok @cc.validate(body: null).body
ok @cc.validate(body: 'body', recipients: [{}]) == undefined
test "#save calls save in batches", ->
spy = @spy()
@server.respondWith("POST", '/api/v1/conversations', (xhr) ->
spy()
xhr.respond([200, { "Content-Type": "application/json"}, JSON.stringify({})])
)
dfd = @cc.save(body: 'body', recipients: [1, 2, 3, 4])
equal dfd.state(), "pending"
@server.respond()
equal dfd.state(), "resolved"
ok spy.calledTwice