2015-12-21 18:01:14 -05:00
|
|
|
ActivateLicensesModal = require 'views/courses/ActivateLicensesModal'
|
2015-11-03 19:41:06 -05:00
|
|
|
app = require 'core/application'
|
|
|
|
CocoCollection = require 'collections/CocoCollection'
|
2015-11-05 20:26:31 -05:00
|
|
|
CocoModel = require 'models/CocoModel'
|
2015-11-03 19:41:06 -05:00
|
|
|
Course = require 'models/Course'
|
2016-04-08 15:59:10 -04:00
|
|
|
Campaigns = require 'collections/Campaigns'
|
2015-11-03 19:41:06 -05:00
|
|
|
Classroom = require 'models/Classroom'
|
2016-03-30 19:20:37 -04:00
|
|
|
Classrooms = require 'collections/Classrooms'
|
2015-12-01 16:41:02 -05:00
|
|
|
InviteToClassroomModal = require 'views/courses/InviteToClassroomModal'
|
2015-11-05 20:26:31 -05:00
|
|
|
User = require 'models/User'
|
2015-11-03 19:41:06 -05:00
|
|
|
CourseInstance = require 'models/CourseInstance'
|
|
|
|
RootView = require 'views/core/RootView'
|
|
|
|
template = require 'templates/courses/teacher-courses-view'
|
2015-11-17 19:09:29 -05:00
|
|
|
ClassroomSettingsModal = require 'views/courses/ClassroomSettingsModal'
|
2015-11-03 19:41:06 -05:00
|
|
|
|
|
|
|
module.exports = class TeacherCoursesView extends RootView
|
|
|
|
id: 'teacher-courses-view'
|
|
|
|
template: template
|
2015-11-19 18:32:52 -05:00
|
|
|
|
2015-11-04 19:54:13 -05:00
|
|
|
events:
|
2015-12-21 18:01:14 -05:00
|
|
|
'click #activate-licenses-btn': 'onClickActivateLicensesButton'
|
2015-12-01 16:41:02 -05:00
|
|
|
'click .btn-add-students': 'onClickAddStudents'
|
2015-11-30 19:20:24 -05:00
|
|
|
'click .create-new-class': 'onClickCreateNewClassButton'
|
2015-11-17 19:09:29 -05:00
|
|
|
'click .edit-classroom-small': 'onClickEditClassroomSmall'
|
2016-04-08 15:59:10 -04:00
|
|
|
'click .play-level-button': 'onClickPlayLevel'
|
2016-03-30 16:57:19 -04:00
|
|
|
|
|
|
|
guideLinks:
|
|
|
|
{
|
2016-04-07 17:55:42 -04:00
|
|
|
"560f1a9f22961295f9427742":
|
|
|
|
python: 'http://files.codecombat.com/teacherguides/CodeCombat_TeacherGuide_intro_python.pdf'
|
|
|
|
javascript: 'http://files.codecombat.com/teacherguides/CodeCombat_TeacherGuide_intro_javascript.pdf'
|
|
|
|
"5632661322961295f9428638":
|
|
|
|
python: 'http://files.codecombat.com/teacherguides/CodeCombat_TeacherGuide_course-2_python.pdf'
|
|
|
|
javascript: 'http://files.codecombat.com/teacherguides/CodeCombat_TeacherGuide_course-2_javascript.pdf'
|
|
|
|
"56462f935afde0c6fd30fc8c":
|
|
|
|
python: 'http://files.codecombat.com/teacherguides/CodeCombat_TeacherGuide_course-3_python.pdf'
|
|
|
|
javascript: 'http://files.codecombat.com/teacherguides/CodeCombat_TeacherGuide_course-3_javascript.pdf'
|
2016-03-30 16:57:19 -04:00
|
|
|
"56462f935afde0c6fd30fc8d": null
|
|
|
|
"569ed916efa72b0ced971447": null
|
|
|
|
}
|
2015-11-03 19:41:06 -05:00
|
|
|
|
|
|
|
constructor: (options) ->
|
|
|
|
super(options)
|
2016-03-30 19:20:37 -04:00
|
|
|
@ownedClassrooms = new Classrooms()
|
|
|
|
@ownedClassrooms.fetchMine({data: {project: '_id'}})
|
|
|
|
@supermodel.trackCollection(@ownedClassrooms)
|
2015-11-03 19:41:06 -05:00
|
|
|
@courses = new CocoCollection([], { url: "/db/course", model: Course})
|
|
|
|
@supermodel.loadCollection(@courses, 'courses')
|
|
|
|
@classrooms = new CocoCollection([], { url: "/db/classroom", model: Classroom })
|
2015-11-05 20:26:31 -05:00
|
|
|
@classrooms.comparator = '_id'
|
|
|
|
@listenToOnce @classrooms, 'sync', @onceClassroomsSync
|
2015-11-03 19:41:06 -05:00
|
|
|
@supermodel.loadCollection(@classrooms, 'classrooms', {data: {ownerID: me.id}})
|
2016-04-08 15:59:10 -04:00
|
|
|
@campaigns = new Campaigns()
|
2016-05-09 18:16:54 -04:00
|
|
|
@supermodel.trackRequest @campaigns.fetchByType('course', { data: { project: 'levels,levelsUpdated' } })
|
2015-11-05 20:26:31 -05:00
|
|
|
@courseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance })
|
|
|
|
@courseInstances.comparator = 'courseID'
|
2015-11-09 20:58:40 -05:00
|
|
|
@courseInstances.sliceWithMembers = -> return @filter (courseInstance) -> _.size(courseInstance.get('members')) and courseInstance.get('classroomID')
|
2015-11-05 20:26:31 -05:00
|
|
|
@supermodel.loadCollection(@courseInstances, 'course_instances', {data: {ownerID: me.id}})
|
|
|
|
@members = new CocoCollection([], { model: User })
|
2015-11-30 19:20:24 -05:00
|
|
|
@listenTo @members, 'sync', @render
|
2015-11-03 19:41:06 -05:00
|
|
|
@
|
2015-11-04 19:54:13 -05:00
|
|
|
|
2015-11-05 20:26:31 -05:00
|
|
|
onceClassroomsSync: ->
|
|
|
|
for classroom in @classrooms.models
|
|
|
|
@members.fetch({
|
|
|
|
remove: false
|
|
|
|
url: "/db/classroom/#{classroom.id}/members"
|
|
|
|
})
|
|
|
|
|
2015-12-21 18:01:14 -05:00
|
|
|
onClickActivateLicensesButton: ->
|
|
|
|
modal = new ActivateLicensesModal({
|
|
|
|
users: @members
|
|
|
|
})
|
|
|
|
@openModalView(modal)
|
|
|
|
modal.once 'redeem-users', -> document.location.reload()
|
|
|
|
application.tracker?.trackEvent 'Courses teachers started enroll students', category: 'Courses'
|
|
|
|
|
2015-12-01 16:41:02 -05:00
|
|
|
onClickAddStudents: (e) ->
|
|
|
|
classroomID = $(e.target).data('classroom-id')
|
|
|
|
classroom = @classrooms.get(classroomID)
|
|
|
|
unless classroom
|
|
|
|
console.error 'No classroom ID found.'
|
|
|
|
return
|
|
|
|
modal = new InviteToClassroomModal({classroom: classroom})
|
|
|
|
@openModalView(modal)
|
2015-12-04 17:19:56 -05:00
|
|
|
application.tracker?.trackEvent 'Classroom started add students', category: 'Courses', classroomID: classroom.id
|
2015-12-01 16:41:02 -05:00
|
|
|
|
2015-11-30 19:20:24 -05:00
|
|
|
onClickCreateNewClassButton: ->
|
2016-03-09 17:40:52 -05:00
|
|
|
return application.router.navigate('/teachers/signup', {trigger: true}) if me.get('anonymous')
|
2015-11-30 19:20:24 -05:00
|
|
|
modal = new ClassroomSettingsModal({})
|
2015-11-17 19:09:29 -05:00
|
|
|
@openModalView(modal)
|
2015-11-30 19:20:24 -05:00
|
|
|
@listenToOnce modal, 'hide', =>
|
|
|
|
# TODO: how to get new classroom from modal?
|
|
|
|
@classrooms.add(modal.classroom)
|
|
|
|
# TODO: will this definitely fire after modal saves new classroom?
|
2015-12-02 19:07:46 -05:00
|
|
|
@listenToOnce modal.classroom, 'sync', ->
|
|
|
|
@addFreeCourseInstances()
|
|
|
|
@render()
|
2015-11-17 19:09:29 -05:00
|
|
|
|
2015-11-30 19:20:24 -05:00
|
|
|
onClickEditClassroomSmall: (e) ->
|
2015-11-04 19:54:13 -05:00
|
|
|
classroomID = $(e.target).data('classroom-id')
|
|
|
|
classroom = @classrooms.get(classroomID)
|
2015-11-30 19:20:24 -05:00
|
|
|
modal = new ClassroomSettingsModal({classroom: classroom})
|
2015-11-05 20:26:31 -05:00
|
|
|
@openModalView(modal)
|
2015-11-30 19:20:24 -05:00
|
|
|
@listenToOnce modal, 'hide', @render
|
2016-04-08 15:59:10 -04:00
|
|
|
|
|
|
|
onClickPlayLevel: (e) ->
|
|
|
|
form = $(e.currentTarget).closest('.play-level-form')
|
|
|
|
levelSlug = form.find('.level-select').val()
|
|
|
|
courseID = form.data('course-id')
|
|
|
|
language = form.find('.language-select').val()
|
|
|
|
url = "/play/level/#{levelSlug}?course=#{courseID}&codeLanguage=#{language}"
|
|
|
|
application.router.navigate(url, { trigger: true })
|
2015-12-04 17:19:56 -05:00
|
|
|
|
2015-12-02 19:07:46 -05:00
|
|
|
onLoaded: ->
|
|
|
|
super()
|
|
|
|
@addFreeCourseInstances()
|
|
|
|
|
|
|
|
addFreeCourseInstances: ->
|
|
|
|
# so that when students join the classroom, they can automatically get free courses
|
|
|
|
# non-free courses are generated when the teacher first adds a student to them
|
|
|
|
for classroom in @classrooms.models
|
|
|
|
for course in @courses.models
|
|
|
|
continue if not course.get('free')
|
|
|
|
courseInstance = @courseInstances.findWhere({classroomID: classroom.id, courseID: course.id})
|
|
|
|
if not courseInstance
|
|
|
|
courseInstance = new CourseInstance({
|
|
|
|
classroomID: classroom.id
|
|
|
|
courseID: course.id
|
|
|
|
})
|
|
|
|
# TODO: figure out a better way to get around triggering validation errors for properties
|
|
|
|
# that the server will end up filling in, like an empty members array, ownerID
|
|
|
|
courseInstance.save(null, {validate: false})
|
|
|
|
@courseInstances.add(courseInstance)
|
|
|
|
@listenToOnce courseInstance, 'sync', @addFreeCourseInstances
|
2015-12-04 17:19:56 -05:00
|
|
|
return
|