Skip to content

Release 2021/03/18 (v1.8.3) #5442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -283,21 +283,21 @@ workflows:
filters:
branches:
only:
- route-redirects
- gig-application-update
# This is alternate dev env for parallel testing
- "build-qa":
context : org-global
filters:
branches:
only:
- tco-leaderboard-fix
- free
# This is beta env for production soft releases
- "build-prod-beta":
context : org-global
filters:
branches:
only:
- free
- develop
# This is stage env for production QA releases
- "build-prod-staging":
context : org-global
Expand Down
12 changes: 12 additions & 0 deletions src/assets/images/checkmark-green.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed src/assets/images/social.jpg
Binary file not shown.
Binary file added src/assets/images/social.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 26 additions & 22 deletions src/server/services/recruitCRM.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ export default class RecruitCRMService {
const { body, file } = req;
const form = JSON.parse(body.form);
const fileData = new FormData();
fileData.append('resume', file.buffer, file.originalname);
if (file) {
fileData.append('resume', file.buffer, file.originalname);
}
let candidateSlug;
let referralCookie = req.cookies[config.GROWSURF_COOKIE];
if (referralCookie) referralCookie = JSON.parse(referralCookie);
Expand Down Expand Up @@ -272,29 +274,31 @@ export default class RecruitCRMService {
});
}
candidateData = await workCandidateResponse.json();
// Attach resume to candidate
const formHeaders = fileData.getHeaders();
const fileCandidateResponse = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateData.slug}`, {
method: 'POST',
headers: {
Authorization: this.private.authorization,
...formHeaders,
},
body: fileData,
});
if (fileCandidateResponse.status >= 300) {
return res.send({
error: true,
status: fileCandidateResponse.status,
url: `${this.private.baseUrl}/v1/candidates/${candidateData.slug}`,
form,
fileData,
file,
formHeaders,
errObj: await fileCandidateResponse.json(),
// Attach resume to candidate if uploaded
if (file) {
const formHeaders = fileData.getHeaders();
const fileCandidateResponse = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateData.slug}`, {
method: 'POST',
headers: {
Authorization: this.private.authorization,
...formHeaders,
},
body: fileData,
});
if (fileCandidateResponse.status >= 300) {
return res.send({
error: true,
status: fileCandidateResponse.status,
url: `${this.private.baseUrl}/v1/candidates/${candidateData.slug}`,
form,
fileData,
file,
formHeaders,
errObj: await fileCandidateResponse.json(),
});
}
candidateData = await fileCandidateResponse.json();
}
candidateData = await fileCandidateResponse.json();
// Candidate ready to apply for job
const applyResponse = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateData.slug}/assign?job_slug=${id}`, {
method: 'POST',
Expand Down
65 changes: 48 additions & 17 deletions src/shared/actions/recruitCRM.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,47 +58,45 @@ function normalizeRecruitPayload(job, payload) {
const perJob = [
`${job.name} ->`,
`Pay Expectation: ${payload.payExpectation}`,
`Date Available: ${new Date(payload.availFrom).toDateString()}`,
`Heard About Gig: ${payload.reffereal}`,
`Why fit: ${payload.whyFit}`,
`Able to work during timezone? ${payload.timezoneConfirm.filter(s => s.value).map(() => getCustomField(job.custom_fields, 'Timezone')).join(',')}`,
`Am I ok to work the duration? ${payload.durationConfirm.filter(s => s.value).map(s => s.label).join(',')}`,
`Notes: ${payload.notes}`,
`Am I ok to work the duration? ${payload.durationConfirm.filter(s => s.value).map(() => getCustomField(job.custom_fields, 'Duration')).join(',')}`,
];
return {
const referral = _.find(payload.reffereal, { selected: true });
const normalized = {
last_name: payload.lname,
first_name: payload.fname,
email: payload.email,
contact_number: payload.phone,
city: payload.city,
locality: _.find(payload.country, { selected: true }).label,
available_from: payload.availFrom,
salary_expectation: payload.payExpectation,
skill: payload.skills.filter(s => s.selected).map(s => s.label).join(','),
custom_fields: [
{
field_id: 13,
value: payload.reffereal || '',
},
{
field_id: 1,
value: payload.tcProfileLink || (payload.handle ? `topcoder.com/members/${payload.handle}` : ''),
value: payload.tcProfileLink || (payload.handle ? `https://topcoder.com/members/${payload.handle}` : ''),
},
{
field_id: 2,
value: payload.handle || '',
},
{
field_id: 3,
value: payload.whyFit || '',
},
{
field_id: 14,
value: perJob.join(','),
},
],
resume: payload.fileCV,
};
if (referral) {
normalized.custom_fields.push({
field_id: 13,
value: referral.label,
});
}
if (payload.fileCV) {
normalized.resume = payload.fileCV;
}

return normalized;
}

/**
Expand All @@ -124,6 +122,37 @@ async function applyForJobDone(job, payload) {
}
}

/**
* Search for cnadidate in recruit
*/
function searchCandidatesInit(email) {
return { email };
}

/**
* Search for cnadidate in recruit and get profile if available
* @param {string} email the email to search
*/
async function searchCandidatesDone(email) {
const ss = new Service();
try {
const res = await ss.searchCandidates(email);

return {
email,
data: res,
};
} catch (error) {
return {
email,
data: {
error: true,
errorObj: error,
},
};
}
}

export default redux.createActions({
RECRUIT: {
GET_JOBS_INIT: getJobsInit,
Expand All @@ -132,5 +161,7 @@ export default redux.createActions({
GET_JOB_DONE: getJobDone,
APPLY_FOR_JOB_INIT: applyForJobInit,
APPLY_FOR_JOB_DONE: applyForJobDone,
SEARCH_CANDIDATES_INIT: searchCandidatesInit,
SEARCH_CANDIDATES_DONE: searchCandidatesDone,
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ $gui-kit-gray-90: #2a2a2a;
$gui-kit-level-2: #0ab88a;
$gui-kit-level-5: #ef476f;
$gui-kit-active-label: #229174;
$gui-kit-readonly: #d4d4d4;

@mixin textInputLabel {
font-size: 12px;
Expand Down
3 changes: 3 additions & 0 deletions src/shared/components/GUIKit/DropdownTerms/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ function DropdownTerms({
selectInput[0].style.borderTop = 'none';
}
}, [focused, selectedOption]);
useEffect(() => {
setInternalTerms(terms);
}, [terms]);

const CustomReactSelectRow = React.forwardRef(({
className,
Expand Down
3 changes: 2 additions & 1 deletion src/shared/components/GUIKit/JobListCard/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import iconBlackSkills from 'assets/images/icon-skills.png';
export default function JobListCard({
job,
}) {
const duration = getCustomField(job.custom_fields, 'Duration');
let skills = getCustomField(job.custom_fields, 'Technologies Required');
if (skills !== 'n/a') {
skills = skills.split(',');
Expand All @@ -39,7 +40,7 @@ export default function JobListCard({
<IconBlackPayment /> ${job.min_annual_salary} - {job.max_annual_salary} (USD) / {getSalaryType(job.salary_type)}
</div>
<div styleName="icon-val">
<IconBlackDuration /> {getCustomField(job.custom_fields, 'Duration')}
<IconBlackDuration /> {/^\d+$/.test(duration) ? `${duration} Weeks` : duration}
</div>
<div styleName="row-btn">
<Link styleName="primary-green-md" to={`${config.GIGS_PAGES_PATH}/${job.slug}`}>VIEW DETAILS</Link>
Expand Down
2 changes: 1 addition & 1 deletion src/shared/components/GUIKit/TextInput/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function TextInput({
const sizeStyle = size === 'lg' ? 'lgSize' : 'xsSize';

return (
<div className="textInputContainer" styleName={`container ${sizeStyle}`}>
<div className="textInputContainer" styleName={`container ${sizeStyle}${readonly ? ' readonly' : ''}`}>
<input
readOnly={readonly}
defaultValue={value}
Expand Down
8 changes: 8 additions & 0 deletions src/shared/components/GUIKit/TextInput/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
}
}

// readonly
&.readonly {
input:not([type='checkbox']) {
border: 1px solid $gui-kit-readonly;
color: $gui-kit-gray-30;
}
}

input:not([type='checkbox']).haveValue + label,
input:not([type='checkbox']).haveError + label,
input:not([type='checkbox']):focus + label {
Expand Down
Loading