mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-05-02 00:43:34 -04:00
Upgrades to employer's candidate indexing.
This commit is contained in:
parent
dd2c7fab60
commit
22ca9507d0
6 changed files with 104 additions and 78 deletions
app
locale
styles
templates
views
server/users
|
@ -198,8 +198,8 @@
|
||||||
done_editing: "Done Editing"
|
done_editing: "Done Editing"
|
||||||
profile_for_prefix: "Profile for "
|
profile_for_prefix: "Profile for "
|
||||||
profile_for_suffix: ""
|
profile_for_suffix: ""
|
||||||
approved: "Approved"
|
featured: "Featured"
|
||||||
not_approved: "Not Approved"
|
not_featured: "Not Featured"
|
||||||
looking_for: "Looking for:"
|
looking_for: "Looking for:"
|
||||||
last_updated: "Last updated:"
|
last_updated: "Last updated:"
|
||||||
contact: "Contact"
|
contact: "Contact"
|
||||||
|
@ -295,7 +295,6 @@
|
||||||
project_link: "Link"
|
project_link: "Link"
|
||||||
project_link_help: "Link to the project."
|
project_link_help: "Link to the project."
|
||||||
|
|
||||||
|
|
||||||
employers:
|
employers:
|
||||||
want_to_hire_our_players: "Want to hire expert CodeCombat players?"
|
want_to_hire_our_players: "Want to hire expert CodeCombat players?"
|
||||||
see_candidates: "Click here to see our candidates"
|
see_candidates: "Click here to see our candidates"
|
||||||
|
@ -309,8 +308,9 @@
|
||||||
candidate_top_skills: "Top Skills"
|
candidate_top_skills: "Top Skills"
|
||||||
candidate_years_experience: "Yrs Exp"
|
candidate_years_experience: "Yrs Exp"
|
||||||
candidate_last_updated: "Last Updated"
|
candidate_last_updated: "Last Updated"
|
||||||
candidate_approved: "Us?"
|
featured_developers: "Featured Developers"
|
||||||
candidate_active: "Them?"
|
other_developers: "Other Developers"
|
||||||
|
inactive_developers: "Inactive Developers"
|
||||||
|
|
||||||
play_level:
|
play_level:
|
||||||
done: "Done"
|
done: "Done"
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#employers-view
|
#employers-view
|
||||||
#see-candidates
|
.see-candidates-header
|
||||||
cursor: pointer
|
margin-bottom: 30px
|
||||||
|
|
||||||
|
#see-candidates
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
.tablesorter
|
.tablesorter
|
||||||
//img
|
//img
|
||||||
// display: none
|
// display: none
|
||||||
|
|
|
@ -37,11 +37,11 @@ block content
|
||||||
if profileApproved
|
if profileApproved
|
||||||
button.btn.btn-success#toggle-job-profile-approved(disabled=!me.isAdmin())
|
button.btn.btn-success#toggle-job-profile-approved(disabled=!me.isAdmin())
|
||||||
i.icon-eye-open
|
i.icon-eye-open
|
||||||
span(data-i18n='account_profile.approved') Approved
|
span(data-i18n='account_profile.featured') Featured
|
||||||
else if me.isAdmin()
|
else if me.isAdmin()
|
||||||
button.btn#toggle-job-profile-approved
|
button.btn#toggle-job-profile-approved
|
||||||
i.icon-eye-close
|
i.icon-eye-close
|
||||||
span(data-i18n='account_profile.not_approved') Not Approved
|
span(data-i18n='account_profile.not_featured') Not Featured
|
||||||
if me.isAdmin() && !myProfile
|
if me.isAdmin() && !myProfile
|
||||||
button.btn.edit-settings-button#enter-espionage-mode 007
|
button.btn.edit-settings-button#enter-espionage-mode 007
|
||||||
//if editing && myProfile
|
//if editing && myProfile
|
||||||
|
|
|
@ -6,62 +6,77 @@ block content
|
||||||
|
|
||||||
p
|
p
|
||||||
span(data-i18n="employers.candidates_count_prefix") We currently have
|
span(data-i18n="employers.candidates_count_prefix") We currently have
|
||||||
if candidates.length
|
if activeCandidates.length
|
||||||
| #{candidates.length}
|
| #{activeCandidates.length}
|
||||||
else
|
else
|
||||||
span(data-i18n="employers.candidates_count_many") many
|
span(data-i18n="employers.candidates_count_many") many
|
||||||
|
|
|
|
||||||
span(data-i18n="employers.candidates_count_suffix") highly skilled and vetted developers looking for work.
|
span(data-i18n="employers.candidates_count_suffix") highly skilled and vetted developers looking for work.
|
||||||
if !isEmployer
|
|
||||||
|
if !isEmployer && !me.isAdmin()
|
||||||
h3
|
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
|
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
|
||||||
|
|
||||||
if candidates.length
|
if candidates.length
|
||||||
table.table.table-condensed.table-hover.table-responsive.tablesorter
|
|
||||||
thead
|
ul.nav.nav-pills
|
||||||
tr
|
li.active
|
||||||
th(data-i18n="general.name") Name
|
a(href="#featured-candidates", data-toggle="tab")
|
||||||
th(data-i18n="employers.candidate_location") Location
|
span(data-i18n="employers.featured_developers") Featured Developers
|
||||||
th(data-i18n="employers.candidate_looking_for") Looking For
|
| (#{featuredCandidates.length})
|
||||||
th(data-i18n="employers.candidate_role") Role
|
if otherCandidates.length
|
||||||
th(data-i18n="employers.candidate_top_skills") Top Skills
|
li
|
||||||
th(data-i18n="employers.candidate_years_experience") Yrs Exp
|
a(href="#other-candidates", data-toggle="tab")
|
||||||
th(data-i18n="employers.candidate_last_updated") Last Updated
|
span(data-i18n="employers.other_developers") Other Developers
|
||||||
if me.isAdmin()
|
| (#{otherCandidates.length})
|
||||||
th(data-i18n="employers.candidate_approved") Us?
|
if me.isAdmin() && inactiveCandidates.length
|
||||||
th(data-i18n="employers.candidate_active") Them?
|
li
|
||||||
|
a(href="#inactive-candidates", data-toggle="tab")
|
||||||
tbody
|
span(data-i18n="employers.inactive_developers") Inactive Developers
|
||||||
for candidate, index in candidates
|
| (#{inactiveCandidates.length})
|
||||||
- var profile = candidate.get('jobProfile');
|
|
||||||
- var authorized = candidate.id; // If we have the id, then we are authorized.
|
div.tab-content
|
||||||
tr(data-candidate-id=candidate.id, id=candidate.id)
|
for area, tabIndex in [{id: "featured-candidates", candidates: featuredCandidates}, {id: "other-candidates", candidates: otherCandidates}, {id: "inactive-candidates", candidates: inactiveCandidates}]
|
||||||
td
|
div(class="tab-pane well" + (tabIndex ? "" : " active"), id=area.id)
|
||||||
if authorized
|
table.table.table-condensed.table-hover.table-responsive.tablesorter
|
||||||
img(src=candidate.getPhotoURL(50), alt=profile.name, title=profile.name, height=50)
|
thead
|
||||||
p= profile.name
|
tr
|
||||||
else
|
th(data-i18n="general.name") Name
|
||||||
img(src="/images/pages/contribute/archmage.png", alt="", title="Sign up as an employer to see our candidates", width=50)
|
th(data-i18n="employers.candidate_location") Location
|
||||||
p Developer ##{index + 1}
|
th(data-i18n="employers.candidate_looking_for") Looking For
|
||||||
if profile.country == 'USA'
|
th(data-i18n="employers.candidate_role") Role
|
||||||
td= profile.city
|
th(data-i18n="employers.candidate_top_skills") Top Skills
|
||||||
else
|
th(data-i18n="employers.candidate_years_experience") Yrs Exp
|
||||||
td= profile.country
|
th(data-i18n="employers.candidate_last_updated") Last Updated
|
||||||
td= profile.lookingFor
|
if me.isAdmin() && area.id == 'inactive-candidates'
|
||||||
td= profile.jobTitle
|
th ✓?
|
||||||
td
|
|
||||||
each skill in profile.skills.slice(0, 10)
|
tbody
|
||||||
code= skill
|
for candidate, index in area.candidates
|
||||||
span
|
- var profile = candidate.get('jobProfile');
|
||||||
td= profile.experience
|
- var authorized = candidate.id; // If we have the id, then we are authorized.
|
||||||
td(data-profile-age=(new Date() - new Date(profile.updated)) / 86400 / 1000)= moment(profile.updated).fromNow()
|
tr(data-candidate-id=candidate.id, id=candidate.id)
|
||||||
if me.isAdmin()
|
td
|
||||||
if candidate.get('jobProfileApproved')
|
if authorized
|
||||||
td ✓
|
img(src=candidate.getPhotoURL(50), alt=profile.name, title=profile.name, height=50)
|
||||||
else
|
p= profile.name
|
||||||
td ✗
|
else
|
||||||
if profile.active
|
img(src="/images/pages/contribute/archmage.png", alt="", title="Sign up as an employer to see our candidates", width=50)
|
||||||
td ✓
|
p Developer ##{index + 1 + (area.id == 'featured-candidates' ? 0 : featuredCandidates.length)}
|
||||||
else
|
if profile.country == 'USA'
|
||||||
td ✗
|
td= profile.city
|
||||||
|
else
|
||||||
|
td= profile.country
|
||||||
|
td= profile.lookingFor
|
||||||
|
td= profile.jobTitle
|
||||||
|
td
|
||||||
|
each skill in profile.skills.slice(0, 10)
|
||||||
|
code= skill
|
||||||
|
span
|
||||||
|
td= profile.experience
|
||||||
|
td(data-profile-age=(new Date() - new Date(profile.updated)) / 86400 / 1000)= moment(profile.updated).fromNow()
|
||||||
|
if me.isAdmin() && area.id == 'inactive-candidates'
|
||||||
|
if candidate.get('jobProfileApproved')
|
||||||
|
td ✓
|
||||||
|
else
|
||||||
|
td ✗
|
||||||
|
|
|
@ -20,10 +20,7 @@ module.exports = class EmployersView extends View
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super options
|
super options
|
||||||
@getCandidates()
|
@getCandidates()
|
||||||
checkForEmployerSignupHash: =>
|
|
||||||
if window.location.hash is "#employerSignupLoggingIn" and not ("employer" in me.get("permissions"))
|
|
||||||
@openModalView application.router.getView("modal/employer_signup","_modal")
|
|
||||||
window.location.hash = ""
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
super()
|
super()
|
||||||
@sortTable() if @candidates.models.length
|
@sortTable() if @candidates.models.length
|
||||||
|
@ -33,13 +30,20 @@ module.exports = class EmployersView extends View
|
||||||
_.delay @checkForEmployerSignupHash, 500
|
_.delay @checkForEmployerSignupHash, 500
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
c = super()
|
ctx = super()
|
||||||
c.candidates = @candidates.models
|
ctx.isEmployer = @isEmployer()
|
||||||
userPermissions = me.get('permissions') ? []
|
ctx.candidates = _.sortBy @candidates.models, (c) -> c.get('jobProfile').updated
|
||||||
|
ctx.activeCandidates = _.filter ctx.candidates, (c) -> c.get('jobProfile').active
|
||||||
|
ctx.inactiveCandidates = _.reject ctx.candidates, (c) -> c.get('jobProfile').active
|
||||||
|
ctx.featuredCandidates = _.filter ctx.activeCandidates, (c) -> c.get('jobProfileApproved')
|
||||||
|
ctx.otherCandidates = _.reject ctx.activeCandidates, (c) -> c.get('jobProfileApproved')
|
||||||
|
ctx.moment = moment
|
||||||
|
ctx._ = _
|
||||||
|
ctx
|
||||||
|
|
||||||
c.isEmployer = _.contains userPermissions, "employer"
|
isEmployer: ->
|
||||||
c.moment = moment
|
userPermissions = me.get('permissions') ? []
|
||||||
c
|
_.contains userPermissions, "employer"
|
||||||
|
|
||||||
getCandidates: ->
|
getCandidates: ->
|
||||||
@candidates = new CandidatesCollection()
|
@candidates = new CandidatesCollection()
|
||||||
|
@ -55,6 +59,11 @@ module.exports = class EmployersView extends View
|
||||||
else if window.location.hash.length is 25
|
else if window.location.hash.length is 25
|
||||||
$(".nano").nanoScroller({scrollTo:$(window.location.hash)})
|
$(".nano").nanoScroller({scrollTo:$(window.location.hash)})
|
||||||
|
|
||||||
|
checkForEmployerSignupHash: =>
|
||||||
|
if window.location.hash is "#employerSignupLoggingIn" and not ("employer" in me.get("permissions"))
|
||||||
|
@openModalView application.router.getView("modal/employer_signup","_modal")
|
||||||
|
window.location.hash = ""
|
||||||
|
|
||||||
sortTable: ->
|
sortTable: ->
|
||||||
# http://mottie.github.io/tablesorter/docs/example-widget-bootstrap-theme.html
|
# http://mottie.github.io/tablesorter/docs/example-widget-bootstrap-theme.html
|
||||||
$.extend $.tablesorter.themes.bootstrap,
|
$.extend $.tablesorter.themes.bootstrap,
|
||||||
|
@ -110,7 +119,7 @@ module.exports = class EmployersView extends View
|
||||||
n *= -1
|
n *= -1
|
||||||
days.push n
|
days.push n
|
||||||
days[0] - days[1]
|
days[0] - days[1]
|
||||||
sortList: [[6, 0]]
|
sortList: if @isEmployer() or me.isAdmin() then [[6, 0]] else [[0, 1]]
|
||||||
# widget code contained in the jquery.tablesorter.widgets.js file
|
# widget code contained in the jquery.tablesorter.widgets.js file
|
||||||
# use the zebra stripe widget if you plan on hiding any rows (filter widget)
|
# use the zebra stripe widget if you plan on hiding any rows (filter widget)
|
||||||
widgets: ["uitheme", "zebra", "filter"]
|
widgets: ["uitheme", "zebra", "filter"]
|
||||||
|
|
|
@ -278,13 +278,11 @@ UserHandler = class UserHandler extends Handler
|
||||||
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()
|
||||||
#query = {'jobProfile.active': true, 'jobProfile.updated': {$gt: since}}
|
|
||||||
query = {'jobProfile.updated': {$gt: since}}
|
query = {'jobProfile.updated': {$gt: since}}
|
||||||
query.jobProfileApproved = true unless req.user.isAdmin()
|
#query.jobProfileApproved = true unless req.user.isAdmin() # We split into featured and other now.
|
||||||
query['jobProfile.active'] = true unless req.user.isAdmin()
|
query['jobProfile.active'] = true unless req.user.isAdmin()
|
||||||
selection = 'jobProfile'
|
selection = 'jobProfile jobProfileApproved'
|
||||||
selection += ' email' if authorized
|
selection += ' email' if authorized
|
||||||
selection += ' jobProfileApproved' if req.user.isAdmin()
|
|
||||||
User.find(query).select(selection).exec (err, documents) =>
|
User.find(query).select(selection).exec (err, documents) =>
|
||||||
return @sendDatabaseError(res, err) if err
|
return @sendDatabaseError(res, err) if err
|
||||||
candidates = (candidate for candidate in documents when @employerCanViewCandidate req.user, candidate.toObject())
|
candidates = (candidate for candidate in documents when @employerCanViewCandidate req.user, candidate.toObject())
|
||||||
|
@ -292,7 +290,7 @@ UserHandler = class UserHandler extends Handler
|
||||||
@sendSuccess(res, candidates)
|
@sendSuccess(res, candidates)
|
||||||
|
|
||||||
formatCandidate: (authorized, document) ->
|
formatCandidate: (authorized, document) ->
|
||||||
fields = if authorized then ['jobProfile', 'jobProfileApproved', 'photoURL', '_id'] else ['jobProfile']
|
fields = if authorized then ['jobProfile', 'jobProfileApproved', 'photoURL', '_id'] else ['jobProfile', 'jobProfileApproved']
|
||||||
obj = _.pick document.toObject(), fields
|
obj = _.pick document.toObject(), fields
|
||||||
obj.photoURL ||= obj.jobProfile.photoURL if authorized
|
obj.photoURL ||= obj.jobProfile.photoURL if authorized
|
||||||
subfields = ['country', 'city', 'lookingFor', 'jobTitle', 'skills', 'experience', 'updated', 'active']
|
subfields = ['country', 'city', 'lookingFor', 'jobTitle', 'skills', 'experience', 'updated', 'active']
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue