mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-01 15:50:11 -04:00
Add detailed progress and links to ClassroomView
This commit is contained in:
parent
b0e9670453
commit
1df87fa685
5 changed files with 63 additions and 33 deletions
app
models
styles/courses
templates/courses
views/courses
|
@ -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']
|
|
@ -5,3 +5,6 @@
|
|||
|
||||
.progress
|
||||
margin-bottom: 5px
|
||||
|
||||
.progress-bar
|
||||
border-right: 1px solid grey
|
||||
|
|
10
app/templates/courses/classroom-level-popover.jade
Normal file
10
app/templates/courses/classroom-level-popover.jade
Normal 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")
|
|
@ -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
|
||||
|
|
|
@ -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"
|
Loading…
Add table
Reference in a new issue