Add rest of CoursesView, untested, unhooked to server

On a plane, so skipping my usual iterative testing.
Bugs are undoubtedly everywhere.
This commit is contained in:
Scott Erickson 2015-11-23 08:46:08 -08:00
parent a98d0b1b2a
commit ea4a98af86
5 changed files with 177 additions and 4 deletions

View file

@ -1,5 +1,6 @@
CocoModel = require './CocoModel'
schema = require 'schemas/models/campaign.schema'
Level = require 'models/Level'
module.exports = class Campaign extends CocoModel
@className: 'Campaign'
@ -8,3 +9,6 @@ module.exports = class Campaign extends CocoModel
saveBackups: true
@denormalizedLevelProperties: _.keys(_.omit(schema.properties.levels.additionalProperties.properties, ['unlocks', 'position', 'rewards']))
@denormalizedCampaignProperties: ['name', 'i18n', 'slug']
levelsCollection: ->
new CocoCollection(_.values(@get('levels')), {model: Level})

View file

@ -5,3 +5,12 @@ module.exports = class Classroom extends CocoModel
@className: 'Classroom'
@schema: schema
urlRoot: '/db/classroom'
joinWithCode: (code, opts) ->
options = {
url: _.result(@, 'url') + '/~/members'
type: 'POST'
data: { code: code }
}
_.extend options, opts
@fetch(options)

View file

@ -13,6 +13,15 @@ module.exports = class CourseInstance extends CocoModel
}
_.extend options, opts
@fetch(options)
addMember: (userID) ->
options = {
method: 'POST'
url: _.result(@, 'url') + '/~/members'
data: { userID: userID }
}
_.extend options, opts
@fetch(options)
firstLevelURL: ->
"/play/level/course-dungeons-of-kithgard?course=#{@get('courseID')}&course-instance=#{@id}"

View file

@ -27,7 +27,22 @@ block content
else
h1.text-center Welcome to your Courses page!
- var showHOCComplete = false;
if view.hocCourseInstance
- var campaign = view.campaigns.get(view.hocCourseInstance.get('CampaignID'));
- showHOCComplete = campaign.sessions.allDone();
.text-center
if !showHOCComplete
h1 Welcome to your Courses page!
else
h1 Amazing! You've completed the Hour of Code course!
h2 Ready for more? Play the campaign mode!
ul
li Use gems to unlock new items!
li Play through brand new worlds and challenges
li Learn even more programming!
a.btn.btn-lg.btn-success(href="/play")
if view.hocCourseInstance
h2 Saved Games
@ -39,10 +54,77 @@ block content
span.spr= (view.hocCourseInstance.get('aceConfig') || {}).language === 'python' ? 'Python' : 'JavaScript'
small
a#change-language-link change language
+course-instance-body(hocCourseInstance)
if view.classrooms.size()
h2 My Classes
for classroom in view.classrooms
- var classroomClass = classroom.justAdded ? 'just-added' : '';
if classroom.justAdded
.text-center.text-info Class successfully added!
div(class=classroomClass) // sigh
h2
span.spr= classroom.get('name')
span.spr (#{(view.hocCourseInstance.get('aceConfig') || {}).language === 'python' ? 'Python' : 'JavaScript'})
a(href="/courses/classroom/"+classroom.id) view class
- var courseInstances = view.courseInstances.where({classroomID: classroom.id});
for courseInstance in courseInstances
.course-instance-body
- var course = view.courses.get(courseInstance.get('courseID'));
h2
span.spr= course.get('name')
small
// TODO: where do we show list of levels?
a(href="/courses/classrooms/"+classroom.id) view levels
+course-instance-body(hocCourseInstance)
h2 Join A Class
form#join-class-form.form-inline
.form-group
.help-block
em Ask your teacher if you have a CodeCombat class code! If so, enter it below:
input#class-code-input.form-control
input#join-class-button(type="submit" value="Join")
if view.state === 'enrolling'
.progress.progress-striped.active
.progress-bar(style="width: 100%") Joining class
if view.state === 'unknown_error'
.alert.alert-danger= view.stateMessage
#begin-hoc-area.hide
h2.text-center(data-i18n="common.loading")
.progress.progress-striped.active
.progress-bar(style="width: 100%")
mixin course-instance-entry(courseInstance, course, levels)
mixin course-instance-body(courseInstance)
- var course = view.courses.get(courseInstance.get('courseID'));
- var campaign = view.campaigns.get(course.get('CampaignID'));
- var levels = view.campaigns.levelsCollection();
if campaign.sessions.allDone()
.text-success
span.glyphicon.glyphicon-ok
span.spl Course Complete!
.pull-right
if campaign.sessions.allDone()
- var arenaLevel = sessions.findWhere({ type: 'course-ladder' });
- var arenaURL = "/play/ladder/"+arenaLevel.get('slug')+"/course/"+courseInstance.id;
a.btn.btn-warning.btn-lg(href=arenaURL)
| Play Arena
else if campaign.sessions.size()
- var lastSession = campaign.sessions.last();
- var lastLevel = levels.findWhere({original: lastSession.get('level').original});
- var levelURL = "/play/level/"+lastLevel.get('slug')+"?course="+courseInstance.get('courseID')+"&course-instance="courseInstance.id;
a.btn.btn-success.btn-lg(href=levelURL)
| Continue
else
- var firstLevel = levels.first();
- var levelURL = "/play/level/"+firstLevel.get('slug')+"?course="+courseInstance.get('courseID')+"&course-instance="courseInstance.id;
a.btn.btn-info.btn-lg(href=levelURL)
| Start

View file

@ -9,6 +9,9 @@ CocoCollection = require 'collections/CocoCollection'
Course = require 'models/Course'
Classroom = require 'models/Classroom'
LevelSession = require 'models/LevelSession'
Campaign = require 'models/Campaign'
# TODO: Test everything
module.exports = class CoursesView extends RootView
id: 'courses-view'
@ -17,7 +20,9 @@ module.exports = class CoursesView extends RootView
events:
'click #log-in-btn': 'onClickLogInButton'
'click #start-new-game-btn': 'onClickStartNewGameButton'
'click #join-class-btn': 'onClickJoinClassButton'
'submit #join-class-form': 'onSubmitJoinClassForm'
initialize: ->
@courseInstances = new CocoCollection([], { url: "/db/user/#{me.id}/course_instances", model: CourseInstance})
@courseInstances.comparator = (ci) -> return ci.get('classroomID') + ci.get('courseID')
@ -26,12 +31,23 @@ module.exports = class CoursesView extends RootView
@supermodel.loadCollection(@classrooms, 'classrooms', { data: {memberID: me.id} })
@courses = new CocoCollection([], { url: "/db/course", model: Course})
@supermodel.loadCollection(@courses, 'courses')
@campaigns = new CocoCollection([], { url: "/db/campaigns", model: Campaign })
# TODO: fetch only course campaigns
@supermodel.loadCollection(@courses, 'courses')
onLoaded: ->
for courseInstance in @courseInstances.models
# TODO: fetch sessions for given course instance
# TODO: make sure we only fetch one per courseID
courseInstance.sessions = new CocoCollection([], { url: '???' })
courseInstance.sessions.allDone = ->
# TODO: should return if all non-arena courses are complete
@hocCourseInstance = @courseInstances.findWhere({hourOfCode: true})
if @hocCourseInstance
@courseInstances.remove(@hocCourseInstance)
@sessions = new CocoCollection([], { url: @hocCourseInstance.url() + '/my-course-level-sessions', model: LevelSession })
@sessions.comparator = 'changed'
@supermodel.loadCollection(@sessions, 'sessions')
super()
@ -56,3 +72,56 @@ module.exports = class CoursesView extends RootView
@listenToOnce hocCourseInstance, 'sync', ->
url = hocCourseInstance.firstLevelURL()
app.router.navigate(url, { trigger: true })
onSubmitJoinClassForm: (e) ->
e.preventDefault()
@joinClass()
onClickJoinClassButton: (e) ->
@joinClass()
joinClass: ->
@state = 'enrolling'
@classCode = @$('#classroom-code-input').val() or utils.getQueryVariable('_cc', false)
return unless @classCode
@renderSelectors '#join-classroom-form'
newClassroom = new Classroom()
newClassroom.joinWithCode(@classCode)
newClassroom.on 'sync', @onJoinClassroomSuccess, @
newClassroom.on 'error', @onJoinClassroomError, @
onJoinClassroomError: (classroom, jqxhr, options) ->
application.tracker?.trackEvent 'Failed to join classroom with code', status: jqxhr.status
@state = 'unknown_error'
if jqxhr.status is 422
@errorMessage = 'Please enter a code.'
else if jqxhr.status is 404
@errorMessage = 'Code not found.'
else
@errorMessage = "#{jqxhr.responseText}"
@renderSelectors '#join-classroom-form'
onJoinClassroomSuccess: (newClassroom, jqxhr, options) ->
application.tracker?.trackEvent 'Joined classroom', {
classroomID: newClassroom.id,
classroomName: newClassroom.get('name')
ownerID: newClassroom.get('ownerID')
}
@classrooms.add(newClassroom)
newClassroom.justAdded = true
@render()
classroomCourseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance })
classroomCourseInstances.fetch({ data: {classroomID: classroom.id} })
@listenToOnce classroomCourseInstances, 'sync', ->
# join any course instances in the classroom which are free to join
jqxhrs = []
for courseInstance in classroomCourseInstances.models
course = @courses.get(courseInstance.get('courseID'))
if course.get('free')
jqxhrs.push = courseInstance.addMember(me.id)
@courseInstances.add(courseInstance)
$.when(jqxhrs...).done =>
@state = ''
@render()
delete newClassroom.justAdded