mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-24 08:08:15 -05:00
Add course complete visual state for student CourseDetailsView
Also including a few misc tweaks to CourseDetailsView and the end-of-course HeroVictoryModal state.
This commit is contained in:
parent
cccf61e2e8
commit
c77e1c0fa2
6 changed files with 165 additions and 44 deletions
|
@ -1360,6 +1360,15 @@
|
||||||
campaigns: "Campaigns"
|
campaigns: "Campaigns"
|
||||||
poll: "Poll"
|
poll: "Poll"
|
||||||
user_polls_record: "Poll Voting History"
|
user_polls_record: "Poll Voting History"
|
||||||
|
course: "Course"
|
||||||
|
courses: "Courses"
|
||||||
|
course_instance: "Course Instance"
|
||||||
|
courses_instances: "Course Instances"
|
||||||
|
classroom: "Classroom"
|
||||||
|
classrooms: "Classrooms"
|
||||||
|
clan: "Clan"
|
||||||
|
clans: "Clans"
|
||||||
|
members: "Members"
|
||||||
|
|
||||||
concepts:
|
concepts:
|
||||||
advanced_strings: "Advanced Strings"
|
advanced_strings: "Advanced Strings"
|
||||||
|
|
|
@ -140,3 +140,11 @@
|
||||||
|
|
||||||
.settings-name-input
|
.settings-name-input
|
||||||
width: 50%
|
width: 50%
|
||||||
|
|
||||||
|
.jumbotron
|
||||||
|
.btn
|
||||||
|
white-space: normal
|
||||||
|
min-height: 200px
|
||||||
|
|
||||||
|
h1
|
||||||
|
font-size: 48px
|
||||||
|
|
|
@ -38,7 +38,8 @@ block content
|
||||||
|
|
||||||
if !view.owner.isNew() && view.getOwnerName()
|
if !view.owner.isNew() && view.getOwnerName()
|
||||||
span.spl.spr - Teacher:
|
span.spl.spr - Teacher:
|
||||||
a(href="/user/#{view.owner.id}")
|
//a(href="/user/#{view.owner.id}") // Don't link to profiles until we improve them
|
||||||
|
span
|
||||||
strong= view.getOwnerName()
|
strong= view.getOwnerName()
|
||||||
|
|
||||||
h1
|
h1
|
||||||
|
@ -51,10 +52,60 @@ block content
|
||||||
each line in courseInstance.get('description').split('\n')
|
each line in courseInstance.get('description').split('\n')
|
||||||
div= line
|
div= line
|
||||||
|
|
||||||
|
if view.courseComplete && !view.teacherMode
|
||||||
|
.jumbotron
|
||||||
|
.row
|
||||||
|
if view.singlePlayerMode && !me.isAnonymous()
|
||||||
|
.col-md-3
|
||||||
|
.col-md-6
|
||||||
|
a.btn.btn-lg.btn-success(href="/play")
|
||||||
|
h1 Play the Campaign
|
||||||
|
p You’re ready to take the next step! Explore hundreds of challenging levels, learn advanced programming skills, and compete in multiplayer arenas!
|
||||||
|
.col-md-3
|
||||||
|
else if view.singlePlayerMode && me.isAnonymous()
|
||||||
|
.col-md-6
|
||||||
|
a.btn.btn-lg.btn-success.signup-button
|
||||||
|
h1 Create an Account
|
||||||
|
p Sign up for a FREE CodeCombat account and gain access to more levels, more programming skills, and more fun!
|
||||||
|
.col-md-6
|
||||||
|
a.btn.btn-lg.btn-success(href="/play")
|
||||||
|
h1 Preview Campaign
|
||||||
|
p Take a sneak peek at all that CodeCombat has to offer before signing up for your FREE account.
|
||||||
|
else if !view.singlePlayerMode
|
||||||
|
.col-md-6
|
||||||
|
if view.arenaLevel
|
||||||
|
a.btn.btn-lg.btn-success.btn-play-level(data-level-slug=view.arenaLevel.slug, data-level-id=view.arenaLevel.original)
|
||||||
|
h1
|
||||||
|
span Arena
|
||||||
|
| :
|
||||||
|
span.spl= view.arenaLevel.name
|
||||||
|
p= view.arenaLevel.description.replace(/!\[.*?\)/, '')
|
||||||
|
else
|
||||||
|
a.btn.btn-lg.btn-success.disabled
|
||||||
|
h1 Arena Coming Soon
|
||||||
|
p We are working on a multiplayer arena for classrooms at the end of #{course.get('name')}.
|
||||||
|
.col-md-6
|
||||||
|
if view.nextCourseInstance
|
||||||
|
a.btn.btn-lg.btn-success(href="/courses/#{view.nextCourse.id}/#{view.nextCourseInstance.id}")
|
||||||
|
h1= view.nextCourse.get('name')
|
||||||
|
p= view.nextCourse.get('description')
|
||||||
|
else if view.nextCourse
|
||||||
|
a.btn.btn-lg.btn-success.disabled
|
||||||
|
h1= view.nextCourse.get('name')
|
||||||
|
p
|
||||||
|
em NOT ENROLLED
|
||||||
|
p Ask your teacher to enroll you in the next course.
|
||||||
|
else
|
||||||
|
a.btn.btn-lg.btn-success(disabled=!view.nextCourse ? "disabled" : "")
|
||||||
|
h1 Next Course
|
||||||
|
p
|
||||||
|
em COMING SOON
|
||||||
|
p We are hard at work making more courses for you!
|
||||||
|
|
||||||
if !me.isAnonymous()
|
if !me.isAnonymous()
|
||||||
div.well.well-sm(role='tabpanel')
|
div.well.well-sm(role='tabpanel')
|
||||||
ul.nav.nav-pills(role='tablist')
|
ul.nav.nav-pills(role='tablist')
|
||||||
if adminMode
|
if view.teacherMode
|
||||||
li.active(role='presentation')
|
li.active(role='presentation')
|
||||||
a(href='#progress', aria-controls='progress', role='tab', data-toggle='tab', data-i18n="courses.progress")
|
a(href='#progress', aria-controls='progress', role='tab', data-toggle='tab', data-i18n="courses.progress")
|
||||||
li(role='presentation')
|
li(role='presentation')
|
||||||
|
@ -65,7 +116,7 @@ block content
|
||||||
li(role='presentation')
|
li(role='presentation')
|
||||||
a(href='#progress', aria-controls='progress', role='tab', data-toggle='tab', data-i18n="courses.progress")
|
a(href='#progress', aria-controls='progress', role='tab', data-toggle='tab', data-i18n="courses.progress")
|
||||||
.tab-content
|
.tab-content
|
||||||
if adminMode
|
if view.teacherMode
|
||||||
.tab-pane.active#progress(role='tabpanel')
|
.tab-pane.active#progress(role='tabpanel')
|
||||||
+progress-tab
|
+progress-tab
|
||||||
.tab-pane#levels(role='tabpanel')
|
.tab-pane#levels(role='tabpanel')
|
||||||
|
@ -241,7 +292,7 @@ mixin progress-members-popup-completed(i, level, session)
|
||||||
p
|
p
|
||||||
span.spr(data-i18n="courses.completed")
|
span.spr(data-i18n="courses.completed")
|
||||||
span #{moment(session.get('changed')).format('MMMM Do YYYY, h:mm:ss a')}
|
span #{moment(session.get('changed')).format('MMMM Do YYYY, h:mm:ss a')}
|
||||||
if adminMode
|
if view.teacherMode || me.isAdmin()
|
||||||
strong(data-i18n="clans.view_solution")
|
strong(data-i18n="clans.view_solution")
|
||||||
|
|
||||||
mixin progress-members-popup-started(i, level, session)
|
mixin progress-members-popup-started(i, level, session)
|
||||||
|
@ -253,7 +304,7 @@ mixin progress-members-popup-started(i, level, session)
|
||||||
p
|
p
|
||||||
span.spr(data-i18n="clans.last_played")
|
span.spr(data-i18n="clans.last_played")
|
||||||
span #{moment(session.get('changed')).format('MMMM Do YYYY, h:mm:ss a')}
|
span #{moment(session.get('changed')).format('MMMM Do YYYY, h:mm:ss a')}
|
||||||
if adminMode
|
if view.teacherMode || me.isAdmin()
|
||||||
strong(data-i18n="clans.view_solution")
|
strong(data-i18n="clans.view_solution")
|
||||||
|
|
||||||
mixin levels-tab
|
mixin levels-tab
|
||||||
|
@ -271,7 +322,7 @@ mixin levels-tab
|
||||||
each level, levelID in campaign.get('levels')
|
each level, levelID in campaign.get('levels')
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
if lastLevelCompleted || adminMode
|
if lastLevelCompleted || view.teacherMode
|
||||||
- var i18n = level.type === 'course-ladder' ? 'play.compete' : 'home.play';
|
- var i18n = level.type === 'course-ladder' ? 'play.compete' : 'home.play';
|
||||||
button.btn.btn-success.btn-play-level(data-level-slug=level.slug, data-i18n=i18n, data-level-id=levelID)
|
button.btn.btn-success.btn-play-level(data-level-slug=level.slug, data-i18n=i18n, data-level-id=levelID)
|
||||||
td
|
td
|
||||||
|
|
|
@ -12,10 +12,11 @@ block modal-body-content
|
||||||
#victory-text= victoryText
|
#victory-text= victoryText
|
||||||
|
|
||||||
if isCourseLevel
|
if isCourseLevel
|
||||||
if currentCourseName
|
.course-name-container
|
||||||
p
|
if currentCourseName
|
||||||
span.spr.level-title(data-i18n="play_level.course")
|
p
|
||||||
span.level-name= currentCourseName
|
span.spr.level-title(data-i18n="play_level.course")
|
||||||
|
span.level-name= currentCourseName
|
||||||
.container-fluid
|
.container-fluid
|
||||||
.row
|
.row
|
||||||
.col-md-6
|
.col-md-6
|
||||||
|
@ -26,6 +27,10 @@ block modal-body-content
|
||||||
if nextLevelName
|
if nextLevelName
|
||||||
.level-title(data-i18n="play_level.next_level")
|
.level-title(data-i18n="play_level.next_level")
|
||||||
.level-name= nextLevelName.replace('Course: ', '')
|
.level-name= nextLevelName.replace('Course: ', '')
|
||||||
|
else
|
||||||
|
.level-title(data-i18n="play_level.course")
|
||||||
|
.level-name(data-i18n="play_level.victory_title_suffix")
|
||||||
|
|
||||||
br
|
br
|
||||||
|
|
||||||
#level-feedback
|
#level-feedback
|
||||||
|
|
|
@ -15,6 +15,9 @@ autoplayedOnce = false
|
||||||
module.exports = class CourseDetailsView extends RootView
|
module.exports = class CourseDetailsView extends RootView
|
||||||
id: 'course-details-view'
|
id: 'course-details-view'
|
||||||
template: template
|
template: template
|
||||||
|
teacherMode: false
|
||||||
|
singlePlayerMode: false
|
||||||
|
memberSort: 'nameAsc'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'change .progress-expand-checkbox': 'onCheckExpandedProgress'
|
'change .progress-expand-checkbox': 'onCheckExpandedProgress'
|
||||||
|
@ -31,8 +34,6 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
@courseID ?= options.courseID
|
@courseID ?= options.courseID
|
||||||
@courseInstanceID ?= options.courseInstanceID
|
@courseInstanceID ?= options.courseInstanceID
|
||||||
@classroom = new Classroom()
|
@classroom = new Classroom()
|
||||||
@adminMode = me.isAdmin()
|
|
||||||
@memberSort = 'nameAsc'
|
|
||||||
@course = @supermodel.getModel(Course, @courseID) or new Course _id: @courseID
|
@course = @supermodel.getModel(Course, @courseID) or new Course _id: @courseID
|
||||||
@listenTo @course, 'sync', @onCourseSync
|
@listenTo @course, 'sync', @onCourseSync
|
||||||
@prepaid = new Prepaid()
|
@prepaid = new Prepaid()
|
||||||
|
@ -43,7 +44,6 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
context = super()
|
context = super()
|
||||||
context.adminMode = @adminMode ? false
|
|
||||||
context.campaign = @campaign
|
context.campaign = @campaign
|
||||||
context.conceptsCompleted = @conceptsCompleted ? {}
|
context.conceptsCompleted = @conceptsCompleted ? {}
|
||||||
context.course = @course if @course?.loaded
|
context.course = @course if @course?.loaded
|
||||||
|
@ -64,11 +64,19 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
context.document = document
|
context.document = document
|
||||||
context
|
context
|
||||||
|
|
||||||
|
afterRender: ->
|
||||||
|
super()
|
||||||
|
if @supermodel.finished() and @courseComplete and me.isAnonymous() and @options.justBeatLevel
|
||||||
|
# TODO: Make an intermediate modal that tells them they've finished HoC and has some snazzy stuff for convincing players to sign up instead of just throwing up the bare AuthModal
|
||||||
|
AuthModal = require 'views/core/AuthModal'
|
||||||
|
@openModalView new AuthModal showSignupRationale: true
|
||||||
|
|
||||||
onCourseSync: ->
|
onCourseSync: ->
|
||||||
|
return if @destroyed
|
||||||
# console.log 'onCourseSync'
|
# console.log 'onCourseSync'
|
||||||
if me.isAnonymous() and (not me.get('hourOfCode') and not @course.get('hourOfCode'))
|
if me.isAnonymous() and (not me.get('hourOfCode') and not @course.get('hourOfCode'))
|
||||||
@noCourseInstance = true
|
@noCourseInstance = true
|
||||||
@render?()
|
@render()
|
||||||
return
|
return
|
||||||
return if @campaign?
|
return if @campaign?
|
||||||
campaignID = @course.get('campaignID')
|
campaignID = @course.get('campaignID')
|
||||||
|
@ -78,24 +86,36 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
@onCampaignSync()
|
@onCampaignSync()
|
||||||
else
|
else
|
||||||
@supermodel.loadModel @campaign, 'campaign'
|
@supermodel.loadModel @campaign, 'campaign'
|
||||||
@render?()
|
@render()
|
||||||
|
|
||||||
onCampaignSync: ->
|
onCampaignSync: ->
|
||||||
|
return if @destroyed
|
||||||
# console.log 'onCampaignSync'
|
# console.log 'onCampaignSync'
|
||||||
if @courseInstanceID
|
if @courseInstanceID
|
||||||
@loadCourseInstance(@courseInstanceID)
|
@loadCourseInstance(@courseInstanceID)
|
||||||
else unless me.isAnonymous()
|
else unless me.isAnonymous()
|
||||||
@courseInstances = new CocoCollection([], { url: "/db/user/#{me.id}/course_instances", model: CourseInstance})
|
@loadCourseInstances()
|
||||||
@listenToOnce @courseInstances, 'sync', @onCourseInstancesSync
|
|
||||||
@supermodel.loadCollection(@courseInstances, 'course_instances')
|
|
||||||
@levelConceptMap = {}
|
@levelConceptMap = {}
|
||||||
for levelID, level of @campaign.get('levels')
|
for levelID, level of @campaign.get('levels')
|
||||||
@levelConceptMap[levelID] ?= {}
|
@levelConceptMap[levelID] ?= {}
|
||||||
for concept in level.concepts
|
for concept in level.concepts
|
||||||
@levelConceptMap[levelID][concept] = true
|
@levelConceptMap[levelID][concept] = true
|
||||||
@render?()
|
if level.type is 'course-ladder'
|
||||||
|
@arenaLevel = level
|
||||||
|
@render()
|
||||||
|
|
||||||
|
loadCourseInstances: ->
|
||||||
|
@courseInstances = new CocoCollection [], {url: "/db/user/#{me.id}/course_instances", model: CourseInstance, comparator: 'courseID'}
|
||||||
|
@listenToOnce @courseInstances, 'sync', @onCourseInstancesSync
|
||||||
|
@supermodel.loadCollection @courseInstances, 'course_instances'
|
||||||
|
|
||||||
|
loadAllCourses: ->
|
||||||
|
@allCourses = new CocoCollection [], {url: "/db/course", model: Course, comparator: '_id'}
|
||||||
|
@listenToOnce @allCourses, 'sync', @onAllCoursesSync
|
||||||
|
@supermodel.loadCollection @allCourses, 'courses'
|
||||||
|
|
||||||
loadCourseInstance: (courseInstanceID) ->
|
loadCourseInstance: (courseInstanceID) ->
|
||||||
|
return if @destroyed
|
||||||
# console.log 'loadCourseInstance'
|
# console.log 'loadCourseInstance'
|
||||||
return if @courseInstance?
|
return if @courseInstance?
|
||||||
@courseInstanceID = courseInstanceID
|
@courseInstanceID = courseInstanceID
|
||||||
|
@ -107,23 +127,29 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
@courseInstance = @supermodel.loadModel(@courseInstance, 'course_instance').model
|
@courseInstance = @supermodel.loadModel(@courseInstance, 'course_instance').model
|
||||||
|
|
||||||
onCourseInstancesSync: ->
|
onCourseInstancesSync: ->
|
||||||
|
return if @destroyed
|
||||||
# console.log 'onCourseInstancesSync'
|
# console.log 'onCourseInstancesSync'
|
||||||
if @courseInstances.models.length is 1
|
@findNextCourseInstance()
|
||||||
@loadCourseInstance(@courseInstances.models[0].id)
|
if not @courseInstance
|
||||||
else
|
# We are loading these to find the one we want to display.
|
||||||
if @courseInstances.models.length is 0
|
if @courseInstances.models.length is 1
|
||||||
@noCourseInstance = true
|
@loadCourseInstance(@courseInstances.models[0].id)
|
||||||
else
|
else
|
||||||
@noCourseInstanceSelected = true
|
if @courseInstances.models.length is 0
|
||||||
@render?()
|
@noCourseInstance = true
|
||||||
|
else
|
||||||
|
@noCourseInstanceSelected = true
|
||||||
|
@render()
|
||||||
|
|
||||||
onCourseInstanceSync: ->
|
onCourseInstanceSync: ->
|
||||||
|
return if @destroyed
|
||||||
# console.log 'onCourseInstanceSync'
|
# console.log 'onCourseInstanceSync'
|
||||||
if @courseInstance.get('classroomID')
|
if @courseInstance.get('classroomID')
|
||||||
@classroom = new Classroom({_id: @courseInstance.get('classroomID')})
|
@classroom = new Classroom({_id: @courseInstance.get('classroomID')})
|
||||||
@supermodel.loadModel @classroom, 'classroom'
|
@supermodel.loadModel @classroom, 'classroom'
|
||||||
@adminMode = true if @courseInstance.get('ownerID') is me.id and @courseInstance.get('name') isnt 'Single Player'
|
@singlePlayerMode = @courseInstance.get('name') is 'Single Player'
|
||||||
@levelSessions = new CocoCollection([], { url: "/db/course_instance/#{@courseInstance.id}/level_sessions", model: LevelSession, comparator:'_id' })
|
@teacherMode = @courseInstance.get('ownerID') is me.id and not @singlePlayerMode
|
||||||
|
@levelSessions = new CocoCollection([], { url: "/db/course_instance/#{@courseInstance.id}/level_sessions", model: LevelSession, comparator: '_id' })
|
||||||
@listenToOnce @levelSessions, 'sync', @onLevelSessionsSync
|
@listenToOnce @levelSessions, 'sync', @onLevelSessionsSync
|
||||||
@supermodel.loadCollection @levelSessions, 'level_sessions', cache: false
|
@supermodel.loadCollection @levelSessions, 'level_sessions', cache: false
|
||||||
@members = new CocoCollection([], { url: "/db/course_instance/#{@courseInstance.id}/members", model: User, comparator: 'nameLower' })
|
@members = new CocoCollection([], { url: "/db/course_instance/#{@courseInstance.id}/members", model: User, comparator: 'nameLower' })
|
||||||
|
@ -131,19 +157,22 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
@supermodel.loadCollection @members, 'members', cache: false
|
@supermodel.loadCollection @members, 'members', cache: false
|
||||||
@owner = new User({_id: @courseInstance.get('ownerID')})
|
@owner = new User({_id: @courseInstance.get('ownerID')})
|
||||||
@supermodel.loadModel @owner, 'user'
|
@supermodel.loadModel @owner, 'user'
|
||||||
if @adminMode and prepaidID = @courseInstance.get('prepaidID')
|
if @teacherMode and prepaidID = @courseInstance.get('prepaidID')
|
||||||
@prepaid = @supermodel.getModel(Prepaid, prepaidID) or new Prepaid _id: prepaidID
|
@prepaid = @supermodel.getModel(Prepaid, prepaidID) or new Prepaid _id: prepaidID
|
||||||
@listenTo @prepaid, 'sync', @onPrepaidSync
|
@listenTo @prepaid, 'sync', @onPrepaidSync
|
||||||
if @prepaid.loaded
|
if @prepaid.loaded
|
||||||
@onPrepaidSync()
|
@onPrepaidSync()
|
||||||
else
|
else
|
||||||
@supermodel.loadModel @prepaid, 'prepaid'
|
@supermodel.loadModel @prepaid, 'prepaid'
|
||||||
@render?()
|
@render()
|
||||||
|
|
||||||
onPrepaidSync: ->
|
onPrepaidSync: ->
|
||||||
@render?()
|
return if @destroyed
|
||||||
|
# TODO: why do we rerender here? Template doesn't use prepaid.
|
||||||
|
@render()
|
||||||
|
|
||||||
onLevelSessionsSync: ->
|
onLevelSessionsSync: ->
|
||||||
|
return if @destroyed
|
||||||
# console.log 'onLevelSessionsSync'
|
# console.log 'onLevelSessionsSync'
|
||||||
@instanceStats = averageLevelsCompleted: 0, furthestLevelCompleted: '', totalLevelsCompleted: 0, totalPlayTime: 0
|
@instanceStats = averageLevelsCompleted: 0, furthestLevelCompleted: '', totalLevelsCompleted: 0, totalPlayTime: 0
|
||||||
@memberStats = {}
|
@memberStats = {}
|
||||||
|
@ -197,39 +226,57 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
@conceptsCompleted[concept] ?= 0
|
@conceptsCompleted[concept] ?= 0
|
||||||
@conceptsCompleted[concept]++
|
@conceptsCompleted[concept]++
|
||||||
|
|
||||||
if @memberStats[me.id]?.totalLevelsCompleted >= _.size @campaign.get('levels')
|
if @memberStats[me.id]?.totalLevelsCompleted >= _.size(@campaign.get('levels')) - 1 # Don't need to complete arena
|
||||||
@courseComplete = true
|
@courseComplete = true
|
||||||
|
@loadCourseInstances() unless @courseInstances # Find the next course instance to do.
|
||||||
|
|
||||||
@render?()
|
@render()
|
||||||
|
|
||||||
# If we just joined a single-player course for Hour of Code, we automatically play.
|
# If we just joined a single-player course for Hour of Code, we automatically play.
|
||||||
if @instanceStats.totalLevelsCompleted is 0 and @instanceStats.totalPlayTime is 0 and @courseInstance.get('members').length is 1 and me.get('hourOfCode') and not @adminMode and not autoplayedOnce
|
if @instanceStats.totalLevelsCompleted is 0 and @instanceStats.totalPlayTime is 0 and @singlePlayerMode and not autoplayedOnce
|
||||||
autoplayedOnce = true
|
autoplayedOnce = true
|
||||||
@$el.find('button.btn-play-level').click()
|
@$el.find('button.btn-play-level').click()
|
||||||
|
|
||||||
onMembersSync: ->
|
onMembersSync: ->
|
||||||
|
return if @destroyed
|
||||||
# console.log 'onMembersSync'
|
# console.log 'onMembersSync'
|
||||||
@memberUserMap = {}
|
@memberUserMap = {}
|
||||||
for user in @members.models
|
for user in @members.models
|
||||||
@memberUserMap[user.id] = user
|
@memberUserMap[user.id] = user
|
||||||
@sortMembers()
|
@sortMembers()
|
||||||
@render?()
|
@render()
|
||||||
|
|
||||||
|
onAllCoursesSync: ->
|
||||||
|
@findNextCourseInstance()
|
||||||
|
|
||||||
|
findNextCourseInstance: ->
|
||||||
|
@nextCourseInstance = _.find @courseInstances.models, (ci) =>
|
||||||
|
# Sorted by courseID
|
||||||
|
ci.get('classroomID') is @courseInstance.get('classroomID') and ci.id isnt @courseInstance.id and ci.get('courseID') > @course.id
|
||||||
|
if @nextCourseInstance
|
||||||
|
nextCourseID = @nextCourseInstance.get('courseID')
|
||||||
|
@nextCourse = @supermodel.getModel(Course, nextCourseID) or new Course _id: nextCourseID
|
||||||
|
@nextCourse = @supermodel.loadModel(@nextCourse, 'course').model
|
||||||
|
else if @allCourses?.loaded
|
||||||
|
@nextCourse = _.find @allCourses.models, (course) => course.id > @course.id
|
||||||
|
else
|
||||||
|
@loadAllCourses()
|
||||||
|
|
||||||
onCheckExpandedProgress: (e) ->
|
onCheckExpandedProgress: (e) ->
|
||||||
@showExpandedProgress = $('.progress-expand-checkbox').prop('checked')
|
@showExpandedProgress = $('.progress-expand-checkbox').prop('checked')
|
||||||
# TODO: why does render reset the checkbox to be unchecked?
|
# TODO: why does render reset the checkbox to be unchecked?
|
||||||
@render?()
|
@render()
|
||||||
$('.progress-expand-checkbox').attr('checked', @showExpandedProgress)
|
$('.progress-expand-checkbox').attr('checked', @showExpandedProgress)
|
||||||
|
|
||||||
onClickMemberHeader: (e) ->
|
onClickMemberHeader: (e) ->
|
||||||
@memberSort = if @memberSort is 'nameAsc' then 'nameDesc' else 'nameAsc'
|
@memberSort = if @memberSort is 'nameAsc' then 'nameDesc' else 'nameAsc'
|
||||||
@sortMembers()
|
@sortMembers()
|
||||||
@render?()
|
@render()
|
||||||
|
|
||||||
onClickProgressHeader: (e) ->
|
onClickProgressHeader: (e) ->
|
||||||
@memberSort = if @memberSort is 'progressAsc' then 'progressDesc' else 'progressAsc'
|
@memberSort = if @memberSort is 'progressAsc' then 'progressDesc' else 'progressAsc'
|
||||||
@sortMembers()
|
@sortMembers()
|
||||||
@render?()
|
@render()
|
||||||
|
|
||||||
onClickPlayLevel: (e) ->
|
onClickPlayLevel: (e) ->
|
||||||
levelSlug = $(e.target).data('level-slug')
|
levelSlug = $(e.target).data('level-slug')
|
||||||
|
@ -237,7 +284,7 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
level = @campaign.get('levels')[levelID]
|
level = @campaign.get('levels')[levelID]
|
||||||
if level.type is 'course-ladder'
|
if level.type is 'course-ladder'
|
||||||
route = '/play/ladder/' + levelSlug
|
route = '/play/ladder/' + levelSlug
|
||||||
route += '/course/' + @courseInstance.id if @courseInstance.get('members').length > 1 # No league for solo courses
|
route += '/course/' + @courseInstance.id unless @singlePlayerMode # No league for solo courses
|
||||||
Backbone.Mediator.publish 'router:navigate', route: route
|
Backbone.Mediator.publish 'router:navigate', route: route
|
||||||
else
|
else
|
||||||
Backbone.Mediator.publish 'router:navigate', {
|
Backbone.Mediator.publish 'router:navigate', {
|
||||||
|
@ -255,7 +302,7 @@ module.exports = class CourseDetailsView extends RootView
|
||||||
@loadCourseInstance(courseInstanceID)
|
@loadCourseInstance(courseInstanceID)
|
||||||
|
|
||||||
onClickProgressLevelCell: (e) ->
|
onClickProgressLevelCell: (e) ->
|
||||||
return unless @adminMode
|
return unless @teacherMode or me.isAdmin()
|
||||||
levelID = $(e.currentTarget).data('level-id')
|
levelID = $(e.currentTarget).data('level-id')
|
||||||
levelSlug = $(e.currentTarget).data('level-slug')
|
levelSlug = $(e.currentTarget).data('level-slug')
|
||||||
userID = $(e.currentTarget).data('user-id')
|
userID = $(e.currentTarget).data('user-id')
|
||||||
|
|
|
@ -63,9 +63,10 @@ module.exports = class HeroVictoryModal extends ModalView
|
||||||
else
|
else
|
||||||
@readyToContinue = true
|
@readyToContinue = true
|
||||||
@playSound 'victory'
|
@playSound 'victory'
|
||||||
if @level.get('type', true) is 'course' and nextLevel = @level.get('nextLevel')
|
if @level.get('type', true) is 'course'
|
||||||
@nextLevel = new Level().setURL "/db/level/#{nextLevel.original}/version/#{nextLevel.majorVersion}"
|
if nextLevel = @level.get('nextLevel')
|
||||||
@nextLevel = @supermodel.loadModel(@nextLevel, 'level').model
|
@nextLevel = new Level().setURL "/db/level/#{nextLevel.original}/version/#{nextLevel.majorVersion}"
|
||||||
|
@nextLevel = @supermodel.loadModel(@nextLevel, 'level').model
|
||||||
if @courseID
|
if @courseID
|
||||||
@course = new Course().setURL "/db/course/#{@courseID}"
|
@course = new Course().setURL "/db/course/#{@courseID}"
|
||||||
@course = @supermodel.loadModel(@course, 'course').model
|
@course = @supermodel.loadModel(@course, 'course').model
|
||||||
|
|
Loading…
Reference in a new issue