Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-06-13 16:04:53 -07:00
commit 9eb495650f
11 changed files with 128 additions and 69 deletions

View file

@ -4,6 +4,7 @@ block content
h1(data-i18n="employers.want_to_hire_our_players") Hire CodeCombat Players h1(data-i18n="employers.want_to_hire_our_players") Hire CodeCombat Players
if !isEmployer && !me.isAdmin()
div#info_wrapper div#info_wrapper
div#leftside div#leftside
@ -49,7 +50,6 @@ block content
strong(data-i18n="employers.why_blurb_6") personally screened by us strong(data-i18n="employers.why_blurb_6") personally screened by us
span(data-i18n="employers.why_blurb_7") . Stop screening and start hiring. span(data-i18n="employers.why_blurb_7") . Stop screening and start hiring.
if !isEmployer && !me.isAdmin()
h3.see-candidates-header h3.see-candidates-header
a#see-candidates(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/employer_signup", data-i18n="employers.see_candidates") Click here to see our candidates a#see-candidates(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/employer_signup", data-i18n="employers.see_candidates") Click here to see our candidates
@ -106,7 +106,7 @@ block content
td= profile.lookingFor td= profile.lookingFor
td= profile.jobTitle td= profile.jobTitle
td td
each skill in profile.skills.slice(0, 10) each skill in profile.skills
code= skill code= skill
span span
td= profile.experience td= profile.experience

View file

@ -10,16 +10,31 @@ block modal-body-content
if userIsAnonymous if userIsAnonymous
if userIsAuthorized if userIsAuthorized
| You appear to be authorized on CodeCombat with LinkedIn. | You appear to be authorized on CodeCombat with LinkedIn.
else if sentMoreInfoEmail
| Thanks! You should receive an email from George shortly.
else else
h4(data-i18n="employer_signup.sub_heading") Let us find your next brilliant developers. h4(data-i18n="employer_signup.sub_heading") Let us find your next brilliant developers.
p Create an account to get started! p Create an account to get started!
.form .form#signup-form
.form-group .form-group
label.control-label(for="signup-email", data-i18n="general.email") Email label.control-label(for="signup-email", data-i18n="general.email") Email
input#signup-email.form-control.input-large(name="email",type="email") input#signup-email.form-control.input-large(name="email",type="email")
.form-group .form-group
label.control-label(for="signup-password", data-i18n="general.password") Password label.control-label(for="signup-password", data-i18n="general.password") Password
input#signup-password.input-large.form-control(name="password", type="password") input#signup-password.input-large.form-control(name="password", type="password")
.modal-footer.linkedin
button.btn.btn-primary(id="create-account-button") Create Account
br
br
| Already have a CodeCombat account?
a.login-link(data-toggle="coco-modal", data-target="modal/auth") Log in to continue!
h4 Want more information first?
p Enter your email and George, our CEO, will contact you shortly.
.form
.form-group
label.control-label(for="more-info-email", data-i18n="general.email") Email
input#more-info-email.form-control.input-large(name="more-info-email",type="email")
button.btn.btn-primary(id="more-info-button") Send me more information!
else if !userIsAuthorized else if !userIsAuthorized
.modal-footer.linkedin .modal-footer.linkedin
p Please sign into your LinkedIn account to verify your identity. p Please sign into your LinkedIn account to verify your identity.
@ -44,14 +59,7 @@ block modal-body-content
| By clicking Agree, you are agreeing to CodeCombat's Placement Agreement on behalf of your company. You also consent to CodeCombat storing basic LinkedIn profile data for verification purposes, including your name, email, public profile URL, and work history. | By clicking Agree, you are agreeing to CodeCombat's Placement Agreement on behalf of your company. You also consent to CodeCombat storing basic LinkedIn profile data for verification purposes, including your name, email, public profile URL, and work history.
block modal-footer block modal-footer
if userIsAnonymous if userIsAnonymous
if !userIsAuthorized if userIsAuthorized
.modal-footer.linkedin
button.btn.btn-primary(id="create-account-button") Create Account
br
br
| Already have a CodeCombat account?
a.login-link(data-toggle="coco-modal", data-target="modal/auth") Log in to continue!
else
.modal-footer.linkedin .modal-footer.linkedin
a.login-link(data-toggle="coco-modal", data-target="modal/auth") Please log in to continue. a.login-link(data-toggle="coco-modal", data-target="modal/auth") Please log in to continue.
else if !userIsAnonymous && !userIsAuthorized else if !userIsAnonymous && !userIsAuthorized

View file

@ -253,7 +253,7 @@ class LatestVersionCollection extends CocoCollection
class LatestVersionReferenceNode extends TreemaNode class LatestVersionReferenceNode extends TreemaNode
searchValueTemplate: '<input placeholder="Search" /><div class="treema-search-results"></div>' searchValueTemplate: '<input placeholder="Search" /><div class="treema-search-results"></div>'
valueClass: 'treema-latest-version' valueClass: 'treema-latest-version'
url: '/db/article/search' url: '/db/article'
lastTerm: null lastTerm: null
constructor: -> constructor: ->
@ -264,7 +264,7 @@ class LatestVersionReferenceNode extends TreemaNode
link = (l for l in links when l.rel is 'db')[0] link = (l for l in links when l.rel is 'db')[0]
return unless link return unless link
parts = (p for p in link.href.split('/') when p.length) parts = (p for p in link.href.split('/') when p.length)
@url = "/db/#{parts[1]}/search" @url = "/db/#{parts[1]}"
@model = require('models/' + _.string.classify(parts[1])) @model = require('models/' + _.string.classify(parts[1]))
buildValueForDisplay: (valEl) -> buildValueForDisplay: (valEl) ->

View file

@ -301,7 +301,7 @@ module.exports = class ProfileView extends View
null null
onContactCandidate: (e) -> onContactCandidate: (e) ->
@openModalView new JobProfileContactView recipientID: @user.id @openModalView new JobProfileContactView recipientID: @user.id, recipientUserName: @user.get('name')
showErrors: (errors) -> showErrors: (errors) ->
section = @$el.find '.saving' section = @$el.find '.saving'

View file

@ -4,6 +4,7 @@ CocoClass = require 'lib/CocoClass'
loadingScreenTemplate = require 'templates/loading' loadingScreenTemplate = require 'templates/loading'
loadingErrorTemplate = require 'templates/loading_error' loadingErrorTemplate = require 'templates/loading_error'
lastToggleModalCall = 0
visibleModal = null visibleModal = null
waitingModal = null waitingModal = null
classCount = 0 classCount = 0
@ -15,9 +16,6 @@ module.exports = class CocoView extends Backbone.View
template: -> '' template: -> ''
events: events:
'click a': 'toggleModal'
'click button': 'toggleModal'
'click li': 'toggleModal'
'click .retry-loading-resource': 'onRetryResource' 'click .retry-loading-resource': 'onRetryResource'
'click .retry-loading-request': 'onRetryRequest' 'click .retry-loading-request': 'onRetryRequest'
@ -46,7 +44,6 @@ module.exports = class CocoView extends Backbone.View
@subviews = {} @subviews = {}
@listenToShortcuts() @listenToShortcuts()
@updateProgressBar = _.debounce @updateProgressBar, 100 @updateProgressBar = _.debounce @updateProgressBar, 100
@toggleModal = _.debounce @toggleModal, 100
# Backbone.Mediator handles subscription setup/teardown automatically # Backbone.Mediator handles subscription setup/teardown automatically
@listenTo(@supermodel, 'loaded-all', @onLoaded) @listenTo(@supermodel, 'loaded-all', @onLoaded)
@ -150,7 +147,15 @@ module.exports = class CocoView extends Backbone.View
# Modals # Modals
@lastToggleModalCall = 0
toggleModal: (e) -> toggleModal: (e) ->
if new Date().getTime() - CocoView.lastToggleModalCall < 5
# Defensive move. This function has had a history of messing things up.
console.error 'toggleModal is getting called too often!'
return
CocoView.lastToggleModalCall = new Date().getTime()
if $(e.currentTarget).prop('target') is '_blank' if $(e.currentTarget).prop('target') is '_blank'
return true return true
# special handler for opening modals that are dynamically loaded, rather than static in the page. It works (or should work) like Bootstrap's modals, except use coco-modal for the data-toggle value. # special handler for opening modals that are dynamically loaded, rather than static in the page. It works (or should work) like Bootstrap's modals, except use coco-modal for the data-toggle value.

View file

@ -7,6 +7,11 @@ module.exports = class ModalView extends CocoView
modalWidthPercent: null modalWidthPercent: null
plain: false plain: false
events:
'click a': 'toggleModal'
'click button': 'toggleModal'
'click li': 'toggleModal'
shortcuts: shortcuts:
'esc': 'hide' 'esc': 'hide'

View file

@ -22,6 +22,9 @@ module.exports = class RootView extends CocoView
'change .language-dropdown': 'onLanguageChanged' 'change .language-dropdown': 'onLanguageChanged'
'click .toggle-fullscreen': 'toggleFullscreen' 'click .toggle-fullscreen': 'toggleFullscreen'
'click .auth-button': 'onClickAuthbutton' 'click .auth-button': 'onClickAuthbutton'
'click a': 'toggleModal'
'click button': 'toggleModal'
'click li': 'toggleModal'
subscriptions: subscriptions:
'achievements:new': 'handleNewAchievements' 'achievements:new': 'handleNewAchievements'

View file

@ -19,6 +19,7 @@ module.exports = class EmployerSignupView extends View
events: events:
"click #contract-agreement-button": "agreeToContract" "click #contract-agreement-button": "agreeToContract"
"click #create-account-button": "createAccount" "click #create-account-button": "createAccount"
"click #more-info-button": "submitMoreInfoEmail"
"click .login-link": "setHashToOpenModalAutomatically" "click .login-link": "setHashToOpenModalAutomatically"
"keydown": "checkForFormSubmissionEnterPress" "keydown": "checkForFormSubmissionEnterPress"
@ -30,6 +31,7 @@ module.exports = class EmployerSignupView extends View
@reloadWhenClosed = false @reloadWhenClosed = false
@linkedinLoaded = Boolean(IN.parse) @linkedinLoaded = Boolean(IN.parse)
@waitingForLinkedIn = false @waitingForLinkedIn = false
@sentMoreInfoEmail = false
window.contractCallback = => window.contractCallback = =>
@authorizedWithLinkedIn = IN?.User?.isAuthorized() @authorizedWithLinkedIn = IN?.User?.isAuthorized()
@render() @render()
@ -59,6 +61,7 @@ module.exports = class EmployerSignupView extends View
context.userIsAuthorized = @authorizedWithLinkedIn context.userIsAuthorized = @authorizedWithLinkedIn
context.userHasSignedContract = "employer" in me.get("permissions") context.userHasSignedContract = "employer" in me.get("permissions")
context.userIsAnonymous = context.me.get('anonymous') context.userIsAnonymous = context.me.get('anonymous')
context.sentMoreInfoEmail = @sentMoreInfoEmail
context context
agreeToContract: -> agreeToContract: ->
@ -80,23 +83,45 @@ module.exports = class EmployerSignupView extends View
alert "There was an error signing the contract. Please contact team@codecombat.com with this error: #{error.responseText}" alert "There was an error signing the contract. Please contact team@codecombat.com with this error: #{error.responseText}"
checkForFormSubmissionEnterPress: (e) -> checkForFormSubmissionEnterPress: (e) ->
if e.which is 13 then @createAccount(e) if e.which is 13
if $("#signup-email").val() isnt '' and $("#signup-password").val() isnt ''
@createAccount(e)
else if $("#more-info-email").val() isnt ''
@submitMoreInfoEmail e
createAccount: (e) => createAccount: (e) =>
window.tracker?.trackEvent 'Finished Employer Signup' window.tracker?.trackEvent 'Finished Employer Signup'
el = $("#signup-form")
e.stopPropagation() e.stopPropagation()
forms.clearFormAlerts(@$el) forms.clearFormAlerts(el)
userObject = forms.formToObject @$el userObject = forms.formToObject el
delete userObject.subscribe delete userObject.subscribe
for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emails"] for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emails"]
userObject[key] ?= val userObject[key] ?= val
userObject.emails ?= {} userObject.emails ?= {}
userObject.emails.employerNotes = {enabled: true} userObject.emails.employerNotes = {enabled: true}
res = tv4.validateMultiple userObject, User.schema res = tv4.validateMultiple userObject, User.schema
return forms.applyErrorsToForm(@$el, res.errors) unless res.valid return forms.applyErrorsToForm(el, res.errors) unless res.valid
@enableModalInProgress(@$el) @enableModalInProgress(el)
auth.createUserWithoutReload userObject, null auth.createUserWithoutReload userObject, null
submitMoreInfoEmail: (e) =>
emailAddress = $("#more-info-email").val()
window.tracker?.trackEvent 'Employer requested more information.'
successFunc = =>
@sentMoreInfoEmail = true
@render()
errorFunc = =>
alert("Something went wrong! Please contact team@codecombat.com for more information and inform them of this error.")
$.ajax
type: "POST"
url: "/contact"
data:
email: emailAddress
message: "THIS IS AN AUTOMATED MESSAGE FROM THE EMPLOYER SIGNUP FORM \n Please send me more info about hiring CodeCombat players."
success: successFunc
error: errorFunc
setHashToOpenModalAutomatically: (e) -> setHashToOpenModalAutomatically: (e) ->
window.location.hash = "employerSignupLoggingIn" window.location.hash = "employerSignupLoggingIn"

View file

@ -36,7 +36,7 @@ module.exports = class JobProfileContactView extends ContactView
contactMessage.recipientID = @options.recipientID contactMessage.recipientID = @options.recipientID
res = tv4.validateMultiple contactMessage, contactSchema res = tv4.validateMultiple contactMessage, contactSchema
return forms.applyErrorsToForm @$el, res.errors unless res.valid return forms.applyErrorsToForm @$el, res.errors unless res.valid
contactMessage.message += '\n\n\n\n[CodeCombat says: please let us know if you end up accepting this job. Thanks!]' contactMessage.message += "\n\n\n\n[CodeCombat says: please let us know if you end up accepting this job. Thanks, #{@options.recipientUserName}!]"
window.tracker?.trackEvent 'Sent Job Profile Message', message: contactMessage window.tracker?.trackEvent 'Sent Job Profile Message', message: contactMessage
sendContactMessage contactMessage, @$el sendContactMessage contactMessage, @$el
$.post "/db/user/#{me.id}/track/contact_candidate" $.post "/db/user/#{me.id}/track/contact_candidate"

View file

@ -4,6 +4,7 @@ template = require 'templates/modal/model'
module.exports = class ModelModal extends View module.exports = class ModelModal extends View
id: 'model-modal' id: 'model-modal'
template: template template: template
plain: true
constructor: (options) -> constructor: (options) ->
super options super options

View file

@ -0,0 +1,12 @@
AuthModalView = require 'views/modal/auth_modal'
RecoverModalView = require 'views/modal/recover_modal'
describe 'AuthModalView', ->
it 'opens the recover modal when you click the recover link', ->
m = new AuthModalView()
m.render()
spyOn(m, 'openModalView')
m.$el.find('#link-to-recover').click()
expect(m.openModalView.calls.count()).toEqual(1)
args = m.openModalView.calls.argsFor(0)
expect(args[0] instanceof RecoverModalView).toBeTruthy()