From 6ac854c40a6ba198df5ab32e504b0ef19fa139d5 Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Fri, 9 Sep 2016 16:04:51 -0700 Subject: [PATCH] Add update classroom buttons to AdministerUserModal --- app/collections/Classrooms.coffee | 5 +++ .../admin/administer-user-modal.jade | 14 +++++++ app/views/admin/AdministerUserModal.coffee | 14 +++++++ server/middleware/classrooms.coffee | 12 ++++-- spec/server/functional/classrooms.spec.coffee | 41 ++++++++++++++++++- 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/app/collections/Classrooms.coffee b/app/collections/Classrooms.coffee index 90ded05de..36af89721 100644 --- a/app/collections/Classrooms.coffee +++ b/app/collections/Classrooms.coffee @@ -15,3 +15,8 @@ module.exports = class Classrooms extends CocoCollection options.data ?= {} options.data.ownerID = me.id @fetch(options) + + fetchByOwner: (ownerID, options={}) -> + options.data ?= {} + options.data.ownerID = ownerID + @fetch(options) diff --git a/app/templates/admin/administer-user-modal.jade b/app/templates/admin/administer-user-modal.jade index e644aa2af..055109178 100644 --- a/app/templates/admin/administer-user-modal.jade +++ b/app/templates/admin/administer-user-modal.jade @@ -82,5 +82,19 @@ block modal-body-content for coupon in view.coupons.models option(value=coupon.id selected=coupon.id===view.currentCouponID)= coupon.formatString() button#save-changes.btn.btn-primary Save Changes + + if view.classrooms.size() + h3.m-t-3 Update Classrooms + table#classroom-table.table + tr + th Name + th # Levels + th + for classroom in view.classrooms.models + tr + td= classroom.get('name') + td= classroom.getLevels().size() + td + button.btn.btn-primary.update-classroom-btn(data-classroom-id=classroom.id) Update block modal-footer diff --git a/app/views/admin/AdministerUserModal.coffee b/app/views/admin/AdministerUserModal.coffee index eae33a16e..62497a25c 100644 --- a/app/views/admin/AdministerUserModal.coffee +++ b/app/views/admin/AdministerUserModal.coffee @@ -5,6 +5,7 @@ Prepaid = require 'models/Prepaid' StripeCoupons = require 'collections/StripeCoupons' forms = require 'core/forms' Prepaids = require 'collections/Prepaids' +Classrooms = require 'collections/Classrooms' module.exports = class AdministerUserModal extends ModalView id: 'administer-user-modal' @@ -15,6 +16,7 @@ module.exports = class AdministerUserModal extends ModalView 'click #add-seats-btn': 'onClickAddSeatsButton' 'click #destudent-btn': 'onClickDestudentButton' 'click #deteacher-btn': 'onClickDeteacherButton' + 'click .update-classroom-btn': 'onClickUpdateClassroomButton' initialize: (options, @userHandle) -> @user = new User({_id:@userHandle}) @@ -23,6 +25,8 @@ module.exports = class AdministerUserModal extends ModalView @supermodel.trackRequest @coupons.fetch({cache: false}) @prepaids = new Prepaids() @supermodel.trackRequest @prepaids.fetchByCreator(@userHandle) + @classrooms = new Classrooms() + @supermodel.trackRequest @classrooms.fetchByOwner(@userHandle) onLoaded: -> # TODO: Figure out a better way to expose this info, perhaps User methods? @@ -103,3 +107,13 @@ module.exports = class AdministerUserModal extends ModalView } if e.stack throw e + + onClickUpdateClassroomButton: (e) -> + classroom = @classrooms.get($(e.currentTarget).data('classroom-id')) + if confirm("Really update #{classroom.get('name')}?") + Promise.resolve(classroom.updateCourses()) + .then => + noty({text: 'Updated classroom courses.'}) + @renderSelectors('#classroom-table') + .catch -> + noty({text: 'Failed to update classroom courses.', type: 'error'}) diff --git a/server/middleware/classrooms.coffee b/server/middleware/classrooms.coffee index 271050e67..d8540380d 100644 --- a/server/middleware/classrooms.coffee +++ b/server/middleware/classrooms.coffee @@ -166,10 +166,16 @@ module.exports = classroom = yield database.getDocFromHandle(req, Classroom) if not classroom throw new errors.NotFound('Classroom not found.') - unless req.user._id.equals(classroom.get('ownerID')) + unless req.user._id.equals(classroom.get('ownerID')) or req.user.isAdmin() throw new errors.Forbidden('Only the owner may update their classroom content') - - coursesData = yield module.exports.generateCoursesData(classroom.get('aceConfig')?.language, req.user?.isAdmin()) + + # make sure updates are based on owner, not logged in user + if not req.user._id.equals(classroom.get('ownerID')) + owner = yield User.findById(classroom.get('ownerID')) + else + owner = req.user + + coursesData = yield module.exports.generateCoursesData(classroom.get('aceConfig')?.language, owner.isAdmin()) classroom.set('courses', coursesData) classroom = yield classroom.save() res.status(200).send(classroom.toObject({req: req})) diff --git a/spec/server/functional/classrooms.spec.coffee b/spec/server/functional/classrooms.spec.coffee index a98343f68..84481aff3 100644 --- a/spec/server/functional/classrooms.spec.coffee +++ b/spec/server/functional/classrooms.spec.coffee @@ -654,25 +654,64 @@ describe 'GET /db/classroom/:handle/update-courses', -> admin = yield utils.initAdmin() teacher = yield utils.initUser({role: 'teacher'}) + # make a single course yield utils.loginUser(admin) yield utils.makeCourse({releasePhase: 'released'}, {campaign: yield utils.makeCampaign()}) + # make a classroom, make sure it has the one course yield utils.loginUser(teacher) data = { name: 'Classroom 2' } [res, body] = yield request.postAsync {uri: classroomsURL, json: data } classroom = yield Classroom.findById(res.body._id) expect(classroom.get('courses').length).toBe(1) + # make a second course yield utils.loginUser(admin) yield utils.makeCourse({releasePhase: 'released'}, {campaign: yield utils.makeCampaign()}) + # make sure classroom still has one course classroom = yield Classroom.findById(res.body._id) expect(classroom.get('courses').length).toBe(1) + # update, check update happens yield utils.loginUser(teacher) [res, body] = yield request.postAsync { uri: classroomsURL + "/#{classroom.id}/update-courses", json: true } expect(body.courses.length).toBe(2) - classroom = yield Classroom.findById(res.body._id) expect(classroom.get('courses').length).toBe(2) + done() + + it 'allows admins to also update a classroom, but uses the owner\'s admin status', utils.wrap (done) -> + yield utils.clearModels [User, Classroom, Course, Level, Campaign] + + admin = yield utils.initAdmin() + teacher = yield utils.initUser({role: 'teacher'}) + + # make two courses, one released, one beta + yield utils.loginUser(admin) + yield utils.makeCourse({releasePhase: 'released'}, {campaign: yield utils.makeCampaign()}) + yield utils.makeCourse({releasePhase: 'beta'}, {campaign: yield utils.makeCampaign()}) + + # make a classroom, make sure it has the one course + yield utils.loginUser(teacher) + data = { name: 'Classroom 2' } + [res, body] = yield request.postAsync {uri: classroomsURL, json: data } + classroom = yield Classroom.findById(res.body._id) + expect(classroom.get('courses').length).toBe(1) + + # make another released course + yield utils.loginUser(admin) + yield utils.makeCourse({releasePhase: 'released'}, {campaign: yield utils.makeCampaign()}) + + # make sure classroom still has one course + classroom = yield Classroom.findById(res.body._id) + expect(classroom.get('courses').length).toBe(1) + + # update, check that classroom has the two released courses + [res, body] = yield request.postAsync { uri: classroomsURL + "/#{classroom.id}/update-courses", json: true } + expect(body.courses.length).toBe(2) + classroom = yield Classroom.findById(res.body._id) + expect(classroom.get('courses').length).toBe(2) + + done()