mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-24 21:13:35 -04:00
Update request demo Ux
Renaming request quote to request demo Changing create class wording to set up class Showing different UI if teacher or not Adding gameplay screenshots to homepage Update request demo email Closes #3449
This commit is contained in:
parent
ee331cc9c5
commit
bce9862be2
11 changed files with 195 additions and 45 deletions
app
assets/images/pages/home
core
locale
models
styles
templates
views
server
BIN
app/assets/images/pages/home/desert.png
Normal file
BIN
app/assets/images/pages/home/desert.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 108 KiB |
|
@ -133,6 +133,7 @@ module.exports = class CocoRouter extends Backbone.Router
|
|||
'teachers': go('NewHomeView')
|
||||
'teachers/freetrial': go('RequestQuoteView')
|
||||
'teachers/quote': go('RequestQuoteView')
|
||||
'teachers/demo': go('RequestQuoteView')
|
||||
|
||||
'test(/*subpath)': go('TestView')
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ module.exports = class Tracker extends CocoClass
|
|||
|
||||
for userTrait in ['email', 'anonymous', 'dateCreated', 'name', 'testGroupNumber', 'gender', 'lastLevel', 'siteref', 'ageRange', 'schoolName', 'coursePrepaidID', 'role']
|
||||
traits[userTrait] ?= me.get(userTrait)
|
||||
if @isTeacher()
|
||||
if me.isTeacher()
|
||||
traits.teacher = true
|
||||
|
||||
console.log 'Would identify', me.id, traits if debugAnalytics
|
||||
|
@ -90,7 +90,7 @@ module.exports = class Tracker extends CocoClass
|
|||
mixpanel.identify(me.id)
|
||||
mixpanel.register(traits)
|
||||
|
||||
if @isTeacher() and @segmentLoaded
|
||||
if me.isTeacher() and @segmentLoaded
|
||||
traits.createdAt = me.get 'dateCreated' # Intercom, at least, wants this
|
||||
analytics.identify me.id, traits
|
||||
|
||||
|
@ -109,7 +109,7 @@ module.exports = class Tracker extends CocoClass
|
|||
mixpanelIncludes = ['', 'courses', 'courses/purchase', 'courses/teachers', 'courses/students', 'schools', 'teachers', 'teachers/freetrial', 'teachers/quote', 'play', 'play/level/dungeons-of-kithgard']
|
||||
mixpanel.track('page viewed', 'page name' : name, url : url) if name in mixpanelIncludes
|
||||
|
||||
if @isTeacher() and @segmentLoaded
|
||||
if me.isTeacher() and @segmentLoaded
|
||||
options = {}
|
||||
if includeIntegrations?.length
|
||||
options.integrations = All: false
|
||||
|
@ -140,7 +140,7 @@ module.exports = class Tracker extends CocoClass
|
|||
# Only log explicit events for now
|
||||
mixpanel.track(action, properties) if 'Mixpanel' in includeIntegrations
|
||||
|
||||
if @isTeacher() and @segmentLoaded
|
||||
if me.isTeacher() and @segmentLoaded
|
||||
options = {}
|
||||
if includeIntegrations
|
||||
# https://segment.com/docs/libraries/analytics.js/#selecting-integrations
|
||||
|
@ -186,11 +186,8 @@ module.exports = class Tracker extends CocoClass
|
|||
return unless me and @isProduction and not me.isAdmin()
|
||||
ga? 'send', 'timing', category, variable, duration, label
|
||||
|
||||
isTeacher: ->
|
||||
return me.get('role') in ['teacher', 'technology coordinator', 'advisor', 'principal', 'superintendent']
|
||||
|
||||
updateRole: ->
|
||||
return unless @isTeacher()
|
||||
return unless me.isTeacher()
|
||||
return require('core/services/segment')() unless @segmentLoaded
|
||||
@identify()
|
||||
#analytics.page() # It looks like we don't want to call this here because it somehow already gets called once in addition to this.
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
im_a_student: "I'm a Student"
|
||||
learn_more: "Learn more"
|
||||
classroom_in_a_box: "A classroom in-a-box for teaching computer science."
|
||||
codecombat_is: "CodeCombat is a platform for students to learn computer science while playing through a real game."
|
||||
our_courses: "Our courses have been specifically playtested to excel in a classroom setting, even by teachers with little to no prior programming experience."
|
||||
codecombat_is: "CodeCombat is a platform <strong>for students</strong> to learn computer science while playing through a real game." # {change}
|
||||
our_courses: "Our courses have been specifically playtested to <strong>excel in the classroom</strong>, even by teachers with little to no prior programming experience." # {change}
|
||||
top_screenshots_hint: "Students write code and see their changes update in real-time"
|
||||
designed_with: "Designed with teachers in mind"
|
||||
real_code: "Real, typed code"
|
||||
from_the_first_level: "from the first level"
|
||||
|
@ -57,9 +58,15 @@
|
|||
great_game: "A great game is more than just badges and achievements - it’s about a player’s journey, well-designed puzzles, and the ability to tackle challenges with agency and confidence."
|
||||
agency: "CodeCombat is a game that gives players that agency and confidence with our robust typed code engine, which helps beginner and advanced students alike write proper, valid code."
|
||||
curious: "Curious? Request a demo and we'll show you the ropes"
|
||||
request_demo_title: "Get your students started today!"
|
||||
request_demo_subtitle: "Request a demo and get your students started in less than an hour."
|
||||
get_started_title: "Set up your class today"
|
||||
get_started_subtitle: "Set up a class, add your students, and monitor their progress as they learn computer science."
|
||||
create_class: "Or create a class and see it for yourself!"
|
||||
teacher_screenshots_hint: "Students write code and see their changes update in real-time"
|
||||
request_demo: "Request a Demo"
|
||||
create_a_class: "Create a Class"
|
||||
setup_a_class: "Set Up a Class"
|
||||
have_an_account: "Already have an account?"
|
||||
logged_in_as: "You are currently logged in as"
|
||||
view_my_classes: "View my classes"
|
||||
|
@ -702,9 +709,9 @@
|
|||
more_info_3: "is a good place to connect with fellow educators who are using CodeCombat."
|
||||
|
||||
teachers_quote:
|
||||
name: "Quote Form"
|
||||
title: "Request a Quote"
|
||||
subtitle: "Get CodeCombat in your classroom, club, school or district!"
|
||||
name: "Demo Form" # {change}
|
||||
title: "Request a Demo" # {change}
|
||||
subtitle: "Get your students started in less than an hour. You'll be able to <strong>create a class, add students, and monitor their progress</strong> as they learn computer science." # {change}
|
||||
email_exists: "User exists with this email."
|
||||
phone_number: "Phone number"
|
||||
phone_number_help: "Where can we reach you during the workday?"
|
||||
|
@ -728,10 +735,10 @@
|
|||
middle_school: "Middle School"
|
||||
college_plus: "College or higher"
|
||||
anything_else: "Anything else we should know?"
|
||||
thanks_header: "Thanks for requesting a quote!"
|
||||
thanks_header: "Thanks for requesting a demo!" # {change}
|
||||
thanks_p: "We'll be in touch soon. Questions? Email us:"
|
||||
thanks_anon: "Login or sign up with your account below to access your two free enrollments (we’ll notify you by email when they have been approved, which usually takes less than 48 hours). As always, the first hour of content is free for an unlimited number of students."
|
||||
thanks_logged_in: "Your two free enrollments are pending approval. We’ll notify you by email when they have been approved (usually within 48 hours). As always, the first hour of content is free for an unlimited number of students."
|
||||
thanks_anon: "Log in or create an account to set up a class, add your students, and monitor their progress as they learn computer science." # {change}
|
||||
thanks_logged_in: "Set up a class, add your students, and monitor their progress as they learn computer science." # {change}
|
||||
|
||||
versions:
|
||||
save_version_title: "Save New Version"
|
||||
|
|
|
@ -59,6 +59,9 @@ module.exports = class User extends CocoModel
|
|||
|
||||
isEmailSubscriptionEnabled: (name) -> (@get('emails') or {})[name]?.enabled
|
||||
|
||||
isTeacher: ->
|
||||
return @get('role') in ['teacher', 'technology coordinator', 'advisor', 'principal', 'superintendent']
|
||||
|
||||
setRole: (role, force=false) ->
|
||||
return if me.isAdmin()
|
||||
oldRole = @get 'role'
|
||||
|
|
|
@ -72,7 +72,41 @@
|
|||
|
||||
#classroom-in-box-row
|
||||
margin: 40px 0
|
||||
|
||||
|
||||
.top-screenshots
|
||||
margin-bottom: 100px
|
||||
margin-top: 50px
|
||||
.label
|
||||
color: black
|
||||
display: block
|
||||
.screenshots
|
||||
text-align: center
|
||||
.screenshot-grid
|
||||
img
|
||||
display: inline-block
|
||||
margin: 6.5px
|
||||
width: 800px
|
||||
border-radius: 8px
|
||||
|
||||
.teacher-screenshots
|
||||
padding: 10px
|
||||
.label
|
||||
color: black
|
||||
display: block
|
||||
.screenshots
|
||||
text-align: center
|
||||
.screenshot-grid
|
||||
img
|
||||
display: inline-block
|
||||
margin: 6.5px
|
||||
width: 300px
|
||||
border-radius: 4px
|
||||
|
||||
#screenshot-lightbox
|
||||
.modal-dialog
|
||||
width: auto
|
||||
max-width: 1024px
|
||||
|
||||
#feature-spread-row
|
||||
.col-sm-4
|
||||
padding: 40px
|
||||
|
@ -177,6 +211,9 @@
|
|||
left: 100%
|
||||
top: 0
|
||||
|
||||
.have-an-account
|
||||
font-size: 10pt
|
||||
|
||||
#school-level-label
|
||||
margin: 15px 15px 0 0
|
||||
display: inline-block
|
||||
|
|
|
@ -44,8 +44,18 @@ block content
|
|||
.col-sm-6
|
||||
h2.text-navy(data-i18n="new_home.classroom_in_a_box")
|
||||
.col-sm-6
|
||||
p(data-i18n="new_home.codecombat_is")
|
||||
p(data-i18n="new_home.our_courses")
|
||||
p(data-i18n="[html]new_home.codecombat_is")
|
||||
p(data-i18n="[html]new_home.our_courses")
|
||||
|
||||
.top-screenshots
|
||||
.screenshots
|
||||
.hidden-sm.hidden-md.hidden-lg
|
||||
small(data-i18n="new_home.top_screenshots_hint")
|
||||
.screenshot-grid(title='Click to view full size')
|
||||
a.screen-thumbnail(data-toggle="modal", data-target="#screenshot-lightbox", data-index='0')
|
||||
img(src="/images/pages/home/desert.png")
|
||||
.clearfix.hidden-xs
|
||||
small(data-i18n="new_home.top_screenshots_hint")
|
||||
|
||||
#feature-spread-row.row.text-center
|
||||
h3(data-i18n="new_home.designed_with")
|
||||
|
@ -148,24 +158,37 @@ block content
|
|||
p
|
||||
span(data-i18n="new_home.agency")
|
||||
|
||||
|
||||
.request-demo-row.text-center
|
||||
h3(data-i18n="new_home.curious")
|
||||
h4(data-i18n="new_home.create_class")
|
||||
div
|
||||
a.btn.btn-primary.btn-lg(href="/teachers/freetrial", data-i18n="new_home.request_demo")
|
||||
a.btn.btn-primary-alt.btn-lg(href="/courses/teachers", data-i18n="new_home.create_a_class")
|
||||
div
|
||||
if me.isAnonymous()
|
||||
if me.isTeacher()
|
||||
h3(data-i18n="new_home.get_started_title")
|
||||
else
|
||||
h3(data-i18n="new_home.request_demo_title")
|
||||
|
||||
.teacher-screenshots
|
||||
.screenshots
|
||||
.hidden-sm.hidden-md.hidden-lg
|
||||
small(data-i18n="new_home.teacher_screenshots_hint")
|
||||
.screenshot-grid(title='Click to view full size')
|
||||
a.screen-thumbnail(data-toggle="modal", data-target="#screenshot-lightbox", data-index='1')
|
||||
img(src="/images/pages/about/forest.png")
|
||||
a.screen-thumbnail(data-toggle="modal", data-target="#screenshot-lightbox", data-index='2')
|
||||
img(src="/images/pages/about/dungeon.png")
|
||||
a.screen-thumbnail(data-toggle="modal", data-target="#screenshot-lightbox", data-index='3')
|
||||
img(src="/images/pages/about/glacier.png")
|
||||
.clearfix.hidden-xs
|
||||
small(data-i18n="new_home.teacher_screenshots_hint")
|
||||
|
||||
if me.isTeacher()
|
||||
h4(data-i18n="new_home.get_started_subtitle")
|
||||
div
|
||||
a.btn.btn-primary.btn-lg(href="/courses/teachers", data-i18n="new_home.setup_a_class")
|
||||
else
|
||||
h4(data-i18n="new_home.request_demo_subtitle")
|
||||
div
|
||||
a.btn.btn-primary.btn-lg(href="/teachers/demo", data-i18n="new_home.request_demo")
|
||||
.have-an-account
|
||||
span.spr(data-i18n="new_home.have_an_account")
|
||||
a.login-button Login
|
||||
else
|
||||
span.spr(data-i18n="new_home.logged_in_as")
|
||||
span= me.broadName()
|
||||
span.spr .
|
||||
a(href="/courses/teachers", data-i18n="new_home.view_my_classes")
|
||||
span.spr.spl(data-i18n="general.or")
|
||||
a#logout-button logout
|
||||
|
||||
h3.text-center(data-i18n="new_home.computer_science")
|
||||
h4.text-center
|
||||
|
@ -246,9 +269,41 @@ block content
|
|||
h6 PC Mag
|
||||
.small pcmag.com
|
||||
|
||||
|
||||
.request-demo-row.text-center
|
||||
h3(data-i18n="new_home.run_class")
|
||||
p
|
||||
a.btn.btn-primary.btn-lg(href="/teachers/freetrial", data-i18n="new_home.request_demo")
|
||||
a.btn.btn-primary-alt.btn-lg(href="/courses/teachers", data-i18n="new_home.create_a_class")
|
||||
if me.isTeacher()
|
||||
div
|
||||
a.btn.btn-primary.btn-lg(href="/courses/teachers", data-i18n="new_home.setup_a_class")
|
||||
else
|
||||
div
|
||||
a.btn.btn-primary.btn-lg(href="/teachers/demo", data-i18n="new_home.request_demo")
|
||||
.have-an-account
|
||||
span.spr(data-i18n="new_home.have_an_account")
|
||||
a.login-button Login
|
||||
|
||||
|
||||
#screenshot-lightbox.modal.fade(data-show="false")
|
||||
.modal-dialog
|
||||
.modal-content
|
||||
#screenshot-carousel.carousel
|
||||
ol.carousel-indicators
|
||||
li(data-target=".screenshot-display", data-slide-to="0").active
|
||||
li(data-target=".screenshot-display", data-slide-to="1")
|
||||
li(data-target=".screenshot-display", data-slide-to="2")
|
||||
li(data-target=".screenshot-display", data-slide-to="3")
|
||||
|
||||
.carousel-inner
|
||||
.item.active
|
||||
img#screenshot-desert(src="/images/pages/home/desert.png")
|
||||
.item
|
||||
img#screenshot-forest(src="/images/pages/about/forest.png")
|
||||
.item
|
||||
img#screenshot-dungeon(src="/images/pages/about/dungeon.png")
|
||||
.item
|
||||
img#screenshot-glacier(src="/images/pages/about/glacier.png")
|
||||
a#carousel-left.left.carousel-control(href="#screenshot-carousel", role="button")
|
||||
span.glyphicon.glyphicons-chevron-left.glyphicon-chevron-left(aria-hidden="true")
|
||||
span.sr-only(data-i18n="about.previous")
|
||||
a#carousel-right.right.carousel-control(href="#screenshot-carousel", role="button")
|
||||
span.glyphicon.glyphicons-chevron-right.glyphicon-chevron-right(aria-hidden="true")
|
||||
span.sr-only(data-i18n="about.next")
|
||||
|
|
|
@ -4,7 +4,7 @@ block content
|
|||
.container
|
||||
form.form(class=view.trialRequest.isNew() ? '' : 'hide')
|
||||
h3.text-center(data-i18n="teachers_quote.title")
|
||||
h4.text-center(data-i18n="teachers_quote.subtitle")
|
||||
h4.text-center(data-i18n="[html]teachers_quote.subtitle")
|
||||
|
||||
#form-teacher-info.section
|
||||
.row
|
||||
|
@ -133,7 +133,7 @@ block content
|
|||
textarea.form-control(rows=8, name="notes")
|
||||
|
||||
#buttons-row.row.text-center
|
||||
input#submit-request-btn.btn.btn-lg.btn-primary(type="submit" data-i18n="[value]common.send")
|
||||
input#submit-request-btn.btn.btn-lg.btn-primary(type="submit" data-i18n="[value]teachers_quote.title")
|
||||
|
||||
|
||||
#form-submit-success.text-center(class=view.trialRequest.isNew() ? 'hide' : '')
|
||||
|
@ -149,4 +149,6 @@ block content
|
|||
button#login-btn.btn.btn-info(data-i18n="login.log_in")
|
||||
button#signup-btn.btn.btn-info(data-i18n="login.sign_up")
|
||||
else
|
||||
p.text-center(data-i18n="teachers_quote.thanks_logged_in")
|
||||
p.text-center(data-i18n="teachers_quote.thanks_logged_in")
|
||||
div
|
||||
a.btn.btn-primary.btn-lg(href="/courses/teachers", data-i18n="teachers_quote.setup_a_class")
|
||||
|
|
|
@ -16,6 +16,14 @@ module.exports = class NewHomeView extends RootView
|
|||
'change #school-level-dropdown': 'onChangeSchoolLevelDropdown'
|
||||
'click #teacher-btn': 'onClickTeacherButton'
|
||||
'click #learn-more-link': 'onClickLearnMoreLink'
|
||||
'click .screen-thumbnail': 'onClickScreenThumbnail'
|
||||
'click #carousel-left': 'onLeftPressed'
|
||||
'click #carousel-right': 'onRightPressed'
|
||||
|
||||
shortcuts:
|
||||
'right': 'onRightPressed'
|
||||
'left': 'onLeftPressed'
|
||||
'esc': 'onEscapePressed'
|
||||
|
||||
initialize: (options) ->
|
||||
@jumbotron = options.jumbotron or utils.getQueryVariable('jumbotron') or 'student'
|
||||
|
@ -47,6 +55,11 @@ module.exports = class NewHomeView extends RootView
|
|||
|
||||
afterRender: ->
|
||||
@onChangeSchoolLevelDropdown()
|
||||
@$('#screenshot-lightbox').modal()
|
||||
@$('#screenshot-carousel').carousel({
|
||||
interval: 0
|
||||
keyboard: false
|
||||
})
|
||||
super()
|
||||
|
||||
onChangeSchoolLevelDropdown: (e) ->
|
||||
|
@ -75,5 +88,26 @@ module.exports = class NewHomeView extends RootView
|
|||
onClickTeacherButton: ->
|
||||
@scrollToLink('.request-demo-row', 600)
|
||||
|
||||
onRightPressed: (event) ->
|
||||
# Special handling, otherwise after you click the control, keyboard presses move the slide twice
|
||||
return if event.type is 'keydown' and $(document.activeElement).is('.carousel-control')
|
||||
if $('#screenshot-lightbox').data('bs.modal')?.isShown
|
||||
event.preventDefault()
|
||||
$('#screenshot-carousel').carousel('next')
|
||||
|
||||
|
||||
onLeftPressed: (event) ->
|
||||
return if event.type is 'keydown' and $(document.activeElement).is('.carousel-control')
|
||||
if $('#screenshot-lightbox').data('bs.modal')?.isShown
|
||||
event.preventDefault()
|
||||
$('#screenshot-carousel').carousel('prev')
|
||||
|
||||
onEscapePressed: (event) ->
|
||||
if $('#screenshot-lightbox').data('bs.modal')?.isShown
|
||||
event.preventDefault()
|
||||
$('#screenshot-lightbox').modal('hide')
|
||||
|
||||
onClickScreenThumbnail: (event) ->
|
||||
unless $('#screenshot-lightbox').data('bs.modal')?.isShown
|
||||
event.preventDefault()
|
||||
# Modal opening happens automatically from bootstrap
|
||||
$('#screenshot-carousel').carousel($(event.currentTarget).data("index"))
|
||||
|
|
|
@ -24,3 +24,4 @@ module.exports.templates =
|
|||
course_invite_email: 'tem_u6D2EFWYC5Ptk38bSykjsU'
|
||||
teacher_free_trial: 'tem_R7d9Hpoba9SceQNiYSXBak'
|
||||
teacher_free_trial_hoc: 'tem_4ZSY9wsA9Qwn4wBFmZgPdc'
|
||||
teacher_request_demo: 'tem_cwG3HZjEyb6QE493hZuUra'
|
||||
|
|
|
@ -6,6 +6,7 @@ hipchat = require '../hipchat'
|
|||
sendwithus = require '../sendwithus'
|
||||
Prepaid = require '../prepaids/Prepaid'
|
||||
jsonSchema = require '../../app/schemas/models/trial_request.schema'
|
||||
Classroom = require '../classrooms/Classroom'
|
||||
User = require '../users/User'
|
||||
|
||||
TrialRequestSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}
|
||||
|
@ -41,9 +42,21 @@ TrialRequestSchema.post 'save', (doc) ->
|
|||
emailParams =
|
||||
recipient:
|
||||
address: email
|
||||
email_id: sendwithus.templates.teacher_free_trial
|
||||
sendwithus.api.send emailParams, (err, result) =>
|
||||
log.error "sendwithus trial request approved error: #{err}, result: #{result}" if err
|
||||
email_id: sendwithus.templates.teacher_request_demo
|
||||
email_data:
|
||||
account_exists: user?.get('anonymous') is false
|
||||
classes_exist: false
|
||||
if user?.get('anonymous') is false
|
||||
Classroom.findOne {ownerID: user.get('_id')}, (err, classroom) =>
|
||||
if err
|
||||
log.error "Trial request classroom find error: #{err}"
|
||||
return
|
||||
emailParams.email_data.classes_exist = classroom?
|
||||
sendwithus.api.send emailParams, (err, result) =>
|
||||
log.error "sendwithus trial request approved error: #{err}, result: #{result}" if err
|
||||
else
|
||||
sendwithus.api.send emailParams, (err, result) =>
|
||||
log.error "sendwithus trial request approved error: #{err}, result: #{result}" if err
|
||||
|
||||
closeIO.createSalesLead(user, email,
|
||||
name: trialProperties.name
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue