mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-27 06:23:41 -04:00
Merge branch 'master' into production
This commit is contained in:
commit
1d51b063c4
13 changed files with 137 additions and 65 deletions
app
assets/docs
styles
templates
views
server/classrooms
BIN
app/assets/docs/HourofCodeGettingStartedGuide.pdf
Normal file
BIN
app/assets/docs/HourofCodeGettingStartedGuide.pdf
Normal file
Binary file not shown.
|
@ -37,7 +37,8 @@
|
|||
margin-bottom: 20px
|
||||
|
||||
img.media-object
|
||||
width: 300px
|
||||
width: 100%
|
||||
margin-bottom: 5px
|
||||
|
||||
.edit-classroom-small
|
||||
cursor: pointer
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
#teachers-view
|
||||
|
||||
font-size: 16px
|
||||
|
||||
.bigger-text
|
||||
font-size: 18px
|
||||
|
||||
.faq-question
|
||||
font-size: 18px
|
||||
font-weight: bold
|
||||
margin: 20px 0px 10px 0px
|
||||
|
||||
.uppercase
|
||||
text-transform: uppercase
|
||||
|
||||
|
@ -16,3 +23,6 @@
|
|||
|
||||
.text-center
|
||||
text-align: center
|
||||
|
||||
.title
|
||||
font-size: 20px
|
||||
|
|
|
@ -53,7 +53,7 @@ block content
|
|||
.progress
|
||||
.progress-bar(style='width:'+stats.levels.pctDone)
|
||||
else if paidFor
|
||||
button.enable-btn.btn.btn-info.btn-sm(data-user-id=user.id, data-course-instance-id=courseInstance.id) Enable
|
||||
button.enable-btn.btn.btn-info.btn-sm(data-user-id=user.id, data-course-instance-cid=courseInstance.cid) Enable
|
||||
|
||||
if !paidFor
|
||||
.text-center
|
||||
|
|
|
@ -244,7 +244,7 @@ mixin progress-members
|
|||
|
||||
mixin progress-members-individual(memberID)
|
||||
- var name = memberUserMap[memberID] ? memberUserMap[memberID].get('name') : 'Anoner'
|
||||
a(href="/user/#{memberID}")= name || 'Anoner'
|
||||
strong= name || 'Anoner'
|
||||
if memberStats && memberStats[memberID]
|
||||
div
|
||||
span #{memberStats[memberID].totalLevelsCompleted}
|
||||
|
|
|
@ -8,6 +8,33 @@ block content
|
|||
else
|
||||
.welcome Welcome, #{me.get('name')}!
|
||||
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-2
|
||||
.col-md-8
|
||||
.well
|
||||
.text-center
|
||||
strong.uppercase Getting Started with Courses
|
||||
br
|
||||
.text-center
|
||||
a.btn.btn-info(href='/docs/HourofCodeGettingStartedGuide.pdf') Download Getting Started Guide [PDF]
|
||||
br
|
||||
ol
|
||||
li Create a new class by clicking the green "Create New Class" button below.
|
||||
li Once you've created a class, click the blue "Add Students" button.
|
||||
li You'll see student's progress below as they sign up and join your class.
|
||||
br
|
||||
.text-center
|
||||
strong Additional Resources
|
||||
ul
|
||||
li
|
||||
span.spr Complete our
|
||||
a.spr(href='/teachers/freetrial') Teacher Survey
|
||||
span to get 15 more hours of content for FREE for 2 months.
|
||||
li
|
||||
span.spr Visit our
|
||||
a.spr(href='http://discourse.codecombat.com/c/teachers') Teacher Forums
|
||||
span to connect to fellow educators who are using CodeCombat.
|
||||
|
||||
.section-header Your Classes
|
||||
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
extends /templates/base
|
||||
|
||||
block content
|
||||
|
||||
p.bigger-text
|
||||
strong Teachers
|
||||
span - share CodeCombat's Hour of Code with your class!
|
||||
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-6
|
||||
.bigger-text
|
||||
.pull-left
|
||||
a(href="/") <- to main CodeCombat website
|
||||
.col-md-6
|
||||
.pull-right
|
||||
a(href="/hoc") Students, click here!
|
||||
.row
|
||||
.col-md-12
|
||||
br
|
||||
.text-center
|
||||
.title
|
||||
strong.spr Teachers
|
||||
span - share CodeCombat's Hour of Code with your class!
|
||||
.row
|
||||
.col-md-4
|
||||
.col-md-4
|
||||
p
|
||||
div In just one hour, students will learn:
|
||||
ul
|
||||
li basic Python syntex
|
||||
|
@ -17,19 +27,7 @@ block content
|
|||
li strings
|
||||
li while loops
|
||||
li variables
|
||||
.col-md-5
|
||||
.well
|
||||
strong.uppercase These easy steps to get started:
|
||||
ol
|
||||
if me.isAnonymous()
|
||||
li
|
||||
a.spr.link-register Register
|
||||
span for a free teacher account to manage classes and monitor student progress
|
||||
else
|
||||
li Register (you've already done this)
|
||||
li
|
||||
a.spr(href='/courses/teachers') Create a class
|
||||
span and invite students via email, unique passcode, or URL.
|
||||
br
|
||||
|
||||
if me.isAnonymous()
|
||||
.text-center
|
||||
|
@ -37,38 +35,24 @@ block content
|
|||
.text-center
|
||||
button.btn.btn-lg.btn-primary.uppercase.btn-login-account Log into Teacher Account
|
||||
|
||||
h2 Free Trial for Teachers!
|
||||
p
|
||||
strong.spr Hour of Code Special!
|
||||
span Complete the survey by December 31st and enroll all your students in the paid courses for 2 months.
|
||||
p(data-i18n="teachers.teacher_subs_0")
|
||||
p
|
||||
span.spr(data-i18n="teachers.teacher_subs_1")
|
||||
a(href='/teachers/freetrial', data-i18n="teachers.teacher_subs_2")
|
||||
span.spl(data-i18n="teachers.teacher_subs_3")
|
||||
br
|
||||
br
|
||||
h2.text-center Hour of Code FAQ
|
||||
|
||||
h2 FAQ
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-2
|
||||
.col-md-8
|
||||
.faq-question(data-i18n="teachers.who_for_title")
|
||||
p(data-i18n="teachers.who_for_1")
|
||||
p(data-i18n="teachers.who_for_2")
|
||||
|
||||
h3(data-i18n="teachers.who_for_title")
|
||||
p(data-i18n="teachers.who_for_1")
|
||||
p(data-i18n="teachers.who_for_2")
|
||||
.faq-question Does it cost anything to play Hour of Code?
|
||||
p No! The first hour of CodeCombat is completely free.
|
||||
p Teachers, please see the free trial information above for further details.
|
||||
|
||||
h3 Does it cost anything to play Hour of Code?
|
||||
p No! The first hour of CodeCombat is completely free.
|
||||
p Teachers, please see the free trial information above for further details.
|
||||
|
||||
//- h3 How much are the paid courses?
|
||||
//- p
|
||||
//- span.spr(data-i18n="teachers.free_3")
|
||||
//- a(href='/courses', data-i18n="teachers.free_4")
|
||||
//- span(data-i18n="teachers.free_5")
|
||||
//- p(data-i18n="teachers.free_6")
|
||||
//- p
|
||||
//- span.spr For more details, please email
|
||||
//- a(href='mailto:team@codecombat.com') team@codecombat.com
|
||||
|
||||
h3(data-i18n="teachers.more_info_title")
|
||||
p
|
||||
span.spr(data-i18n="teachers.more_info_1")
|
||||
a(href='http://discourse.codecombat.com/c/teachers', data-i18n="teachers.more_info_2")
|
||||
span.spl(data-i18n="teachers.more_info_3")
|
||||
.faq-question(data-i18n="teachers.more_info_title")
|
||||
p
|
||||
span.spr(data-i18n="teachers.more_info_1")
|
||||
a(href='http://discourse.codecombat.com/c/teachers', data-i18n="teachers.more_info_2")
|
||||
span.spl(data-i18n="teachers.more_info_3")
|
||||
|
|
|
@ -11,6 +11,12 @@ module.exports = class TeachersView extends RootView
|
|||
'click .btn-login-account': 'onClickLogin'
|
||||
'click .link-register': 'onClickSignup'
|
||||
|
||||
constructor: ->
|
||||
super()
|
||||
unless me.isAnonymous()
|
||||
_.defer ->
|
||||
application.router.navigate "/courses/teachers", trigger: true
|
||||
|
||||
onClickLogin: (e) ->
|
||||
@openModalView new AuthModal(mode: 'login') if me.get('anonymous')
|
||||
|
||||
|
|
|
@ -50,10 +50,22 @@ module.exports = class ClassroomView extends RootView
|
|||
@supermodel.loadCollection(sessions, 'sessions')
|
||||
courseInstance.sessions = sessions
|
||||
sessions.courseInstance = courseInstance
|
||||
courseInstance.sessionsByUser = {}
|
||||
@listenToOnce sessions, 'sync', (sessions) ->
|
||||
@sessions.add(sessions.slice())
|
||||
sessions.courseInstance.sessionsByUser = sessions.groupBy('creator')
|
||||
|
||||
|
||||
# generate course instance JIT, in the meantime have models w/out equivalents in the db
|
||||
for course in @courses.models
|
||||
query = {courseID: course.id, classroomID: @classroom.id}
|
||||
courseInstance = @courseInstances.findWhere(query)
|
||||
if not courseInstance
|
||||
courseInstance = new CourseInstance(query)
|
||||
@courseInstances.add(courseInstance)
|
||||
courseInstance.sessions = new CocoCollection([], {model: LevelSession})
|
||||
sessions.courseInstance = courseInstance
|
||||
courseInstance.sessionsByUser = {}
|
||||
|
||||
onLoaded: ->
|
||||
userSessions = @sessions.groupBy('creator')
|
||||
for user in @users.models
|
||||
|
@ -105,11 +117,20 @@ module.exports = class ClassroomView extends RootView
|
|||
@openModalView(modal)
|
||||
|
||||
onClickEnableButton: (e) ->
|
||||
courseInstance = @courseInstances.get($(e.target).data('course-instance-id'))
|
||||
courseInstance = @courseInstances.get($(e.target).data('course-instance-cid'))
|
||||
userID = $(e.target).data('user-id')
|
||||
courseInstance.addMember(userID)
|
||||
$(e.target).attr('disabled', true)
|
||||
@listenToOnce courseInstance, 'sync', @render
|
||||
|
||||
onCourseInstanceCreated = =>
|
||||
courseInstance.addMember(userID)
|
||||
@listenToOnce courseInstance, 'sync', @render
|
||||
|
||||
if courseInstance.isNew()
|
||||
# adding the first student to this course, so generate the course instance for it
|
||||
courseInstance.save(null, {validate: false})
|
||||
courseInstance.once 'sync', onCourseInstanceCreated
|
||||
else
|
||||
onCourseInstanceCreated()
|
||||
|
||||
onClickRemoveStudentLink: (e) ->
|
||||
user = @users.get($(e.target).closest('a').data('user-id'))
|
||||
|
|
|
@ -7,7 +7,7 @@ module.exports = class InviteToClassroomModal extends ModalView
|
|||
|
||||
events:
|
||||
'click #send-invites-btn': 'onClickSendInvitesButton'
|
||||
'click #copy-url-btn': 'onClickCopyURLButton'
|
||||
'click #copy-url-btn, #join-url-input': 'copyURL'
|
||||
|
||||
initialize: (options) ->
|
||||
@classroom = options.classroom
|
||||
|
@ -34,7 +34,7 @@ module.exports = class InviteToClassroomModal extends ModalView
|
|||
@$('#invite-emails-success-alert').removeClass('hide')
|
||||
})
|
||||
|
||||
onClickCopyURLButton: ->
|
||||
copyURL: ->
|
||||
@$('#join-url-input').val(@joinURL).select()
|
||||
try
|
||||
document.execCommand('copy')
|
||||
|
|
|
@ -26,7 +26,7 @@ module.exports = class PurchaseCoursesView extends RootView
|
|||
getPrice: -> @pricePerStudent * @numberOfStudents
|
||||
|
||||
onInputStudentsInput: ->
|
||||
@numberOfStudents = parseInt(@$('#students-input').val()) or 0
|
||||
@numberOfStudents = Math.max(parseInt(@$('#students-input').val()) or 0, 0)
|
||||
@updatePrice()
|
||||
|
||||
updatePrice: ->
|
||||
|
@ -54,7 +54,6 @@ module.exports = class PurchaseCoursesView extends RootView
|
|||
onStripeReceivedToken: (e) ->
|
||||
@state = 'purchasing'
|
||||
@render?()
|
||||
console.log 'e', e
|
||||
|
||||
data =
|
||||
maxRedeemers: @numberOfStudents
|
||||
|
|
|
@ -60,7 +60,9 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
# TODO: how to get new classroom from modal?
|
||||
@classrooms.add(modal.classroom)
|
||||
# TODO: will this definitely fire after modal saves new classroom?
|
||||
@listenToOnce modal.classroom, 'sync', @render
|
||||
@listenToOnce modal.classroom, 'sync', ->
|
||||
@addFreeCourseInstances()
|
||||
@render()
|
||||
|
||||
onClickEditClassroomSmall: (e) ->
|
||||
classroomID = $(e.target).data('classroom-id')
|
||||
|
@ -68,3 +70,26 @@ module.exports = class TeacherCoursesView extends RootView
|
|||
modal = new ClassroomSettingsModal({classroom: classroom})
|
||||
@openModalView(modal)
|
||||
@listenToOnce modal, 'hide', @render
|
||||
|
||||
onLoaded: ->
|
||||
super()
|
||||
@addFreeCourseInstances()
|
||||
|
||||
addFreeCourseInstances: ->
|
||||
# so that when students join the classroom, they can automatically get free courses
|
||||
# non-free courses are generated when the teacher first adds a student to them
|
||||
for classroom in @classrooms.models
|
||||
for course in @courses.models
|
||||
continue if not course.get('free')
|
||||
courseInstance = @courseInstances.findWhere({classroomID: classroom.id, courseID: course.id})
|
||||
if not courseInstance
|
||||
courseInstance = new CourseInstance({
|
||||
classroomID: classroom.id
|
||||
courseID: course.id
|
||||
})
|
||||
# TODO: figure out a better way to get around triggering validation errors for properties
|
||||
# that the server will end up filling in, like an empty members array, ownerID
|
||||
courseInstance.save(null, {validate: false})
|
||||
@courseInstances.add(courseInstance)
|
||||
@listenToOnce courseInstance, 'sync', @addFreeCourseInstances
|
||||
return
|
|
@ -106,8 +106,7 @@ ClassroomHandler = class ClassroomHandler extends Handler
|
|||
address: email
|
||||
email_data:
|
||||
class_name: classroom.get('name')
|
||||
# TODO: join_link
|
||||
join_link: "https://codecombat.com/courses/students?_cc=" + (classroom.get('codeCamel') or classroom.get('code'))
|
||||
join_link: "https://codecombat.com/courses?_cc=" + (classroom.get('codeCamel') or classroom.get('code'))
|
||||
sendwithus.api.send context, _.noop
|
||||
return @sendSuccess(res, {})
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue