Route /hoc to courses
When in HoC mode: Students have an option to play through as a single player, in addition to entering a code to join an existing class. Teachers get the normal course enrollment flow, without a sales blurb on /courses.
This commit is contained in:
parent
56c4c5a1b3
commit
708f78153b
5 changed files with 92 additions and 14 deletions
app
core
locale
styles/courses
templates/courses
views/courses
|
@ -96,6 +96,8 @@ module.exports = class CocoRouter extends Backbone.Router
|
||||||
|
|
||||||
'github/*path': 'routeToServer'
|
'github/*path': 'routeToServer'
|
||||||
|
|
||||||
|
'hoc': go('courses/CoursesView')
|
||||||
|
|
||||||
'i18n': go('i18n/I18NHomeView')
|
'i18n': go('i18n/I18NHomeView')
|
||||||
'i18n/thang/:handle': go('i18n/I18NEditThangTypeView')
|
'i18n/thang/:handle': go('i18n/I18NEditThangTypeView')
|
||||||
'i18n/component/:handle': go('i18n/I18NEditComponentView')
|
'i18n/component/:handle': go('i18n/I18NEditComponentView')
|
||||||
|
|
|
@ -913,7 +913,7 @@
|
||||||
see_the: "See the"
|
see_the: "See the"
|
||||||
more_info: "for more information."
|
more_info: "for more information."
|
||||||
choose_course: "Choose Your Course:"
|
choose_course: "Choose Your Course:"
|
||||||
enter_code: "Enter an unlock code"
|
enter_code: "Enter an unlock code to join an existing class" # {change}
|
||||||
enter_code1: "Enter unlock code"
|
enter_code1: "Enter unlock code"
|
||||||
enroll: "Enroll"
|
enroll: "Enroll"
|
||||||
pick_from_classes: "Pick from your current classes"
|
pick_from_classes: "Pick from your current classes"
|
||||||
|
|
|
@ -25,9 +25,6 @@
|
||||||
margin-bottom: 20px
|
margin-bottom: 20px
|
||||||
font-size: 14pt
|
font-size: 14pt
|
||||||
|
|
||||||
.btn-enroll
|
|
||||||
margin-top: 20px
|
|
||||||
|
|
||||||
.center
|
.center
|
||||||
text-align: center
|
text-align: center
|
||||||
|
|
||||||
|
|
|
@ -15,24 +15,44 @@ block content
|
||||||
if state === 'unknown_error'
|
if state === 'unknown_error'
|
||||||
.alert.alert-danger.alert-dismissible= stateMessage
|
.alert.alert-danger.alert-dismissible= stateMessage
|
||||||
|
|
||||||
if studentMode
|
if hocLandingPage
|
||||||
+student-main
|
+hoc-landing
|
||||||
else
|
else
|
||||||
+teacher-main
|
if studentMode
|
||||||
.container-fluid
|
+student-main
|
||||||
- var i = 0
|
else
|
||||||
while i < courses.length
|
if hocMode
|
||||||
.row
|
+teacher-hoc
|
||||||
+course-block(courses[i], instances)
|
else
|
||||||
- i++
|
+teacher-main
|
||||||
if i < courses.length
|
.container-fluid
|
||||||
|
- var i = 0
|
||||||
|
while i < courses.length
|
||||||
|
.row
|
||||||
+course-block(courses[i], instances)
|
+course-block(courses[i], instances)
|
||||||
- i++
|
- i++
|
||||||
|
if i < courses.length
|
||||||
|
+course-block(courses[i], instances)
|
||||||
|
- i++
|
||||||
|
|
||||||
|
mixin hoc-landing
|
||||||
|
h1.center Welcome Hour of Code!
|
||||||
|
br
|
||||||
|
.container-fluid
|
||||||
|
.row
|
||||||
|
.col-md-6.center
|
||||||
|
button.btn.btn-lg.btn-success.btn-student(data-i18n="courses.students_click")
|
||||||
|
.col-md-6.center
|
||||||
|
button.btn.btn-lg.btn-default.btn-teacher(data-i18n="courses.teachers_click")
|
||||||
|
|
||||||
mixin student-main
|
mixin student-main
|
||||||
button.btn.btn-warning.btn-teacher(data-i18n="courses.teachers_click")
|
button.btn.btn-warning.btn-teacher(data-i18n="courses.teachers_click")
|
||||||
h1.center(data-i18n="courses.courses_on_coco")
|
h1.center(data-i18n="courses.courses_on_coco")
|
||||||
|
|
||||||
|
mixin teacher-hoc
|
||||||
|
button.btn.btn-warning.btn-student(data-i18n="courses.students_click")
|
||||||
|
h1.center(data-i18n="courses.courses_on_coco")
|
||||||
|
|
||||||
mixin teacher-main
|
mixin teacher-main
|
||||||
button.btn.btn-warning.btn-student(data-i18n="courses.students_click")
|
button.btn.btn-warning.btn-student(data-i18n="courses.students_click")
|
||||||
h1.center(data-i18n="courses.courses_on_coco")
|
h1.center(data-i18n="courses.courses_on_coco")
|
||||||
|
@ -87,6 +107,14 @@ mixin student-dialog(course)
|
||||||
input.code-input(type='text', data-course-id="#{course.id}", data-i18n="[placeholder]courses.enter_code1", placeholder="Enter unlock code")
|
input.code-input(type='text', data-course-id="#{course.id}", data-i18n="[placeholder]courses.enter_code1", placeholder="Enter unlock code")
|
||||||
.col-md-4
|
.col-md-4
|
||||||
button.btn.btn-success.btn-enroll(data-course-id="#{course.id}", data-i18n="courses.enroll")
|
button.btn.btn-success.btn-enroll(data-course-id="#{course.id}", data-i18n="courses.enroll")
|
||||||
|
if hocMode && course.get('pricePerSeat') === 0
|
||||||
|
.row.button-row.center.row-pick-class
|
||||||
|
.col-md-12
|
||||||
|
br
|
||||||
|
div.or(data-i18n="courses.or")
|
||||||
|
.row.button-row.center
|
||||||
|
.col-md-12
|
||||||
|
button.btn.btn-success.btn-lg.btn-hoc-student-continue(data-course-id="#{course.id}") Continue by yourself
|
||||||
|
|
||||||
mixin teacher-dialog(course)
|
mixin teacher-dialog(course)
|
||||||
.modal.continue-dialog(id="continueModal#{course.id}")
|
.modal.continue-dialog(id="continueModal#{course.id}")
|
||||||
|
|
|
@ -7,6 +7,8 @@ RootView = require 'views/core/RootView'
|
||||||
template = require 'templates/courses/courses'
|
template = require 'templates/courses/courses'
|
||||||
utils = require 'core/utils'
|
utils = require 'core/utils'
|
||||||
|
|
||||||
|
# TODO: Hour of Code (HoC) integration is a mess
|
||||||
|
|
||||||
module.exports = class CoursesView extends RootView
|
module.exports = class CoursesView extends RootView
|
||||||
id: 'courses-view'
|
id: 'courses-view'
|
||||||
template: template
|
template: template
|
||||||
|
@ -15,12 +17,15 @@ module.exports = class CoursesView extends RootView
|
||||||
'click .btn-buy': 'onClickBuy'
|
'click .btn-buy': 'onClickBuy'
|
||||||
'click .btn-enroll': 'onClickEnroll'
|
'click .btn-enroll': 'onClickEnroll'
|
||||||
'click .btn-enter': 'onClickEnter'
|
'click .btn-enter': 'onClickEnter'
|
||||||
|
'click .btn-hoc-student-continue': 'onClickHocStudentContinue'
|
||||||
'click .btn-student': 'onClickStudent'
|
'click .btn-student': 'onClickStudent'
|
||||||
'click .btn-teacher': 'onClickTeacher'
|
'click .btn-teacher': 'onClickTeacher'
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super(options)
|
super(options)
|
||||||
@praise = utils.getCoursePraise()
|
@praise = utils.getCoursePraise()
|
||||||
|
@hocLandingPage = Backbone.history.getFragment()?.indexOf('hoc') >= 0
|
||||||
|
@hocMode = utils.getQueryVariable('hoc', false)
|
||||||
@studentMode = Backbone.history.getFragment()?.indexOf('courses/students') >= 0
|
@studentMode = Backbone.history.getFragment()?.indexOf('courses/students') >= 0
|
||||||
@courses = new CocoCollection([], { url: "/db/course", model: Course})
|
@courses = new CocoCollection([], { url: "/db/course", model: Course})
|
||||||
@supermodel.loadCollection(@courses, 'courses')
|
@supermodel.loadCollection(@courses, 'courses')
|
||||||
|
@ -38,6 +43,8 @@ module.exports = class CoursesView extends RootView
|
||||||
context = super()
|
context = super()
|
||||||
context.courses = @courses.models ? []
|
context.courses = @courses.models ? []
|
||||||
context.enrolledCourses = @enrolledCourses ? {}
|
context.enrolledCourses = @enrolledCourses ? {}
|
||||||
|
context.hocLandingPage = @hocLandingPage
|
||||||
|
context.hocMode = @hocMode
|
||||||
context.instances = @courseInstances.models ? []
|
context.instances = @courseInstances.models ? []
|
||||||
context.praise = @praise
|
context.praise = @praise
|
||||||
context.state = @state
|
context.state = @state
|
||||||
|
@ -95,14 +102,58 @@ module.exports = class CoursesView extends RootView
|
||||||
navigationEvent = route: route, viewClass: viewClass, viewArgs: viewArgs
|
navigationEvent = route: route, viewClass: viewClass, viewArgs: viewArgs
|
||||||
Backbone.Mediator.publish 'router:navigate', navigationEvent
|
Backbone.Mediator.publish 'router:navigate', navigationEvent
|
||||||
|
|
||||||
|
onClickHocStudentContinue: (e) ->
|
||||||
|
$('.continue-dialog').modal('hide')
|
||||||
|
return @openModalView new AuthModal() if me.isAnonymous()
|
||||||
|
courseID = $(e.target).data('course-id')
|
||||||
|
|
||||||
|
@state = 'enrolling'
|
||||||
|
@stateMessage = undefined
|
||||||
|
@render?()
|
||||||
|
|
||||||
|
# TODO: Copied from CourseEnrollView
|
||||||
|
|
||||||
|
data =
|
||||||
|
name: 'Single Player'
|
||||||
|
seats: 9999
|
||||||
|
courseID: courseID
|
||||||
|
jqxhr = $.post('/db/course_instance/-/create', data)
|
||||||
|
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?()
|
||||||
|
|
||||||
onClickStudent: (e) ->
|
onClickStudent: (e) ->
|
||||||
route = "/courses/students"
|
route = "/courses/students"
|
||||||
|
route += "?hoc=true" if @hocLandingPage or @hocMode
|
||||||
viewClass = require 'views/courses/CoursesView'
|
viewClass = require 'views/courses/CoursesView'
|
||||||
navigationEvent = route: route, viewClass: viewClass, viewArgs: []
|
navigationEvent = route: route, viewClass: viewClass, viewArgs: []
|
||||||
Backbone.Mediator.publish 'router:navigate', navigationEvent
|
Backbone.Mediator.publish 'router:navigate', navigationEvent
|
||||||
|
|
||||||
onClickTeacher: (e) ->
|
onClickTeacher: (e) ->
|
||||||
route = "/courses/teachers"
|
route = "/courses/teachers"
|
||||||
|
route += "?hoc=true" if @hocLandingPage or @hocMode
|
||||||
viewClass = require 'views/courses/CoursesView'
|
viewClass = require 'views/courses/CoursesView'
|
||||||
navigationEvent = route: route, viewClass: viewClass, viewArgs: []
|
navigationEvent = route: route, viewClass: viewClass, viewArgs: []
|
||||||
Backbone.Mediator.publish 'router:navigate', navigationEvent
|
Backbone.Mediator.publish 'router:navigate', navigationEvent
|
||||||
|
|
Reference in a new issue