Add framework for new courses pages

This commit is contained in:
Scott Erickson 2015-11-03 16:41:06 -08:00
parent aafdce6fbe
commit 66432990f4
16 changed files with 240 additions and 555 deletions

View file

@ -66,8 +66,8 @@ module.exports = class CocoRouter extends Backbone.Router
'courses/mock1/enroll/:courseID': go('courses/mock1/CourseEnrollView')
'courses/mock1/:courseID': go('courses/mock1/CourseDetailsView')
'courses': go('courses/CoursesView')
'courses/students': go('courses/CoursesView')
'courses/teachers': go('courses/CoursesView')
'courses/students': go('courses/StudentCoursesView')
'courses/teachers': go('courses/TeacherCoursesView')
'courses/enroll(/:courseID)': go('courses/CourseEnrollView')
'courses/:courseID(/:courseInstanceID)': go('courses/CourseDetailsView')
@ -97,7 +97,7 @@ module.exports = class CocoRouter extends Backbone.Router
'github/*path': 'routeToServer'
'hoc': go('courses/CoursesView')
'hoc': go('courses/HourOfCodeView')
'i18n': go('i18n/I18NHomeView')
'i18n/thang/:handle': go('i18n/I18NEditThangTypeView')

View file

@ -0,0 +1,7 @@
CocoModel = require './CocoModel'
schema = require 'schemas/models/classroom.schema'
module.exports = class Classroom extends CocoModel
@className: 'Classroom'
@schema: schema
urlRoot: '/db/classroom'

View file

@ -0,0 +1,3 @@
#courses-view
.row
margin-top: 40px

View file

@ -1,85 +0,0 @@
#courses-view
.logged_out
font-size: 24px
.signup-button
background: red
color: white
font-size: 18px
font-variant: small-caps
line-height: 27px
text-transform: uppercase
margin-right: 20px
.login-button
background: white
color: black
font-size: 18px
font-variant: small-caps
line-height: 27px
text-transform: uppercase
.center
text-align: center
.code-input
width: 100%
.course-image
width: 100%
.course-panel
margin: 20px
.faq-blurb
font-size: 14px
.continue-dialog .modal-dialog
background-color: white
max-width: 400px
.instruction-label
font-size: 14pt
.or
margin-bottom: 20px
font-size: 14pt
.center
text-align: center
.concepts-container
width: 200px
.contact-container
margin-top: 20px
text-align: center
.info-container
margin: 0% 10%
font-size: 18px
.monitoring-img-container
margin-top: 10px
.praise-caption
font-size: 14px
.praise-quote
font-size: 20px
font-style: italic
.progress-container
font-size: 20px
.img-quote
height: 160px
.popover
z-index: 1050
min-width: 400px
h3
background: transparent
border: 0
font-size: 30px

View file

@ -0,0 +1 @@
//#hour-of-code-view

View file

@ -0,0 +1 @@
//#student-courses-view

View file

@ -0,0 +1 @@
//#teacher-courses-view

View file

@ -0,0 +1,12 @@
extends /templates/base
block content
h1.text-center Welcome to CodeCombat Courses
.row
.col-sm-6.text-center
a(href="/courses/students").btn.btn-default Students Click Here
.col-sm-6.text-center
a(href="/courses/teachers").btn.btn-default Teachers Click Here

View file

@ -1,236 +0,0 @@
extends /templates/base
block content
div(style='border-bottom: 1px solid black')
span *UNDER CONSTRUCTION, please send feedback to
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
br
.hidden-md.hidden-lg
.alert.alert-danger Courses not supported on mobile devices.
.hidden-xs.hidden-sm
if state === 'enrolling'
.alert.alert-info Enrolling in course..
else if state === 'ppc_logged_out'
.alert.alert-danger.logged_out Create account or log in to join this course.
button.btn.btn-sm.btn-primary.header-font.signup-button(data-i18n="login.sign_up")
button.btn.btn-sm.btn-default.header-font.login-button(data-i18n="login.log_in")
else
if state === 'unknown_error'
.alert.alert-danger.alert-dismissible= stateMessage
if hocLandingPage
+hoc-landing
else
if view.courseInstances.size()
+course-instance-list
if studentMode
+student-main
else
if hocMode
+teacher-hoc
else
+teacher-main
.container-fluid
- var i = 0
while i < courses.length
.row
+course-block(courses[i], instances)
- i++
if i < courses.length
+course-block(courses[i], instances)
- i++
mixin hoc-landing
h1.center Welcome to CodeCombat's 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 course-instance-list
h1.center Courses You Are In
.row
.col-md-10.col-md-offset-1
.list-group
for courseInstance in view.courseInstances.models
- var course = view.courses.get(courseInstance.get('courseID'));
.list-group-item
.list-group-item-heading
h3
a(href="/courses/#{course.id}/#{courseInstance.id}")
span.spr #{courseInstance.get('name')}
small (#{course.get('name')})
p= courseInstance.get('description')
mixin student-main
button.btn.btn-warning.btn-teacher(data-i18n="courses.teachers_click")
h1.center(data-i18n="courses.courses_on_coco")
mixin teacher-hoc
button.btn.btn-warning.btn-student(data-i18n="courses.students_click")
h1.center Welcome to CodeCombat's Hour of Code!
p
strong How to use CodeCombat with your students:
ol
li Click the green 'Get FREE course' button below
li Follow the enrollment instructions
li Add students via the 'Add Students' tab
p
span.spr If you have any problems, please email
a(href='mailto:team@codecombat.com') team@codecombat.com
br
mixin teacher-main
button.btn.btn-warning.btn-student(data-i18n="courses.students_click")
h1.center(data-i18n="courses.courses_on_coco")
.info-container
p(data-i18n="courses.designed_to")
.container-fluid
.row
.col-md-6
ul
li(data-i18n="courses.more_in_less")
li(data-i18n="courses.no_experience")
li(data-i18n="courses.easy_monitor")
p(data-i18n="courses.purchase_for_class")
p.faq-blurb
span.spr(data-i18n="courses.see_the")
a.courses-faq(data-i18n="courses.faq")
span.spl(data-i18n="courses.more_info")
.col-md-6
img.img-quote(src="/images/pages/courses/coco_complab.png")
p
.well.well-sm
div.praise-quote "#{praise.quote}"
div.praise-caption - #{praise.source}
//- h1.center(data-i18n="courses.free_trial")
//- .info-container
//- p
//- span.spr(data-i18n="teachers.teacher_subs_1")
//- a(href='/teachers/freetrial', data-i18n="teachers.teacher_subs_2")
//- span.spl(data-i18n="courses.get_access")
h2.center(data-i18n="courses.choose_course")
mixin student-dialog(course)
.modal.continue-dialog(id="continueModal#{course.id}")
.modal-dialog
.modal-header
button.close(data-dismiss='modal')
span &times;
h3.modal-title= course.get('name')
.modal-body
.container-fluid
.row.button-row
.col-md-12
.well.well-sm
p
div.instruction-label(data-i18n="courses.enter_code")
.container-fluid
.row.student-dialog-state-row
.col-md-12
if view.state === 'enrolling-by-modal'
.progress.progress-striped.active
.progress-bar(style="width: 100%")
else if view.state === 'unknown_error'
.alert.alert-danger= view.stateMessage
.row
.col-md-8
input.code-input(type='text', data-course-id="#{course.id}", data-i18n="[placeholder]courses.enter_code1", placeholder="Enter unlock code")
.col-md-4
button.btn.btn-success.btn-enroll(data-course-id="#{course.id}", data-i18n="courses.enroll")
if hocMode && course.get('pricePerSeat') === 0 || me.isAdmin()
.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)
.modal.continue-dialog(id="continueModal#{course.id}")
.modal-dialog
.modal-header
button.close(data-dismiss='modal')
span &times;
h3.modal-title= course.get('name')
.modal-body
.container-fluid
if enrolledCourses[course.id]
.row.button-row.row-pick-class
.col-md-12
.well.well-sm
p
div.instruction-label(data-i18n="courses.pick_from_classes")
.container-fluid
.row
.col-md-8
select.form-control.select-session(data-course-id="#{course.id}")
each inst in instances
if inst.get('courseID') == course.id
if inst.get('name')
option(value="#{inst.id}")= inst.get('name')
else
option(value="#{inst.id}", data-i18n="courses.unnamed")
.col-md-4
button.btn.btn-success.btn-enter(data-course-id="#{course.id}", data-i18n="courses.enter")
.row.button-row.center.row-pick-class
.col-md-12
div.or(data-i18n="courses.or")
.row.button-row.center
.col-md-12
if course.get('pricePerSeat') === 0 || me.isAdmin()
button.btn.btn-success.btn-lg.btn-buy(data-course-id="#{course.id}") Start new class
else
button.btn.btn-success.btn-lg.btn-buy(data-course-id="#{course.id}", data-i18n="courses.buy_course1")
mixin course-block(course)
if studentMode
+student-dialog(course)
else
+teacher-dialog(course)
.col-md-6
.well.panel.course-panel(class=enrolledCourses[course.id] ? 'panel-success' : 'panel-info')
.panel-heading
.panel-title
span.spr #{course.get('name')}
strong #{enrolledCourses[course.id] ? '[ enrolled ]' : ''}
.panel-body
.container-fluid
.row
.col-md-12
p
img.course-image(src="#{course.get('screenshot')}")
.row.button-row
.col-md-6
strong(data-i18n="courses.topics")
ul
each concept in course.get('concepts')
li(data-i18n="concepts." + concept)
strong
span.spr(data-i18n="courses.hours_content")
span #{course.get('duration')}
.col-md-6.center(style='margin-top: 40px;')
if studentMode
if enrolledCourses[course.id]
a.btn.btn-lg.btn-success.btn-continue(href="/courses/#{course.id}?student=true", data-i18n="common.continue")
else
button.btn.btn-lg.btn-success.btn-continue(data-toggle='modal', data-target="#continueModal#{course.id}", data-i18n="courses.enter") Enter
else if enrolledCourses[course.id]
button.btn.btn-lg.btn-success.btn-continue(data-toggle='modal', data-target="#continueModal#{course.id}", data-i18n="common.continue")
else if course.get('pricePerSeat') === 0 || me.isAdmin()
button.btn.btn-lg.btn-success.btn-buy(data-course-id="#{course.id}", data-i18n='courses.get_free')
else
button.btn.btn-lg.btn-success.btn-buy(data-course-id="#{course.id}", data-i18n='courses.buy_course')

View file

@ -0,0 +1,4 @@
extends /templates/base
block content
p Hour of Code

View file

@ -0,0 +1,22 @@
extends /templates/base
block content
p To join a class, ask your teacher for an unlock code.
.form-horizontal
.form-group
.col-sm-2
button.btn.btn-default.btn-block Join Class
.col-sm-6
input#classroom-code.form-control(placeholder='<enter unlock code here>')
.panel.panel-default
.panel-heading
.panel-title My Courses
.panel-body.row
.col-sm-3 Class 1
.col-sm-3 Course 1
.col-sm-6
button.btn.btn-default.btn-sm Enter

View file

@ -0,0 +1,10 @@
extends /templates/base
block content
span *UNDER CONSTRUCTION, please send feedback to
a.spl(href='mailto:team@codecombat.com') team@codecombat.com
hr
p Teacher courses view

View file

@ -1,238 +1,8 @@
app = require 'core/application'
AuthModal = require 'views/core/AuthModal'
CocoCollection = require 'collections/CocoCollection'
Course = require 'models/Course'
CourseInstance = require 'models/CourseInstance'
RootView = require 'views/core/RootView'
template = require 'templates/courses/courses'
utils = require 'core/utils'
# TODO: Hour of Code (HoC) integration is a mess
template = require 'templates/courses/courses-view'
module.exports = class CoursesView extends RootView
id: 'courses-view'
template: template
events:
'click .btn-buy': 'onClickBuy'
'click .btn-enroll': 'onClickEnroll'
'click .btn-enter': 'onClickEnter'
'click .btn-hoc-student-continue': 'onClickHOCStudentContinue'
'click .btn-student': 'onClickStudent'
'click .btn-teacher': 'onClickTeacher'
constructor: (options) ->
super(options)
@setUpHourOfCode()
@praise = utils.getCoursePraise()
@studentMode = Backbone.history.getFragment()?.indexOf('courses/students') >= 0
@courses = new CocoCollection([], { url: "/db/course", model: Course})
@supermodel.loadCollection(@courses, 'courses')
@courseInstances = new CocoCollection([], { url: "/db/user/#{me.id}/course_instances", model: CourseInstance})
@listenToOnce @courseInstances, 'sync', @onCourseInstancesLoaded
@supermodel.loadCollection(@courseInstances, 'course_instances')
if prepaidCode = utils.getQueryVariable('_ppc', false)
if me.isAnonymous()
@state = 'ppc_logged_out'
else
@studentMode = true
@courseEnrollByURL(prepaidCode)
setUpHourOfCode: ->
# If we are coming in at /hoc, then we show the landing page.
# If we have ?hoc=true (for the step after the landing page), then we show any HoC-specific instructions.
# If we haven't tracked this player as an hourOfCode player yet, and it's a new account, we do that now.
@hocLandingPage = Backbone.history.getFragment()?.indexOf('hoc') >= 0
@hocMode = utils.getQueryVariable('hoc', false)
elapsed = new Date() - new Date(me.get('dateCreated'))
if not me.get('hourOfCode') and (@hocLandingPage or @hocMode) and elapsed < 5 * 60 * 1000
me.set('hourOfCode', true)
me.patch()
$('body').append($('<img src="https://code.org/api/hour/begin_codecombat.png" style="visibility: hidden;">'))
application.tracker?.trackEvent 'Hour of Code Begin'
if me.get('hourOfCode') and elapsed < 24 * 60 * 60 * 1000
@hocMode = true # If they really just arrived, make sure we're still in hocMode even if they lost ?hoc=true.
getRenderData: ->
context = super()
context.courses = @courses.models ? []
context.enrolledCourses = @enrolledCourses ? {}
context.hocLandingPage = @hocLandingPage
context.hocMode = @hocMode
context.instances = @courseInstances.models ? []
context.praise = @praise
context.state = @state
context.stateMessage = @stateMessage
context.studentMode = @studentMode
context
afterRender: ->
super()
@setupCoursesFAQPopover()
onCourseInstancesLoaded: ->
@enrolledCourses = {}
@enrolledCourses[courseInstance.get('courseID')] = true for courseInstance in @courseInstances.models
setupCoursesFAQPopover: ->
popoverTitle = "<h3>" + $.i18n.t('courses.faq') + "<button type='button' class='close' onclick='$(&#39;.courses-faq&#39;).popover(&#39;hide&#39;);'>&times;</button></h3>"
popoverContent = "<p><strong>" + $.i18n.t('courses.question') + "</strong> " + $.i18n.t('courses.question1') + "</p>"
popoverContent += "<p><strong>" + $.i18n.t('courses.answer') + "</strong> " + $.i18n.t('courses.answer1') + "</p>"
popoverContent += "<p>" + $.i18n.t('courses.answer2') + "</p>"
@$el.find('.courses-faq').popover(
animation: true
html: true
placement: 'top'
trigger: 'click'
title: popoverTitle
content: popoverContent
container: @$el
).on 'shown.bs.popover', =>
application.tracker?.trackEvent 'Subscription payment methods hover'
onClickBuy: (e) ->
$('.continue-dialog').modal('hide')
courseID = $(e.target).data('course-id')
route = "/courses/enroll/#{courseID}"
viewClass = require 'views/courses/CourseEnrollView'
viewArgs = [{}, courseID]
navigationEvent = route: route, viewClass: viewClass, viewArgs: viewArgs
Backbone.Mediator.publish 'router:navigate', navigationEvent
onClickEnroll: (e) ->
return @openModalView new AuthModal() if me.isAnonymous()
courseID = $(e.target).data('course-id')
prepaidCode = ($(".code-input[data-course-id=#{courseID}]").val() ? '').trim()
@courseEnrollByModal(prepaidCode)
onClickEnter: (e) ->
$('.continue-dialog').modal('hide')
courseID = $(e.target).data('course-id')
courseInstanceID = $(".select-session[data-course-id=#{courseID}]").val()
route = "/courses/#{courseID}/#{courseInstanceID}"
viewClass = require 'views/courses/CourseDetailsView'
viewArgs = [{}, courseID, courseInstanceID]
navigationEvent = route: route, viewClass: viewClass, viewArgs: viewArgs
Backbone.Mediator.publish 'router:navigate', navigationEvent
onClickHOCStudentContinue: (e) ->
$('.continue-dialog').modal('hide')
if e
courseID = $(e.target).data('course-id')
else
courseID = '560f1a9f22961295f9427742'
@state = 'enrolling'
@stateMessage = undefined
@render?()
# TODO: Copied from CourseEnrollView
data =
name: 'Single Player'
seats: 9999
courseID: courseID
hourOfCode: true
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) ->
if @supermodel.finished() and @hocLandingPage
# Automatically enroll in first course
@onClickHOCStudentContinue()
return
route = "/courses/students"
route += "?hoc=true" if @hocLandingPage or @hocMode
viewClass = require 'views/courses/CoursesView'
navigationEvent = route: route, viewClass: viewClass, viewArgs: []
Backbone.Mediator.publish 'router:navigate', navigationEvent
onClickTeacher: (e) ->
route = "/courses/teachers"
route += "?hoc=true" if @hocLandingPage or @hocMode
viewClass = require 'views/courses/CoursesView'
navigationEvent = route: route, viewClass: viewClass, viewArgs: []
Backbone.Mediator.publish 'router:navigate', navigationEvent
courseEnrollByURL: (prepaidCode) ->
@state = 'enrolling'
@render?()
$.ajax({
method: 'POST'
url: '/db/course_instance/-/redeem_prepaid'
data: prepaidCode: prepaidCode
context: @
success: @onRedeemPrepaidSuccess
error: (xhr, textStatus, errorThrown) ->
console.error 'Got an error redeeming a course prepaid code:', textStatus, errorThrown
application.tracker?.trackEvent 'Failed to redeem course prepaid code by url', status: textStatus
@state = 'unknown_error'
@stateMessage = "Failed to redeem code: #{xhr.responseText}"
@render?()
})
courseEnrollByModal: (prepaidCode) ->
@state = 'enrolling-by-modal'
@renderSelectors '.student-dialog-state-row'
$.ajax({
method: 'POST'
url: '/db/course_instance/-/redeem_prepaid'
data: prepaidCode: prepaidCode
context: @
success: ->
$('.continue-dialog').modal('hide')
@onRedeemPrepaidSuccess(arguments...)
error: (jqxhr, textStatus, errorThrown) ->
application.tracker?.trackEvent 'Failed to redeem course prepaid code by modal', status: textStatus
@state = 'unknown_error'
if jqxhr.status is 422
@stateMessage = 'Please enter a code.'
else if jqxhr.status is 404
@stateMessage = 'Code not found.'
else
@stateMessage = "#{jqxhr.responseText}"
@renderSelectors '.student-dialog-state-row'
})
onRedeemPrepaidSuccess: (data, textStatus, jqxhr) ->
prepaidID = data[0]?.prepaidID
application.tracker?.trackEvent 'Redeemed course prepaid code', {prepaidCode: prepaidID}
me.fetch(cache: false).always =>
if data?.length > 0 && data[0].courseID && data[0]._id
courseID = data[0].courseID
courseInstanceID = data[0]._id
route = "/courses/#{courseID}/#{courseInstanceID}"
viewArgs = [{}, courseID, courseInstanceID]
Backbone.Mediator.publish 'router:navigate',
route: route
viewClass: 'views/courses/CourseDetailsView'
viewArgs: viewArgs
else
@state = 'unknown_error'
@stateMessage = "Database error."
@render?()

View file

@ -0,0 +1,77 @@
app = require 'core/application'
AuthModal = require 'views/core/AuthModal'
CocoCollection = require 'collections/CocoCollection'
Course = require 'models/Course'
CourseInstance = require 'models/CourseInstance'
RootView = require 'views/core/RootView'
template = require 'templates/courses/hour-of-code-view'
utils = require 'core/utils'
module.exports = class HourOfCodeView extends RootView
id: 'hour-of-code-view'
template: template
constructor: (options) ->
super(options)
# @setUpHourOfCode()
#
# setUpHourOfCode: ->
# # If we are coming in at /hoc, then we show the landing page.
# # If we have ?hoc=true (for the step after the landing page), then we show any HoC-specific instructions.
# # If we haven't tracked this player as an hourOfCode player yet, and it's a new account, we do that now.
# @hocLandingPage = Backbone.history.getFragment()?.indexOf('hoc') >= 0
# @hocMode = utils.getQueryVariable('hoc', false)
# elapsed = new Date() - new Date(me.get('dateCreated'))
# if not me.get('hourOfCode') and (@hocLandingPage or @hocMode) and elapsed < 5 * 60 * 1000
# me.set('hourOfCode', true)
# me.patch()
# $('body').append($('<img src="https://code.org/api/hour/begin_codecombat.png" style="visibility: hidden;">'))
# application.tracker?.trackEvent 'Hour of Code Begin'
# if me.get('hourOfCode') and elapsed < 24 * 60 * 60 * 1000
# @hocMode = true # If they really just arrived, make sure we're still in hocMode even if they lost ?hoc=true.
#
# onClickHOCStudentContinue: (e) ->
# $('.continue-dialog').modal('hide')
# if e
# courseID = $(e.target).data('course-id')
# else
# courseID = '560f1a9f22961295f9427742'
#
# @state = 'enrolling'
# @stateMessage = undefined
# @render?()
#
# # TODO: Copied from CourseEnrollView
#
# data =
# name: 'Single Player'
# seats: 9999
# courseID: courseID
# hourOfCode: true
# 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?()

View file

@ -0,0 +1,74 @@
app = require 'core/application'
AuthModal = require 'views/core/AuthModal'
CocoCollection = require 'collections/CocoCollection'
Course = require 'models/Course'
CourseInstance = require 'models/CourseInstance'
RootView = require 'views/core/RootView'
template = require 'templates/courses/student-courses-view'
utils = require 'core/utils'
# TODO: Implement join class
# TODO: Implement course instance links
module.exports = class StudentCoursesView extends RootView
id: 'student-courses-view'
template: template
events:
'click #join-class-btn': 'onClickJoinClassButton'
constructor: (options) ->
super(options)
@courseInstances = new CocoCollection([], { url: "/db/user/#{me.id}/course_instances", model: CourseInstance})
@supermodel.loadCollection(@courseInstances, 'course_instances')
# if classCode = utils.getQueryVariable('_cc', false) and not me.isAnonymous()
# @joinClass(classCode)
#
# onClickJoinClassButton: (e) ->
# return @openModalView new AuthModal() if me.isAnonymous()
# courseID = $(e.target).data('course-id')
# classCode = ($(".code-input[data-course-id=#{courseID}]").val() ? '').trim()
# @courseEnrollByModal(prepaidCode)
#
# joinClass: (prepaidCode) ->
# @state = 'enrolling-by-modal'
# @renderSelectors '.student-dialog-state-row'
# $.ajax({
# method: 'POST'
# url: '/db/course_instance/-/redeem_prepaid'
# data: prepaidCode: prepaidCode
# context: @
# success: ->
# $('.continue-dialog').modal('hide')
# @onRedeemPrepaidSuccess(arguments...)
# error: (jqxhr, textStatus, errorThrown) ->
# application.tracker?.trackEvent 'Failed to redeem course prepaid code by modal', status: textStatus
# @state = 'unknown_error'
# if jqxhr.status is 422
# @stateMessage = 'Please enter a code.'
# else if jqxhr.status is 404
# @stateMessage = 'Code not found.'
# else
# @stateMessage = "#{jqxhr.responseText}"
# @renderSelectors '.student-dialog-state-row'
# })
#
# onRedeemPrepaidSuccess: (data, textStatus, jqxhr) ->
# prepaidID = data[0]?.prepaidID
# application.tracker?.trackEvent 'Redeemed course prepaid code', {prepaidCode: prepaidID}
# me.fetch(cache: false).always =>
# if data?.length > 0 && data[0].courseID && data[0]._id
# courseID = data[0].courseID
# courseInstanceID = data[0]._id
# route = "/courses/#{courseID}/#{courseInstanceID}"
# viewArgs = [{}, courseID, courseInstanceID]
# Backbone.Mediator.publish 'router:navigate',
# route: route
# viewClass: 'views/courses/CourseDetailsView'
# viewArgs: viewArgs
# else
# @state = 'unknown_error'
# @stateMessage = "Database error."
# @render?()

View file

@ -0,0 +1,24 @@
app = require 'core/application'
AuthModal = require 'views/core/AuthModal'
CocoCollection = require 'collections/CocoCollection'
Course = require 'models/Course'
Classroom = require 'models/Classroom'
CourseInstance = require 'models/CourseInstance'
RootView = require 'views/core/RootView'
template = require 'templates/courses/teacher-courses-view'
utils = require 'core/utils'
#
module.exports = class TeacherCoursesView extends RootView
id: 'teacher-courses-view'
template: template
constructor: (options) ->
super(options)
@courses = new CocoCollection([], { url: "/db/course", model: Course})
@supermodel.loadCollection(@courses, 'courses')
@classrooms = new CocoCollection([], { url: "/db/classroom", model: Classroom })
@listenToOnce @classrooms, 'sync', @onCourseInstancesLoaded
@supermodel.loadCollection(@classrooms, 'classrooms', {data: {ownerID: me.id}})
@