2015-06-29 15:15:07 -04:00
|
|
|
app = require 'core/application'
|
|
|
|
RootView = require 'views/core/RootView'
|
|
|
|
template = require 'templates/courses/mock1/course-details'
|
2015-07-09 20:53:32 -04:00
|
|
|
CocoCollection = require 'collections/CocoCollection'
|
|
|
|
Campaign = require 'models/Campaign'
|
2015-06-29 15:15:07 -04:00
|
|
|
|
|
|
|
module.exports = class CourseDetailsView extends RootView
|
|
|
|
id: 'course-details-view'
|
|
|
|
template: template
|
|
|
|
|
2015-06-30 19:53:33 -04:00
|
|
|
events:
|
2015-07-01 18:11:40 -04:00
|
|
|
'change .expand-progress-checkbox': 'onExpandedProgressCheckbox'
|
|
|
|
'change .select-session': 'onChangeSession'
|
2015-07-10 13:37:41 -04:00
|
|
|
'change .student-mode-checkbox': 'onChangeStudent'
|
2015-07-10 20:10:46 -04:00
|
|
|
'click .btn-play-level': 'onClickPlayLevel'
|
2015-07-29 18:38:57 -04:00
|
|
|
'click .edit-description-save-btn': 'onEditDescriptionSave'
|
|
|
|
'click .edit-name-save-btn': 'onEditNameSave'
|
2015-07-10 20:10:46 -04:00
|
|
|
'click .member-header': 'onClickMemberHeader'
|
|
|
|
'click .progress-header': 'onClickProgressHeader'
|
2015-06-30 19:53:33 -04:00
|
|
|
|
2015-06-29 15:15:07 -04:00
|
|
|
constructor: (options, @courseID) ->
|
|
|
|
super options
|
|
|
|
@initData()
|
|
|
|
|
2015-07-09 20:53:32 -04:00
|
|
|
destroy: ->
|
|
|
|
@stopListening?()
|
|
|
|
|
2015-06-29 15:15:07 -04:00
|
|
|
getRenderData: ->
|
|
|
|
context = super()
|
2015-07-09 20:53:32 -04:00
|
|
|
context.conceptsProgression = @conceptsProgression ? []
|
2015-06-29 15:15:07 -04:00
|
|
|
context.course = @course ? {}
|
2015-07-09 20:53:32 -04:00
|
|
|
context.courseConcepts = @courseConcepts ? []
|
2015-06-30 19:53:33 -04:00
|
|
|
context.instance = @instances?[@currentInstanceIndex] ? {}
|
|
|
|
context.instances = @instances ? []
|
2015-07-09 20:53:32 -04:00
|
|
|
context.levelConceptsMap = @levelConceptsMap ? {}
|
2015-07-01 18:11:40 -04:00
|
|
|
context.maxLastStartedIndex = @maxLastStartedIndex ? 0
|
2015-07-10 20:10:46 -04:00
|
|
|
context.memberSort = @memberSort
|
2015-07-09 20:53:32 -04:00
|
|
|
context.userConceptsMap = @userConceptsMap ? {}
|
2015-07-01 18:11:40 -04:00
|
|
|
context.userLevelStateMap = @userLevelStateMap ? {}
|
2015-07-09 20:53:32 -04:00
|
|
|
context.showExpandedProgress = @course.levels.length <= 30 or @showExpandedProgress
|
2015-07-24 20:37:42 -04:00
|
|
|
context.studentMode = @options.studentMode ? false
|
2015-07-30 18:30:36 -04:00
|
|
|
|
|
|
|
conceptsCompleted = {}
|
|
|
|
for user of context.userConceptsMap
|
|
|
|
for concept of context.userConceptsMap[user]
|
|
|
|
conceptsCompleted[concept] ?= 0
|
|
|
|
conceptsCompleted[concept]++
|
|
|
|
context.conceptsCompleted = conceptsCompleted
|
|
|
|
|
2015-06-29 15:15:07 -04:00
|
|
|
context
|
|
|
|
|
|
|
|
initData: ->
|
2015-07-10 20:10:46 -04:00
|
|
|
@memberSort = 'nameAsc'
|
2015-06-29 15:15:07 -04:00
|
|
|
mockData = require 'views/courses/mock1/CoursesMockData'
|
|
|
|
@course = mockData.courses[@courseID]
|
2015-06-30 19:53:33 -04:00
|
|
|
@currentInstanceIndex = 0
|
|
|
|
@instances = mockData.instances
|
2015-07-01 18:36:33 -04:00
|
|
|
@updateLevelMaps()
|
2015-06-30 19:53:33 -04:00
|
|
|
|
2015-07-09 20:53:32 -04:00
|
|
|
@campaigns = new CocoCollection([], { url: "/db/campaign", model: Campaign, comparator:'_id' })
|
|
|
|
@listenTo @campaigns, 'sync', @onCampaignSync
|
|
|
|
@supermodel.loadModel @campaigns, 'clan', cache: false
|
|
|
|
|
2015-07-01 18:36:33 -04:00
|
|
|
updateLevelMaps: ->
|
2015-07-09 20:53:32 -04:00
|
|
|
@levelMap = {}
|
|
|
|
@levelMap[level] = true for level in @course.levels
|
2015-07-01 18:11:40 -04:00
|
|
|
@userLevelStateMap = {}
|
|
|
|
@maxLastStartedIndex = -1
|
|
|
|
for student in @instances?[@currentInstanceIndex].students
|
2015-07-09 20:53:32 -04:00
|
|
|
@userLevelStateMap[student] = {}
|
2015-07-29 12:51:01 -04:00
|
|
|
lastCompletedIndex = _.random(-1, @course.levels.length)
|
2015-07-09 20:53:32 -04:00
|
|
|
for i in [0..lastCompletedIndex]
|
|
|
|
@userLevelStateMap[student][@course.levels[i]] = 'complete'
|
2015-07-01 18:11:40 -04:00
|
|
|
lastStartedIndex = lastCompletedIndex + 1
|
2015-07-09 20:53:32 -04:00
|
|
|
@userLevelStateMap[student][@course.levels[lastStartedIndex]] = 'started'
|
2015-07-01 18:11:40 -04:00
|
|
|
@maxLastStartedIndex = lastStartedIndex if lastStartedIndex > @maxLastStartedIndex
|
2015-07-10 20:10:46 -04:00
|
|
|
@sortMembers()
|
|
|
|
|
|
|
|
sortMembers: ->
|
|
|
|
# Progress sort precedence: most completed concepts, most started concepts, most levels, name sort
|
|
|
|
instance = @instances?[@currentInstanceIndex] ? {}
|
|
|
|
return if _.isEmpty(instance)
|
|
|
|
switch @memberSort
|
|
|
|
when "nameDesc"
|
|
|
|
instance.students.sort (a, b) -> b.localeCompare(a)
|
|
|
|
when "progressAsc"
|
|
|
|
instance.students.sort (a, b) =>
|
|
|
|
for level in @course.levels
|
|
|
|
if @userLevelStateMap[a][level] isnt 'complete' and @userLevelStateMap[b][level] is 'complete'
|
|
|
|
return -1
|
|
|
|
else if @userLevelStateMap[a][level] is 'complete' and @userLevelStateMap[b][level] isnt 'complete'
|
|
|
|
return 1
|
|
|
|
0
|
|
|
|
when "progressDesc"
|
|
|
|
instance.students.sort (a, b) =>
|
|
|
|
for level in @course.levels
|
|
|
|
if @userLevelStateMap[a][level] isnt 'complete' and @userLevelStateMap[b][level] is 'complete'
|
|
|
|
return 1
|
|
|
|
else if @userLevelStateMap[a][level] is 'complete' and @userLevelStateMap[b][level] isnt 'complete'
|
|
|
|
return -1
|
|
|
|
0
|
|
|
|
else
|
|
|
|
instance.students.sort (a, b) -> a.localeCompare(b)
|
2015-07-01 18:11:40 -04:00
|
|
|
|
2015-07-09 20:53:32 -04:00
|
|
|
onCampaignSync: ->
|
|
|
|
return unless @campaigns.loaded
|
|
|
|
@conceptsProgression = []
|
|
|
|
@courseConcepts = []
|
|
|
|
@levelConceptsMap = {}
|
|
|
|
@levelNameSlugMap = {}
|
|
|
|
@userConceptsMap = {}
|
2015-07-29 12:51:01 -04:00
|
|
|
# Update course levels if course has a specific campaign
|
|
|
|
for campaign in @campaigns.models when campaign.get('slug') is @course.campaign
|
|
|
|
@course.levels = []
|
|
|
|
for levelID, level of campaign.get('levels')
|
|
|
|
if campaign.get('slug') is @course.campaign
|
|
|
|
@course.levels.push level.name
|
|
|
|
@updateLevelMaps()
|
|
|
|
|
2015-07-09 20:53:32 -04:00
|
|
|
for campaign in @campaigns.models
|
|
|
|
continue if campaign.get('slug') is 'auditions'
|
|
|
|
for levelID, level of campaign.get('levels')
|
|
|
|
@levelNameSlugMap[level.name] = level.slug
|
|
|
|
if level.concepts?
|
|
|
|
for concept in level.concepts
|
|
|
|
@conceptsProgression.push concept unless concept in @conceptsProgression
|
|
|
|
continue unless @levelMap[level.name]
|
|
|
|
@courseConcepts.push concept unless concept in @courseConcepts
|
|
|
|
@levelConceptsMap[level.name] ?= {}
|
|
|
|
@levelConceptsMap[level.name][concept] = true
|
|
|
|
for student in @instances?[@currentInstanceIndex].students
|
|
|
|
@userConceptsMap[student] ?= {}
|
|
|
|
if @userLevelStateMap[student][level.name] is 'complete'
|
|
|
|
@userConceptsMap[student][concept] = 'complete'
|
|
|
|
else if @userLevelStateMap[student][level.name] is 'started'
|
|
|
|
@userConceptsMap[student][concept] ?= 'started'
|
|
|
|
@courseConcepts.sort (a, b) => if @conceptsProgression.indexOf(a) < @conceptsProgression.indexOf(b) then -1 else 1
|
|
|
|
@render?()
|
|
|
|
|
2015-07-10 13:37:41 -04:00
|
|
|
onChangeStudent: (e) ->
|
2015-07-24 20:37:42 -04:00
|
|
|
@options.studentMode = $('.student-mode-checkbox').prop('checked')
|
2015-07-10 13:37:41 -04:00
|
|
|
@render?()
|
2015-07-24 20:37:42 -04:00
|
|
|
$('.student-mode-checkbox').attr('checked', @options.studentMode)
|
2015-07-09 20:53:32 -04:00
|
|
|
|
2015-06-30 19:53:33 -04:00
|
|
|
onChangeSession: (e) ->
|
2015-07-01 18:36:33 -04:00
|
|
|
@showExpandedProgress = false
|
2015-06-30 19:53:33 -04:00
|
|
|
newSessionValue = $(e.target).val()
|
2015-07-02 13:54:19 -04:00
|
|
|
for val, index in @instances when val.name is newSessionValue
|
|
|
|
@currentInstanceIndex = index
|
2015-07-01 18:36:33 -04:00
|
|
|
@updateLevelMaps()
|
2015-07-10 20:10:46 -04:00
|
|
|
@onCampaignSync()
|
2015-06-30 19:53:33 -04:00
|
|
|
|
2015-07-01 18:11:40 -04:00
|
|
|
onExpandedProgressCheckbox: (e) ->
|
|
|
|
@showExpandedProgress = $('.expand-progress-checkbox').prop('checked')
|
|
|
|
# TODO: why does render reset the checkbox to be unchecked?
|
|
|
|
@render?()
|
|
|
|
$('.expand-progress-checkbox').attr('checked', @showExpandedProgress)
|
|
|
|
|
2015-06-30 19:53:33 -04:00
|
|
|
onClickEditClassName: (e) ->
|
|
|
|
alert 'TODO: Popup for editing name for this course session'
|
|
|
|
|
|
|
|
onClickEditClassDescription: (e) ->
|
|
|
|
alert 'TODO: Popup for editing description for this course session'
|
2015-07-09 20:53:32 -04:00
|
|
|
|
2015-07-10 20:10:46 -04:00
|
|
|
onClickMemberHeader: (e) ->
|
|
|
|
@memberSort = if @memberSort is 'nameAsc' then 'nameDesc' else 'nameAsc'
|
|
|
|
@sortMembers()
|
|
|
|
@render?()
|
|
|
|
|
|
|
|
onClickProgressHeader: (e) ->
|
|
|
|
@memberSort = if @memberSort is 'progressAsc' then 'progressDesc' else 'progressAsc'
|
|
|
|
@sortMembers()
|
|
|
|
@render?()
|
|
|
|
|
2015-07-09 20:53:32 -04:00
|
|
|
onClickPlayLevel: (e) ->
|
|
|
|
levelName = $(e.target).data('level')
|
|
|
|
levelSlug = @levelNameSlugMap[levelName]
|
|
|
|
Backbone.Mediator.publish 'router:navigate', {
|
|
|
|
route: "/play/level/#{levelSlug}"
|
|
|
|
viewClass: 'views/play/level/PlayLevelView'
|
|
|
|
viewArgs: [{}, levelSlug]
|
|
|
|
}
|
2015-07-29 18:38:57 -04:00
|
|
|
|
|
|
|
onEditDescriptionSave: (e) ->
|
|
|
|
description = $('.edit-description-input').val()
|
|
|
|
@instances[@currentInstanceIndex].description = description
|
|
|
|
$('#editDescriptionModal').modal('hide')
|
|
|
|
@render?()
|
|
|
|
|
|
|
|
onEditNameSave: (e) ->
|
|
|
|
if name = $('.edit-name-input').val()
|
|
|
|
@instances[@currentInstanceIndex].name = name
|
|
|
|
$('#editNameModal').modal('hide')
|
|
|
|
@render?()
|