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