Add detailed progress and links to ClassroomView

This commit is contained in:
Scott Erickson 2015-12-03 12:07:12 -08:00
parent b0e9670453
commit 1df87fa685
5 changed files with 63 additions and 33 deletions

View file

@ -9,30 +9,4 @@ module.exports = class Campaign extends CocoModel
urlRoot: '/db/campaign'
saveBackups: true
@denormalizedLevelProperties: _.keys(_.omit(schema.properties.levels.additionalProperties.properties, ['unlocks', 'position', 'rewards']))
@denormalizedCampaignProperties: ['name', 'i18n', 'slug']
statsForSessions: (sessions) ->
# common code for crunching stats for a user's progress on a campaign/course
return null unless sessions
stats = {}
sessions = sessions.models or sessions
sessions = _.sortBy sessions, (s) -> s.get('changed')
levels = _.values(@get('levels'))
levels = (level for level in levels when not _.contains(level.type, 'ladder'))
levelOriginals = _.pluck(levels, 'original')
sessionOriginals = (session.get('level').original for session in sessions when session.get('state').complete)
levelsLeft = _.size(_.difference(levelOriginals, sessionOriginals))
lastSession = _.last(sessions)
stats.levels = {
size: _.size(levels)
left: levelsLeft
done: levelsLeft is 0
numDone: _.size(levels) - levelsLeft
pctDone: (100 * (_.size(levels) - levelsLeft) / _.size(levels)).toFixed(1) + '%'
lastPlayed: if lastSession then _.findWhere levels, { original: lastSession.get('level').original } else null
first: _.first(levels)
arena: _.find _.values(@get('levels')), (level) -> _.contains(level.type, 'ladder')
}
sum = (nums) -> _.reduce(nums, (s, num) -> s + num) or 0
stats.playtime = sum((session.get('playtime') or 0 for session in sessions))
return stats
@denormalizedCampaignProperties: ['name', 'i18n', 'slug']

View file

@ -5,3 +5,6 @@
.progress
margin-bottom: 5px
.progress-bar
border-right: 1px solid grey

View file

@ -0,0 +1,10 @@
- var completed = session && session.get('state').complete;
h3 #{i + 1}. #{level.name.replace('Course: ', '')}
p
span.spr(data-i18n="courses.play_time")
span #{moment.duration(session.get('playtime'), "seconds").humanize()}
p
span.spr(data-i18n=completed ? "courses.completed" : "clans.last_played")
span #{moment(session.get('changed')).format('MMMM Do YYYY, h:mm:ss a')}
if canViewSolution
strong(data-i18n=completed ? "clans.view_solution" : "clans.view_attempt")

View file

@ -43,15 +43,33 @@ block content
- var inCourse = _.contains(courseInstance.get('members'), user.id);
- var course = view.courses.get(courseInstance.get('courseID'));
- var campaign = view.campaigns.get(course.get('campaignID'));
- var stats = campaign.statsForSessions(courseInstance.sessionsByUser[user.id] || []);
- var sessions = courseInstance.sessionsByUser[user.id] || [];
if !(course.get('free') || paidFor)
- continue;
.row
.col-sm-3.col-sm-offset-1= campaign.get('fullName')
.col-sm-7
.col-sm-3.text-right= campaign.get('fullName')
.col-sm-9
if inCourse
- var levels = campaign.get('levels');
- var numLevels = Object.keys(levels).length;
- var sessionMap = _.zipObject(_.map(sessions, function(s) { return s.get('level').original; }), sessions);
- var levelCellWidth = 100.00;
if numLevels > 0
- levelCellWidth = 100.00 / numLevels;
- var css = "width:"+levelCellWidth+"%;"
- var i = 0;
.progress
.progress-bar(style='width:'+stats.levels.pctDone)
each level, levelID in campaign.get('levels')
- var session = sessionMap[levelID];
a(href=view.getLevelURL(level, course, courseInstance, session))
- var content = view.levelPopoverContent(level, session, i);
if session && session.get('state').complete
.progress-bar.progress-bar-success(style=css, data-content=content, data-toggle='popover')= i + 1
else if session
.progress-bar.progress-bar-warning(style=css, data-content=content, data-toggle='popover')= i + 1
else
- break;
- i++
else if paidFor
button.enable-btn.btn.btn-info.btn-sm(data-user-id=user.id, data-course-instance-cid=courseInstance.cid) Enable
@ -62,4 +80,4 @@ block content
p
button.activate-single-license-btn.btn.btn-info.btn-sm(data-user-id=user.id) Activate
hr
hr

View file

@ -13,10 +13,12 @@ ClassroomSettingsModal = require 'views/courses/ClassroomSettingsModal'
ActivateLicensesModal = require 'views/courses/ActivateLicensesModal'
InviteToClassroomModal = require 'views/courses/InviteToClassroomModal'
RemoveStudentModal = require 'views/courses/RemoveStudentModal'
popoverTemplate = require 'templates/courses/classroom-level-popover'
module.exports = class ClassroomView extends RootView
id: 'classroom-view'
template: template
teacherMode: false
events:
'click #edit-class-details-link': 'onClickEditClassDetailsLink'
@ -79,6 +81,14 @@ module.exports = class ClassroomView extends RootView
campaign = @campaigns.get(campaignID)
courseInstance.sessions.campaign = campaign
super()
afterRender: ->
@$('[data-toggle="popover"]').popover({
html: true
trigger: 'hover'
placement: 'top'
})
super()
onClickActivateLicensesButton: ->
modal = new ActivateLicensesModal({
@ -144,4 +154,19 @@ module.exports = class ClassroomView extends RootView
onStudentRemoved: (e) ->
@users.remove(e.user)
@render()
@render()
levelPopoverContent: (level, session, i) ->
return '' unless level and session
context = {
moment: moment
level: level
session: session
i: i
canViewSolution: me.isAdmin() or @classroom.get('ownerID') is me.id
}
return popoverTemplate(context)
getLevelURL: (level, course, courseInstance, session) ->
return '#' unless _.all(arguments)
"/play/level/#{level.slug}?course=#{course.id}&course-instance=#{courseInstance.id}&session=#{session.id}&observing=true"