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:
Scott Erickson 2015-11-09 17:58:40 -08:00
parent c8a47818c2
commit 97cb5275c3
8 changed files with 63 additions and 46 deletions

View file

@ -12,3 +12,9 @@ module.exports = class Prepaid extends CocoModel
for redeemer in @get('redeemers')
return redeemer.date if redeemer.userID is userID
return null
initialize: ->
@listenTo @, 'add', ->
maxRedeemers = @get('maxRedeemers')
if _.isString(maxRedeemers)
@set 'maxRedeemers', parseInt(maxRedeemers)

View file

@ -8,4 +8,4 @@ block content
.col-md-6.text-center
button#student-btn.btn.btn-lg.btn-success(data-i18n="courses.students_click")
.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")

View file

@ -27,12 +27,19 @@ block content
.list-group
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
.row
- var classroom = view.classrooms.get(courseInstance.get('classroomID'))
- var course = view.courses.get(courseInstance.get('courseID'))
.col-sm-3= classroom.get('name')
.col-sm-3= course.get('name')
.col-sm-3
if classroom
| #{classroom.get('name')}
.col-sm-3
if course
| #{course.get('name')}
.col-sm-6
a.btn.btn-default.btn-sm(href="/courses/#{course.id}/#{courseInstance.id}") Enter

View file

@ -2,21 +2,48 @@ extends /templates/base
block content
span *UNDER CONSTRUCTION, please send feedback to
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
hr
if view.hoc
h1 Welcome to Hour of Code!
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')
li.active(role='presentation')
a(href="#courses-tab-pane" aria-controls="courses" role="tab" data-toggle="tab") Courses
li(role='presentation')
a(href="#manage-tab-pane" aria-controls="manage" role="tab" data-toggle="tab") Manage
if !me.isAnonymous()
ul.nav.nav-tabs(role='tablist')
li.active(role='presentation')
a(href="#courses-tab-pane" aria-controls="courses" role="tab" data-toggle="tab") Courses
li(role='presentation')
a(href="#manage-tab-pane" aria-controls="manage" role="tab" data-toggle="tab") Manage
.tab-content
#courses-tab-pane.tab-pane.well.active
h3 Your Courses
- 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
span.spr You currently have no students assigned to courses.
a#manage-tab-link Go to the manage tab to get set up.
@ -35,8 +62,9 @@ block content
if classroom
| #{classroom.get('name')}
td
if courseInstance.course
| #{courseInstance.course.get('name')}
- var course = view.courses.get(courseInstance.get('courseID'))
if course
| #{course.get('name')}
td= _.size(courseInstance.get('members'))
td
a.btn.btn-primary.btn-sm(href='/courses/#{courseInstance.get("courseID")}/#{courseInstance.id}') Enter

View file

@ -42,34 +42,8 @@ module.exports = class HourOfCodeView extends RootView
url: '/db/course_instance/-/create-for-hoc'
context: @
success: (data) ->
application.tracker?.trackEvent 'Finished HoC student course creation', {courseID: data.courseID}
app.router.navigate("/courses/#{data.courseID}/#{data._id}", {
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?()
})

View file

@ -33,7 +33,7 @@ module.exports = class TeacherCoursesView extends RootView
@supermodel.loadCollection(@classrooms, 'classrooms', {data: {ownerID: me.id}})
@courseInstances = new CocoCollection([], { url: "/db/course_instance", model: CourseInstance })
@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}})
@members = new CocoCollection([], { model: User })
@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}})
@listenTo @members, 'sync', @renderManageTab
@usersToRedeem = new CocoCollection([], { model: User })
@hoc = utils.getQueryVariable('hoc')
@
onceClassroomsSync: ->

View file

@ -55,6 +55,7 @@ CourseInstanceHandler = class CourseInstanceHandler extends Handler
name: 'Single Player'
ownerID: req.user.get('_id')
aceConfig: { language: 'python' }
hourOfCode: true
})
courseInstance.save (err, courseInstance) =>
return @sendDatabaseError(res, err) if err

View file

@ -239,7 +239,7 @@ PrepaidHandler = class PrepaidHandler extends Handler
return @sendBadInputError(res, 'Bad creator') unless utils.isID creator
Prepaid.find {creator: mongoose.Types.ObjectId(creator)}, (err, prepaids) =>
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
super(arguments...)