Merge branch 'master' into production

This commit is contained in:
phoenixeliot 2016-05-24 16:05:57 -07:00
commit 9555a12e5c
8 changed files with 0 additions and 98 deletions

View file

@ -1367,7 +1367,6 @@
earliest_incomplete: "Earliest incomplete level" earliest_incomplete: "Earliest incomplete level"
latest_complete: "Latest completed level" latest_complete: "Latest completed level"
enroll_student: "Enroll student" enroll_student: "Enroll student"
revoke_enrollment: "Revoke Enrollment"
adding_students: "Adding students" adding_students: "Adding students"
course_progress: "Course Progress" course_progress: "Course Progress"
not_applicable: "N/A" not_applicable: "N/A"
@ -1438,8 +1437,6 @@
status_expired: "Expired on {{date}}" status_expired: "Expired on {{date}}"
status_not_enrolled: "Not Enrolled" status_not_enrolled: "Not Enrolled"
status_enrolled: "Expires on {{date}}" status_enrolled: "Expires on {{date}}"
revoke_confirm: "Are you sure you want to revoke enrollment from {{student_name}}?"
revoking: "Revoking..."
classes: classes:
archmage_title: "Archmage" archmage_title: "Archmage"

View file

@ -40,10 +40,3 @@ module.exports = class Prepaid extends CocoModel
options.data ?= {} options.data ?= {}
options.data.userID = user.id or user options.data.userID = user.id or user
@fetch(options) @fetch(options)
revoke: (user, options={}) ->
options.url = _.result(@, 'url')+'/redeemers'
options.type = 'DELETE'
options.data ?= {}
options.data.userID = user.id or user
@fetch(options)

View file

@ -308,7 +308,5 @@
width: 300px width: 300px
.enroll-col .enroll-col
width: 140px width: 140px
.revoke-col
width: 170px
td td
vertical-align: middle vertical-align: middle

View file

@ -419,6 +419,3 @@ mixin enrollmentStatusTab
td.enroll-col td.enroll-col
if status !== 'enrolled' if status !== 'enrolled'
button.enroll-student-button.btn.btn-navy(data-i18n="teacher.enroll_student", data-user-id=student.id) button.enroll-student-button.btn.btn-navy(data-i18n="teacher.enroll_student", data-user-id=student.id)
td.revoke-col
if status === 'enrolled'
button.revoke-student-button.btn.btn-burgandy-alt(data-i18n="teacher.revoke_enrollment", data-user-id=student.id)

View file

@ -35,7 +35,6 @@ module.exports = class TeacherClassView extends RootView
'click .remove-student-link': 'onClickRemoveStudentLink' 'click .remove-student-link': 'onClickRemoveStudentLink'
'click .assign-student-button': 'onClickAssignStudentButton' 'click .assign-student-button': 'onClickAssignStudentButton'
'click .enroll-student-button': 'onClickEnrollStudentButton' 'click .enroll-student-button': 'onClickEnrollStudentButton'
'click .revoke-student-button': 'onClickRevokeStudentButton'
'click .assign-to-selected-students': 'onClickBulkAssign' 'click .assign-to-selected-students': 'onClickBulkAssign'
'click .enroll-selected-students': 'onClickBulkEnroll' 'click .enroll-selected-students': 'onClickBulkEnroll'
'click .export-student-progress-btn': 'onClickExportStudentProgress' 'click .export-student-progress-btn': 'onClickExportStudentProgress'
@ -372,23 +371,6 @@ module.exports = class TeacherClassView extends RootView
} }
null null
onClickRevokeStudentButton: (e) ->
button = $(e.currentTarget)
userID = button.data('user-id')
user = @students.get(userID)
s = $.i18n.t('teacher.revoke_confirm').replace('{{student_name}}', user.broadName())
return unless confirm(s)
prepaid = user.makeCoursePrepaid()
button.text($.i18n.t('teacher.revoking'))
prepaid.revoke(user, {
success: =>
user.unset('coursePrepaid')
error: (prepaid, jqxhr) =>
msg = jqxhr.responseJSON.message
noty text: msg, layout: 'center', type: 'error', killer: true, timeout: 3000
complete: => @render()
})
onClickSelectAll: (e) -> onClickSelectAll: (e) ->
e.preventDefault() e.preventDefault()
checkboxes = @$('.student-checkbox input') checkboxes = @$('.student-checkbox input')

View file

@ -90,49 +90,7 @@ module.exports =
redeemers.push({ date: new Date(), userID: user._id }) redeemers.push({ date: new Date(), userID: user._id })
prepaid.set('redeemers', redeemers) prepaid.set('redeemers', redeemers)
res.status(201).send(prepaid.toObject({req: req})) res.status(201).send(prepaid.toObject({req: req}))
revoke: wrap (req, res) ->
if not req.user?.isTeacher()
throw new errors.Forbidden('Must be a teacher to use enrollments')
prepaid = yield database.getDocFromHandle(req, Prepaid)
if not prepaid
throw new errors.NotFound('Prepaid not found.')
unless prepaid.get('creator').equals(req.user._id)
throw new errors.Forbidden('You may not revoke enrollments you do not own.')
unless prepaid.get('type') is 'course'
throw new errors.Forbidden('This prepaid is not of type "course".')
if prepaid.get('endDate') and new Date(prepaid.get('endDate')) < new Date()
throw new errors.Forbidden('This prepaid is expired.')
user = yield User.findById(req.body?.userID)
if not user
throw new errors.NotFound('User not found.')
if not user.isEnrolled()
throw new errors.UnprocessableEntity('User to revoke must be enrolled first.')
if not _.any(prepaid.get('redeemers'), (obj) -> obj.userID.equals(user._id))
throw new errors.UnprocessableEntity('User was not enrolled with this set of enrollments')
query =
_id: prepaid._id
'redeemers.userID': { $eq: user._id }
update = { $pull: { redeemers : { userID: user._id } }}
result = yield Prepaid.update(query, update)
if result.nModified is 0
@logError(req.user, "POST prepaid redeemer lost race on maxRedeemers")
throw new errors.UnprocessableEntity('User was not enrolled with this set of enrollments (race)')
user.set('coursePrepaid', undefined)
yield user.save()
# return prepaid with new redeemer added locally
prepaid.set('redeemers', _.filter(prepaid.get('redeemers') or [], (obj) -> not obj.userID.equals(user._id)))
res.status(200).send(prepaid.toObject({req: req}))
fetchByCreator: wrap (req, res, next) -> fetchByCreator: wrap (req, res, next) ->
creator = req.query.creator creator = req.query.creator
return next() if not creator return next() if not creator

View file

@ -91,7 +91,6 @@ module.exports.setup = (app) ->
app.get('/db/prepaid', mw.auth.checkLoggedIn(), mw.prepaids.fetchByCreator) app.get('/db/prepaid', mw.auth.checkLoggedIn(), mw.prepaids.fetchByCreator)
app.post('/db/prepaid', mw.auth.checkHasPermission(['admin']), mw.prepaids.post) app.post('/db/prepaid', mw.auth.checkHasPermission(['admin']), mw.prepaids.post)
app.post('/db/prepaid/:handle/redeemers', mw.prepaids.redeem) app.post('/db/prepaid/:handle/redeemers', mw.prepaids.redeem)
app.delete('/db/prepaid/:handle/redeemers', mw.prepaids.revoke)
app.get '/db/products', require('./db/product').get app.get '/db/products', require('./db/product').get

View file

@ -113,25 +113,3 @@ describe 'TeacherClassView', ->
users = @view.enrollStudents.calls.argsFor(0)[0] users = @view.enrollStudents.calls.argsFor(0)[0]
expect(users.size()).toBe(1) expect(users.size()).toBe(1)
expect(users.first().id).toBe(@view.students.first().id) expect(users.first().id).toBe(@view.students.first().id)
describe 'Revoke button', ->
it 'opens a confirm modal once clicked', ->
spyOn(window, 'confirm').and.returnValue(true)
@view.$('.revoke-student-button:first').click()
expect(window.confirm).toHaveBeenCalled()
describe 'once the prepaid is successfully revoked', ->
beforeEach ->
spyOn(window, 'confirm').and.returnValue(true)
button = @view.$('.revoke-student-button:first')
@revokedUser = @view.students.get(button.data('user-id'))
@view.$('.revoke-student-button:first').click()
request = jasmine.Ajax.requests.mostRecent()
request.respondWith({
status: 200
responseText: '{}'
})
it 'updates the user and rerenders the page', ->
if @view.$(".enroll-student-button[data-user-id='#{@revokedUser.id}']").length isnt 1
fail('Could not find enroll student button for user whose enrollment was revoked')