mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-29 18:45:48 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
9eb495650f
11 changed files with 128 additions and 69 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) ->
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
12
test/app/views/modal/AuthModalView.spec.coffee
Normal file
12
test/app/views/modal/AuthModalView.spec.coffee
Normal 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()
|
Loading…
Reference in a new issue