Merge pull request #920 from codecombat/master

Merge master into production
This commit is contained in:
Michael Schmatz 2014-04-25 11:19:43 -07:00
commit daca71786a
7 changed files with 43 additions and 60 deletions

View file

@ -7,22 +7,21 @@ storage = require 'lib/storage'
module.exports = LinkedInHandler = class LinkedInHandler extends CocoClass module.exports = LinkedInHandler = class LinkedInHandler extends CocoClass
constructor: -> constructor: ->
super() super()
subscriptions: subscriptions:
'linkedin-loaded':'onLinkedInLoaded' 'linkedin-loaded': 'onLinkedInLoaded'
onLinkedInLoaded: (e) => onLinkedInLoaded: (e) ->
IN.Event.on IN, "auth", @onLinkedInAuth IN.Event.on IN, "auth", @onLinkedInAuth
onLinkedInAuth: (e) => console.log "Authorized with LinkedIn" onLinkedInAuth: (e) => console.log "Authorized with LinkedIn"
constructEmployerAgreementObject: (cb) => constructEmployerAgreementObject: (cb) =>
IN.API.Profile("me") IN.API.Profile("me")
.fields(["positions","public-profile-url","id","first-name","last-name","email-address"]) .fields(["positions","public-profile-url","id","first-name","last-name","email-address"])
.error(cb) .error(cb)
.result (profiles) => .result (profiles) =>
cb null, profiles.values[0] cb null, profiles.values[0]
destroy: -> destroy: ->
super() super()

View file

@ -30,10 +30,11 @@ UserSchema = c.object {},
artisanNews: { $ref: '#/definitions/emailSubscription' } artisanNews: { $ref: '#/definitions/emailSubscription' }
diplomatNews: { $ref: '#/definitions/emailSubscription' } diplomatNews: { $ref: '#/definitions/emailSubscription' }
scribeNews: { $ref: '#/definitions/emailSubscription' } scribeNews: { $ref: '#/definitions/emailSubscription' }
# notifications # notifications
anyNotes: { $ref: '#/definitions/emailSubscription' } # overrides any other notifications settings anyNotes: { $ref: '#/definitions/emailSubscription' } # overrides any other notifications settings
recruitNotes: { $ref: '#/definitions/emailSubscription' } recruitNotes: { $ref: '#/definitions/emailSubscription' }
employerNotes: { $ref: '#/definitions/emailSubscription' }
# server controlled # server controlled
permissions: c.array {'default': []}, c.shortString() permissions: c.array {'default': []}, c.shortString()
@ -53,7 +54,7 @@ UserSchema = c.object {},
#Internationalization stuff #Internationalization stuff
preferredLanguage: {type: 'string', default: 'en', 'enum': c.getLanguageCodeArray()} preferredLanguage: {type: 'string', default: 'en', 'enum': c.getLanguageCodeArray()}
signedCLA: c.date({title: 'Date Signed the CLA'}) signedCLA: c.date({title: 'Date Signed the CLA'})
wizard: c.object {}, wizard: c.object {},
colorConfig: c.object {additionalProperties: c.colorConfig()} colorConfig: c.object {additionalProperties: c.colorConfig()}
@ -112,8 +113,8 @@ UserSchema = c.object {},
signedEmployerAgreement: c.object {}, signedEmployerAgreement: c.object {},
linkedinID: c.shortString {title:"LinkedInID", description: "The user's LinkedIn ID when they signed the contract."} linkedinID: c.shortString {title:"LinkedInID", description: "The user's LinkedIn ID when they signed the contract."}
date: c.date {title: "Date signed employer agreement"} date: c.date {title: "Date signed employer agreement"}
data: c.object data: c.object {description: "Cached LinkedIn data slurped from profile."}
c.extendBasicProperties UserSchema, 'user' c.extendBasicProperties UserSchema, 'user'

View file

@ -63,6 +63,6 @@ block modal-footer
button.btn.btn-primary(id="contract-agreement-button") I agree button.btn.btn-primary(id="contract-agreement-button") I agree
else else
.modal-footer.linkedin .modal-footer.linkedin
| Thanks #{firstName}! You've already agreed to the contract. | Thanks! You've already agreed to the contract.

View file

@ -28,7 +28,7 @@ module.exports = class EmployersView extends View
getRenderData: -> getRenderData: ->
c = super() c = super()
c.candidates = @candidates.models c.candidates = @candidates.models
userPermissions = me.get('permissions') || [] userPermissions = me.get('permissions') ? []
c.isEmployer = _.contains userPermissions, "employer" c.isEmployer = _.contains userPermissions, "employer"
c.moment = moment c.moment = moment

View file

@ -10,27 +10,27 @@ module.exports = class EmployerSignupView extends View
template: template template: template
closeButton: true closeButton: true
subscriptions: subscriptions:
"server-error": "onServerError" "server-error": "onServerError"
"created-user-without-reload": "linkedInAuth" "created-user-without-reload": "linkedInAuth"
events: events:
"click #contract-agreement-button": "agreeToContract" "click #contract-agreement-button": "agreeToContract"
constructor: (options) -> constructor: (options) ->
super(options) super(options)
@authorizedWithLinkedIn = IN?.User?.isAuthorized() @authorizedWithLinkedIn = IN?.User?.isAuthorized()
window.tracker?.trackEvent 'Started Employer Signup' window.tracker?.trackEvent 'Started Employer Signup'
@reloadWhenClosed = false @reloadWhenClosed = false
window.contractCallback = => window.contractCallback = =>
@authorizedWithLinkedIn = IN?.User?.isAuthorized() @authorizedWithLinkedIn = IN?.User?.isAuthorized()
@render() @render()
onServerError: (e) -> onServerError: (e) ->
@disableModalInProgress(@$el) @disableModalInProgress(@$el)
afterInsert: -> afterInsert: ->
super() super()
linkedInButtonParentElement = document.getElementById("linkedInAuthButton")?.parentNode linkedInButtonParentElement = document.getElementById("linkedInAuthButton")?.parentNode
@ -38,16 +38,14 @@ module.exports = class EmployerSignupView extends View
IN.parse() IN.parse()
if me.get('anonymous') if me.get('anonymous')
$(".IN-widget").get(0).addEventListener('click', @createAccount, true) $(".IN-widget").get(0).addEventListener('click', @createAccount, true)
console.log "Parsed linkedin button element!"
console.log linkedInButtonParentElement
getRenderData: -> getRenderData: ->
context = super() context = super()
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 context
agreeToContract: -> agreeToContract: ->
application.linkedinHandler.constructEmployerAgreementObject (err, profileData) => application.linkedinHandler.constructEmployerAgreementObject (err, profileData) =>
if err? then return handleAgreementFailure err if err? then return handleAgreementFailure err
@ -57,54 +55,37 @@ module.exports = class EmployerSignupView extends View
type: "POST" type: "POST"
success: @handleAgreementSuccess success: @handleAgreementSuccess
error: @handleAgreementFailure error: @handleAgreementFailure
handleAgreementSuccess: (result) -> handleAgreementSuccess: (result) ->
window.tracker?.trackEvent 'Employer Agreed to Contract' window.tracker?.trackEvent 'Employer Agreed to Contract'
me.fetch() me.fetch()
window.location.reload() window.location.reload()
handleAgreementFailure: (error) -> handleAgreementFailure: (error) ->
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}"
createAccount: (e) => createAccount: (e) =>
window.tracker?.trackEvent 'Finished Employer Signup' window.tracker?.trackEvent 'Finished Employer Signup'
console.log "Tried to create account!"
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
subscribe = true
#TODO: Enable all email subscriptions
userObject.emails ?= {} userObject.emails ?= {}
userObject.emails.generalNews ?= {} userObject.emails.employerNotes = {enabled: true}
userObject.emails.generalNews.enabled = subscribe
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
window.tracker?.trackEvent 'Finished Signup'
@enableModalInProgress(@$el) @enableModalInProgress(@$el)
auth.createUserWithoutReload userObject, null auth.createUserWithoutReload userObject, null
console.log "Authorizing with linkedin" IN.User.authorize @render, @
IN.User.authorize(@recordUserDetails, @)
linkedInAuth: (e) ->
linkedInAuth: (e) =>
me.fetch() me.fetch()
@reloadWhenClosed = true @reloadWhenClosed = true
recordUserDetails: (e) =>
#TODO: refactor this out
@render()
destroy: -> destroy: ->
reloadWhenClosed = @reloadWhenClosed reloadWhenClosed = @reloadWhenClosed
super() super()
if reloadWhenClosed if reloadWhenClosed
window.location.reload() window.location.reload()

View file

@ -29,7 +29,7 @@ UserSchema.post('init', ->
UserSchema.methods.isAdmin = -> UserSchema.methods.isAdmin = ->
p = @get('permissions') p = @get('permissions')
return p and 'admin' in p return p and 'admin' in p
emailNameMap = emailNameMap =
generalNews: 'announcement' generalNews: 'announcement'
adventurerNews: 'tester' adventurerNews: 'tester'
@ -39,20 +39,20 @@ emailNameMap =
diplomatNews: 'translator' diplomatNews: 'translator'
ambassadorNews: 'support' ambassadorNews: 'support'
anyNotes: 'notification' anyNotes: 'notification'
UserSchema.methods.setEmailSubscription = (newName, enabled) -> UserSchema.methods.setEmailSubscription = (newName, enabled) ->
oldSubs = _.clone @get('emailSubscriptions') oldSubs = _.clone @get('emailSubscriptions')
if oldSubs and oldName = emailNameMap[newName] if oldSubs and oldName = emailNameMap[newName]
oldSubs = (s for s in oldSubs when s isnt oldName) oldSubs = (s for s in oldSubs when s isnt oldName)
oldSubs.push(oldName) if enabled oldSubs.push(oldName) if enabled
@set('emailSubscriptions', oldSubs) @set('emailSubscriptions', oldSubs)
newSubs = _.clone(@get('emails') or _.cloneDeep(jsonschema.properties.emails.default)) newSubs = _.clone(@get('emails') or _.cloneDeep(jsonschema.properties.emails.default))
newSubs[newName] ?= {} newSubs[newName] ?= {}
newSubs[newName].enabled = enabled newSubs[newName].enabled = enabled
@set('emails', newSubs) @set('emails', newSubs)
@newsSubsChanged = true if newName in mail.NEWS_GROUPS @newsSubsChanged = true if newName in mail.NEWS_GROUPS
UserSchema.methods.isEmailSubscriptionEnabled = (newName) -> UserSchema.methods.isEmailSubscriptionEnabled = (newName) ->
emails = @get 'emails' emails = @get 'emails'
if not emails if not emails
@ -74,10 +74,10 @@ UserSchema.statics.updateMailChimp = (doc, callback) ->
newGroups = [] newGroups = []
for [mailchimpEmailGroup, emailGroup] in _.zip(mail.MAILCHIMP_GROUPS, mail.NEWS_GROUPS) for [mailchimpEmailGroup, emailGroup] in _.zip(mail.MAILCHIMP_GROUPS, mail.NEWS_GROUPS)
newGroups.push(mailchimpEmailGroup) if doc.isEmailSubscriptionEnabled(emailGroup) newGroups.push(mailchimpEmailGroup) if doc.isEmailSubscriptionEnabled(emailGroup)
if (not existingProps) and newGroups.length is 0 if (not existingProps) and newGroups.length is 0
return callback?() # don't add totally unsubscribed people to the list return callback?() # don't add totally unsubscribed people to the list
params = {} params = {}
params.id = mail.MAILCHIMP_LIST_ID params.id = mail.MAILCHIMP_LIST_ID
params.email = if existingProps then {leid:existingProps.leid} else {email:doc.get('email')} params.email = if existingProps then {leid:existingProps.leid} else {email:doc.get('email')}
@ -113,7 +113,7 @@ UserSchema.pre('save', (next) ->
recipient: recipient:
address: @get 'email' address: @get 'email'
sendwithus.api.send data, (err, result) -> sendwithus.api.send data, (err, result) ->
log.error 'error', err, 'result', result if err log.error "sendwithus post-save error: #{err}, result: #{result}" if err
next() next()
) )

View file

@ -232,6 +232,7 @@ UserHandler = class UserHandler extends Handler
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
documents = (LevelSessionHandler.formatEntity(req, doc) for doc in documents) documents = (LevelSessionHandler.formatEntity(req, doc) for doc in documents)
@sendSuccess(res, documents) @sendSuccess(res, documents)
agreeToEmployerAgreement: (req, res) -> agreeToEmployerAgreement: (req, res) ->
userIsAnonymous = req.user?.get('anonymous') userIsAnonymous = req.user?.get('anonymous')
if userIsAnonymous then return errors.unauthorized(res, "You need to be logged in to agree to the employer agreeement.") if userIsAnonymous then return errors.unauthorized(res, "You need to be logged in to agree to the employer agreeement.")
@ -244,19 +245,20 @@ UserHandler = class UserHandler extends Handler
return errors.conflict(res, "You already have signed the agreement!") return errors.conflict(res, "You already have signed the agreement!")
#TODO: Search for the current position #TODO: Search for the current position
employerAt = _.filter(profileData.positions.values,"isCurrent")[0]?.company.name ? "Not available" employerAt = _.filter(profileData.positions.values,"isCurrent")[0]?.company.name ? "Not available"
signedEmployerAgreement = signedEmployerAgreement =
linkedinID: profileData.id linkedinID: profileData.id
date: new Date() date: new Date()
data: profileData data: profileData
updateObject = updateObject =
"employerAt": employerAt "employerAt": employerAt
"signedEmployerAgreement": signedEmployerAgreement "signedEmployerAgreement": signedEmployerAgreement
$push: "permissions":'employer' $push: "permissions":'employer'
User.update {"_id": req.user.id}, updateObject, (err, result) => 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}") 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.send({"message": "The agreement was successful."})
res.end() res.end()
getCandidates: (req, res) -> getCandidates: (req, res) ->
authorized = req.user.isAdmin() or ('employer' in req.user.get('permissions')) authorized = req.user.isAdmin() or ('employer' in req.user.get('permissions'))
since = (new Date((new Date()) - 2 * 30.4 * 86400 * 1000)).toISOString() since = (new Date((new Date()) - 2 * 30.4 * 86400 * 1000)).toISOString()