Courses UI: Add course details condensed progress view

Defaulting to condensed view, with checkbox to expand details.
This commit is contained in:
Matt Lott 2015-08-21 17:00:44 -07:00
parent cf720ce270
commit f966b8a2fc
3 changed files with 113 additions and 58 deletions

View file

@ -23,7 +23,6 @@
font-size: 9pt
font-weight: normal
border: 1px solid gray
border-radius: 5px
margin: 0px
padding: 2px
background-color: white
@ -62,10 +61,10 @@
cursor: default
display: inline-block
white-space: nowrap
font-size: 9pt
font-size: 12px
line-height: 12px
font-weight: normal
border: 1px solid gray
border-radius: 5px
margin: 0px
padding: 2px
@ -83,7 +82,7 @@
font-size: 14px
.student-cell
min-width: 150px
width: 150px
.progress-cell
padding: 2px
@ -114,9 +113,9 @@
.progress-level-cell
display: inline-block
white-space: nowrap
font-size: 9pt
font-size: 12px
line-height: 12px
border: 1px solid gray
border-radius: 5px
margin: 0px
padding: 2px
@ -131,9 +130,9 @@
.progress-concept-cell
display: inline-block
white-space: nowrap
font-size: 9pt
font-size: 12px
line-height: 12px
border: 1px solid gray
border-radius: 5px
margin: 0px
padding: 2px
@ -142,3 +141,6 @@
.progress-concept-cell-complete
background-color: lightgray
.condense-progress
width: 100%

View file

@ -147,60 +147,107 @@ mixin progress-tab
span.progress-key.progress-key-complete complete
span.progress-key.progress-key-started started
span.progress-key not started
if maxLastStartedIndex > 30
input.expand-progress-checkbox(type='checkbox')
span.spl.expand-progress-label(data-i18n="clans.exp_levels") Expand levels
input.expand-progress-checkbox(type='checkbox')
span.spl.expand-progress-label Expand details
tbody
each student in instance.students
tr
td.student-cell
a= student
- var levelsCompleted = 0
each level in course.levels
if userLevelStateMap[student][level] === 'complete'
- levelsCompleted++
- var secondsPlayed = Math.round(Math.random() * 1000 * (levelsCompleted + 1))
- var secondsLastPlayed = Math.round(Math.random() * 100000)
div #{levelsCompleted} levels completed
div #{moment.duration(secondsPlayed, 'seconds').humanize()} played
div Played #{moment().subtract(secondsLastPlayed, 'seconds').fromNow()}
div #{stats[student].levelsCompleted} levels completed
div #{moment.duration(stats[student].secondsPlayed, 'seconds').humanize()} played
div Played #{moment().subtract(stats[student].secondsLastPlayed, 'seconds').fromNow()}
td.progress-cell
.level-progression-concepts Concepts
each concept in courseConcepts
if userConceptsMap[student] && userConceptsMap[student][concept] === 'complete'
span.spr.progress-concept-cell.progress-concept-cell-complete(data-i18n="concepts." + concept)
else if userConceptsMap[student] && userConceptsMap[student][concept] === 'started'
span.spr.progress-concept-cell.progress-concept-cell-started(data-i18n="concepts." + concept)
else
span.spr.progress-concept-cell.progress-concept-cell-not-started(data-i18n="concepts." + concept)
if showExpandedProgress
.level-progression-concepts Concepts
each concept in courseConcepts
if userConceptsMap[student] && userConceptsMap[student][concept] === 'complete'
span.spr.progress-concept-cell.progress-concept-cell-complete(data-i18n="concepts." + concept)
else if userConceptsMap[student] && userConceptsMap[student][concept] === 'started'
span.spr.progress-concept-cell.progress-concept-cell-started(data-i18n="concepts." + concept)
else
span.spr.progress-concept-cell.progress-concept-cell-not-started(data-i18n="concepts." + concept)
.level-progression-levels Levels
- var i = 0
each level in course.levels
if userLevelStateMap[student][level] === 'complete'
span.progress-level-cell.progress-level-cell-complete #{i + 1}
if showExpandedProgress || i === 0 || i === course.levels.length - 1
.level-progression-levels Levels
- var i = 0
each level in course.levels
if userLevelStateMap[student][level] === 'complete'
span.progress-level-cell.progress-level-cell-complete #{i + 1}
span.spl= level.replace('Course: ', '')
.level-popup-container
h3 #{i + 1}. #{level.replace('Course: ', '')}
p
div
.level-popup-container
h3 #{i + 1}. #{level.replace('Course: ', '')}
p
- var playTime = Math.round(Math.random() * 600)
span Time to solve
span : #{moment.duration(playTime, "seconds").humanize()}
div
p
- var completionDate = new Date()
- completionDate.setUTCDate(completionDate.getUTCDate() - Math.round(Math.random() * 60))
span Completed on
span : #{moment(completionDate).format('MMMM Do YYYY, h:mm:ss a')}
strong(data-i18n="clans.view_solution") Click to view solution.
else if userLevelStateMap[student][level] === 'started'
span.progress-level-cell.progress-level-cell-started #{i + 1} #{level.replace('Course: ', '')}
else
span.progress-level-cell.level-progression-level-not-started #{i + 1}
if showExpandedProgress || i === 0
span.spl= level.replace('Course: ', '')
- i++
strong(data-i18n="clans.view_solution") Click to view solution.
else if userLevelStateMap[student][level] === 'started'
span.progress-level-cell.progress-level-cell-started #{i + 1} #{level.replace('Course: ', '')}
.level-popup-container
h3 #{i + 1}. #{level.replace('Course: ', '')}
p
- var completionDate = new Date()
- completionDate.setUTCDate(completionDate.getUTCDate() - Math.round(Math.random() * 60))
span Last played on
span : #{moment(completionDate).format('MMMM Do YYYY, h:mm:ss a')}
strong(data-i18n="clans.view_solution") Click to view solution.
else
span.progress-level-cell.level-progression-level-not-started #{i + 1} #{level.replace('Course: ', '')}
- i++
else
//- Condensed view
table
tbody
tr
td
.level-progression-concepts(style='margin:0px;') Concepts
td.condense-progress
each concept in courseConcepts
if userConceptsMap[student] && userConceptsMap[student][concept] === 'complete'
span.spr.progress-concept-cell.progress-concept-cell-complete(data-i18n="concepts." + concept)
else if userConceptsMap[student] && userConceptsMap[student][concept] === 'started'
span.spr.progress-concept-cell.progress-concept-cell-started(data-i18n="concepts." + concept)
else
break
tr
td
.level-progression-levels(style='margin:0px;') Levels
td.condense-progress
- var levelCellWidth = 100.00 / course.levels.length
- var i = 0
each level in course.levels
if userLevelStateMap[student][level] === 'complete'
span.progress-level-cell.progress-level-cell-complete(style="width:#{levelCellWidth}%;") #{i + 1}
.level-popup-container
h3 #{i + 1}. #{level.replace('Course: ', '')}
p
- var playTime = Math.round(Math.random() * 600)
span Time to solve
span : #{moment.duration(playTime, "seconds").humanize()}
p
- var completionDate = new Date()
- completionDate.setUTCDate(completionDate.getUTCDate() - Math.round(Math.random() * 60))
span Completed on
span : #{moment(completionDate).format('MMMM Do YYYY, h:mm:ss a')}
strong(data-i18n="clans.view_solution") Click to view solution.
else if userLevelStateMap[student][level] === 'started'
span.progress-level-cell.progress-level-cell-started(style="width:#{levelCellWidth}%;") #{i + 1}
.level-popup-container
h3 #{i + 1}. #{level.replace('Course: ', '')}
p
- var completionDate = new Date()
- completionDate.setUTCDate(completionDate.getUTCDate() - Math.round(Math.random() * 60))
span Last played on
span : #{moment(completionDate).format('MMMM Do YYYY, h:mm:ss a')}
strong(data-i18n="clans.view_solution") Click to view solution.
else
break
- i++
mixin levels-tab
table.table.table-striped.table-condensed

View file

@ -37,7 +37,8 @@ module.exports = class CourseDetailsView extends RootView
context.memberSort = @memberSort
context.userConceptsMap = @userConceptsMap ? {}
context.userLevelStateMap = @userLevelStateMap ? {}
context.showExpandedProgress = @course.levels.length <= 30 or @showExpandedProgress
context.showExpandedProgress = @showExpandedProgress
context.stats = @stats
context.studentMode = @options.studentMode ? false
conceptsCompleted = {}
@ -46,15 +47,6 @@ module.exports = class CourseDetailsView extends RootView
conceptsCompleted[concept] ?= 0
conceptsCompleted[concept]++
context.conceptsCompleted = conceptsCompleted
stats =
averageLevelPlaytime: _.random(30, 240)
averageLevelsCompleted: _.random(1, @course.levels.length)
stats.totalPlayTime = context.instance.students?.length * stats.averageLevelPlaytime ? 0
stats.totalLevelsCompleted = context.instance.students?.length * stats.averageLevelsCompleted ? 0
stats.lastLevelCompleted = @course.levels[@maxLastStartedIndex] ? @course.levels[@course.levels.length - 1]
context.stats = stats
context
initData: ->
@ -73,6 +65,10 @@ module.exports = class CourseDetailsView extends RootView
@levelMap = {}
@levelMap[level] = true for level in @course.levels
@userLevelStateMap = {}
@stats =
averageLevelPlaytime: _.random(30, 240)
averageLevelsCompleted: _.random(1, @course.levels.length)
students: {}
@maxLastStartedIndex = -1
for student in @instances?[@currentInstanceIndex].students
@userLevelStateMap[student] = {}
@ -82,7 +78,17 @@ module.exports = class CourseDetailsView extends RootView
lastStartedIndex = lastCompletedIndex + 1
@userLevelStateMap[student][@course.levels[lastStartedIndex]] = 'started'
@maxLastStartedIndex = lastStartedIndex if lastStartedIndex > @maxLastStartedIndex
@stats[student] ?= {}
@stats[student].levelsCompleted = 0
@stats[student].levelsCompleted++ for level in @course.levels when @userLevelStateMap[student][level] is 'complete'
@stats[student].secondsPlayed = Math.round(Math.random() * 1000 * (@stats[student].levelsCompleted + 1))
@stats[student].secondsLastPlayed = Math.round(Math.random() * 100000)
@sortMembers()
@stats.totalPlayTime = @instances?[@currentInstanceIndex].students?.length * @stats.averageLevelPlaytime ? 0
@stats.totalLevelsCompleted = @instances?[@currentInstanceIndex].students?.length * @stats.averageLevelsCompleted ? 0
@stats.totalPlayTime = @instances?[@currentInstanceIndex].students?.length * @stats.averageLevelPlaytime ? 0
@stats.lastLevelCompleted = @course.levels[0] ? @course.levels[@course.levels.length - 1]
sortMembers: ->
# Progress sort precedence: most completed concepts, most started concepts, most levels, name sort
@ -188,7 +194,7 @@ module.exports = class CourseDetailsView extends RootView
container = $(e.target).find('.level-popup-container').show()
margin = 20
offset = $(e.target).offset()
scrollTop = $(e.target).offsetParent().scrollTop()
scrollTop = $('#page-container').scrollTop()
height = container.outerHeight()
container.css('left', offset.left + e.offsetX)
container.css('top', offset.top + scrollTop - height - margin)