Implemented George's jobs page design.
This commit is contained in:
parent
b96bca8c18
commit
f17775cc10
12 changed files with 230 additions and 76 deletions
app
assets/images/pages/account/profile
education.pngicon_facebook.pngicon_github.pngicon_gplus.pngicon_linkedin.pngicon_twitter.pngwork.png
styles/account
templates/account
views/account
server/users
BIN
app/assets/images/pages/account/profile/education.png
Normal file
BIN
app/assets/images/pages/account/profile/education.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 559 B |
BIN
app/assets/images/pages/account/profile/icon_facebook.png
Normal file
BIN
app/assets/images/pages/account/profile/icon_facebook.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 684 B |
BIN
app/assets/images/pages/account/profile/icon_github.png
Normal file
BIN
app/assets/images/pages/account/profile/icon_github.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 890 B |
BIN
app/assets/images/pages/account/profile/icon_gplus.png
Normal file
BIN
app/assets/images/pages/account/profile/icon_gplus.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 1.2 KiB |
BIN
app/assets/images/pages/account/profile/icon_linkedin.png
Normal file
BIN
app/assets/images/pages/account/profile/icon_linkedin.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 750 B |
BIN
app/assets/images/pages/account/profile/icon_twitter.png
Normal file
BIN
app/assets/images/pages/account/profile/icon_twitter.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 791 B |
BIN
app/assets/images/pages/account/profile/work.png
Normal file
BIN
app/assets/images/pages/account/profile/work.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 563 B |
|
@ -1,37 +1,160 @@
|
||||||
#profile-view
|
#profile-view
|
||||||
button
|
.profile-control-bar
|
||||||
float: right
|
background-color: rgb(78, 78, 78)
|
||||||
i
|
width: 100%
|
||||||
margin-right: 5px
|
text-align: center
|
||||||
|
|
||||||
|
button.edit-settings-button
|
||||||
|
margin: 2px
|
||||||
|
i
|
||||||
|
margin-right: 5px
|
||||||
|
|
||||||
|
|
||||||
img.img-thumbnail
|
img.img-thumbnail
|
||||||
margin: 5px 20px 20px 20px
|
margin: 5px 20px 20px 20px
|
||||||
|
|
||||||
ul.links, ul.projects
|
|
||||||
margin: 0
|
|
||||||
padding: 0
|
|
||||||
|
|
||||||
li
|
|
||||||
list-style: none
|
|
||||||
|
|
||||||
.profile-header-container
|
|
||||||
h1
|
|
||||||
margin-bottom: 0px
|
|
||||||
|
|
||||||
.project-image
|
|
||||||
width: 360px
|
|
||||||
height: 270px
|
|
||||||
background-size: cover
|
|
||||||
background-repeat: no-repeat
|
|
||||||
background-position: center
|
|
||||||
|
|
||||||
ul.projects
|
|
||||||
li
|
|
||||||
margin-top: 20px
|
|
||||||
|
|
||||||
.approved, .not-approved
|
.approved, .not-approved
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
#job-profile-notes
|
.main-content-area
|
||||||
width: 100%
|
padding: 0
|
||||||
height: 100px
|
|
||||||
|
.flat-button
|
||||||
|
width: 100%
|
||||||
|
margin-bottom: 10px
|
||||||
|
background: rgb(78, 78, 78)
|
||||||
|
border: 0
|
||||||
|
border-radius: 0
|
||||||
|
padding: 10px
|
||||||
|
|
||||||
|
.job-profile-container
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
padding: 0
|
||||||
|
display: table
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif
|
||||||
|
color: #555
|
||||||
|
|
||||||
|
ul.links, ul.projects
|
||||||
|
margin: 0
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
li
|
||||||
|
list-style: none
|
||||||
|
|
||||||
|
.job-profile-row
|
||||||
|
height: 100%
|
||||||
|
display: table-row
|
||||||
|
|
||||||
|
.full-height-column
|
||||||
|
height: 100%
|
||||||
|
padding: 5px
|
||||||
|
display: table-cell
|
||||||
|
vertical-align: top
|
||||||
|
|
||||||
|
h3:first-child
|
||||||
|
margin: 5px 0 5px 0
|
||||||
|
|
||||||
|
.left-column
|
||||||
|
width: 250px
|
||||||
|
padding: 5px
|
||||||
|
background-color: rgb(220, 220, 220)
|
||||||
|
|
||||||
|
.profile-photo-container
|
||||||
|
position: relative
|
||||||
|
margin-bottom: 10px
|
||||||
|
|
||||||
|
img.profile-photo
|
||||||
|
width: 240px
|
||||||
|
border-radius: 6px
|
||||||
|
|
||||||
|
.profile-caption
|
||||||
|
background-color: rgba(0, 0, 0, 0.5)
|
||||||
|
color: white
|
||||||
|
border-bottom-right-radius: 6px
|
||||||
|
border-bottom-left-radius: 6px
|
||||||
|
position: absolute
|
||||||
|
width: 100%
|
||||||
|
bottom: 0px
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
ul.links
|
||||||
|
li.has-icon
|
||||||
|
display: inline-block
|
||||||
|
img
|
||||||
|
margin: 0 0 10px 0
|
||||||
|
li.has-icon:not(:nth-child(5))
|
||||||
|
img
|
||||||
|
margin: 0 10px 10px 0
|
||||||
|
|
||||||
|
#contact-candidate
|
||||||
|
margin-top: 20px
|
||||||
|
background-color: rgb(177, 55, 25)
|
||||||
|
padding: 15px
|
||||||
|
font-size: 20px
|
||||||
|
|
||||||
|
.middle-column
|
||||||
|
width: 524px
|
||||||
|
background-color: white
|
||||||
|
padding-left: 20px
|
||||||
|
padding-right: 20px
|
||||||
|
|
||||||
|
code
|
||||||
|
background-color: rgb(220, 220, 220)
|
||||||
|
color: #555
|
||||||
|
margin: 2px 0
|
||||||
|
display: inline-block
|
||||||
|
text-transform: lowercase
|
||||||
|
|
||||||
|
.long-description
|
||||||
|
margin-top: 10px
|
||||||
|
img
|
||||||
|
max-width: 524px - 60px
|
||||||
|
|
||||||
|
.header-icon
|
||||||
|
margin-right: 10px
|
||||||
|
width: 32px
|
||||||
|
height: 32px
|
||||||
|
|
||||||
|
.duration
|
||||||
|
margin-left: 10px
|
||||||
|
margin-bottom: 10px
|
||||||
|
|
||||||
|
#job-profile-notes
|
||||||
|
width: 100%
|
||||||
|
height: 100px
|
||||||
|
|
||||||
|
.right-column
|
||||||
|
width: 250px
|
||||||
|
background-color: white
|
||||||
|
|
||||||
|
ul.projects
|
||||||
|
li
|
||||||
|
margin-bottom: 10px
|
||||||
|
padding: 5px 5px
|
||||||
|
border: 2px solid rgb(220, 220, 220)
|
||||||
|
|
||||||
|
.project-image
|
||||||
|
width: 230px
|
||||||
|
height: 115px
|
||||||
|
background-size: cover
|
||||||
|
background-repeat: no-repeat
|
||||||
|
background-position: center
|
||||||
|
|
||||||
|
-webkit-filter: grayscale(100%)
|
||||||
|
-webkit-transition: .5s ease-in-out
|
||||||
|
-moz-filter: grayscale(100%)
|
||||||
|
-moz-transition: .5s ease-in-out
|
||||||
|
-o-filter: grayscale(100%)
|
||||||
|
-o-transition: .5s ease-in-out
|
||||||
|
filter: grayscale(100%)
|
||||||
|
transition: .5s ease-in-out
|
||||||
|
|
||||||
|
li:hover
|
||||||
|
.project-image
|
||||||
|
-webkit-filter: grayscale(0%)
|
||||||
|
-moz-filter: grayscale(0%)
|
||||||
|
-o-filter: grayscale(0%)
|
||||||
|
filter: grayscale(0%)
|
||||||
|
|
|
@ -2,60 +2,70 @@ extends /templates/base
|
||||||
|
|
||||||
block content
|
block content
|
||||||
|
|
||||||
if myProfile
|
if myProfile || (me.isAdmin() && user.get('jobProfile'))
|
||||||
a(href="/account/settings")
|
.profile-control-bar
|
||||||
button.btn
|
if myProfile
|
||||||
i.icon-cog
|
a(href="/account/settings")
|
||||||
span(data-i18n="account_profile.edit_settings") Edit Settings
|
button.btn.edit-settings-button
|
||||||
|
i.icon-cog
|
||||||
|
span(data-i18n="account_profile.edit_settings") Edit Settings
|
||||||
|
if me.isAdmin() && user.get('jobProfile')
|
||||||
|
button.btn.edit-settings-button#toggle-job-profile-approved
|
||||||
|
i.icon-cog
|
||||||
|
span(data-i18n='account_profile.approved').approved Approved
|
||||||
|
span(data-i18n='account_profile.approved').not-approved Not Approved
|
||||||
|
|
||||||
if user.get('jobProfile')
|
if user.get('jobProfile')
|
||||||
if me.isAdmin()
|
|
||||||
button.btn#toggle-job-profile-approved
|
|
||||||
i.icon-cog
|
|
||||||
span(data-i18n='account_profile.approved').approved Approved
|
|
||||||
span(data-i18n='account_profile.approved').not-approved Not Approved
|
|
||||||
|
|
||||||
- var profile = user.get('jobProfile');
|
- var profile = user.get('jobProfile');
|
||||||
.profile-header-container
|
.job-profile-container
|
||||||
img(src=photoURL).img-thumbnail.pull-left
|
.job-profile-row
|
||||||
h1= profile.name
|
.left-column.full-height-column
|
||||||
p.lead= profile.shortDescription
|
.profile-photo-container
|
||||||
.clearfix
|
img.profile-photo(src=photoURL)
|
||||||
.container
|
.profile-caption= profile.jobTitle || 'Software Developer'
|
||||||
.row
|
|
||||||
.col-md-2
|
if profileLinks.length
|
||||||
h2 Info
|
ul.links
|
||||||
|
each link in profileLinks
|
||||||
|
li(title=profile.name + " on " + link.name, class=link.icon ? "has-icon" : "")
|
||||||
|
a(href=link.link)
|
||||||
|
if link.icon
|
||||||
|
img(src=link.icon.url, alt=link.icon.name)
|
||||||
|
else
|
||||||
|
button.btn.btn-large.btn-inverse.flat-button= link.name
|
||||||
|
|
||||||
div= profile.city + ', ' + profile.country
|
div= profile.city + ', ' + profile.country
|
||||||
div= profile.visa
|
div= profile.visa
|
||||||
div Looking for: #{profile.lookingFor}
|
div Looking for: #{profile.lookingFor}
|
||||||
div Profile last updated #{moment(profile.updated).fromNow()}
|
div Last updated #{moment(profile.updated).fromNow()}
|
||||||
h3 Skills
|
|
||||||
|
button#contact-candidate.btn.btn-large.btn-inverse.flat-button Contact #{profile.name.split(' ')[0]}
|
||||||
|
|
||||||
|
.middle-column.full-height-column
|
||||||
|
h3= profile.name
|
||||||
|
p= profile.shortDescription
|
||||||
|
|
||||||
each skill in profile.skills
|
each skill in profile.skills
|
||||||
code= skill
|
code= skill
|
||||||
span
|
span
|
||||||
if profile.links.length
|
div.long-description!= marked(profile.longDescription)
|
||||||
h3 Links
|
|
||||||
ul.links
|
|
||||||
each link in profile.links
|
|
||||||
li
|
|
||||||
a(href=link.link) #{link.name}
|
|
||||||
|
|
||||||
.col-md-4
|
|
||||||
h2 About
|
|
||||||
div!= marked(profile.longDescription)
|
|
||||||
|
|
||||||
if profile.work.length
|
if profile.work.length
|
||||||
h3 Work Experience
|
h3
|
||||||
|
img.header-icon(src="/images/pages/account/profile/work.png", alt="")
|
||||||
|
| Work Experience
|
||||||
each job in profile.work
|
each job in profile.work
|
||||||
div.pull-right= job.duration
|
div.duration.pull-right= job.duration
|
||||||
strong #{job.role} at #{job.employer}
|
| #{job.role} at #{job.employer}
|
||||||
.clearfix
|
.clearfix
|
||||||
|
|
||||||
if profile.education.length
|
if profile.education.length
|
||||||
h3 Education
|
h3
|
||||||
|
img.header-icon(src="/images/pages/account/profile/education.png", alt="")
|
||||||
|
| Education
|
||||||
each school in profile.education
|
each school in profile.education
|
||||||
div.pull-right= school.duration
|
div.duration.pull-right= school.duration
|
||||||
strong #{school.degree} at #{school.school}
|
| #{school.degree} at #{school.school}
|
||||||
.clearfix
|
.clearfix
|
||||||
|
|
||||||
if user.get('jobProfileNotes') || me.isAdmin()
|
if user.get('jobProfileNotes') || me.isAdmin()
|
||||||
|
@ -66,16 +76,17 @@ block content
|
||||||
else
|
else
|
||||||
p!= marked(notes)
|
p!= marked(notes)
|
||||||
|
|
||||||
.col-md-4
|
.right-column.full-height-column
|
||||||
if profile.projects.length
|
if profile.projects.length
|
||||||
h2 Projects
|
h3 Projects
|
||||||
ul.projects
|
ul.projects
|
||||||
each project in profile.projects
|
each project in profile.projects
|
||||||
a(href="#{project.link}")
|
|
||||||
li
|
li
|
||||||
h3 #{project.name}
|
a(href=project.link)
|
||||||
.project-image(style="background-image: url(/file/" + project.picture + ")")
|
.project-image(style="background-image: url(/file/" + project.picture + ")")
|
||||||
|
p= project.name
|
||||||
p!= marked(project.description)
|
p!= marked(project.description)
|
||||||
|
a(href=project.link).btn.btn-large.btn-inverse.flat-button Check it out
|
||||||
|
|
||||||
else
|
else
|
||||||
h2
|
h2
|
||||||
|
|
|
@ -8,7 +8,7 @@ module.exports = class JobProfileView extends CocoView
|
||||||
|
|
||||||
editableSettings: [
|
editableSettings: [
|
||||||
'lookingFor', 'active', 'name', 'city', 'country', 'skills', 'experience', 'shortDescription', 'longDescription',
|
'lookingFor', 'active', 'name', 'city', 'country', 'skills', 'experience', 'shortDescription', 'longDescription',
|
||||||
'work', 'education', 'visa', 'projects', 'links'
|
'work', 'education', 'visa', 'projects', 'links', 'jobTitle'
|
||||||
]
|
]
|
||||||
readOnlySettings: [
|
readOnlySettings: [
|
||||||
'updated'
|
'updated'
|
||||||
|
|
|
@ -40,6 +40,11 @@ module.exports = class ProfileView extends View
|
||||||
context[key] = addedContext[key] for key of addedContext
|
context[key] = addedContext[key] for key of addedContext
|
||||||
context.marked = marked
|
context.marked = marked
|
||||||
context.moment = moment
|
context.moment = moment
|
||||||
|
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
|
||||||
context
|
context
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
|
@ -61,3 +66,17 @@ module.exports = class ProfileView extends View
|
||||||
notes = @$el.find("#job-profile-notes").val()
|
notes = @$el.find("#job-profile-notes").val()
|
||||||
@user.set 'jobProfileNotes', notes
|
@user.set 'jobProfileNotes', notes
|
||||||
@user.save()
|
@user.save()
|
||||||
|
|
||||||
|
iconForLink: (link) ->
|
||||||
|
icons = [
|
||||||
|
{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', 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}
|
||||||
|
]
|
||||||
|
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
|
||||||
|
|
|
@ -56,8 +56,9 @@ UserSchema = c.object {},
|
||||||
simulatedBy: {type: 'integer', minimum: 0, default: 0}
|
simulatedBy: {type: 'integer', minimum: 0, default: 0}
|
||||||
simulatedFor: {type: 'integer', minimum: 0, default: 0}
|
simulatedFor: {type: 'integer', minimum: 0, default: 0}
|
||||||
|
|
||||||
jobProfile: c.object {title: 'Job Profile', required: ['lookingFor', 'active', 'name', 'city', 'country', 'skills', 'experience', 'shortDescription', 'longDescription', 'visa', 'work', 'education', 'projects', 'links']},
|
jobProfile: c.object {title: 'Job Profile', required: ['lookingFor', 'jobTitle', 'active', 'name', 'city', 'country', 'skills', 'experience', 'shortDescription', 'longDescription', 'visa', 'work', 'education', 'projects', 'links']},
|
||||||
lookingFor: {title: 'Looking For', type: 'string', enum: ['Full-time', 'Part-time', 'Remote', 'Contracting', 'Internship'], default: 'Full-time', description: 'What kind of developer position do you want?'}
|
lookingFor: {title: 'Looking For', type: 'string', enum: ['Full-time', 'Part-time', 'Remote', 'Contracting', 'Internship'], default: 'Full-time', description: 'What kind of developer position do you want?'}
|
||||||
|
jobTitle: {type: 'string', maxLength: 50, title: 'Desired Job Title', description: 'What role are you looking for? Ex.: "Full Stack Engineer", "Front-End Developer", "iOS Developer"', default: 'Software Developer'}
|
||||||
active: {title: 'Active', type: 'boolean', description: 'Want interview offers right now?'}
|
active: {title: 'Active', type: 'boolean', description: 'Want interview offers right now?'}
|
||||||
updated: c.date {title: 'Last Updated', description: 'How fresh your profile appears to employers. The fresher, the better. Profiles go inactive after 30 days.'}
|
updated: c.date {title: 'Last Updated', description: 'How fresh your profile appears to employers. The fresher, the better. Profiles go inactive after 30 days.'}
|
||||||
name: c.shortString {title: 'Name', description: 'Name you want employers to see, like "Nick Winter".'}
|
name: c.shortString {title: 'Name', description: 'Name you want employers to see, like "Nick Winter".'}
|
||||||
|
@ -67,7 +68,7 @@ UserSchema = c.object {},
|
||||||
{type: 'string', minLength: 1, maxLength: 20, description: 'Ex.: "objective-c", "mongodb", "rails", "android", "javascript"'}
|
{type: 'string', minLength: 1, maxLength: 20, description: 'Ex.: "objective-c", "mongodb", "rails", "android", "javascript"'}
|
||||||
experience: {type: 'integer', title: 'Years of Experience', minimum: 0, description: 'How many years of professional experience (getting paid) developing software do you have?'}
|
experience: {type: 'integer', title: 'Years of Experience', minimum: 0, description: 'How many years of professional experience (getting paid) developing software do you have?'}
|
||||||
shortDescription: {type: 'string', maxLength: 140, title: 'Short Description', description: 'Who are you, and what are you looking for? 140 characters max.', default: 'Programmer seeking to build great software.'}
|
shortDescription: {type: 'string', maxLength: 140, title: 'Short Description', description: 'Who are you, and what are you looking for? 140 characters max.', default: 'Programmer seeking to build great software.'}
|
||||||
longDescription: {type: 'string', maxLength: 2000, title: 'Long Description', description: 'What are you looking for? Give employeers more details. Highlight your stunning personality. Markdown okay. 2000 characters max.', format: 'markdown', default: '* I write great code.\n* You need great code?\n* Great!'}
|
longDescription: {type: 'string', maxLength: 600, title: 'Description', description: 'What are you looking for? Give employeers more details. Highlight your stunning personality. Tasteful markdown okay. 600 characters max.', format: 'markdown', default: '* I write great code.\n* You need great code?\n* Great!'}
|
||||||
visa: c.shortString {title: 'US Work Status', description: 'Are you authorized to work in the US, or do you need visa sponsorship?', enum: ['Authorized to work in the US', 'Need visa sponsorship'], default: 'Authorized to work in the US'}
|
visa: c.shortString {title: 'US Work Status', description: 'Are you authorized to work in the US, or do you need visa sponsorship?', enum: ['Authorized to work in the US', 'Need visa sponsorship'], default: 'Authorized to work in the US'}
|
||||||
work: c.array {title: 'Work Experience', description: 'List your relevant work experience, most recent first.'},
|
work: c.array {title: 'Work Experience', description: 'List your relevant work experience, most recent first.'},
|
||||||
c.object {title: 'Job', description: 'Some work experience you had.', required: ['employer', 'role', 'duration']},
|
c.object {title: 'Job', description: 'Some work experience you had.', required: ['employer', 'role', 'duration']},
|
||||||
|
@ -83,7 +84,7 @@ UserSchema = c.object {},
|
||||||
c.object {title: 'Project', description: 'A project you created.', required: ['name', 'description', 'picture', 'link']},
|
c.object {title: 'Project', description: 'A project you created.', required: ['name', 'description', 'picture', 'link']},
|
||||||
name: c.shortString {title: 'Project Name', description: 'What was the project called?'}
|
name: c.shortString {title: 'Project Name', description: 'What was the project called?'}
|
||||||
description: {type: 'string', title: 'Description', description: 'Briefly describe the project.', maxLength: 400, format: 'markdown'}
|
description: {type: 'string', title: 'Description', description: 'Briefly describe the project.', maxLength: 400, format: 'markdown'}
|
||||||
picture: {type: 'string', title: 'Picture', format: 'image-file', description: 'Upload a 360x270px or larger image showing off the project.'}
|
picture: {type: 'string', title: 'Picture', format: 'image-file', description: 'Upload a 230x115px or larger image showing off the project.'}
|
||||||
link: c.url {title: 'Link', description: 'Link to the project.', default: 'http://codecombat.com'}
|
link: c.url {title: 'Link', description: 'Link to the project.', default: 'http://codecombat.com'}
|
||||||
links: c.array {title: 'Links', description: 'Link any other sites or profiles you want to highlight, like your GitHub, your LinkedIn, or your blog.'},
|
links: c.array {title: 'Links', description: 'Link any other sites or profiles you want to highlight, like your GitHub, your LinkedIn, or your blog.'},
|
||||||
c.object {title: 'Link', description: 'A link to another site you want to highlight, like your GitHub, your LinkedIn, or your blog.', required: ['name', 'link']},
|
c.object {title: 'Link', description: 'A link to another site you want to highlight, like your GitHub, your LinkedIn, or your blog.', required: ['name', 'link']},
|
||||||
|
|
Reference in a new issue