Skip to content

Commit

Permalink
Merge pull request #5485 from topcoder-platform/develop
Browse files Browse the repository at this point in the history
Release 2021/04/15 (v1.8.8)
  • Loading branch information
luizrrodrigues authored Apr 15, 2021
2 parents c96d810 + f21c1de commit d82d898
Show file tree
Hide file tree
Showing 21 changed files with 460 additions and 48 deletions.
5 changes: 1 addition & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,13 @@ workflows:
branches:
only:
- develop
- remove-outage-banner
# This is alternate dev env for parallel testing
- "build-test":
context : org-global
filters:
branches:
only:
only:
- free

# This is alternate dev env for parallel testing
- "build-qa":
context : org-global
Expand All @@ -306,7 +304,6 @@ workflows:
branches:
only:
- develop
- remove-outage-banner
- "approve-smoke-test-on-staging":
type: approval
requires:
Expand Down
8 changes: 8 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ ARG MAILCHIMP_BASE_URL
ARG NODE_CONFIG_ENV
ARG OPEN_EXCHANGE_RATES_KEY
ARG SEGMENT_IO_API_KEY
ARG CHAMELEON_VERIFICATION_SECRET
ARG SERVER_API_KEY

# TC M2M credentials for Community App server
Expand All @@ -72,6 +73,9 @@ ARG SENDGRID_API_KEY
ARG GROWSURF_API_KEY
ARG GROWSURF_CAMPAIGN_ID

# Optimizely
ARG OPTIMIZELY_SDK_KEY

################################################################################
# Setting of environment variables in the Docker image.

Expand Down Expand Up @@ -108,6 +112,7 @@ ENV MAILCHIMP_BASE_URL=$MAILCHIMP_BASE_URL
ENV NODE_CONFIG_ENV=$NODE_CONFIG_ENV
ENV OPEN_EXCHANGE_RATES_KEY=$OPEN_EXCHANGE_RATES_KEY
ENV SEGMENT_IO_API_KEY=$SEGMENT_IO_API_KEY
ENV CHAMELEON_VERIFICATION_SECRET=$CHAMELEON_VERIFICATION_SECRET
ENV SERVER_API_KEY=$SERVER_API_KEY

# TC M2M credentials for Community App server
Expand All @@ -131,6 +136,9 @@ ENV GROWSURF_API_KEY=$GROWSURF_API_KEY
ENV GROWSURF_CAMPAIGN_ID=$GROWSURF_CAMPAIGN_ID
ENV GSHEETS_API_KEY=$GSHEETS_API_KEY

# Optimizely
ENV OPTIMIZELY_SDK_KEY=$OPTIMIZELY_SDK_KEY

################################################################################
# Testing and build of the application inside the container.

Expand Down
2 changes: 2 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ docker build -t $TAG \
--build-arg NODE_CONFIG_ENV=$NODE_CONFIG_ENV \
--build-arg OPEN_EXCHANGE_RATES_KEY=$OPEN_EXCHANGE_RATES_KEY \
--build-arg SEGMENT_IO_API_KEY=$SEGMENT_IO_API_KEY \
--build-arg CHAMELEON_VERIFICATION_SECRET=$CHAMELEON_VERIFICATION_SECRET \
--build-arg SERVER_API_KEY=$SERVER_API_KEY \
--build-arg TC_M2M_CLIENT_ID=$TC_M2M_CLIENT_ID \
--build-arg TC_M2M_CLIENT_SECRET=$TC_M2M_CLIENT_SECRET \
Expand All @@ -48,6 +49,7 @@ docker build -t $TAG \
--build-arg GROWSURF_API_KEY=$GROWSURF_API_KEY \
--build-arg GROWSURF_CAMPAIGN_ID=$GROWSURF_CAMPAIGN_ID \
--build-arg GSHEETS_API_KEY=$GSHEETS_API_KEY \
--build-arg OPTIMIZELY_SDK_KEY=$OPTIMIZELY_SDK_KEY \
--build-arg COMMUNITY_APP_URL=$COMMUNITY_APP_URL .

# Copies "node_modules" from the created image, if necessary for caching.
Expand Down
4 changes: 4 additions & 0 deletions config/custom-environment-variables.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ module.exports = {
RECRUITCRM_API_KEY: 'RECRUITCRM_API_KEY',
GROWSURF_API_KEY: 'GROWSURF_API_KEY',
SENDGRID_API_KEY: 'SENDGRID_API_KEY',
CHAMELEON_VERIFICATION_SECRET: 'CHAMELEON_VERIFICATION_SECRET',
},
GROWSURF_CAMPAIGN_ID: 'GROWSURF_CAMPAIGN_ID',
AUTH_CONFIG: {
Expand All @@ -108,4 +109,7 @@ module.exports = {
TOKEN_CACHE_TIME: 'TOKEN_CACHE_TIME',
},
GSHEETS_API_KEY: 'GSHEETS_API_KEY',
OPTIMIZELY: {
SDK_KEY: 'OPTIMIZELY_SDK_KEY',
},
};
3 changes: 3 additions & 0 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,4 +426,7 @@ module.exports = {
DEBOUNCE_ON_CHANGE_TIME: 150,
},
ENABLE_RECOMMENDER: true,
OPTIMIZELY: {
SDK_KEY: '7V4CJhurXT3Y3bnzv1hv1',
},
};
13 changes: 13 additions & 0 deletions docs/secure-identity-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Setup
1. Make sure you have a Chameleon Account and segment.com account
2. Integrate Chameleon Account with Segment. https://help.trychameleon.com/en/articles/1161770-installing-using-segment
3. Set Environment secret variable retrieved here https://app.trychameleon.com/settings/integrations/segment. Run the following command
`export CHAMELEON_VERIFICATION_SECRET=<Your Chameleon Secret>`
4. Run community app

## Verification
1. Log in to topcoder-dev account
2. Access http://local.topcoder-dev.com/challenges
3. You will notice in the network tab there will be 2 requests POST to https://api.segment.io/v1/i, one will send it to segment and one will send only to chameleon (with request payload `{ integrations: { All: false, Chameleon: true }}`)

Repeat the proses and log in to different account and make sure the `uid_hash` is different for each different user.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
},
"dependencies": {
"@hapi/joi": "^16.1.4",
"@optimizely/react-sdk": "^2.5.0",
"@topcoder-platform/tc-auth-lib": "topcoder-platform/tc-auth-lib#1.0.4",
"aos": "^2.3.4",
"atob": "^2.1.1",
Expand Down
Binary file added src/assets/images/gig-work/tag-dolars.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/gig-work/tag-hot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/gig-work/tag-new.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 20 additions & 5 deletions src/client/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ const { setErrorsStore } = errors;
* Performs AnalyticsJS identification of the user.
* @param {Object} profile TC user profile.
* @param {Array} roles User roles.
* @param {String} userIdHash Unique Hash per user.
*/
function identify(profile, roles) {
analytics.identify(profile.userId, {
function identify(profile, roles, userIdHash) {
const payload = {
avatar: profile.photoURL,
createdAt: profile.createdAt,
email: profile.email,
Expand All @@ -39,7 +40,21 @@ function identify(profile, roles) {
})),
tracks: profile.tracks || [],
username: profile.handle,
});
};
analytics.identify(
profile.userId,
payload,
{
integrations: { Chameleon: false },
},
);
analytics.identify(
profile.userId,
{ uid_hash: userIdHash, ...payload },
{
integrations: { All: false, Chameleon: true },
},
);
}

/**
Expand Down Expand Up @@ -74,7 +89,7 @@ function authenticate(store) {
}).then(({ tctV2, tctV3 }) => {
const { auth } = store.getState();
if (auth.profile && !analyticsIdentitySet) {
identify(auth.profile, _.get(auth, 'user.roles'));
identify(auth.profile, _.get(auth, 'user.roles'), auth.userIdHash);
analyticsIdentitySet = true;
}
if (auth.tokenV3 !== (tctV3 || null)) {
Expand All @@ -85,7 +100,7 @@ function authenticate(store) {
const userId = profile && profile.userId;
const prevUserId = _.get(store.getState(), 'auth.profile.userId');
if (userId && userId !== prevUserId) {
identify(profile, _.get(auth, user.roles));
identify(profile, _.get(auth, user.roles), auth.userIdHash);
analyticsIdentitySet = true;
}
});
Expand Down
1 change: 1 addition & 0 deletions src/server/services/recruitCRM.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const JOB_FIELDS_RESPONSE = [
'salary_type',
'max_annual_salary',
'job_description_text',
'job_status',
];
const CANDIDATE_FIELDS_RESPONSE = [
'id',
Expand Down
26 changes: 23 additions & 3 deletions src/shared/components/GUIKit/JobListCard/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@ import React from 'react';
import PT from 'prop-types';
import { config, Link } from 'topcoder-react-utils';
import { getSalaryType, getCustomField } from 'utils/gigs';
import { withOptimizely } from '@optimizely/react-sdk';
import './style.scss';
import IconBlackDuration from 'assets/images/icon-black-duration.svg';
import IconBlackLocation from 'assets/images/icon-black-location.svg';
import IconBlackPayment from 'assets/images/icon-black-payment.svg';
import iconBlackSkills from 'assets/images/icon-skills.png';
import newTag from 'assets/images/gig-work/tag-new.png';
import hotTag from 'assets/images/gig-work/tag-hot.png';
import dolarsTag from 'assets/images/gig-work/tag-dolars.png';

export default function JobListCard({
const TAGS = {
New: newTag,
Hot: hotTag,
$$$: dolarsTag,
};
function JobListCard({
job,
optimizely,
}) {
const duration = getCustomField(job.custom_fields, 'Duration');
let skills = getCustomField(job.custom_fields, 'Technologies Required');
Expand All @@ -25,10 +35,17 @@ export default function JobListCard({
skills = skills.join(', ');
}
}
const tag = getCustomField(job.custom_fields, 'Job Tag');
const onHotlistApply = () => {
optimizely.track('View Details Click');
};

return (
<div styleName="container">
<Link to={`${config.GIGS_PAGES_PATH}/${job.slug}`} styleName="gig-name">{job.name}</Link>
{
tag !== 'n/a' && <img src={TAGS[tag]} alt="gig-job-tag" styleName="gig-tag" />
}
<Link to={`${config.GIGS_PAGES_PATH}/${job.slug}`} styleName="gig-name" onClick={onHotlistApply}>{job.name}</Link>
<div styleName="job-infos">
<div styleName="icon-val">
<img src={iconBlackSkills} alt="skills-icon" /> {skills}
Expand All @@ -43,7 +60,7 @@ export default function JobListCard({
<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>
<Link styleName="primary-green-md" to={`${config.GIGS_PAGES_PATH}/${job.slug}`} onClick={onHotlistApply}>VIEW DETAILS</Link>
</div>
</div>
</div>
Expand All @@ -56,4 +73,7 @@ JobListCard.defaultProps = {

JobListCard.propTypes = {
job: PT.shape().isRequired,
optimizely: PT.shape().isRequired,
};

export default withOptimizely(JobListCard);
32 changes: 31 additions & 1 deletion src/shared/components/GUIKit/JobListCard/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,23 @@
display: flex;
flex-direction: column;
color: #2a2a2a;
padding: 25px 35px;
padding: 25px 35px 25px 44px;
margin-bottom: 15px;
position: relative;

@include gui-kit-headers;
@include gui-kit-content;
@include roboto-regular;

.gig-tag {
position: absolute;
top: -1px;
left: 10px;
width: 24px;
height: 56px;
border-radius: 0;
}

.gig-name,
.gig-name:visited,
.gig-name:active,
Expand Down Expand Up @@ -50,18 +60,38 @@

&:first-child {
width: 250px;

@media (max-width: 1280px) {
width: auto;
margin-right: 20px;
}
}

&:nth-child(2) {
width: 204px;

@media (max-width: 1280px) {
width: auto;
margin-right: 20px;
}
}

&:nth-child(3) {
width: 263px;

@media (max-width: 1280px) {
width: auto;
margin-right: 20px;
}
}

&:nth-child(4) {
width: 255px;

@media (max-width: 1280px) {
width: auto;
margin-right: 20px;
}
}

&:last-child {
Expand Down
2 changes: 1 addition & 1 deletion src/shared/components/Gigs/GigDetails/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function GigDetails(props) {
return (
<div styleName="container">
{
job.error || job.enable_job_application_form !== 1 ? (
job.error || job.job_status.id !== 1 || job.enable_job_application_form !== 1 ? (
<div styleName="error">
{ job.error ? <SadFace /> : null }
<h3>{ job.error ? 'Gig does not exist' : 'This Gig has been Fulfilled'}</h3>
Expand Down
8 changes: 6 additions & 2 deletions src/shared/containers/Gigs/RecruitCRMJobApply.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import PT from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { isValidEmail } from 'utils/tc';
import { withOptimizely } from '@optimizely/react-sdk';
import techSkills from './techSkills';


const countries = require('i18n-iso-countries');
countries.registerLocale(require('i18n-iso-countries/langs/en.json'));

Expand Down Expand Up @@ -120,12 +122,13 @@ class RecruitCRMJobApplyContainer extends React.Component {
}

onApplyClick() {
const { applyForJob, job } = this.props;
const { applyForJob, job, optimizely } = this.props;
const { formData } = this.state;
this.validateForm();
this.setState((state) => {
if (_.isEmpty(state.formErrors)) {
applyForJob(job, formData);
optimizely.track('Submit Application Form');
}
});
}
Expand Down Expand Up @@ -269,6 +272,7 @@ RecruitCRMJobApplyContainer.propTypes = {
application: PT.shape(),
searchCandidates: PT.func.isRequired,
recruitProfile: PT.shape(),
optimizely: PT.shape().isRequired,
};

function mapStateToProps(state, ownProps) {
Expand Down Expand Up @@ -312,4 +316,4 @@ function mapDispatchToActions(dispatch) {
export default connect(
mapStateToProps,
mapDispatchToActions,
)(RecruitCRMJobApplyContainer);
)(withOptimizely(RecruitCRMJobApplyContainer));
Loading

0 comments on commit d82d898

Please sign in to comment.