diff --git a/app/assets/images/pages/base/recruitment_logo.png b/app/assets/images/pages/base/recruitment_logo.png new file mode 100644 index 000000000..6e107540b Binary files /dev/null and b/app/assets/images/pages/base/recruitment_logo.png differ diff --git a/app/assets/images/pages/employer/anon_user.png b/app/assets/images/pages/employer/anon_user.png new file mode 100644 index 000000000..34c2f197b Binary files /dev/null and b/app/assets/images/pages/employer/anon_user.png differ diff --git a/app/assets/images/pages/employer/briefcase.png b/app/assets/images/pages/employer/briefcase.png new file mode 100644 index 000000000..66e605a47 Binary files /dev/null and b/app/assets/images/pages/employer/briefcase.png differ diff --git a/app/assets/images/pages/employer/education.png b/app/assets/images/pages/employer/education.png new file mode 100644 index 000000000..6c4d5b63c Binary files /dev/null and b/app/assets/images/pages/employer/education.png differ diff --git a/app/assets/images/pages/employer/location.png b/app/assets/images/pages/employer/location.png new file mode 100644 index 000000000..3a21f6422 Binary files /dev/null and b/app/assets/images/pages/employer/location.png differ diff --git a/app/assets/images/pages/employer/tag.png b/app/assets/images/pages/employer/tag.png new file mode 100644 index 000000000..0b022ce92 Binary files /dev/null and b/app/assets/images/pages/employer/tag.png differ diff --git a/app/styles/employers.sass b/app/styles/employers.sass index 233dd5e10..1e11323fa 100644 --- a/app/styles/employers.sass +++ b/app/styles/employers.sass @@ -1,7 +1,61 @@ #employers-view - h1, h2, h3 - font: Arial + button + background: #fce232 /* Old browsers */ + background: -moz-linear-gradient(top, #fce232 0%, #ea8e2b 100%) + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fce232), color-stop(100%,#ea8e2b)) + background: -webkit-linear-gradient(top, #fce232 0%,#ea8e2b 100%) + background: -o-linear-gradient(top, #fce232 0%,#ea8e2b 100%) + background: -ms-linear-gradient(top, #fce232 0%,#ea8e2b 100%) + background: linear-gradient(to bottom, #fce232 0%,#ea8e2b 100%) + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fce232', endColorstr='#ea8e2b',GradientType=0 ) + vertical-align: text-bottom + margin-left: 30px + + //filter panels + #filter + margin-bottom: 10px + .panel-heading + background-color: darkgrey + .panel-body + background-color: darkgrey + + #filters + .filter_section + width: 16% + display: inline-block + vertical-align: top + margin-bottom: 10px + .get-started-button + vertical-align: text-bottom + margin-left: 10px + + #filter-button, #create-alert-button + float: right + + #login-link, #logout-button + float: right + color: #333333 + display: inline-block + :visited + color: #333333 + #logout-button:hover + cursor: pointer + + #tagline, .hiring-call-to-action + width: 100% + text-align: center + display: inline-block + margin-top: 20px + h1, h2, h3 + display: inline-block + button + display: inline-block + h1, h2, h3, h4 + font-family: Arial, Helvetica, sans-serif + color: #333333 + #tagline + margin-bottom: 20px .see-candidates-header margin: 30px @@ -10,23 +64,85 @@ #see-candidates cursor: pointer - .employer_icon - width: 125px - float: left - margin: 0px 15px 15px 0px + .reasons + height: 275px + margin-bottom: 25px + width: 100% - .information_row - height: 150px - padding-right: 15px - - #leftside - width: 500px - float: left - - #rightside - width: 500px - float: left + .information_row + height: 150px + padding-right: 15px + + .reason + width: 33% + padding-left: 3% + height: 150px + display: inline-block + .employer_icon + width: 125px + margin: 0px auto + + .reason_long + width: 50% + padding-left: 3% + display: inline-block + .employer_icon + display: inline-block + width: 25% + max-width: 125px + vertical-align: text-bottom + .reason_text + display: inline-block + width: 75% + #bottom_row + height: auto + #candidate-table + width: 96% + margin-left: 2% + margin-right: 2% + background-color: #E7E7E7 + table + cursor: pointer + width: 96% + margin-left: 2% + margin-right: 2% + margin-bottom: 30px + .tag_column + width: 25% + display: inline-block + .location_column + display: inline-block + width: 25% + .education_column + display: inline-block + width: 25% + .work_column + display: inline-block + width: 25% + tr + .candidate-picture + width: 50px + height: 50px + border-radius: 5px + overflow: hidden + margin-right: 10px + + .candidate-description + width: 100% + vertical-align: bottom + td + margin-bottom: 10px + margin-top: 10px + padding-bottom: 5px + padding-top: 10px + .border_row + border-bottom: 1px solid #d3d3d3 + vertical-align: bottom + padding-top: 0px + + #results + display: inline-block .tablesorter //img // display: none @@ -68,7 +184,7 @@ #employers-view, #profile-view.viewed-by-employer #outer-content-wrapper, #intermediate-content-wrapper, #inner-content-wrapper - background: #949494 + background: #B4B4B4 .main-content-area background-color: #EAEAEA diff --git a/app/styles/recruitment_base.sass b/app/styles/recruitment_base.sass new file mode 100644 index 000000000..06bfe815c --- /dev/null +++ b/app/styles/recruitment_base.sass @@ -0,0 +1,21 @@ +@import "bootstrap/variables" +@import "bootstrap/mixins" +@import "base" + +#employers-wrapper + background-color: #B4B4B4 + height: 100% + #outer-content-wrapper, #intermediate-content-wrapper, #inner-content-wrapper + background: #B4B4B4 + + .navbar, #top-nav, .content.clearfix + background-color: #B4B4B4 + + .footer + border-top: none + background-color: #B4B4B4 + padding-bottom: 50px + + +#employer-content-area + margin: auto \ No newline at end of file diff --git a/app/templates/community.jade b/app/templates/community.jade index 3ff8d3444..755e55cf4 100644 --- a/app/templates/community.jade +++ b/app/templates/community.jade @@ -79,9 +79,6 @@ block content li a(href="/contribute#ambassador", data-i18n="classes.ambassador_title") | : support our community of educators and coders. - li - a(href="/contribute#counselor", data-i18n="classes.counselor_title") - | : offer your advice and business acumen to the founders. | Check out the a(href="/contribute", data-i18n="nav.contribute") diff --git a/app/templates/contribute/contribute.jade b/app/templates/contribute/contribute.jade index d9457e6d8..5fdb19698 100644 --- a/app/templates/contribute/contribute.jade +++ b/app/templates/contribute/contribute.jade @@ -179,23 +179,4 @@ block content .contributor-signup(data-contributor-class-id="support", data-contributor-class-name="ambassador") - #counselor.header-scrolling-fix - - .class_image - img.img-responsive(src="/images/pages/contribute/counselor.png", alt="") - - h3.header-scrolling-fix - span(data-i18n="classes.counselor_title") Counselor - span - span(data-i18n="classes.counselor_title_description") (Expert/Teacher) - p(data-i18n="contribute.counselor_summary") - | None of the above roles fit what you are interested in? Do not worry, we are on the - | lookout for anybody who wants a hand in the development of CodeCombat! If you are - | interested in teaching, game development, open source management, or anything else - | that you think will be relevant to us, then this class is for you. - - a(href="/contribute/counselor") - p.lead(data-i18n="contribute.more_about_counselor") - | Learn More About Becoming a Counselor - div.clearfix \ No newline at end of file diff --git a/app/templates/contribute/contribute_nav.jade b/app/templates/contribute/contribute_nav.jade index c7379e975..90b07133e 100644 --- a/app/templates/contribute/contribute_nav.jade +++ b/app/templates/contribute/contribute_nav.jade @@ -30,9 +30,4 @@ ul.contribute_class.affix.nav.nav-list.nav-pills#contribute-nav a(href=navPrefix + "#ambassador") span(data-i18n="classes.ambassador_title") Ambassador span - span(data-i18n="classes.ambassador_title_description") (Support) - li - a(href=navPrefix + "#counselor") - span(data-i18n="classes.counselor_title") Counselor - span - span(data-i18n="classes.counselor_title_description") (Expert/Teacher) \ No newline at end of file + span(data-i18n="classes.ambassador_title_description") (Support) \ No newline at end of file diff --git a/app/templates/contribute/counselor.jade b/app/templates/contribute/counselor.jade deleted file mode 100644 index 36a79d8cc..000000000 --- a/app/templates/contribute/counselor.jade +++ /dev/null @@ -1,49 +0,0 @@ -extends /templates/base - -block content - - div.contribute_class - - include /templates/contribute/contribute_nav - - div.class-main#sounselor-main - - .class_image - img.img-responsive(src="/images/pages/contribute/counselor.png", alt="") - - h2 - span(data-i18n="classes.counselor_title") Counselor - span - span(data-i18n="classes.counselor_title_description") (Expert/Teacher) - p(data-i18n="contribute.counselor_introduction_1") - | Do you have life experience? - | A different perspective on things that can help us decide how to shape CodeCombat? - | Of all these roles, this will probably take the least time, but - | individually you may make the most difference. - | We're on the lookout for wisened sages, particularly in areas like: teaching, - | game development, open source project management, technical recruiting, entrepreneurship, - | or design. - - p(data-i18n="contribute.counselor_introduction_2") - | Or really anything that is relevant to the development of CodeCombat. - | If you have knowledge and want to share it to help grow this project, then - | this class might be for you. - - h4(data-i18n="contribute.class_attributes") Class Attributes - ul - li(data-i18n="contribute.counselor_attribute_1") - | Experience, in any of the areas above or something you think might be helpful. - li(data-i18n="contribute.counselor_attribute_2") - | A little bit of free time! - - h4(data-i18n="contribute.how_to_join") How to Join - p - a(title='Contact', tabindex=-1, data-toggle="coco-modal", data-target="modal/contact", data-i18n="contribute.contact_us_url") - | Contact us - span , - span(data-i18n="contribute.counselor_join_desc") - | tell us a little about yourself, what you've done and what you'd - | be interested in doing. We'll put you in our contact list and be in touch - | when we could use advice (not too often). - - div.clearfix diff --git a/app/templates/employers.jade b/app/templates/employers.jade index 665a0e28d..01f6debd7 100644 --- a/app/templates/employers.jade +++ b/app/templates/employers.jade @@ -1,140 +1,175 @@ -extends /templates/base +extends /templates/recruitment_base block content - - h1(data-i18n="employers.want_to_hire_our_players") Hire CodeCombat Players + if me.get('anonymous') + a#login-link Login + br + if !isEmployer && !me.isAdmin() + #tagline + h1(data-i18n="employers.hire_developers_not_credentials") Hire developers, not credentials. + button.btn.get-started-button Get started + else + if !me.get('anonymous') + a#logout-button(data-i18n="login.log_out") Logout + br + #filter + .panel-group#filter_panel + a#filter-link(data-toggle="collapse" data-target="#collapseOne") + .panel.panel-default + .panel-heading + h4.panel-title + + span.glyphicon.glyphicon-folder-open#folder-icon + | Filter + .panel-collapse.collapse.in#collapseOne + .panel-body + form#filters + .filter_section#screened_filter + h4 Screened + input(type="checkbox" name="phoneScreenFilter" value="true") + | Phone Screened + br + input(type="checkbox" name="phoneScreenFilter" value="false") + | Not Phone Screened + .filter_section#visa_filter + h4 Visa + input(type="checkbox" name="visa" value="Authorized to work in the US") + | US Authorized + br + input(type="checkbox" name="visa" value="Need visa sponsorship") + | Not Authorized + .filter_section#school_filter + h4 School + input(type="checkbox" name="schoolFilter" value="Top 20 Eng.") + | Top 20 Eng. + br + input(type="checkbox" name="schoolFilter" value="Other US") + | Other US + br + input(type="checkbox" name="schoolFilter" value="Other Intl.") + | Other Intl. + .filter_section#location_filter + h4 Location + input(type="checkbox" name="locationFilter" value="Bay Area") + | Bay Area + br + input(type="checkbox" name="locationFilter" value="New York") + | New York + br + input(type="checkbox" name="locationFilter" value="Other US") + | Other US + br + input(type="checkbox" name="locationFilter" value="International") + | International + .filter_section#role_filter + h4 Role + input(type="checkbox" name="roleFilter" value="Web Developer") + | Web Developer + br + input(type="checkbox" name="roleFilter" value="Software Developer") + | Software Developer + br + input(type="checkbox" name="roleFilter" value="iOS Developer") + | iOS Developer + br + input(type="checkbox" name="roleFilter" value="Android Developer") + | Android Developer + br + input(type="checkbox" name="roleFilter" value="Project Manager") + | Project Developer + .filter_section#seniority_filter + h4 Seniority + input(type="checkbox" name="seniorityFilter" value="College Student") + | College Student + br + input(type="checkbox" name="seniorityFilter" value="Recent Grad") + | Recent Grad + br + input(type="checkbox" name="seniorityFilter" value="Junior") + | Junior + br + input(type="checkbox" name="seniorityFilter" value="Senior") + | Senior + br + input(type="checkbox" name="seniorityFilter" value="Management") + | Management + //input#select_all_checkbox(type="checkbox" name="select_all" checked) + //| Select all + button.btn#filter-button Filter + p#results #{numberOfCandidates} results + //button.btn#create-alert-button Create Alert + if candidates.length + #candidate-table + table + tbody + for candidate, index in featuredCandidates + - var profile = candidate.get('jobProfile'); + - var authorized = candidate.id; // If we have the id, then we are authorized. + - var profileAge = (new Date() - new Date(profile.updated)) / 86400 / 1000; + - var expired = profileAge > 2 * 30.4; + - var curated = profile.curated; + + tr.candidate-row(data-candidate-id=candidate.id, id=candidate.id, class=expired ? "expired" : "") + td(rowspan=2) + .candidate-picture + img(src=candidate.getPhotoURL(50), alt=profile.name, title=profile.name, width=50) + if curated && curated.shortDescription + td.candidate-description #{curated.shortDescription} + else + td.candidate-description #{profile.shortDescription} + tr.border_row(data-candidate-id=candidate.id) + if curated + - var workHistory = curated.workHistory.join(","); + td.tag_column + img(src="/images/pages/employer/tag.png") + | #{curated.mainTag} + td.location_column + img(src="/images/pages/employer/location.png") + | #{curated.location} + td.education_column + img(src="/images/pages/employer/education.png") + | #{curated.education} + td.work_column + img(src="/images/pages/employer/briefcase.png") + | #{workHistory} + else + td Hi if !isEmployer && !me.isAdmin() div#info_wrapper - - div#leftside - - div.information_row - - img(class="employer_icon" src="/images/pages/employer/employer_icon1.png") - - h2(data-i18n="employers.what") What is CodeCombat? - - p(data-i18n="employers.what_blurb") CodeCombat is a multiplayer browser programming game. Players write code to control their forces in battle against other developers. We support JavaScript, Python, Lua, Clojure, CoffeeScript, and Io. - - div.information_row - + span.hiring-call-to-action + h2#start-hiring(data-i18n="employers.start_hiring") Start hiring. + button.btn.get-started-button Get started + + h2#hiring-reasons.hiring-call-to-action(data-i18n="employers.reasons") 3 reasons you should hire through us: + .reasons#top_row + .reason + img.employer_icon(src="/images/pages/employer/employer_icon2.png") + h3(data-i18n="employers.everyone_looking") Everyone here is looking for work. + p(data-i18n="employers.everyone_looking_blurb") Forget about 20% LinkedIn InMail response rates. Everyone that we list on this site wants to find their next position and will respond to your request for an introduction. + .reason + img.employer_icon(src="/images/pages/employer/employer_icon6.png") + h3(data-i18n="employers.weeding") We've done the weeding for you. + //this will break in i18n. Fix the inlining + p(data-i18n="employers.weeding_blurb") + | Every candidate that has a + span.glyphicon.glyphicon-earphone + | icon has already gone through a phone screen with us. We only feature developers that we would work with. + .reason img(class="employer_icon" src="/images/pages/employer/employer_icon3.png") - - h2(data-i18n="employers.who") Who Are the Players? - - p(data-i18n="employers.who_blurb") CodeCombateers are CTOs, VPs of Engineering, and graduates of top 20 engineering schools. No junior developers here. Our players enjoy playing with code and solving problems. - - div.information_row - - img(class="employer_icon" src="/images/pages/employer/employer_icon5.png") - - h2(data-i18n="employers.cost") Who Are the Players? - - p(data-i18n="employers.cost_blurb") CodeCombateers are CTOs, VPs of Engineering, and graduates of top 20 engineering schools. No junior developers here. Our players enjoy playing with code and solving problems. - - div#rightside - - div.information_row - - img(class="employer_icon" src="/images/pages/employer/employer_icon2.png") - - h2(data-i18n="employers.how") How Much Do we Charge? - - p(data-i18n="employers.how_blurb") We charge 15% of first year's salary and offer a 100% money back guarantee for 90 days. We don't charge for candidates who are already actively being interviewed at your company. - - div.information_row - - img(class="employer_icon" src="/images/pages/employer/employer_icon4.png") - - h2(data-i18n="employers.why") Why Hire Through Us? - - p - span(data-i18n="employers.why_blurb_1") We will save you time. Every CodeCombateer we feaure is - strong(data-i18n="employers.why_blurb_2") looking for work - span(data-i18n="employers.why_blurb_3") , has - strong(data-i18n="employers.why_blurb_4") demonstrated top notch technical skills - span(data-i18n="employers.why_blurb_5") , and has been - strong(data-i18n="employers.why_blurb_6") personally screened by us - span(data-i18n="employers.why_blurb_7") . Stop screening and start hiring. - - div.information_row - - img(class="employer_icon" src="/images/pages/employer/employer_icon6.png") - - h2(data-i18n="employers.response") What's the Response Rate? - - p(data-i18n="employers.response_blurb") Almost every developer you contact on CodeCombat will respond to inquires whether or not they want to interivew. If you would like help finding a candidate for your role, we can make recommendations. - - if candidates.length - - 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() - th(data-i18n="employers.candidate_who") Who - 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. - - var profileAge = (new Date() - new Date(profile.updated)) / 86400 / 1000; - - var expired = profileAge > 2 * 30.4; - tr(data-candidate-id=candidate.id, id=candidate.id, class=expired ? "expired" : "") - td - if authorized - img(src=candidate.getPhotoURL(50), alt=profile.name, title=profile.name, height=50) - if profile.name - p= profile.name - else if me.isAdmin() - p (#{candidate.get('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 - code= skill - span - td= profile.experience - td(data-profile-age=profileAge)= moment(profile.updated).fromNow() - if me.isAdmin() - td= remarks[candidate.id] ? remarks[candidate.id].get('contactName') : '' - if me.isAdmin() && area.id == 'inactive-candidates' - if candidate.get('jobProfileApproved') - td ✓ - else - td ✗ + h3(data-i18n="employers.pass_screen") They will pass your technical screen. + p(data-i18n="employers.pass_screen_blurb") All of these developers have ranked in our programming competitions. One employer found that 5x as many of our devs passed their technical screen than hiring from Hacker News. + span.hiring-call-to-action + h2(data-i18n="employers.make_hiring_easier") Make my hiring easier, please. + button.btn.get-started-button Get started + .reasons#bottom_row + .reason_long + img.employer_icon(src="/images/pages/employer/employer_icon1.png") + .reason_text + h3(data-i18n="employers.what") What is CodeCombat? + p(data-i18n="employers.what_blurb") CodeCombat is a multiplayer browser programming game. Players write code to control their forces in battle against other developers. We support JavaScript, Python, Lua, Clojure, CoffeeScript, and Io. + .reason_long + img.employer_icon(src="/images/pages/employer/employer_icon5.png") + .reason_text + h3(data-i18n="employers.cost") Who Are the Players? + p(data-i18n="employers.cost_blurb") CodeCombateers are CTOs, VPs of Engineering, and graduates of top 20 engineering schools. No junior developers here. Our players enjoy playing with code and solving problems. diff --git a/app/templates/recruitment_base.jade b/app/templates/recruitment_base.jade new file mode 100644 index 000000000..b04d4848d --- /dev/null +++ b/app/templates/recruitment_base.jade @@ -0,0 +1,21 @@ +body + #fb-root + #employers-wrapper + block header + .nav + .content.clearfix + .navbar-header + a.navbar-brand(href='/') + img(src="/images/pages/base/recruitment_logo.png", title="CodeCombat - Learn how to code by playing a game", alt="CodeCombat") + block outer_content + #outer-content-wrapper + + #intermediate-content-wrapper + + #inner-content-wrapper + .main-content-area#employer-content-area + block content + p If this is showing, you dun goofed + + block footer + .footer \ No newline at end of file diff --git a/app/views/contribute/counselor_view.coffee b/app/views/contribute/counselor_view.coffee deleted file mode 100644 index 6e5a6be2c..000000000 --- a/app/views/contribute/counselor_view.coffee +++ /dev/null @@ -1,8 +0,0 @@ -ContributeClassView = require 'views/contribute/contribute_class_view' -template = require 'templates/contribute/counselor' -{me} = require('lib/auth') - -module.exports = class CounselorView extends ContributeClassView - id: "counselor-view" - template: template - contributorClassName: 'counselor' diff --git a/app/views/employers_view.coffee b/app/views/employers_view.coffee index 2b1186422..788a2d584 100644 --- a/app/views/employers_view.coffee +++ b/app/views/employers_view.coffee @@ -21,11 +21,20 @@ module.exports = class EmployersView extends View events: 'click tbody tr': 'onCandidateClicked' + 'change #filters input': 'onFilterChanged' + 'click #filter-button': 'applyFilters' + 'change #select_all_checkbox': 'handleSelectAllChange' + 'click .get-started-button': 'openSignupModal' + 'click .navbar-brand': 'restoreBodyColor' + 'click #login-link': 'onClickAuthbutton' + 'click #filter-link': 'swapFolderIcon' constructor: (options) -> super options @getCandidates() - + @setFilterDefaults() + + afterRender: -> super() @sortTable() if @candidates.models.length @@ -33,19 +42,98 @@ module.exports = class EmployersView extends View afterInsert: -> super() _.delay @checkForEmployerSignupHash, 500 - + #fairly hacky, change this in the future + @originalBackgroundColor = $("body").css 'background-color' + $("body").css 'background-color', '#B4B4B4' + + restoreBodyColor: -> + $("body").css 'background-color', @originalBackgroundColor + + swapFolderIcon: -> + $("#folder-icon").toggleClass("glyphicon-folder-close").toggleClass("glyphicon-folder-open") + onFilterChanged: -> + @resetFilters() + that = @ + $("#filters :input").each -> + input = $(this) + checked = input.prop 'checked' + name = input.attr 'name' + value = input.val() + if name is "phoneScreenFilter" + value = JSON.parse(input.prop 'value') + if checked + that.filters[name] = _.union that.filters[name], [value] + else + that.filters[name] = _.difference that.filters[name], [value] + + for filterName, filterValues of @filters + if filterValues.length is 0 + @filters[filterName] = @defaultFilters[filterName] + + openSignupModal: -> + @openModalView new EmployerSignupView + handleSelectAllChange: (e) -> + checkedState = e.currentTarget.checked + $("#filters :input").each -> + $(this).prop 'checked', checkedState + @onFilterChanged() + + resetFilters: -> + for filterName, filterValues of @filters + @filters[filterName] = [] + + applyFilters: -> + candidateList = _.sortBy @candidates.models, (c) -> c.get('jobProfile').updated + candidateList = _.filter candidateList, (c) -> c.get('jobProfileApproved') + + filteredCandidates = candidateList + for filterName, filterValues of @filters + if filterName is "visa" + filteredCandidates = _.difference filteredCandidates, _.filter(filteredCandidates, (c) -> + fieldValue = c.get('jobProfile').visa + return not (_.contains filterValues, fieldValue) + ) + else + filteredCandidates = _.difference filteredCandidates, _.filter(filteredCandidates, (c) -> + unless c.get('jobProfile').curated then return true + fieldValue = c.get('jobProfile').curated?[filterName] + return not (_.contains filterValues, fieldValue) + ) + candidateIDsToShow = _.pluck filteredCandidates, 'id' + $("#candidate-table tr").each -> $(this).hide() + candidateIDsToShow.forEach (id) -> + $("[data-candidate-id=#{id}]").show() + $("#results").text(candidateIDsToShow.length + " results") + + + return filteredCandidates + setFilterDefaults: -> + @filters = + phoneScreenFilter: [true, false] + visa: ['Authorized to work in the US', 'Need visa sponsorship'] + schoolFilter: ['Top 20 Eng.', 'Other US', 'Other Intl.'] + locationFilter: ['Bay Area', 'New York', 'Other US', 'International'] + roleFilter: ['Web Developer', 'Software Developer', 'iOS Developer', 'Android Developer', 'Project Manager'] + seniorityFilter: ['College Student', 'Recent Grad', 'Junior', 'Senior', 'Management'] + @defaultFilters = _.cloneDeep @filters + + getRenderData: -> ctx = super() ctx.isEmployer = @isEmployer() - ctx.candidates = _.sortBy @candidates.models, (c) -> c.get('jobProfile').updated + ctx.candidates = _.sortBy @candidates.models, (c) -> -1 * c.get('jobProfile').experience 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') + unless @isEmployer() or me.isAdmin() + ctx.featuredCandidates = _.filter ctx.featuredCandidates, (c) -> c.get('jobProfile').curated + ctx.featuredCandidates = ctx.featuredCandidates.slice(0,7) ctx.otherCandidates = _.reject ctx.activeCandidates, (c) -> c.get('jobProfileApproved') ctx.remarks = {} ctx.remarks[remark.get('user')] = remark for remark in @remarks.models ctx.moment = moment ctx._ = _ + ctx.numberOfCandidates = ctx.featuredCandidates.length ctx isEmployer: -> @@ -64,10 +152,10 @@ module.exports = class EmployersView extends View renderCandidatesAndSetupScrolling: => @render() $(".nano").nanoScroller() - if window.history?.state?.lastViewedCandidateID - $(".nano").nanoScroller({scrollTo:$("#" + window.history.state.lastViewedCandidateID)}) - else if window.location.hash.length is 25 - $(".nano").nanoScroller({scrollTo:$(window.location.hash)}) + #if window.history?.state?.lastViewedCandidateID + # $(".nano").nanoScroller({scrollTo:$("#" + window.history.state.lastViewedCandidateID)}) + #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")) @@ -194,7 +282,7 @@ module.exports = class EmployersView extends View onCandidateClicked: (e) -> id = $(e.target).closest('tr').data('candidate-id') - if id + if id and (@isEmployer() or me.isAdmin()) if window.history oldState = _.cloneDeep window.history.state ? {} oldState["lastViewedCandidateID"] = id diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee index 3bd3bed78..0ed4f6a51 100644 --- a/server/users/user_handler.coffee +++ b/server/users/user_handler.coffee @@ -321,10 +321,10 @@ UserHandler = class UserHandler extends Handler @sendSuccess(res, candidates) formatCandidate: (authorized, document) -> - fields = if authorized then ['name', 'jobProfile', 'jobProfileApproved', 'photoURL', '_id'] else ['jobProfile', 'jobProfileApproved'] + fields = if authorized then ['name', 'jobProfile', 'jobProfileApproved', 'photoURL', '_id'] else ['_id','jobProfile', 'jobProfileApproved'] obj = _.pick document.toObject(), fields - obj.photoURL ||= obj.jobProfile.photoURL if authorized - subfields = ['country', 'city', 'lookingFor', 'jobTitle', 'skills', 'experience', 'updated', 'active'] + obj.photoURL ||= obj.jobProfile.photoURL #if authorized + subfields = ['country', 'city', 'lookingFor', 'jobTitle', 'skills', 'experience', 'updated', 'active', 'shortDescription', 'curated', 'visa'] if authorized subfields = subfields.concat ['name'] obj.jobProfile = _.pick obj.jobProfile, subfields