mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-14 05:55:00 -04:00
Share progress modal
Shown after forgetful-gemsmith
This commit is contained in:
parent
e311eb2700
commit
972c3d0d6f
9 changed files with 232 additions and 13 deletions
app
assets/images/pages/play/modal
locale
styles/play/modal
templates/play/modal
views/play
server
BIN
app/assets/images/pages/play/modal/parental_nudge_wizard.png
Normal file
BIN
app/assets/images/pages/play/modal/parental_nudge_wizard.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 214 KiB |
Binary file not shown.
After ![]() (image error) Size: 41 KiB |
|
@ -94,6 +94,16 @@
|
|||
campaign_classic_algorithms: "Classic Algorithms"
|
||||
campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
|
||||
|
||||
share_progress_modal:
|
||||
blurb: "You’re making great progress! Tell someone how much you've learned with CodeCombat."
|
||||
email_invalid: "Email address invalid."
|
||||
form_blurb: "Enter their email below and we’ll show them!"
|
||||
form_label: "Email Address"
|
||||
placeholder: "email address"
|
||||
title: "Excellent Work, Apprentice"
|
||||
tell_friend: "Tell your Friend"
|
||||
tell_parent: "Tell your Parent"
|
||||
|
||||
login:
|
||||
sign_up: "Create Account"
|
||||
log_in: "Log In"
|
||||
|
@ -131,6 +141,8 @@
|
|||
books: "Books"
|
||||
|
||||
common:
|
||||
back: "Back" # When used as an action verb, like "Navigate backward"
|
||||
continue: "Continue" # When used as an action verb, like "Continue forward"
|
||||
loading: "Loading..."
|
||||
saving: "Saving..."
|
||||
sending: "Sending..."
|
||||
|
|
97
app/styles/play/modal/share-progress-modal.sass
Normal file
97
app/styles/play/modal/share-progress-modal.sass
Normal file
|
@ -0,0 +1,97 @@
|
|||
@import "app/styles/mixins"
|
||||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
#share-progress-modal
|
||||
|
||||
.modal-dialog
|
||||
margin: 60px auto 0 auto
|
||||
padding: 0
|
||||
height: 460px
|
||||
width: 700px
|
||||
background: none
|
||||
|
||||
.modal-content
|
||||
height: 100%
|
||||
width: 100%
|
||||
|
||||
.background-img
|
||||
position: absolute
|
||||
top: -61px
|
||||
left: 0px
|
||||
height: 100%
|
||||
width: 100%
|
||||
|
||||
.wizard-img
|
||||
position: absolute
|
||||
top: 70px
|
||||
left: 32px
|
||||
height: 301px
|
||||
|
||||
.blurb-container
|
||||
position: absolute
|
||||
right: 50px
|
||||
top: 70px
|
||||
margin: 0
|
||||
width: 300px
|
||||
|
||||
h1
|
||||
font-size: 29px
|
||||
font-weight: bold
|
||||
color: black
|
||||
|
||||
p.parent-blurb, p.friend-blurb
|
||||
line-height: 16px
|
||||
display: none
|
||||
|
||||
.tell-parent-btn, .tell-friend-btn
|
||||
margin: 10px
|
||||
border-image: url(/images/level/code_toolbar_submit_button_active.png) 14 20 20 20 fill round
|
||||
color: white
|
||||
// width: 80px
|
||||
font-size: 28px
|
||||
line-height: 28px
|
||||
text-transform: none
|
||||
font-variant: small-caps
|
||||
font-family: "Open Sans Condensed", "Helvetica Neue", Helvetica, Arial, sans-serif
|
||||
|
||||
.send-container
|
||||
margin-top: 10px
|
||||
display: none
|
||||
.email-form
|
||||
.email-input
|
||||
width: 200px
|
||||
|
||||
button
|
||||
color: white
|
||||
width: 80px
|
||||
font-size: 28px
|
||||
line-height: 28px
|
||||
text-transform: none
|
||||
font-variant: small-caps
|
||||
font-family: "Open Sans Condensed", "Helvetica Neue", Helvetica, Arial, sans-serif
|
||||
button.back-btn
|
||||
border-image: url(/images/common/button-background-primary-disabled.png) 14 20 20 20 fill round
|
||||
button.send-btn
|
||||
border-image: url(/images/level/code_toolbar_submit_button_active.png) 14 20 20 20 fill round
|
||||
|
||||
.continue-container
|
||||
margin-top: 10px
|
||||
margin-right: -12px
|
||||
.back-link, .continue-link
|
||||
color: black
|
||||
font-weight: normal
|
||||
font-size: 11px
|
||||
text-decoration: underline
|
||||
|
||||
.email-invalid
|
||||
color: red
|
||||
display: none
|
||||
|
||||
//- Errors
|
||||
|
||||
.alert
|
||||
position: absolute
|
||||
left: 10%
|
||||
width: 80%
|
||||
top: 20px
|
||||
border: 5px solid gray
|
36
app/templates/play/modal/share-progress-modal.jade
Normal file
36
app/templates/play/modal/share-progress-modal.jade
Normal file
|
@ -0,0 +1,36 @@
|
|||
.modal-dialog
|
||||
.modal-content
|
||||
img.background-img(src="/images/pages/play/modal/parental_prompt_modal_background.png")
|
||||
img.wizard-img(src="/images/pages/play/modal/parental_nudge_wizard.png")
|
||||
|
||||
.blurb-container
|
||||
h1(data-i18n="play.share_progress_modal.title")
|
||||
p(data-i18n="play.share_progress_modal.blurb")
|
||||
.container-fluid.btn-picker-container
|
||||
.row
|
||||
.col-xs-12.text-center
|
||||
button.btn.btn-illustrated.tell-parent-btn(data-i18n="play.share_progress_modal.tell_parent")
|
||||
.row
|
||||
.col-xs-12.text-center
|
||||
button.btn.btn-illustrated.tell-friend-btn(data-i18n="play.share_progress_modal.tell_friend")
|
||||
.row.continue-container
|
||||
.col-xs-12.text-right
|
||||
a.continue-link(data-i18n="common.continue")
|
||||
|
||||
.container-fluid.send-container
|
||||
.row
|
||||
.col-xs-12.email-form
|
||||
p(data-i18n="play.share_progress_modal.form_blurb")
|
||||
div
|
||||
label(data-i18n="play.share_progress_modal.form_label")
|
||||
input.form-control.email-input(type='email' data-i18n="[placeholder]play.share_progress_modal.placeholder")
|
||||
.row
|
||||
.col-xs-8
|
||||
.email-invalid(data-i18n="play.share_progress_modal.email_invalid")
|
||||
.col-xs-4.text-right
|
||||
button.btn.btn-illustrated.send-btn(data-i18n="common.send")
|
||||
.row.continue-container
|
||||
.col-xs-6
|
||||
a.back-link(data-i18n="common.back")
|
||||
.col-xs-6.text-right
|
||||
a.continue-link(data-i18n="common.continue")
|
|
@ -16,6 +16,7 @@ Level = require 'models/Level'
|
|||
utils = require 'core/utils'
|
||||
require 'vendor/three'
|
||||
ParticleMan = require 'core/ParticleMan'
|
||||
ShareProgressModal = require 'views/play/modal/ShareProgressModal'
|
||||
|
||||
trackedHourOfCode = false
|
||||
|
||||
|
@ -142,6 +143,8 @@ module.exports = class CampaignView extends RootView
|
|||
@render()
|
||||
@preloadTopHeroes() unless me.get('heroConfig')?.thangType
|
||||
@$el.find('#campaign-status').delay(4000).animate({top: "-=58"}, 1000) unless @terrain is 'dungeon'
|
||||
@openModalView new ShareProgressModal() if @terrain and me.get('lastLevel') is 'forgetful-gemsmith'
|
||||
|
||||
|
||||
setCampaign: (@campaign) ->
|
||||
@render()
|
||||
|
|
53
app/views/play/modal/ShareProgressModal.coffee
Normal file
53
app/views/play/modal/ShareProgressModal.coffee
Normal file
|
@ -0,0 +1,53 @@
|
|||
ModalView = require 'views/core/ModalView'
|
||||
template = require 'templates/play/modal/share-progress-modal'
|
||||
|
||||
module.exports = class SubscribeModal extends ModalView
|
||||
id: 'share-progress-modal'
|
||||
template: template
|
||||
plain: true
|
||||
closesOnClickOutside: false
|
||||
|
||||
events:
|
||||
'click .back-link': 'onBackClick'
|
||||
'click .close-btn': 'hide'
|
||||
'click .continue-link': 'hide'
|
||||
'click .send-btn': 'onClickSend'
|
||||
'click .tell-friend-btn': 'onClickTellFriend'
|
||||
'click .tell-parent-btn': 'onClickTellParent'
|
||||
|
||||
onBackClick: (e) ->
|
||||
$('.email-input').val('')
|
||||
$('.send-container').hide()
|
||||
$('.friend-blurb').hide()
|
||||
$('.parent-blurb').hide()
|
||||
$('.btn-picker-container').show()
|
||||
$('.email-input').parent().removeClass('has-error')
|
||||
$('.email-invalid').hide()
|
||||
|
||||
onClickTellFriend: (e) ->
|
||||
@emailType = 'share progress modal friend'
|
||||
$('.btn-picker-container').hide()
|
||||
$('.friend-blurb').show()
|
||||
$('.send-container').show()
|
||||
|
||||
onClickTellParent: (e) ->
|
||||
@emailType = 'share progress modal parent'
|
||||
$('.btn-picker-container').hide()
|
||||
$('.parent-blurb').show()
|
||||
$('.send-container').show()
|
||||
|
||||
onClickSend: (e) ->
|
||||
email = $('.email-input').val()
|
||||
unless /[\w\.]+@\w+\.\w+/.test email
|
||||
$('.email-input').parent().addClass('has-error')
|
||||
$('.email-invalid').show()
|
||||
return false
|
||||
|
||||
request = @supermodel.addRequestResource 'send_one_time_email', {
|
||||
url: '/db/user/-/send_one_time_email'
|
||||
data: {email: email, type: @emailType}
|
||||
method: 'POST'
|
||||
}, 0
|
||||
request.load()
|
||||
|
||||
@hide()
|
|
@ -11,6 +11,7 @@ if config.unittest
|
|||
module.exports.api.send = ->
|
||||
module.exports.templates =
|
||||
parent_subscribe_email: 'tem_2APERafogvwKhmcnouigud'
|
||||
share_progress_email: 'tem_VHE3ihhGmVa3727qds9zY8'
|
||||
welcome_email: 'utnGaBHuSU4Hmsi7qrAypU'
|
||||
ladder_update_email: 'JzaZxf39A4cKMxpPZUfWy4'
|
||||
patch_created: 'tem_xhxuNosLALsizTNojBjNcL'
|
||||
|
|
|
@ -248,17 +248,33 @@ UserHandler = class UserHandler extends Handler
|
|||
@sendSuccess(res, JSON.stringify(customer, null, '\t'))
|
||||
|
||||
sendOneTimeEmail: (req, res) ->
|
||||
# TODO: should this API be somewhere else?
|
||||
# TODO: Should this API be somewhere else?
|
||||
# TODO: Where should email types be stored?
|
||||
# TODO: How do we schema validate an update db call?
|
||||
|
||||
return @sendForbiddenError(res) unless req.user
|
||||
email = req.query.email or req.body.email
|
||||
type = req.query.type or req.body.type
|
||||
return @sendBadInputError res, 'No email given.' unless email?
|
||||
return @sendBadInputError res, 'No type given.' unless type?
|
||||
|
||||
return @sendBadInputError res, "Unknown one-time email type #{type}" unless type is 'subscribe modal parent'
|
||||
# log.warn "sendOneTimeEmail #{type} #{email}"
|
||||
|
||||
unless type in ['subscribe modal parent', 'share progress modal parent', 'share progress modal friend']
|
||||
return @sendBadInputError res, "Unknown one-time email type #{type}"
|
||||
|
||||
sendMail = (emailParams) =>
|
||||
sendwithus.api.send emailParams, (err, result) =>
|
||||
if err
|
||||
log.error "sendwithus one-time email error: #{err}, result: #{result}"
|
||||
return @sendError res, 500, 'send mail failed.'
|
||||
req.user.update {$push: {"emails.oneTimes": {type: type, email: email, sent: new Date()}}}, (err) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
@sendSuccess(res, {result: 'success'})
|
||||
AnalyticsLogEvent.logEvent req.user, 'Sent one time email', email: email, type: type
|
||||
|
||||
# Generic email data
|
||||
emailParams =
|
||||
email_id: sendwithus.templates.parent_subscribe_email
|
||||
recipient:
|
||||
address: email
|
||||
email_data:
|
||||
|
@ -266,16 +282,17 @@ UserHandler = class UserHandler extends Handler
|
|||
if codeLanguage = req.user.get('aceConfig.language')
|
||||
codeLanguage = codeLanguage[0].toUpperCase() + codeLanguage.slice(1)
|
||||
emailParams['email_data']['codeLanguage'] = codeLanguage
|
||||
sendwithus.api.send emailParams, (err, result) =>
|
||||
if err
|
||||
log.error "sendwithus one-time email error: #{err}, result: #{result}"
|
||||
return @sendError res, 500, 'send mail failed.'
|
||||
req.user.update {$push: {"emails.oneTimes": {type: type, email: email, sent: new Date()}}}, (err) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
req.user.save (err) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
@sendSuccess(res, {result: 'success'})
|
||||
AnalyticsLogEvent.logEvent req.user, 'Sent one time email', email: email, type: type
|
||||
|
||||
# Type-specific email data
|
||||
if type is 'subscribe modal parent'
|
||||
emailParams['email_id'] = sendwithus.templates.parent_subscribe_email
|
||||
else if type in ['share progress modal parent', 'share progress modal friend']
|
||||
emailParams['email_id'] = sendwithus.templates.share_progress_email
|
||||
emailParams['email_data']['premium'] = req.user.isPremium()
|
||||
emailParams['email_data']['parent'] = type is 'share progress modal parent'
|
||||
emailParams['email_data']['friend'] = type is 'share progress modal friend'
|
||||
|
||||
sendMail emailParams
|
||||
|
||||
agreeToCLA: (req, res) ->
|
||||
return @sendForbiddenError(res) unless req.user
|
||||
|
|
Loading…
Add table
Reference in a new issue