Merge branch 'update-invite-to-classroom'

Work was duplicated. Merging in changes from branch, but leaving
the master version as is in this commit.
This commit is contained in:
Scott Erickson 2016-06-02 10:20:19 -07:00
commit 6e48d700bc
7 changed files with 76 additions and 21 deletions

View file

@ -121,3 +121,10 @@ module.exports = class Classroom extends CocoModel
url: _.result(courseInstance, 'url') + '/classroom'
})
@fetch(options)
inviteMembers: (emails, options={}) ->
options.data ?= {}
options.data.email = emails
options.url = @url() + '/invite-members'
options.type = 'POST'
@fetch(options)

View file

@ -20,17 +20,12 @@ module.exports = class InviteToClassroomModal extends ModalView
emails = _.filter((_.string.trim(email) for email in emails))
if not emails.length
return
url = @classroom.url() + '/invite-members'
@$('#send-invites-btn, #invite-emails-textarea').addClass('hide')
@$('#invite-emails-sending-alert').removeClass('hide')
application.tracker?.trackEvent 'Classroom invite via email', category: 'Courses', classroomID: @classroom.id, emails: emails
$.ajax({
url: url
data: {emails: emails}
method: 'POST'
context: @
success: ->
@classroom.inviteMembers(emails, {
success: =>
@$('#invite-emails-sending-alert').addClass('hide')
@$('#invite-emails-success-alert').removeClass('hide')
})

View file

@ -15,6 +15,8 @@ parse = require '../commons/parse'
LevelSession = require '../models/LevelSession'
User = require '../models/User'
CourseInstance = require '../models/CourseInstance'
TrialRequest = require '../models/TrialRequest'
sendwithus = require '../sendwithus'
module.exports =
fetchByCode: wrap (req, res, next) ->
@ -216,3 +218,33 @@ module.exports =
throw new errors.UnprocessableEntity(error.message)
yield student.update({ $set: { passwordHash: User.hashPassword(newPassword) } })
res.status(200).send({})
inviteMembers: wrap (req, res) ->
if not req.body.emails
throw new errors.UnprocessableEntity('Emails not included')
classroom = yield database.getDocFromHandle(req, Classroom)
if not classroom
throw new errors.NotFound('Classroom not found.')
unless classroom.get('ownerID').equals(req.user?._id)
throw new errors.Forbidden('Must be owner of classroom to send invites.')
user = req.user
teacherName = user.get('name')
teacherName ?= _.filter([user.get('firstName'), user.get('lastName')]).join(' ')
trialRequest = yield TrialRequest.findOne({applicant: user._id})
schoolName = trialRequest?.get('properties')?.organization
for email in req.body.emails
context =
email_id: sendwithus.templates.course_invite_email
recipient:
address: email
email_data:
class_name: classroom.get('name')
teacher_name: teacherName
school_name: schoolName
join_link: "https://codecombat.com/courses?_cc=" + (classroom.get('codeCamel') or classroom.get('code'))
sendwithus.api.send context, _.noop
res.status(200).send({})

View file

@ -60,6 +60,7 @@ module.exports.setup = (app) ->
app.get('/db/classroom', mw.classrooms.fetchByCode, mw.classrooms.getByOwner)
app.get('/db/classroom/:handle/levels', mw.classrooms.fetchAllLevels)
app.get('/db/classroom/:handle/courses/:courseID/levels', mw.classrooms.fetchLevelsForCourse)
# app.post('/db/classroom/:handle/invite-members', mw.classrooms.inviteMembers)
app.get('/db/classroom/:handle/member-sessions', mw.classrooms.fetchMemberSessions)
app.get('/db/classroom/:handle/members', mw.classrooms.fetchMembers) # TODO: Use mw.auth?
app.post('/db/classroom/:classroomID/members/:memberID/reset-password', mw.classrooms.setStudentPassword)

View file

@ -9,7 +9,7 @@ module.exports.setupRoutes = (app) ->
debug = not config.isProduction
module.exports.api =
send: (context, cb) ->
log.debug('Tried to send email with context: ', JSON.stringify(context, null, '\t'))
log.debug('Tried to send email with context: ', JSON.stringify(context, null, ' '))
setTimeout(cb, 10)
if swuAPIKey

View file

@ -343,18 +343,22 @@ describe 'DELETE /db/classroom/:id/members', ->
describe 'POST /db/classroom/:id/invite-members', ->
it 'takes a list of emails and sends invites', (done) ->
loginNewUser (user1) ->
user1.set('role', 'teacher')
user1.save (err) ->
data = { name: 'Classroom 6' }
request.post {uri: classroomsURL, json: data }, (err, res, body) ->
expect(res.statusCode).toBe(201)
url = classroomsURL + '/' + body._id + '/invite-members'
data = { emails: ['test@test.com'] }
request.post { uri: url, json: data }, (err, res, body) ->
expect(res.statusCode).toBe(200)
done()
it 'takes a list of emails and sends invites', utils.wrap (done) ->
user = yield utils.initUser({role: 'teacher', name: 'Mr Professerson'})
yield utils.loginUser(user)
yield utils.makeTrialRequest({ properties: { organization: 'Greendale' } })
classroom = yield utils.makeClassroom()
url = classroomsURL + "/#{classroom.id}/invite-members"
data = { emails: ['test@test.com'] }
sendwithus = require '../../../server/sendwithus'
spyOn(sendwithus.api, 'send').and.callFake (context, cb) ->
expect(context.email_id).toBe(sendwithus.templates.course_invite_email)
expect(context.recipient.address).toBe('test@test.com')
expect(context.email_data.teacher_name).toBe('Mr Professerson')
expect(context.email_data.school_name).toBe('Greendale')
done()
[res, body] = yield request.postAsync { uri: url, json: data }
expect(res.statusCode).toBe(200)
describe 'GET /db/classroom/:handle/member-sessions', ->

View file

@ -11,6 +11,8 @@ Prepaid = require '../../server/models/Prepaid'
Classroom = require '../../server/models/Classroom'
CourseInstance = require '../../server/models/CourseInstance'
moment = require 'moment'
Classroom = require '../../server/models/Classroom'
TrialRequest = require '../../server/models/TrialRequest'
campaignSchema = require '../../app/schemas/models/campaign.schema'
campaignLevelProperties = _.keys(campaignSchema.properties.levels.additionalProperties.properties)
campaignAdjacentCampaignProperties = _.keys(campaignSchema.properties.adjacentCampaigns.additionalProperties.properties)
@ -186,3 +188,17 @@ module.exports = mw =
expect(res.statusCode).toBe(200)
courseInstance = yield CourseInstance.findById(res.body._id)
return courseInstance
makeTrialRequest: Promise.promisify (data, sources, done) ->
args = Array.from(arguments)
[done, [data, sources]] = [args.pop(), args]
data = _.extend({}, {
type: 'course'
properties: {}
}, data)
request.post { uri: getURL('/db/trial.request'), json: data }, (err, res) ->
return done(err) if err
expect(res.statusCode).toBe(201)
TrialRequest.findById(res.body._id).exec done