mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 17:45:40 -05:00
Admin class progress CSV export
This commit is contained in:
parent
98da7962cf
commit
a884fbf38b
2 changed files with 109 additions and 0 deletions
|
@ -44,6 +44,9 @@ block content
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
a(href="/admin/classroom-levels") Classroom Levels
|
a(href="/admin/classroom-levels") Classroom Levels
|
||||||
|
li
|
||||||
|
button.classroom-progress-csv.btn.btn-sm.btn-success Classroom Progress CSV
|
||||||
|
input.classroom-progress-class-code(type=text value="<class code>")
|
||||||
li
|
li
|
||||||
a(href="/admin/analytics") Dashboard
|
a(href="/admin/analytics") Dashboard
|
||||||
li
|
li
|
||||||
|
|
|
@ -4,7 +4,14 @@ RootView = require 'views/core/RootView'
|
||||||
template = require 'templates/admin'
|
template = require 'templates/admin'
|
||||||
AdministerUserModal = require 'views/admin/AdministerUserModal'
|
AdministerUserModal = require 'views/admin/AdministerUserModal'
|
||||||
forms = require 'core/forms'
|
forms = require 'core/forms'
|
||||||
|
|
||||||
|
Campaigns = require 'collections/Campaigns'
|
||||||
|
Classroom = require 'models/Classroom'
|
||||||
|
CocoCollection = require 'collections/CocoCollection'
|
||||||
|
Course = require 'models/Course'
|
||||||
|
LevelSessions = require 'collections/LevelSessions'
|
||||||
User = require 'models/User'
|
User = require 'models/User'
|
||||||
|
Users = require 'collections/Users'
|
||||||
|
|
||||||
module.exports = class MainAdminView extends RootView
|
module.exports = class MainAdminView extends RootView
|
||||||
id: 'admin-view'
|
id: 'admin-view'
|
||||||
|
@ -19,6 +26,7 @@ module.exports = class MainAdminView extends RootView
|
||||||
'click #user-search-result': 'onClickUserSearchResult'
|
'click #user-search-result': 'onClickUserSearchResult'
|
||||||
'click #create-free-sub-btn': 'onClickFreeSubLink'
|
'click #create-free-sub-btn': 'onClickFreeSubLink'
|
||||||
'click #terminal-create': 'onClickTerminalSubLink'
|
'click #terminal-create': 'onClickTerminalSubLink'
|
||||||
|
'click .classroom-progress-csv': 'onClickExportProgress'
|
||||||
|
|
||||||
getTitle: -> return $.i18n.t('account_settings.admin')
|
getTitle: -> return $.i18n.t('account_settings.admin')
|
||||||
|
|
||||||
|
@ -27,6 +35,27 @@ module.exports = class MainAdminView extends RootView
|
||||||
@amActually = new User({_id: window.amActually})
|
@amActually = new User({_id: window.amActually})
|
||||||
@amActually.fetch()
|
@amActually.fetch()
|
||||||
@supermodel.trackModel(@amActually)
|
@supermodel.trackModel(@amActually)
|
||||||
|
if me.isAdmin()
|
||||||
|
@campaigns = new Campaigns()
|
||||||
|
@supermodel.trackRequest @campaigns.fetchByType('course', { data: { project: 'levels' } })
|
||||||
|
@courses = new CocoCollection([], { url: "/db/course", model: Course})
|
||||||
|
@supermodel.loadCollection(@courses, 'courses')
|
||||||
|
super()
|
||||||
|
|
||||||
|
onLoaded: ->
|
||||||
|
campaignCourseIndexMap = {}
|
||||||
|
for course, index in @courses.models
|
||||||
|
campaignCourseIndexMap[course.get('campaignID')] = index + 1
|
||||||
|
@courseLevels = []
|
||||||
|
for campaign in @campaigns.models
|
||||||
|
continue unless campaignCourseIndexMap[campaign.id]
|
||||||
|
for levelID, level of campaign.get('levels')
|
||||||
|
@courseLevels.push({
|
||||||
|
levelID
|
||||||
|
slug: level.slug
|
||||||
|
courseIndex: campaignCourseIndexMap[campaign.id]
|
||||||
|
})
|
||||||
|
super()
|
||||||
|
|
||||||
onClickStopSpyingButton: ->
|
onClickStopSpyingButton: ->
|
||||||
button = @$('#stop-spying-btn')
|
button = @$('#stop-spying-btn')
|
||||||
|
@ -126,3 +155,80 @@ module.exports = class MainAdminView extends RootView
|
||||||
console.error 'Failed to create prepaid', response
|
console.error 'Failed to create prepaid', response
|
||||||
@supermodel.addRequestResource('create_prepaid', options, 0).load()
|
@supermodel.addRequestResource('create_prepaid', options, 0).load()
|
||||||
|
|
||||||
|
onClickExportProgress: ->
|
||||||
|
return unless @courseLevels?.length > 0
|
||||||
|
$('.classroom-progress-csv').prop('disabled', true)
|
||||||
|
|
||||||
|
classCode = $('.classroom-progress-class-code').val()
|
||||||
|
userMap = {}
|
||||||
|
new Promise((resolve, reject) =>
|
||||||
|
new Classroom().fetchByCode(classCode, {
|
||||||
|
success: resolve
|
||||||
|
error: (model, response, options) => reject(response)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then (classroom) =>
|
||||||
|
new Promise((resolve, reject) =>
|
||||||
|
new Classroom({ _id: classroom.id }).fetch({
|
||||||
|
success: resolve
|
||||||
|
error: (model, response, options) => reject(response)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then (classroom) =>
|
||||||
|
new Promise((resolve, reject) =>
|
||||||
|
new Users().fetchForClassroom(classroom, {
|
||||||
|
success: (users) =>
|
||||||
|
userMap[user.id] = user for user in users.models
|
||||||
|
new LevelSessions().fetchForAllClassroomMembers(classroom, {
|
||||||
|
success: resolve
|
||||||
|
error: (model, response, options) => reject(response)
|
||||||
|
})
|
||||||
|
error: (model, response, options) => reject(response)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then (sessions) =>
|
||||||
|
userLevelPlaytimeMap = {}
|
||||||
|
for session in sessions.models
|
||||||
|
continue unless session.get('state')?.complete
|
||||||
|
levelID = session.get('level').original
|
||||||
|
userID = session.get('creator')
|
||||||
|
userLevelPlaytimeMap[userID] ?= {}
|
||||||
|
userLevelPlaytimeMap[userID][levelID] ?= {}
|
||||||
|
userLevelPlaytimeMap[userID][levelID] = session.get('playtime')
|
||||||
|
|
||||||
|
userPlaytimes = []
|
||||||
|
for userID, user of userMap
|
||||||
|
playtimes = [user.get('name') ? 'Anonymous']
|
||||||
|
for level in @courseLevels
|
||||||
|
if userLevelPlaytimeMap[userID]?[level.levelID]?
|
||||||
|
rawSeconds = parseInt(userLevelPlaytimeMap[userID][level.levelID])
|
||||||
|
hours = Math.floor(rawSeconds / 60 / 60)
|
||||||
|
minutes = Math.floor(rawSeconds / 60 - hours * 60)
|
||||||
|
seconds = Math.round(rawSeconds - hours * 60 - minutes * 60)
|
||||||
|
hours = "0#{hours}" if hours < 10
|
||||||
|
minutes = "0#{minutes}" if minutes < 10
|
||||||
|
seconds = "0#{seconds}" if seconds < 10
|
||||||
|
playtimes.push "#{hours}:#{minutes}:#{seconds}"
|
||||||
|
else
|
||||||
|
playtimes.push 'Incomplete'
|
||||||
|
userPlaytimes.push(playtimes)
|
||||||
|
|
||||||
|
columnLabels = "Username"
|
||||||
|
currentLevel = 1
|
||||||
|
lastCourseIndex = 1
|
||||||
|
for level in @courseLevels
|
||||||
|
unless level.courseIndex is lastCourseIndex
|
||||||
|
currentLevel = 1
|
||||||
|
lastCourseIndex = level.courseIndex
|
||||||
|
columnLabels += ",CS#{level.courseIndex}.#{currentLevel++} #{level.slug}"
|
||||||
|
csvContent = "data:text/csv;charset=utf-8,#{columnLabels}\n"
|
||||||
|
for studentRow in userPlaytimes
|
||||||
|
csvContent += studentRow.join(',') + "\n"
|
||||||
|
csvContent = csvContent.substring(0, csvContent.length - 1)
|
||||||
|
encodedUri = encodeURI(csvContent)
|
||||||
|
window.open(encodedUri)
|
||||||
|
$('.classroom-progress-csv').prop('disabled', false)
|
||||||
|
|
||||||
|
.catch (error) ->
|
||||||
|
$('.classroom-progress-csv').prop('disabled', false)
|
||||||
|
console.error error
|
||||||
|
|
Loading…
Reference in a new issue