Skip to content

Commit 6258b77

Browse files
committed
Add optimizely
1 parent 322624a commit 6258b77

File tree

4 files changed

+78
-13
lines changed

4 files changed

+78
-13
lines changed

src/shared/components/GUIKit/JobListCard/index.jsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import React from 'react';
66
import PT from 'prop-types';
77
import { config, Link } from 'topcoder-react-utils';
88
import { getSalaryType, getCustomField } from 'utils/gigs';
9+
import { withOptimizely } from '@optimizely/react-sdk';
910
import './style.scss';
1011
import IconBlackDuration from 'assets/images/icon-black-duration.svg';
1112
import IconBlackLocation from 'assets/images/icon-black-location.svg';
@@ -20,8 +21,9 @@ const TAGS = {
2021
Hot: hotTag,
2122
$$$: dolarsTag,
2223
};
23-
export default function JobListCard({
24+
function JobListCard({
2425
job,
26+
optimizely,
2527
}) {
2628
const duration = getCustomField(job.custom_fields, 'Duration');
2729
let skills = getCustomField(job.custom_fields, 'Technologies Required');
@@ -34,13 +36,16 @@ export default function JobListCard({
3436
}
3537
}
3638
const tag = getCustomField(job.custom_fields, 'Job Tag');
39+
const onHotlistApply = () => {
40+
optimizely.track('View Details Click');
41+
};
3742

3843
return (
3944
<div styleName="container">
4045
{
4146
tag !== 'n/a' && <img src={TAGS[tag]} alt="gig-job-tag" styleName="gig-tag" />
4247
}
43-
<Link to={`${config.GIGS_PAGES_PATH}/${job.slug}`} styleName="gig-name">{job.name}</Link>
48+
<Link to={`${config.GIGS_PAGES_PATH}/${job.slug}`} styleName="gig-name" onClick={onHotlistApply}>{job.name}</Link>
4449
<div styleName="job-infos">
4550
<div styleName="icon-val">
4651
<img src={iconBlackSkills} alt="skills-icon" /> {skills}
@@ -55,7 +60,7 @@ export default function JobListCard({
5560
<IconBlackDuration /> {/^\d+$/.test(duration) ? `${duration} Weeks` : duration}
5661
</div>
5762
<div styleName="row-btn">
58-
<Link styleName="primary-green-md" to={`${config.GIGS_PAGES_PATH}/${job.slug}`}>VIEW DETAILS</Link>
63+
<Link styleName="primary-green-md" to={`${config.GIGS_PAGES_PATH}/${job.slug}`} onClick={onHotlistApply}>VIEW DETAILS</Link>
5964
</div>
6065
</div>
6166
</div>
@@ -68,4 +73,7 @@ JobListCard.defaultProps = {
6873

6974
JobListCard.propTypes = {
7075
job: PT.shape().isRequired,
76+
optimizely: PT.shape().isRequired,
7177
};
78+
79+
export default withOptimizely(JobListCard);

src/shared/containers/Gigs/RecruitCRMJobApply.jsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import PT from 'prop-types';
1010
import React from 'react';
1111
import { connect } from 'react-redux';
1212
import { isValidEmail } from 'utils/tc';
13+
import { withOptimizely } from '@optimizely/react-sdk';
1314
import techSkills from './techSkills';
1415

16+
1517
const countries = require('i18n-iso-countries');
1618
countries.registerLocale(require('i18n-iso-countries/langs/en.json'));
1719

@@ -120,12 +122,13 @@ class RecruitCRMJobApplyContainer extends React.Component {
120122
}
121123

122124
onApplyClick() {
123-
const { applyForJob, job } = this.props;
125+
const { applyForJob, job, optimizely } = this.props;
124126
const { formData } = this.state;
125127
this.validateForm();
126128
this.setState((state) => {
127129
if (_.isEmpty(state.formErrors)) {
128130
applyForJob(job, formData);
131+
optimizely.track('Submit Application Form');
129132
}
130133
});
131134
}
@@ -269,6 +272,7 @@ RecruitCRMJobApplyContainer.propTypes = {
269272
application: PT.shape(),
270273
searchCandidates: PT.func.isRequired,
271274
recruitProfile: PT.shape(),
275+
optimizely: PT.shape().isRequired,
272276
};
273277

274278
function mapStateToProps(state, ownProps) {
@@ -312,4 +316,4 @@ function mapDispatchToActions(dispatch) {
312316
export default connect(
313317
mapStateToProps,
314318
mapDispatchToActions,
315-
)(RecruitCRMJobApplyContainer);
319+
)(withOptimizely(RecruitCRMJobApplyContainer));

src/shared/containers/Gigs/RecruitCRMJobs.jsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { getSalaryType, getCustomField } from 'utils/gigs';
1616
import IconBlackLocation from 'assets/images/icon-black-location.svg';
1717
import { config, Link } from 'topcoder-react-utils';
1818
import { getQuery, updateQuery } from 'utils/url';
19+
import { withOptimizely } from '@optimizely/react-sdk';
1920
import './jobLisingStyles.scss';
2021

2122
const CONTENT_PREVIEW_LENGTH = 175;
@@ -46,6 +47,7 @@ class RecruitCRMJobsContainer extends React.Component {
4647
this.onFilter = this.onFilter.bind(this);
4748
this.onLocation = this.onLocation.bind(this);
4849
this.onSort = this.onSort.bind(this);
50+
this.onHotlistApply = this.onHotlistApply.bind(this);
4951
}
5052

5153
componentDidMount() {
@@ -119,10 +121,16 @@ class RecruitCRMJobsContainer extends React.Component {
119121
});
120122
}
121123

124+
onHotlistApply() {
125+
const { optimizely } = this.props;
126+
optimizely.track('Hotlist ads click');
127+
}
128+
122129
render() {
123130
const {
124131
loading,
125132
jobs,
133+
optimizely,
126134
} = this.props;
127135
const {
128136
term,
@@ -140,6 +148,8 @@ class RecruitCRMJobsContainer extends React.Component {
140148
);
141149
}
142150

151+
// optimizely decide
152+
const decision = optimizely.decide('gig_listing_hotlist');
143153
let jobsToDisplay = jobs;
144154
// build hotlist of jobs if present
145155
let hotlistJobs = _.filter(jobs, (job) => {
@@ -205,7 +215,7 @@ class RecruitCRMJobsContainer extends React.Component {
205215
);
206216

207217
return (
208-
<div styleName={hotlistJobs.length ? 'container-with-hotlist' : 'container'}>
218+
<div styleName={hotlistJobs.length && decision.enabled ? 'container-with-hotlist' : 'container'}>
209219
<div styleName="gigs">
210220
<div styleName="filters">
211221
<SearchCombo placeholder="Search Gig Listings by Name or Skills" onSearch={this.onSearch} term={term} />
@@ -225,13 +235,13 @@ class RecruitCRMJobsContainer extends React.Component {
225235
}
226236
</div>
227237
{
228-
hotlistJobs.length && (
238+
hotlistJobs.length && decision.enabled && (
229239
<div styleName="hotlist">
230240
<h5>HOT THIS WEEK</h5>
231241
<div styleName="hotlist-items">
232242
{
233243
hotlistJobs.map((hjob, indx) => (indx <= 1 ? (
234-
<Link styleName={`hotlist-item-${indx + 1}`} to={`${config.GIGS_PAGES_PATH}/${hjob.slug}`} key={`hotlist-item-${indx + 1}`}>
244+
<Link styleName={`hotlist-item-${indx + 1}`} to={`${config.GIGS_PAGES_PATH}/${hjob.slug}`} key={`hotlist-item-${indx + 1}`} onClick={this.onHotlistApply}>
235245
<div styleName="location"><IconBlackLocation /> {hjob.country}</div>
236246
<h5 styleName="job-title">{hjob.name}</h5>
237247
<div styleName="job-money">${hjob.min_annual_salary} - ${hjob.max_annual_salary} / {getSalaryType(hjob.salary_type)}</div>
@@ -246,7 +256,7 @@ class RecruitCRMJobsContainer extends React.Component {
246256
`${getCustomField(hjob.custom_fields, 'Hotlist excerpt') === 'n/a' ? '' : `${getCustomField(hjob.custom_fields, 'Hotlist excerpt').substring(0, CONTENT_PREVIEW_LENGTH)}...`}`
247257
}
248258
</div>
249-
<Link styleName={`hotlist-item-button-${indx + 1}`} to={`${config.GIGS_PAGES_PATH}/${hjob.slug}`}>Apply Now</Link>
259+
<Link styleName={`hotlist-item-button-${indx + 1}`} to={`${config.GIGS_PAGES_PATH}/${hjob.slug}`} onClick={this.onHotlistApply}>Apply Now</Link>
250260
</div>
251261
)))
252262
}
@@ -268,6 +278,7 @@ RecruitCRMJobsContainer.propTypes = {
268278
getJobs: PT.func.isRequired,
269279
loading: PT.bool,
270280
jobs: PT.arrayOf(PT.shape),
281+
optimizely: PT.shape().isRequired,
271282
};
272283

273284
function mapStateToProps(state) {
@@ -291,4 +302,4 @@ function mapDispatchToActions(dispatch) {
291302
export default connect(
292303
mapStateToProps,
293304
mapDispatchToActions,
294-
)(RecruitCRMJobsContainer);
305+
)(withOptimizely(RecruitCRMJobsContainer));

src/shared/containers/GigsPages.jsx

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,40 @@ import RecruitCRMJobDetails from 'containers/Gigs/RecruitCRMJobDetails';
1111
import { Helmet } from 'react-helmet';
1212
import MetaTags from 'components/MetaTags';
1313
import { OptimizelyProvider, createInstance } from '@optimizely/react-sdk';
14+
import { connect } from 'react-redux';
15+
import _ from 'lodash';
16+
import { v4 as uuidv4 } from 'uuid';
1417

1518
const optimizelyClient = createInstance({
1619
sdkKey: config.OPTIMIZELY.SDK_KEY,
1720
});
18-
export default function GigsPagesContainer(props) {
19-
const { match } = props;
21+
const cookies = require('browser-cookies');
22+
23+
function GigsPagesContainer(props) {
24+
const { match, profile } = props;
25+
const optProfile = {
26+
attributes: {},
27+
};
28+
if (!_.isEmpty(profile)) {
29+
optProfile.id = String(profile.userId);
30+
optProfile.attributes.TC_Handle = profile.handle;
31+
optProfile.attributes.HomeCountryCode = profile.homeCountryCode;
32+
optProfile.attributes.email = profile.email;
33+
} else {
34+
const idCookie = cookies.get('_tc.aid');
35+
if (idCookie) {
36+
optProfile.id = JSON.parse(idCookie).aid;
37+
} else {
38+
optProfile.id = uuidv4();
39+
cookies.set('_tc.aid', JSON.stringify({
40+
aid: optProfile.id,
41+
}), {
42+
secure: true,
43+
domain: '',
44+
expires: 365, // days
45+
});
46+
}
47+
}
2048
const { id, type } = match.params;
2149
const isApply = `${config.GIGS_PAGES_PATH}/${id}/apply` === match.url;
2250
const title = 'Gig Work | Topcoder Community | Topcoder';
@@ -57,16 +85,30 @@ window._chatlio = window._chatlio||[];
5785
<Footer />
5886
</div>
5987
);
88+
6089
return isomorphy.isClientSide() ? (
61-
<OptimizelyProvider optimizely={optimizelyClient} user={{ id: 123 }}>
90+
<OptimizelyProvider optimizely={optimizelyClient} user={optProfile} timeout={500}>
6291
{inner}
6392
</OptimizelyProvider>
6493
) : inner;
6594
}
6695

6796
GigsPagesContainer.defaultProps = {
97+
profile: null,
6898
};
6999

70100
GigsPagesContainer.propTypes = {
71101
match: PT.shape().isRequired,
102+
profile: PT.shape(),
72103
};
104+
105+
function mapStateToProps(state) {
106+
const profile = state.auth && state.auth.profile ? { ...state.auth.profile } : {};
107+
return {
108+
profile,
109+
};
110+
}
111+
112+
export default connect(
113+
mapStateToProps,
114+
)(GigsPagesContainer);

0 commit comments

Comments
 (0)