Employer signup works

This commit is contained in:
Michael Schmatz 2014-04-24 17:36:07 -07:00
parent 6644c6a9ee
commit 4f6f845c2d
8 changed files with 102 additions and 37 deletions

View file

@ -23,6 +23,13 @@ module.exports = LinkedInHandler = class LinkedInHandler extends CocoClass
me.set("linkedIn", @linkedInData)
console.log "LinkedIn data is #{@linkedInData}"
constructEmployerAgreementObject: (cb) =>
IN.API.Profile("me")
.fields(["positions","public-profile-url","id","first-name","last-name","email-address"])
.error(cb)
.result (profiles) =>
cb null, profiles.values[0]
destroy: ->
super()

View file

@ -53,7 +53,7 @@ UserSchema = c.object {},
#Internationalization stuff
preferredLanguage: {type: 'string', default: 'en', 'enum': c.getLanguageCodeArray()}
signedCLA: c.date({title: 'Date Signed the CLA'})
wizard: c.object {},
colorConfig: c.object {additionalProperties: c.colorConfig()}
@ -109,6 +109,11 @@ UserSchema = c.object {},
jobProfileApproved: {title: 'Job Profile Approved', type: 'boolean', description: 'Whether your profile has been approved by CodeCombat.'}
jobProfileNotes: {type: 'string', maxLength: 1000, title: 'Our Notes', description: "CodeCombat's notes on the candidate.", format: 'markdown', default: ''}
employerAt: c.shortString {description: "If given employer permissions to view job candidates, for which employer?"}
signedEmployerAgreement: c.object {},
linkedinID: c.shortString {title:"LinkedInID", description: "The user's LinkedIn ID when they signed the contract."}
date: c.date {title: "Date signed employer agreement"}
data: c.object
c.extendBasicProperties UserSchema, 'user'

View file

@ -138,8 +138,8 @@ a[data-toggle="modal"]
.signin-text
font-size: 15px
padding-bottom: 10px
.login-link
cursor: pointer
.login-link
cursor: pointer
// Bigger versions of some Bootstrap icons

View file

@ -12,9 +12,11 @@ block content
span(data-i18n="employers.candidates_count_many") many
|
span(data-i18n="employers.candidates_count_suffix") highly skilled and vetted developers looking for work.
h3
a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/employer_signup", data-i18n="employers.contact_george") Contact George to see our candidates
if !isEmployer
h3
a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/employer_signup") Click here to see candidates
if candidates.length
table.table.table-condensed.table-hover.table-responsive.tablesorter
thead

View file

@ -4,49 +4,57 @@ block modal-header-content
if userIsAnonymous || !userIsAuthorized
h3(data-i18n="employer_signup.title") Sign up to hire CodeCombat players!
else
h3 Hiring Contract
h3 CodeCombat Placement Agreement
block modal-body-content
if userIsAnonymous
h4(data-i18n="employer_signup.sub_heading") Let us find your next brilliant developers.
p Create an account to get started!
.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")
if userIsAuthorized
| You appear to be authorized on CodeCombat with LinkedIn.
else
h4(data-i18n="employer_signup.sub_heading") Let us find your next brilliant developers.
p Create an account to get started!
.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")
else if !userIsAuthorized
.modal-footer.linkedin
p Please sign into your LinkedIn account to verify your identity.
script(type="in/Login" id="linkedInAuthButton" data-onAuth="contractCallback")
else
| We (CodeCombat) are providing you (the Company) access to information about our best players. In exchange, you agree to pay us 15% of the first year's annualized starting base salary for any person that you hire on a full time basis through this site. That 15% is due on the first date that our candidate is employed and is 100% refundable for 90 days after that date if the candidate doesn't remain employed at the company for any reason.
| Please agree to our terms before accessing our candidates.
br
br
b Who we are:
| CodeCombat is a programming game that both teaches and vets programmers. If you accept this agreement, we will let you hire the most talented developers on our platform.
br
br
b Placement fee:
| If you hire our any of our players, you agree to pay us 15% of the candidate's first year annualized starting base salary. The fee is due on the first day that the candidate is employed and is 100% refundable for up to 90 day if the candidate doesn't remain employed at the company for any reason.
br
br
b Interns are free:
| We will not bill you for interns and part time hires (remote or onsite) hired through this site, provided they do not become full time hires within 1 year of their start date. If they do become full time hires within 1 year of their start date, we will invoice you 15% of their first year's annualized starting base salary on their first day of full time employment. For these hires, the 90 day guarantee does not apply.
br
br
| You must keep all of the information you access on this site confidential. That means you cannot share it with third parties and will only use it for recruiting.
br
br
| We will invoice this account via email and you agree to pay within 30 days of that email being sent.
br
br
| Neither you or CodeCombat will be liable for any damages that result from this contract.
| 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 && !userisAuthorized
.modal-footer.linkedin
b.signin-text Sign in with LinkedIn to complete the registration process.
script(type="in/Login" id="linkedInAuthButton" data-onAuth="contractCallback")
br
br
| Already have a CodeCombat account?
a.login-link(data-toggle="coco-modal", data-target="modal/login") Log in to continue!
if userIsAnonymous
if !userIsAuthorized
.modal-footer.linkedin
b.signin-text Sign in with LinkedIn to complete the registration process.
script(type="in/Login" id="linkedInAuthButton" data-onAuth="contractCallback")
br
br
| Already have a CodeCombat account?
a.login-link(data-toggle="coco-modal", data-target="modal/login") Log in to continue!
else
.modal-footer.linkedin
a.login-link(data-toggle="coco-modal", data-target="modal/login") Please log in to continue.
else if !userIsAnonymous && !userIsAuthorized
.modal-footer.linkedin
| We will record your name and work history for verification purposes.

View file

@ -2,6 +2,7 @@ View = require 'views/kinds/RootView'
template = require 'templates/employers'
app = require 'application'
User = require 'models/User'
{me} = require 'lib/auth'
CocoCollection = require 'models/CocoCollection'
EmployerSignupView = require 'views/modal/employer_signup_modal'
@ -27,6 +28,9 @@ module.exports = class EmployersView extends View
getRenderData: ->
c = super()
c.candidates = @candidates.models
userPermissions = me.get('permissions') || []
c.isEmployer = _.contains userPermissions, "employer"
c.moment = moment
c

View file

@ -54,7 +54,21 @@ module.exports = class EmployerSignupView extends View
context
agreeToContract: ->
application.linkedinHandler.constructEmployerAgreementObject (err, profileData) =>
if err? then return handleAgreementFailure err
$.ajax
url: "/db/user/#{me.id}/agreeToEmployerAgreement"
data: profileData
type: "POST"
success: @handleAgreementSuccess
error: @handleAgreementFailure
handleAgreementSuccess: (result) ->
me.fetch()
window.location.reload()
handleAgreementFailure: (error) ->
createAccount: (e) =>
console.log "Tried to create account!"
e.stopPropagation()
@ -84,7 +98,7 @@ module.exports = class EmployerSignupView extends View
recordUserDetails: (e) =>
console.log "Record user details here!"
#TODO: refactor this out
@render()
destroy: ->

View file

@ -14,7 +14,7 @@ LevelSessionHandler = require '../levels/sessions/level_session_handler'
serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset']
privateProperties = [
'permissions', 'email', 'firstName', 'lastName', 'gender', 'facebookID',
'gplusID', 'music', 'volume', 'aceConfig', 'employerAt'
'gplusID', 'music', 'volume', 'aceConfig', 'employerAt', 'signedEmployerAgreement'
]
candidateProperties = [
'jobProfile', 'jobProfileApproved', 'jobProfileNotes'
@ -182,6 +182,7 @@ UserHandler = class UserHandler extends Handler
getByRelationship: (req, res, args...) ->
return @agreeToCLA(req, res) if args[1] is 'agreeToCLA'
return @agreeToEmployerAgreement(req,res) if args[1] is 'agreeToEmployerAgreement'
return @avatar(req, res, args[0]) if args[1] is 'avatar'
return @getNamesByIDs(req, res) if args[1] is 'names'
return @nameToID(req, res, args[0]) if args[1] is 'nameToID'
@ -231,7 +232,31 @@ UserHandler = class UserHandler extends Handler
return @sendDatabaseError(res, err) if err
documents = (LevelSessionHandler.formatEntity(req, doc) for doc in documents)
@sendSuccess(res, documents)
agreeToEmployerAgreement: (req, res) ->
userIsAnonymous = req.user?.get('anonymous')
if userIsAnonymous then return errors.unauthorized(res, "You need to be logged in to agree to the employer agreeement.")
profileData = req.body
#TODO: refactor this bit to make it more elegant
if not profileData.id or not profileData.positions or not profileData.emailAddress or not profileData.firstName or not profileData.lastName
return errors.badInput(res, "You need to have a more complete profile to sign up for this service.")
@modelClass.findById(req.user.id).exec (err, user) =>
if user.get('employerAt') or user.get('signedEmployerAgreement') or "employer" in user.get('permissions')
return errors.conflict(res, "You already have signed the agreement!")
#TODO: Search for the current position
employerAt = profileData.positions.values[0].company.name
signedEmployerAgreement =
linkedinID: profileData.id
date: new Date()
data: profileData
updateObject =
"employerAt": employerAt
"signedEmployerAgreement": signedEmployerAgreement
$push: "permissions":'employer'
User.update {"_id": req.user.id}, updateObject, (err, result) =>
if err? then return errors.serverError(res, "There was an issue updating the user object to reflect employer status: #{err}")
res.send({"message": "The agreement was successful."})
res.end()
getCandidates: (req, res) ->
authorized = req.user.isAdmin() or ('employer' in req.user.get('permissions'))
since = (new Date((new Date()) - 2 * 30.4 * 86400 * 1000)).toISOString()