mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 17:45:40 -05:00
Fixes for courses, hoc
* Handling prepaids with strings for maxRedeemers * Add link to TeacherCoursesView from HourOfCodeView * Show only course instances with classrooms attached in TeacherCoursesView and StudentCoursesView * Add event tracking to HourOfCodeView * Add not-logged-in handling to TeacherCoursesView * Fixed a GET prepaids bug * Have course instances created for hour of code have hourOfCode property set to true.
This commit is contained in:
parent
c8a47818c2
commit
97cb5275c3
8 changed files with 63 additions and 46 deletions
|
@ -12,3 +12,9 @@ module.exports = class Prepaid extends CocoModel
|
||||||
for redeemer in @get('redeemers')
|
for redeemer in @get('redeemers')
|
||||||
return redeemer.date if redeemer.userID is userID
|
return redeemer.date if redeemer.userID is userID
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
initialize: ->
|
||||||
|
@listenTo @, 'add', ->
|
||||||
|
maxRedeemers = @get('maxRedeemers')
|
||||||
|
if _.isString(maxRedeemers)
|
||||||
|
@set 'maxRedeemers', parseInt(maxRedeemers)
|
||||||
|
|
|
@ -8,4 +8,4 @@ block content
|
||||||
.col-md-6.text-center
|
.col-md-6.text-center
|
||||||
button#student-btn.btn.btn-lg.btn-success(data-i18n="courses.students_click")
|
button#student-btn.btn.btn-lg.btn-success(data-i18n="courses.students_click")
|
||||||
.col-md-6.text-center
|
.col-md-6.text-center
|
||||||
button#teacher-btn.btn.btn-lg.btn-default(data-i18n="courses.teachers_click")
|
a.btn.btn-lg.btn-default(data-i18n="courses.teachers_click", href="/courses/teachers?hoc=true")
|
|
@ -27,12 +27,19 @@ block content
|
||||||
|
|
||||||
.list-group
|
.list-group
|
||||||
for courseInstance in view.courseInstances.models
|
for courseInstance in view.courseInstances.models
|
||||||
|
- var classroom = view.classrooms.get(courseInstance.get('classroomID'))
|
||||||
|
- var course = view.courses.get(courseInstance.get('courseID'))
|
||||||
|
if !(classroom && course)
|
||||||
|
- continue;
|
||||||
|
|
||||||
.list-group-item
|
.list-group-item
|
||||||
.row
|
.row
|
||||||
- var classroom = view.classrooms.get(courseInstance.get('classroomID'))
|
.col-sm-3
|
||||||
- var course = view.courses.get(courseInstance.get('courseID'))
|
if classroom
|
||||||
.col-sm-3= classroom.get('name')
|
| #{classroom.get('name')}
|
||||||
.col-sm-3= course.get('name')
|
.col-sm-3
|
||||||
|
if course
|
||||||
|
| #{course.get('name')}
|
||||||
.col-sm-6
|
.col-sm-6
|
||||||
a.btn.btn-default.btn-sm(href="/courses/#{course.id}/#{courseInstance.id}") Enter
|
a.btn.btn-default.btn-sm(href="/courses/#{course.id}/#{courseInstance.id}") Enter
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,48 @@ extends /templates/base
|
||||||
|
|
||||||
block content
|
block content
|
||||||
|
|
||||||
span *UNDER CONSTRUCTION, please send feedback to
|
if view.hoc
|
||||||
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
|
h1 Welcome to Hour of Code!
|
||||||
hr
|
|
||||||
|
p
|
||||||
|
| Thank you for choosing CodeCombat for your students.
|
||||||
|
span.spr.spl To get your kids started, simply send them to
|
||||||
|
a(href="/hoc") https://codecombat.com/hoc
|
||||||
|
span .
|
||||||
|
|
||||||
|
p
|
||||||
|
| If you'd like to use our courses system to view their progress:
|
||||||
|
|
||||||
|
ol
|
||||||
|
li Login/create your account if you have not already.
|
||||||
|
li Create a classroom on this page.
|
||||||
|
li Invite your students to the classroom.
|
||||||
|
|
||||||
|
p
|
||||||
|
| You can invite your students even if they've already started playing CodeCombat.
|
||||||
|
|
||||||
|
p
|
||||||
|
span.spr If you have any problems, please email
|
||||||
|
a(href="mailto:team@codecombat.com") team@codecombat.com
|
||||||
|
span .
|
||||||
|
|
||||||
ul.nav.nav-tabs(role='tablist')
|
if !me.isAnonymous()
|
||||||
li.active(role='presentation')
|
ul.nav.nav-tabs(role='tablist')
|
||||||
a(href="#courses-tab-pane" aria-controls="courses" role="tab" data-toggle="tab") Courses
|
li.active(role='presentation')
|
||||||
li(role='presentation')
|
a(href="#courses-tab-pane" aria-controls="courses" role="tab" data-toggle="tab") Courses
|
||||||
a(href="#manage-tab-pane" aria-controls="manage" role="tab" data-toggle="tab") Manage
|
li(role='presentation')
|
||||||
|
a(href="#manage-tab-pane" aria-controls="manage" role="tab" data-toggle="tab") Manage
|
||||||
|
|
||||||
.tab-content
|
.tab-content
|
||||||
#courses-tab-pane.tab-pane.well.active
|
#courses-tab-pane.tab-pane.well.active
|
||||||
h3 Your Courses
|
h3 Your Courses
|
||||||
- var courseInstances = view.courseInstances.sliceWithMembers();
|
- var courseInstances = view.courseInstances.sliceWithMembers();
|
||||||
if !_.size(courseInstances)
|
|
||||||
|
if me.isAnonymous()
|
||||||
|
.alert.alert-info
|
||||||
|
strong Please click "Create Account" or "Log In" above to view and manage your courses.
|
||||||
|
|
||||||
|
else if !_.size(courseInstances)
|
||||||
.alert.alert-info
|
.alert.alert-info
|
||||||
span.spr You currently have no students assigned to courses.
|
span.spr You currently have no students assigned to courses.
|
||||||
a#manage-tab-link Go to the manage tab to get set up.
|
a#manage-tab-link Go to the manage tab to get set up.
|
||||||
|
@ -35,8 +62,9 @@ block content
|
||||||
if classroom
|
if classroom
|
||||||
| #{classroom.get('name')}
|
| #{classroom.get('name')}
|
||||||
td
|
td
|
||||||
if courseInstance.course
|
- var course = view.courses.get(courseInstance.get('courseID'))
|
||||||
| #{courseInstance.course.get('name')}
|
if course
|
||||||
|
| #{course.get('name')}
|
||||||
td= _.size(courseInstance.get('members'))
|
td= _.size(courseInstance.get('members'))
|
||||||
td
|
td
|
||||||
a.btn.btn-primary.btn-sm(href='/courses/#{courseInstance.get("courseID")}/#{courseInstance.id}') Enter
|
a.btn.btn-primary.btn-sm(href='/courses/#{courseInstance.get("courseID")}/#{courseInstance.id}') Enter
|
||||||
|
|
|
@ -42,34 +42,8 @@ module.exports = class HourOfCodeView extends RootView
|
||||||
url: '/db/course_instance/-/create-for-hoc'
|
url: '/db/course_instance/-/create-for-hoc'
|
||||||
context: @
|
context: @
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
application.tracker?.trackEvent 'Finished HoC student course creation', {courseID: data.courseID}
|
||||||
app.router.navigate("/courses/#{data.courseID}/#{data._id}", {
|
app.router.navigate("/courses/#{data.courseID}/#{data._id}", {
|
||||||
trigger: true
|
trigger: true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
# jqxhr = $.post()
|
|
||||||
# jqxhr.done (data, textStatus, jqXHR) =>
|
|
||||||
# application.tracker?.trackEvent 'Finished HoC student course creation', {courseID: courseID}
|
|
||||||
# # TODO: handle fetch errors
|
|
||||||
# me.fetch(cache: false).always =>
|
|
||||||
# courseID = courseID
|
|
||||||
# route = "/courses/#{courseID}"
|
|
||||||
# viewArgs = [{}, courseID]
|
|
||||||
# if data?.length > 0
|
|
||||||
# courseInstanceID = data[0]._id
|
|
||||||
# route += "/#{courseInstanceID}"
|
|
||||||
# viewArgs[0].courseInstanceID = courseInstanceID
|
|
||||||
# Backbone.Mediator.publish 'router:navigate',
|
|
||||||
# route: route
|
|
||||||
# viewClass: 'views/courses/CourseDetailsView'
|
|
||||||
# viewArgs: viewArgs
|
|
||||||
# jqxhr.fail (xhr, textStatus, errorThrown) =>
|
|
||||||
# console.error 'Got an error purchasing a course:', textStatus, errorThrown
|
|
||||||
# application.tracker?.trackEvent 'Failed HoC student course creation', status: textStatus
|
|
||||||
# if xhr.status is 402
|
|
||||||
# @state = 'declined'
|
|
||||||
# @stateMessage = arguments[2]
|
|
||||||
# else
|
|
||||||
# @state = 'unknown_error'
|
|
||||||
# @stateMessage = "#{xhr.status}: #{xhr.responseText}"
|
|
||||||
# @render?()
|
|
|
@ -33,7 +33,7 @@ module.exports = class TeacherCoursesView extends RootView
|
||||||
@supermodel.loadCollection(@classrooms, 'classrooms', {data: {ownerID: me.id}})
|
@supermodel.loadCollection(@classrooms, 'classrooms', {data: {ownerID: me.id}})
|
||||||
@courseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance })
|
@courseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance })
|
||||||
@courseInstances.comparator = 'courseID'
|
@courseInstances.comparator = 'courseID'
|
||||||
@courseInstances.sliceWithMembers = -> return @filter (courseInstance) -> _.size(courseInstance.get('members'))
|
@courseInstances.sliceWithMembers = -> return @filter (courseInstance) -> _.size(courseInstance.get('members')) and courseInstance.get('classroomID')
|
||||||
@supermodel.loadCollection(@courseInstances, 'course_instances', {data: {ownerID: me.id}})
|
@supermodel.loadCollection(@courseInstances, 'course_instances', {data: {ownerID: me.id}})
|
||||||
@members = new CocoCollection([], { model: User })
|
@members = new CocoCollection([], { model: User })
|
||||||
@prepaids = new CocoCollection([], { url: "/db/prepaid", model: Prepaid })
|
@prepaids = new CocoCollection([], { url: "/db/prepaid", model: Prepaid })
|
||||||
|
@ -44,6 +44,7 @@ module.exports = class TeacherCoursesView extends RootView
|
||||||
@supermodel.loadCollection(@prepaids, 'prepaids', {data: {creator: me.id}})
|
@supermodel.loadCollection(@prepaids, 'prepaids', {data: {creator: me.id}})
|
||||||
@listenTo @members, 'sync', @renderManageTab
|
@listenTo @members, 'sync', @renderManageTab
|
||||||
@usersToRedeem = new CocoCollection([], { model: User })
|
@usersToRedeem = new CocoCollection([], { model: User })
|
||||||
|
@hoc = utils.getQueryVariable('hoc')
|
||||||
@
|
@
|
||||||
|
|
||||||
onceClassroomsSync: ->
|
onceClassroomsSync: ->
|
||||||
|
|
|
@ -55,6 +55,7 @@ CourseInstanceHandler = class CourseInstanceHandler extends Handler
|
||||||
name: 'Single Player'
|
name: 'Single Player'
|
||||||
ownerID: req.user.get('_id')
|
ownerID: req.user.get('_id')
|
||||||
aceConfig: { language: 'python' }
|
aceConfig: { language: 'python' }
|
||||||
|
hourOfCode: true
|
||||||
})
|
})
|
||||||
courseInstance.save (err, courseInstance) =>
|
courseInstance.save (err, courseInstance) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
|
|
|
@ -239,7 +239,7 @@ PrepaidHandler = class PrepaidHandler extends Handler
|
||||||
return @sendBadInputError(res, 'Bad creator') unless utils.isID creator
|
return @sendBadInputError(res, 'Bad creator') unless utils.isID creator
|
||||||
Prepaid.find {creator: mongoose.Types.ObjectId(creator)}, (err, prepaids) =>
|
Prepaid.find {creator: mongoose.Types.ObjectId(creator)}, (err, prepaids) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
return @sendSuccess(res, (@formatEntity(req, prepaids) for prepaids in prepaids))
|
return @sendSuccess(res, (@formatEntity(req, prepaid) for prepaid in prepaids))
|
||||||
else
|
else
|
||||||
super(arguments...)
|
super(arguments...)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue