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,52 +4,52 @@ block content
h1(data-i18n="employers.want_to_hire_our_players") Hire CodeCombat Players
div#info_wrapper
div#leftside
div.information_row
img(class="employer_icon" src="/images/pages/employer/employer_icon1.png")
h2(data-i18n="employers.what") What is CodeCombat?
p(data-i18n="employers.what_blurb") CodeCombat is a multiplayer browser programming game. Players write code to control their forces in battle against other developers. We support JavaScript, Python, Lua, Clojure, CoffeeScript, and Io.
div.information_row
img(class="employer_icon" src="/images/pages/employer/employer_icon3.png")
h2(data-i18n="employers.who") Who Are the Players?
p(data-i18n="employers.who_blurb") CodeCombateers are software developers who enjoy using their programming skills to play games. They range from college seniors at top 20 engineering programs to 20-year industry veterans.
div#rightside
div.information_row
img(class="employer_icon" src="/images/pages/employer/employer_icon2.png")
h2(data-i18n="employers.how") How Do We Find Developers?
p(data-i18n="employers.how_blurb") We host competitive tournaments to attract competitive software engieneers. We then use in-house algorithms to identify the best players among the top 5% of tournament winners.
div.information_row
img(class="employer_icon" src="/images/pages/employer/employer_icon4.png")
h2(data-i18n="employers.why") Why Hire Through Us?
p
span(data-i18n="employers.why_blurb_1") We will save you time. Every CodeCombateer we feaure is
strong(data-i18n="employers.why_blurb_2") looking for work
span(data-i18n="employers.why_blurb_3") , has
strong(data-i18n="employers.why_blurb_4") demonstrated top notch technical skills
span(data-i18n="employers.why_blurb_5") , and has been
strong(data-i18n="employers.why_blurb_6") personally screened by us
span(data-i18n="employers.why_blurb_7") . Stop screening and start hiring.
if !isEmployer && !me.isAdmin()
div#info_wrapper
div#leftside
div.information_row
img(class="employer_icon" src="/images/pages/employer/employer_icon1.png")
h2(data-i18n="employers.what") What is CodeCombat?
p(data-i18n="employers.what_blurb") CodeCombat is a multiplayer browser programming game. Players write code to control their forces in battle against other developers. We support JavaScript, Python, Lua, Clojure, CoffeeScript, and Io.
div.information_row
img(class="employer_icon" src="/images/pages/employer/employer_icon3.png")
h2(data-i18n="employers.who") Who Are the Players?
p(data-i18n="employers.who_blurb") CodeCombateers are software developers who enjoy using their programming skills to play games. They range from college seniors at top 20 engineering programs to 20-year industry veterans.
div#rightside
div.information_row
img(class="employer_icon" src="/images/pages/employer/employer_icon2.png")
h2(data-i18n="employers.how") How Do We Find Developers?
p(data-i18n="employers.how_blurb") We host competitive tournaments to attract competitive software engieneers. We then use in-house algorithms to identify the best players among the top 5% of tournament winners.
div.information_row
img(class="employer_icon" src="/images/pages/employer/employer_icon4.png")
h2(data-i18n="employers.why") Why Hire Through Us?
p
span(data-i18n="employers.why_blurb_1") We will save you time. Every CodeCombateer we feaure is
strong(data-i18n="employers.why_blurb_2") looking for work
span(data-i18n="employers.why_blurb_3") , has
strong(data-i18n="employers.why_blurb_4") demonstrated top notch technical skills
span(data-i18n="employers.why_blurb_5") , and has been
strong(data-i18n="employers.why_blurb_6") personally screened by us
span(data-i18n="employers.why_blurb_7") . Stop screening and start hiring.
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
@ -106,7 +106,7 @@ block content
td= profile.lookingFor
td= profile.jobTitle
td
each skill in profile.skills.slice(0, 10)
each skill in profile.skills
code= skill
span
td= profile.experience

View file

@ -10,16 +10,31 @@ block modal-body-content
if userIsAnonymous
if userIsAuthorized
| You appear to be authorized on CodeCombat with LinkedIn.
else if sentMoreInfoEmail
| Thanks! You should receive an email from George shortly.
else
h4(data-i18n="employer_signup.sub_heading") Let us find your next brilliant developers.
p Create an account to get started!
.form
.form#signup-form
.form-group
label.control-label(for="signup-email", data-i18n="general.email") Email
input#signup-email.form-control.input-large(name="email",type="email")
.form-group
label.control-label(for="signup-password", data-i18n="general.password") 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
.modal-footer.linkedin
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.
block modal-footer
if userIsAnonymous
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
if userIsAuthorized
.modal-footer.linkedin
a.login-link(data-toggle="coco-modal", data-target="modal/auth") Please log in to continue.
else if !userIsAnonymous && !userIsAuthorized

View file

@ -253,7 +253,7 @@ class LatestVersionCollection extends CocoCollection
class LatestVersionReferenceNode extends TreemaNode
searchValueTemplate: '<input placeholder="Search" /><div class="treema-search-results"></div>'
valueClass: 'treema-latest-version'
url: '/db/article/search'
url: '/db/article'
lastTerm: null
constructor: ->
@ -264,7 +264,7 @@ class LatestVersionReferenceNode extends TreemaNode
link = (l for l in links when l.rel is 'db')[0]
return unless link
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]))
buildValueForDisplay: (valEl) ->

View file

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

View file

@ -4,6 +4,7 @@ CocoClass = require 'lib/CocoClass'
loadingScreenTemplate = require 'templates/loading'
loadingErrorTemplate = require 'templates/loading_error'
lastToggleModalCall = 0
visibleModal = null
waitingModal = null
classCount = 0
@ -15,9 +16,6 @@ module.exports = class CocoView extends Backbone.View
template: -> ''
events:
'click a': 'toggleModal'
'click button': 'toggleModal'
'click li': 'toggleModal'
'click .retry-loading-resource': 'onRetryResource'
'click .retry-loading-request': 'onRetryRequest'
@ -46,7 +44,6 @@ module.exports = class CocoView extends Backbone.View
@subviews = {}
@listenToShortcuts()
@updateProgressBar = _.debounce @updateProgressBar, 100
@toggleModal = _.debounce @toggleModal, 100
# Backbone.Mediator handles subscription setup/teardown automatically
@listenTo(@supermodel, 'loaded-all', @onLoaded)
@ -149,8 +146,16 @@ module.exports = class CocoView extends Backbone.View
$(e.target).closest('.loading-error-alert').remove()
# Modals
@lastToggleModalCall = 0
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'
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.

View file

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

View file

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

View file

@ -19,6 +19,7 @@ module.exports = class EmployerSignupView extends View
events:
"click #contract-agreement-button": "agreeToContract"
"click #create-account-button": "createAccount"
"click #more-info-button": "submitMoreInfoEmail"
"click .login-link": "setHashToOpenModalAutomatically"
"keydown": "checkForFormSubmissionEnterPress"
@ -30,6 +31,7 @@ module.exports = class EmployerSignupView extends View
@reloadWhenClosed = false
@linkedinLoaded = Boolean(IN.parse)
@waitingForLinkedIn = false
@sentMoreInfoEmail = false
window.contractCallback = =>
@authorizedWithLinkedIn = IN?.User?.isAuthorized()
@render()
@ -59,6 +61,7 @@ module.exports = class EmployerSignupView extends View
context.userIsAuthorized = @authorizedWithLinkedIn
context.userHasSignedContract = "employer" in me.get("permissions")
context.userIsAnonymous = context.me.get('anonymous')
context.sentMoreInfoEmail = @sentMoreInfoEmail
context
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}"
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) =>
window.tracker?.trackEvent 'Finished Employer Signup'
el = $("#signup-form")
e.stopPropagation()
forms.clearFormAlerts(@$el)
userObject = forms.formToObject @$el
forms.clearFormAlerts(el)
userObject = forms.formToObject el
delete userObject.subscribe
for key, val of me.attributes when key in ["preferredLanguage", "testGroupNumber", "dateCreated", "wizardColor1", "name", "music", "volume", "emails"]
userObject[key] ?= val
userObject.emails ?= {}
userObject.emails.employerNotes = {enabled: true}
res = tv4.validateMultiple userObject, User.schema
return forms.applyErrorsToForm(@$el, res.errors) unless res.valid
@enableModalInProgress(@$el)
return forms.applyErrorsToForm(el, res.errors) unless res.valid
@enableModalInProgress(el)
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) ->
window.location.hash = "employerSignupLoggingIn"

View file

@ -36,7 +36,7 @@ module.exports = class JobProfileContactView extends ContactView
contactMessage.recipientID = @options.recipientID
res = tv4.validateMultiple contactMessage, contactSchema
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
sendContactMessage contactMessage, @$el
$.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
id: 'model-modal'
template: template
plain: true
constructor: (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()