codecombat/app/views/courses/ClassroomView.coffee

205 lines
8.4 KiB
CoffeeScript
Raw Normal View History

2015-11-30 14:14:27 -05:00
Campaign = require 'models/Campaign'
CocoCollection = require 'collections/CocoCollection'
Course = require 'models/Course'
CourseInstance = require 'models/CourseInstance'
Classroom = require 'models/Classroom'
LevelSession = require 'models/LevelSession'
RootView = require 'views/core/RootView'
template = require 'templates/courses/classroom-view'
User = require 'models/User'
utils = require 'core/utils'
Prepaid = require 'models/Prepaid'
ClassroomSettingsModal = require 'views/courses/ClassroomSettingsModal'
ActivateLicensesModal = require 'views/courses/ActivateLicensesModal'
2015-12-01 16:17:21 -05:00
InviteToClassroomModal = require 'views/courses/InviteToClassroomModal'
RemoveStudentModal = require 'views/courses/RemoveStudentModal'
popoverTemplate = require 'templates/courses/classroom-level-popover'
2015-11-30 14:14:27 -05:00
module.exports = class ClassroomView extends RootView
id: 'classroom-view'
template: template
teacherMode: false
2015-11-30 14:14:27 -05:00
events:
'click #edit-class-details-link': 'onClickEditClassDetailsLink'
'click #activate-licenses-btn': 'onClickActivateLicensesButton'
'click .activate-single-license-btn': 'onClickActivateSingleLicenseButton'
2015-12-01 16:17:21 -05:00
'click #add-students-btn': 'onClickAddStudentsButton'
2015-12-01 16:27:12 -05:00
'click .enable-btn': 'onClickEnableButton'
'click .remove-student-link': 'onClickRemoveStudentLink'
2015-11-30 14:14:27 -05:00
initialize: (options, classroomID) ->
@classroom = new Classroom({_id: classroomID})
@supermodel.loadModel @classroom, 'classroom'
@courses = new CocoCollection([], { url: "/db/course", model: Course})
@courses.comparator = '_id'
@supermodel.loadCollection(@courses, 'courses')
@campaigns = new CocoCollection([], { url: "/db/campaign", model: Campaign })
@courses.comparator = '_id'
@supermodel.loadCollection(@campaigns, 'campaigns', { data: { type: 'course' }})
@courseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance})
@courseInstances.comparator = 'courseID'
@supermodel.loadCollection(@courseInstances, 'course_instances', { data: { classroomID: classroomID } })
@users = new CocoCollection([], { url: "/db/classroom/#{classroomID}/members", model: User })
@users.comparator = (user) => user.broadName().toLowerCase()
2015-11-30 14:14:27 -05:00
@supermodel.loadCollection(@users, 'users')
@listenToOnce @courseInstances, 'sync', @onCourseInstancesSync
2015-12-03 17:51:38 -05:00
@sessions = new CocoCollection([], { model: LevelSession })
2015-11-30 14:14:27 -05:00
onCourseInstancesSync: ->
@sessions = new CocoCollection([], { model: LevelSession })
for courseInstance in @courseInstances.models
sessions = new CocoCollection([], { url: "/db/course_instance/#{courseInstance.id}/level_sessions", model: LevelSession })
@supermodel.loadCollection(sessions, 'sessions', { data: { project: ['level', 'playtime', 'creator', 'changed', 'state.complete'].join(' ') } })
2015-11-30 14:14:27 -05:00
courseInstance.sessions = sessions
sessions.courseInstance = courseInstance
courseInstance.sessionsByUser = {}
2015-11-30 14:14:27 -05:00
@listenToOnce sessions, 'sync', (sessions) ->
@sessions.add(sessions.slice())
sessions.courseInstance.sessionsByUser = sessions.groupBy('creator')
# generate course instance JIT, in the meantime have models w/out equivalents in the db
for course in @courses.models
query = {courseID: course.id, classroomID: @classroom.id}
courseInstance = @courseInstances.findWhere(query)
if not courseInstance
courseInstance = new CourseInstance(query)
@courseInstances.add(courseInstance)
courseInstance.sessions = new CocoCollection([], {model: LevelSession})
sessions.courseInstance = courseInstance
courseInstance.sessionsByUser = {}
2015-11-30 14:14:27 -05:00
onLoaded: ->
@teacherMode = me.isAdmin() or @classroom.get('ownerID') is me.id
2015-11-30 14:14:27 -05:00
userSessions = @sessions.groupBy('creator')
for user in @users.models
user.sessions = new CocoCollection(userSessions[user.id], { model: LevelSession })
user.sessions.comparator = 'changed'
user.sessions.sort()
for courseInstance in @courseInstances.models
courseID = courseInstance.get('courseID')
course = @courses.get(courseID)
campaignID = course.get('campaignID')
campaign = @campaigns.get(campaignID)
courseInstance.sessions.campaign = campaign
super()
afterRender: ->
@$('[data-toggle="popover"]').popover({
html: true
trigger: 'hover'
placement: 'top'
})
super()
2015-11-30 14:14:27 -05:00
onClickActivateLicensesButton: ->
modal = new ActivateLicensesModal({
classroom: @classroom
users: @users
})
@openModalView(modal)
modal.once 'redeem-users', -> document.location.reload()
2015-12-04 17:11:17 -05:00
application.tracker?.trackEvent 'Classroom started enroll students', category: 'Courses'
onClickActivateSingleLicenseButton: (e) ->
userID = $(e.target).data('user-id')
user = @users.get(userID)
modal = new ActivateLicensesModal({
classroom: @classroom
users: @users
user: user
})
@openModalView(modal)
modal.once 'redeem-users', -> document.location.reload()
2015-12-04 17:11:17 -05:00
application.tracker?.trackEvent 'Classroom started enroll student', category: 'Courses', userID: userID
2015-11-30 14:14:27 -05:00
onClickEditClassDetailsLink: ->
modal = new ClassroomSettingsModal({classroom: @classroom})
@openModalView(modal)
@listenToOnce modal, 'hidden', @render
2015-12-03 17:51:38 -05:00
userLastPlayedString: (user) ->
2015-11-30 14:14:27 -05:00
session = user.sessions.last()
return '' if not session
campaign = session.collection.campaign
levelOriginal = session.get('level').original
campaignLevel = campaign.get('levels')[levelOriginal]
return "#{campaign.get('fullName')}, #{campaignLevel.name}"
2015-12-01 16:17:21 -05:00
2015-12-03 17:51:38 -05:00
userPlaytimeString: (user) ->
playtime = _.reduce user.sessions.pluck('playtime'), (s1, s2) -> (s1 or 0) + (s2 or 0)
return '' unless playtime
return moment.duration(playtime, 'seconds').humanize()
2015-12-03 17:51:38 -05:00
classStats: ->
stats = {}
2015-12-03 17:51:38 -05:00
playtime = 0
total = 0
for session in @sessions.models
pt = session.get('playtime') or 0
playtime += pt
total += 1
stats.averagePlaytime = if playtime and total then moment.duration(playtime / total, "seconds").humanize() else 0
stats.totalPlaytime = if playtime then moment.duration(playtime, "seconds").humanize() else 0
completeSessions = @sessions.filter (s) -> s.get('state')?.complete
2015-12-03 17:51:38 -05:00
stats.averageLevelsComplete = if @users.size() then (_.size(completeSessions) / @users.size()).toFixed(1) else 'N/A'
stats.totalLevelsComplete = _.size(completeSessions)
enrolledUsers = @users.filter (user) -> user.get('coursePrepaidID')
stats.enrolledUsers = _.size(enrolledUsers)
2015-12-03 17:51:38 -05:00
return stats
2015-12-01 16:17:21 -05:00
onClickAddStudentsButton: (e) ->
modal = new InviteToClassroomModal({classroom: @classroom})
2015-12-01 16:27:12 -05:00
@openModalView(modal)
2015-12-04 17:11:17 -05:00
application.tracker?.trackEvent 'Classroom started add students', category: 'Courses', classroomID: @classroom.id
2015-12-01 16:27:12 -05:00
onClickEnableButton: (e) ->
courseInstance = @courseInstances.get($(e.target).data('course-instance-cid'))
2015-12-01 16:27:12 -05:00
userID = $(e.target).data('user-id')
$(e.target).attr('disabled', true)
2015-12-04 17:11:17 -05:00
application.tracker?.trackEvent 'Course assign student', category: 'Courses', courseInstanceID: courseInstance.id, userID: userID
onCourseInstanceCreated = =>
courseInstance.addMember(userID)
@listenToOnce courseInstance, 'sync', @render
if courseInstance.isNew()
# adding the first student to this course, so generate the course instance for it
courseInstance.save(null, {validate: false})
courseInstance.once 'sync', onCourseInstanceCreated
else
onCourseInstanceCreated()
onClickRemoveStudentLink: (e) ->
user = @users.get($(e.target).closest('a').data('user-id'))
modal = new RemoveStudentModal({
classroom: @classroom
user: user
courseInstances: @courseInstances
})
@openModalView(modal)
modal.once 'remove-student', @onStudentRemoved, @
onStudentRemoved: (e) ->
@users.remove(e.user)
@render()
2015-12-04 17:11:17 -05:00
application.tracker?.trackEvent 'Classroom removed student', category: 'Courses', courseInstanceID: @courseInstance.id, userID: e.user.id
levelPopoverContent: (level, session, i) ->
return null unless level
context = {
moment: moment
level: level
session: session
i: i
canViewSolution: @teacherMode
}
return popoverTemplate(context)
getLevelURL: (level, course, courseInstance, session) ->
return null unless @teacherMode and _.all(arguments)
"/play/level/#{level.slug}?course=#{course.id}&course-instance=#{courseInstance.id}&session=#{session.id}&observing=true"