2014-01-03 13:32:13 -05:00
|
|
|
View = require 'views/kinds/RootView'
|
|
|
|
template = require 'templates/account/profile'
|
|
|
|
User = require 'models/User'
|
2014-04-10 17:59:32 -04:00
|
|
|
JobProfileContactView = require 'views/modal/job_profile_contact_modal'
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
module.exports = class ProfileView extends View
|
|
|
|
id: "profile-view"
|
|
|
|
template: template
|
2014-05-31 01:12:44 -04:00
|
|
|
editing: false
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-04-07 20:58:02 -04:00
|
|
|
events:
|
2014-05-31 01:12:44 -04:00
|
|
|
'click #toggle-editing': 'toggleEditing'
|
2014-04-07 20:58:02 -04:00
|
|
|
'click #toggle-job-profile-approved': 'toggleJobProfileApproved'
|
2014-05-01 20:36:49 -04:00
|
|
|
'click save-notes-button': 'onJobProfileNotesChanged'
|
2014-04-10 17:59:32 -04:00
|
|
|
'click #contact-candidate': 'onContactCandidate'
|
2014-04-25 19:57:42 -04:00
|
|
|
'click #enter-espionage-mode': 'enterEspionageMode'
|
2014-05-31 01:12:44 -04:00
|
|
|
'click .editable-profile .profile-photo': 'onEditProfilePhoto'
|
|
|
|
'click .editable-profile .editable-display': 'onEditSection'
|
|
|
|
'click .editable-profile .save-section': 'onSaveSection'
|
|
|
|
'click .editable-profile .glyphicon-remove': 'onCancelSectionEdit'
|
|
|
|
'change .editable-profile .editable-array input': 'onEditArray'
|
2014-04-07 20:58:02 -04:00
|
|
|
|
2014-01-03 13:32:13 -05:00
|
|
|
constructor: (options, @userID) ->
|
2014-04-07 20:58:02 -04:00
|
|
|
@onJobProfileNotesChanged = _.debounce @onJobProfileNotesChanged, 1000
|
2014-01-03 13:32:13 -05:00
|
|
|
super options
|
2014-04-09 19:46:44 -04:00
|
|
|
if @userID is me.id
|
|
|
|
@user = me
|
2014-05-07 16:56:10 -04:00
|
|
|
else if me.isAdmin() or "employer" in me.get('permissions')
|
2014-04-09 19:46:44 -04:00
|
|
|
@user = User.getByID(@userID)
|
2014-04-29 18:12:50 -04:00
|
|
|
@user.fetch()
|
|
|
|
@listenTo @user, "sync", =>
|
|
|
|
@render()
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
getRenderData: ->
|
|
|
|
context = super()
|
2014-04-09 19:46:44 -04:00
|
|
|
context.user = @user
|
|
|
|
context.myProfile = @user.id is context.me.id
|
2014-05-31 01:12:44 -04:00
|
|
|
context.allowedToViewJobProfile = me.isAdmin() or "employer" in me.get('permissions') or context.myProfile
|
|
|
|
context.allowedToEditJobProfile = me.isAdmin() or context.myProfile
|
|
|
|
context.editing = @editing
|
|
|
|
context.jobProfileSchema = me.schema().properties.jobProfile
|
2014-04-07 18:21:05 -04:00
|
|
|
context.marked = marked
|
|
|
|
context.moment = moment
|
2014-04-09 16:14:52 -04:00
|
|
|
context.iconForLink = @iconForLink
|
|
|
|
if links = @user.get('jobProfile')?.links
|
|
|
|
links = ($.extend(true, {}, link) for link in links)
|
|
|
|
link.icon = @iconForLink link for link in links
|
|
|
|
context.profileLinks = _.sortBy links, (link) -> not link.icon # icons first
|
2014-01-03 13:32:13 -05:00
|
|
|
context
|
2014-04-07 20:58:02 -04:00
|
|
|
|
|
|
|
afterRender: ->
|
|
|
|
super()
|
|
|
|
@updateProfileApproval() if me.isAdmin()
|
2014-05-31 01:12:44 -04:00
|
|
|
unless @user.get('jobProfile')?.projects?.length or @editing
|
2014-04-10 20:54:28 -04:00
|
|
|
@$el.find('.right-column').hide()
|
|
|
|
@$el.find('.middle-column').addClass('double-column')
|
2014-05-31 01:12:44 -04:00
|
|
|
unless @editing
|
|
|
|
@$el.find('.editable-display').attr('title', '')
|
2014-04-07 20:58:02 -04:00
|
|
|
|
|
|
|
updateProfileApproval: ->
|
|
|
|
approved = @user.get 'jobProfileApproved'
|
|
|
|
@$el.find('.approved').toggle Boolean(approved)
|
|
|
|
@$el.find('.not-approved').toggle not approved
|
|
|
|
|
2014-05-31 01:12:44 -04:00
|
|
|
toggleEditing: ->
|
|
|
|
@editing = not @editing
|
|
|
|
@render()
|
|
|
|
|
2014-04-07 20:58:02 -04:00
|
|
|
toggleJobProfileApproved: ->
|
|
|
|
approved = not @user.get 'jobProfileApproved'
|
|
|
|
@user.set 'jobProfileApproved', approved
|
|
|
|
@user.save()
|
|
|
|
@updateProfileApproval()
|
|
|
|
|
2014-04-25 19:57:42 -04:00
|
|
|
enterEspionageMode: ->
|
|
|
|
postData = emailLower: @user.get('email').toLowerCase(), usernameLower: @user.get('name').toLowerCase()
|
|
|
|
$.ajax
|
|
|
|
type: "POST",
|
|
|
|
url: "/auth/spy"
|
|
|
|
data: postData
|
|
|
|
success: @espionageSuccess
|
|
|
|
|
|
|
|
espionageSuccess: (model) ->
|
|
|
|
window.location.reload()
|
|
|
|
|
2014-04-07 20:58:02 -04:00
|
|
|
onJobProfileNotesChanged: (e) =>
|
|
|
|
notes = @$el.find("#job-profile-notes").val()
|
|
|
|
@user.set 'jobProfileNotes', notes
|
|
|
|
@user.save()
|
2014-04-09 16:14:52 -04:00
|
|
|
|
|
|
|
iconForLink: (link) ->
|
|
|
|
icons = [
|
2014-04-23 14:26:20 -04:00
|
|
|
{icon: 'facebook', name: 'Facebook', domain: /facebook\.com/, match: /facebook/i}
|
|
|
|
{icon: 'twitter', name: 'Twitter', domain: /twitter\.com/, match: /twitter/i}
|
|
|
|
{icon: 'github', name: 'GitHub', domain: /github\.(com|io)/, match: /github/i}
|
|
|
|
{icon: 'gplus', name: 'Google Plus', domain: /plus\.google\.com/, match: /(google|^g).?(\+|plus)/i}
|
|
|
|
{icon: 'linkedin', name: 'LinkedIn', domain: /linkedin\.com/, match: /(google|^g).?(\+|plus)/i}
|
2014-04-09 16:14:52 -04:00
|
|
|
]
|
|
|
|
for icon in icons
|
|
|
|
if (link.name.search(icon.match) isnt -1) or (link.link.search(icon.domain) isnt -1)
|
|
|
|
icon.url = "/images/pages/account/profile/icon_#{icon.icon}.png"
|
|
|
|
return icon
|
|
|
|
null
|
2014-04-10 17:59:32 -04:00
|
|
|
|
|
|
|
onContactCandidate: (e) ->
|
|
|
|
@openModalView new JobProfileContactView recipientID: @user.id
|
2014-05-31 01:12:44 -04:00
|
|
|
|
|
|
|
saveEdits: (e) ->
|
|
|
|
res = @user.validate()
|
|
|
|
if res?
|
|
|
|
console.error "Couldn't save because of validation errors:", res
|
|
|
|
# TODO: show some sort of problem message here
|
|
|
|
return
|
|
|
|
jobProfile = @user.get('jobProfile')
|
|
|
|
jobProfile.updated = (new Date()).toISOString()
|
|
|
|
@user.set 'jobProfile', jobProfile
|
|
|
|
return unless res = @user.save()
|
|
|
|
res.error ->
|
|
|
|
errors = JSON.parse(res.responseText)
|
|
|
|
# TODO: show some sort of problem message here
|
|
|
|
res.success (model, response, options) =>
|
|
|
|
@render()
|
|
|
|
|
|
|
|
onEditProfilePhoto: (e) ->
|
|
|
|
filepicker.pick {mimetypes: 'image/*'}, @onProfilePhotoChosen
|
|
|
|
|
|
|
|
onProfilePhotoChosen: (inkBlob) =>
|
|
|
|
filePath = "db/user/#{@user.id}"
|
|
|
|
body =
|
|
|
|
url: inkBlob.url
|
|
|
|
filename: inkBlob.filename
|
|
|
|
mimetype: inkBlob.mimetype
|
|
|
|
path: filePath
|
|
|
|
force: true
|
|
|
|
|
|
|
|
@uploadingPath = [filePath, inkBlob.filename].join('/')
|
|
|
|
@$el.find('.profile-photo').addClass('saving')
|
|
|
|
$.ajax '/file', type: 'POST', data: body, success: @onFileUploaded
|
|
|
|
|
|
|
|
onFileUploaded: (e) =>
|
|
|
|
@user.get('jobProfile').photoURL = @uploadingPath
|
|
|
|
@saveEdits()
|
|
|
|
|
|
|
|
onEditSection: (e) ->
|
|
|
|
section = $(e.target).closest('.editable-section')
|
|
|
|
section.find('.editable-form').show()
|
|
|
|
section.find('.editable-display').hide()
|
|
|
|
@$el.find('.editable-section').not(section).addClass 'deemphasized'
|
|
|
|
column = section.closest('.full-height-column')
|
|
|
|
@$el.find('.full-height-column').not(column).addClass 'deemphasized'
|
|
|
|
|
|
|
|
onCancelSectionEdit: (e) ->
|
|
|
|
@render()
|
|
|
|
|
|
|
|
onSaveSection: (e) ->
|
|
|
|
e.preventDefault()
|
|
|
|
section = $(e.target).closest('.editable-section')
|
|
|
|
isEmpty = @arrayItemIsEmpty
|
|
|
|
section.find('.editable-array .array-item').each ->
|
|
|
|
$(@).remove() if isEmpty @
|
|
|
|
resetOnce = false # We have to clear out arrays if we're going to redo them
|
|
|
|
for field in $(e.target).closest('form').serializeArray()
|
|
|
|
keyChain = @extractFieldKeyChain field.name
|
|
|
|
value = @extractFieldValue keyChain[0], field.value
|
|
|
|
console.log "Should save", keyChain, value
|
|
|
|
parent = @user.get('jobProfile')
|
|
|
|
for key, i in keyChain
|
|
|
|
break if i is keyChain.length - 1
|
|
|
|
child = parent[key]
|
|
|
|
if _.isArray(child) and not resetOnce
|
|
|
|
child = parent[key] = []
|
|
|
|
resetOnce = true
|
|
|
|
else unless child?
|
|
|
|
child = parent[key] = {}
|
|
|
|
parent = child
|
|
|
|
console.log " Setting", parent, "prop", key, "to", value
|
|
|
|
parent[key] = value
|
|
|
|
section.addClass 'saving'
|
|
|
|
@saveEdits()
|
|
|
|
|
|
|
|
extractFieldKeyChain: (key) ->
|
|
|
|
# "root[projects][0][name]" -> ["projects", "0", "name"]
|
|
|
|
key.replace(/^root/, '').replace(/\[(.*?)\]/g, '.$1').replace(/^\./, '').split(/\./)
|
|
|
|
|
|
|
|
extractFieldValue: (key, value) ->
|
|
|
|
switch key
|
|
|
|
when 'active' then Boolean value
|
|
|
|
else value
|
|
|
|
|
|
|
|
arrayItemIsEmpty: (arrayItem) ->
|
|
|
|
for input in $(arrayItem).find('input')
|
|
|
|
return false if $(input).val()
|
|
|
|
true
|
|
|
|
|
|
|
|
onEditArray: (e) ->
|
|
|
|
array = $(e.target).closest('.editable-array')
|
|
|
|
arrayItems = array.find('.array-item')
|
|
|
|
toRemove = []
|
|
|
|
for arrayItem, index in arrayItems
|
|
|
|
empty = @arrayItemIsEmpty arrayItem
|
|
|
|
if index is arrayItems.length - 1
|
|
|
|
lastEmpty = empty
|
|
|
|
else if empty
|
|
|
|
toRemove.unshift index
|
|
|
|
$(arrayItems[emptyIndex]).remove() for emptyIndex in toRemove
|
|
|
|
unless lastEmpty
|
|
|
|
clone = $(arrayItem).clone(true)
|
|
|
|
clone.find('input').each -> $(@).val('')
|
|
|
|
array.append clone
|
|
|
|
for arrayItem, index in array.find('.array-item')
|
|
|
|
for input in $(arrayItem).find('input')
|
|
|
|
$(input).attr('name', $(input).attr('name').replace(/\[\d+\]/, "[#{index}]"))
|