diff --git a/app/locale/en.coffee b/app/locale/en.coffee index d2095a23e..f64795613 100644 --- a/app/locale/en.coffee +++ b/app/locale/en.coffee @@ -1253,6 +1253,7 @@ joining: "Joining class" course_complete: "Course Complete" play_arena: "Play Arena" + view_project: "View Project" start: "Start" last_level: "Last Level" welcome_to_hoc: "Adventurers, welcome to our Hour of Code!" diff --git a/app/models/Classroom.coffee b/app/models/Classroom.coffee index 1047ea78a..982bd5f94 100644 --- a/app/models/Classroom.coffee +++ b/app/models/Classroom.coffee @@ -98,10 +98,19 @@ module.exports = class Classroom extends CocoModel levels = new Levels(course.levels) return levels.find (l) -> l.isLadder() + getProjectLevel: (courseID) -> + Levels = require 'collections/Levels' + courses = @get('courses') + course = _.findWhere(courses, {_id: courseID}) + return unless course + levels = new Levels(course.levels) + return levels.find (l) -> l.isProject() + statsForSessions: (sessions, courseID) -> return null unless sessions sessions = sessions.models or sessions arena = @getLadderLevel(courseID) + project = @getProjectLevel(courseID) courseLevels = @getLevels({courseID: courseID, withoutLadderLevels: true}) levelSessionMap = {} levelSessionMap[session.get('level').original] = session for session in sessions @@ -151,6 +160,7 @@ module.exports = class Classroom extends CocoModel next: nextLevel first: courseLevels.first() arena: arena + project: project playtime: playtime stats diff --git a/app/models/Level.coffee b/app/models/Level.coffee index 998e40c2c..38731be81 100644 --- a/app/models/Level.coffee +++ b/app/models/Level.coffee @@ -263,6 +263,9 @@ module.exports = class Level extends CocoModel isLadder: -> return @get('type')?.indexOf('ladder') > -1 + isProject: -> + return @get('shareable') is 'project' + isType: (types...) -> return @get('type', true) in types diff --git a/app/templates/courses/courses-view.jade b/app/templates/courses/courses-view.jade index 69e5265b5..19597c3c1 100644 --- a/app/templates/courses/courses-view.jade +++ b/app/templates/courses/courses-view.jade @@ -110,10 +110,15 @@ mixin course-instance-body(courseInstance, classroom) .pull-right if stats.levels.done - var arenaLevel = stats.levels.arena; + - var projectLevel = stats.levels.project; if arenaLevel - var arenaURL = "/play/ladder/"+arenaLevel.get('slug')+"/course/"+courseInstance.id; a.play-btn.btn.btn-burgandy.btn-lg.m-b-1(data-href=arenaURL, data-level-slug=arenaLevel.get('slug'), data-event-action="Students Play Arena") span(data-i18n="courses.play_arena") + else if projectLevel + - var projectURL = "/play/level/"+projectLevel.get('slug')+"?course="+course.id+"&course-instance="+courseInstance.id; + a.play-btn.btn.btn-burgandy.btn-lg.m-b-1(data-href=projectURL, data-level-slug=projectLevel.get('slug'), data-event-action="Students Play Project") + span(data-i18n="courses.view_project") else a.btn.btn-default.btn-lg.m-b-1(disabled=true, data-i18n="courses.course_complete") else if stats.levels.next != stats.levels.first diff --git a/scripts/mongodb/updateCourses.js b/scripts/mongodb/updateCourses.js index 1e92d7cf7..414b1dfd8 100644 --- a/scripts/mongodb/updateCourses.js +++ b/scripts/mongodb/updateCourses.js @@ -63,7 +63,7 @@ var courses = name: "CS: Game Development 1", slug: "game-dev-1", campaignID: ObjectId("5789236960deed1f00ec2ab8"), - description: "Learn to create your owns games which you can share with your friends.", + description: "Learn to create your own games which you can share with your friends.", duration: NumberInt(1), free: false, releasePhase: 'beta' diff --git a/server/middleware/courses.coffee b/server/middleware/courses.coffee index 2070e5b1d..abb9a07f1 100644 --- a/server/middleware/courses.coffee +++ b/server/middleware/courses.coffee @@ -24,10 +24,15 @@ module.exports = campaign = yield Campaign.findById course.get('campaignID') throw new errors.NotFound('Campaign not found.') unless campaign - levelOriginals = (mongoose.Types.ObjectId(levelID) for levelID of campaign.get('levels')) + # TODO: why does campaign.get('levels') return opposite order from direct db query? + sortedLevelIDs = _.keys campaign.get('levels') + sortedLevelIDs.reverse() + + levelOriginals = (mongoose.Types.ObjectId(levelID) for levelID in sortedLevelIDs) query = { original: { $in: levelOriginals }, slug: { $exists: true }} - select = {documentation: 1, intro: 1, name: 1, slug: 1, thangs: 1} + select = {documentation: 1, intro: 1, name: 1, original: 1, slug: 1, thangs: 1} levels = yield Level.find(query).select(select).lean() + levels.sort((a, b) -> sortedLevelIDs.indexOf(a.original + '') - sortedLevelIDs.indexOf(b.original + '')) res.status(200).send(levels) fetchNextLevel: wrap (req, res) -> diff --git a/spec/server/functional/course_instance.spec.coffee b/spec/server/functional/course_instance.spec.coffee index 3393eb2f2..e8aef634e 100644 --- a/spec/server/functional/course_instance.spec.coffee +++ b/spec/server/functional/course_instance.spec.coffee @@ -12,7 +12,6 @@ Level = require '../../../server/models/Level' LevelSession = require '../../../server/models/LevelSession' Prepaid = require '../../../server/models/Prepaid' request = require '../request' -moment = require 'moment' courseFixture = { name: 'Unnamed course' @@ -424,18 +423,19 @@ describe 'POST /db/course_instance/-/recent', -> done() it 'returns course instances within a specified range', utils.wrap (done) -> - startDay = moment().subtract(1, 'day').format('YYYY-MM-DD') - endDay = moment().add(1, 'day').format('YYYY-MM-DD') + startDay = utils.createDay(-1) + endDay = utils.createDay(1) [res, body] = yield request.postAsync(url, { json: { startDay, endDay } }) expect(res.body.courseInstances.length).toBe(1) - startDay = moment().add(1, 'day').format('YYYY-MM-DD') - endDay = moment().add(2, 'day').format('YYYY-MM-DD') + startDay = utils.createDay(1) + endDay = utils.createDay(2) [res, body] = yield request.postAsync(url, { json: { startDay, endDay } }) + console.log startDay, endDay, res.body.courseInstances.length expect(res.body.courseInstances.length).toBe(0) - startDay = moment().subtract(2, 'day').format('YYYY-MM-DD') - endDay = moment().subtract(1, 'day').format('YYYY-MM-DD') + startDay = utils.createDay(-2) + endDay = utils.createDay(-1) [res, body] = yield request.postAsync(url, { json: { startDay, endDay } }) expect(res.body.courseInstances.length).toBe(0) diff --git a/spec/server/functional/courses.spec.coffee b/spec/server/functional/courses.spec.coffee index beb867f20..77cd499af 100644 --- a/spec/server/functional/courses.spec.coffee +++ b/spec/server/functional/courses.spec.coffee @@ -150,8 +150,8 @@ describe 'GET /db/course/:handle/level-solutions', -> paredLevelB = _.pick(res.body, 'name', 'original', 'type') campaignJSONA = { name: 'Campaign A', levels: {} } - campaignJSONA.levels[paredLevelA.original] = paredLevelA campaignJSONA.levels[paredLevelB.original] = paredLevelB + campaignJSONA.levels[paredLevelA.original] = paredLevelA [res, body] = yield request.postAsync({uri: getURL('/db/campaign'), json: campaignJSONA}) @campaignA = yield Campaign.findById(res.body._id) diff --git a/spec/server/utils.coffee b/spec/server/utils.coffee index a002e51f7..702dab9eb 100644 --- a/spec/server/utils.coffee +++ b/spec/server/utils.coffee @@ -206,3 +206,8 @@ module.exports = mw = return done(err) if err expect(res.statusCode).toBe(201) TrialRequest.findById(res.body._id).exec done + + createDay: (offset) -> + day = new Date() + day.setUTCDate(day.getUTCDate() + offset) + day.toISOString().substring(0, 10)