Skip to content

Commit adc0439

Browse files
Merge pull request #5729 from topcoder-platform/develop
Release v1.13.1
2 parents f16c99a + 2f01abd commit adc0439

File tree

17 files changed

+513
-8
lines changed

17 files changed

+513
-8
lines changed

.circleci/config.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,21 +349,21 @@ workflows:
349349
filters:
350350
branches:
351351
only:
352-
- free
352+
- gig-apply-new-options-dropdown
353353
# This is alternate dev env for parallel testing
354354
- "build-qa":
355355
context : org-global
356356
filters:
357357
branches:
358358
only:
359-
- gig-cache-layer
359+
- member-path-component
360360
# This is beta env for production soft releases
361361
- "build-prod-beta":
362362
context : org-global
363363
filters:
364364
branches:
365365
only:
366-
- slash-tc
366+
- slash-home-hotfix
367367
# This is stage env for production QA releases
368368
- "build-prod-staging":
369369
context : org-global

__tests__/shared/components/__snapshots__/Content.jsx.snap

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,16 @@ exports[`Matches shallow shapshot 1`] = `
10751075
10761076
- Demo of Blog Feed component
10771077
</li>
1078+
<li>
1079+
<Link
1080+
replace={false}
1081+
to="/examples/member-path-selector"
1082+
>
1083+
Member Path - Path Selector
1084+
</Link>
1085+
1086+
— Demo for path selector component on member path page
1087+
</li>
10781088
</ul>
10791089
</div>
10801090
`;

config/default.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ module.exports = {
102102
/* This is the same value as above, but it is used by topcoder-react-lib,
103103
* as a more verbose name for the param. */
104104
COMMUNITY_APP: 'https://community-app.topcoder-dev.com',
105-
CHALLENGES_URL: 'https://platform.topcoder.com/earn/find/challenges',
105+
CHALLENGES_URL: 'https://www.topcoder-dev.com/challenges',
106106

107107
ARENA: 'https://arena.topcoder-dev.com',
108108
AUTH: 'https://accounts-auth0.topcoder-dev.com',

config/production.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = {
2525
/* This is the same value as above, but it is used by topcoder-react-lib,
2626
* as a more verbose name for the param. */
2727
COMMUNITY_APP: 'https://community-app.topcoder.com',
28+
CHALLENGES_URL: 'https://www.topcoder.com/challenges',
2829

2930
AUTH: 'https://accounts-auth0.topcoder.com',
3031
BASE: 'https://www.topcoder.com',
Lines changed: 19 additions & 0 deletions
Loading
Lines changed: 13 additions & 0 deletions
Loading
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"title": "WHAT DO YOU WANT TO DO TODAY?",
3+
"items": [
4+
{
5+
"title": "COMPETE",
6+
"iconURL": "https://media-bucket-s3.s3.eu-central-1.amazonaws.com/sx/icon-compete.svg",
7+
"activeIconURL": "https://s3.eu-central-1.amazonaws.com/media-bucket-s3/sx/icon-compete-active.svg",
8+
"contentText": "A competition based, gig economy, a typical 9-5 job for you",
9+
"btnText": "Topcoder Challenges",
10+
"btnURL": "https://www.topcoder.com/challenges",
11+
"btnNewTab": true
12+
}, {
13+
"title": "BUILD SKILLS",
14+
"iconURL": "https://media-bucket-s3.s3.eu-central-1.amazonaws.com/sx/icon-build-skills.svg",
15+
"activeIconURL": "https://s3.eu-central-1.amazonaws.com/media-bucket-s3/sx/icon-build-skills-active.svg",
16+
"contentText": "Get stronger with Skill Builder Competitions",
17+
"btnText": "Find a Competition",
18+
"btnURL": "https://www.topcoder.com/challenges?bucket=openForRegistration&search=Topcoder%20Skill%20Builder%20Competition&tracks[DS]=true&tracks[Des]=true&tracks[Dev]=true&tracks[QA]=true&types[]=CH&types[]=F2F&types[]=TSK",
19+
"btnNewTab": true
20+
},
21+
{
22+
"title": "LEARN",
23+
"iconURL": "https://s3.eu-central-1.amazonaws.com/media-bucket-s3/sx/icon-learn.svg",
24+
"activeIconURL": "https://s3.eu-central-1.amazonaws.com/media-bucket-s3/sx/icon-learn-active.svg",
25+
"contentText": "Tutorials and workshops that matter",
26+
"btnText": "Thrive",
27+
"btnURL": "https://www.topcoder.com/thrive",
28+
"btnNewTab": true
29+
},
30+
{
31+
"title": "GET A GIG",
32+
"iconURL": "https://s3.eu-central-1.amazonaws.com/media-bucket-s3/sx/icon-gig.svg",
33+
"activeIconURL": "https://s3.eu-central-1.amazonaws.com/media-bucket-s3/sx/icon-get-a-gig-active.svg",
34+
"contentText": "Find a freelance job with our help",
35+
"btnText": "Gig Work",
36+
"btnURL": "https://www.topcoder.com/gigs",
37+
"btnNewTab": true
38+
}
39+
]
40+
}

src/shared/components/Content/index.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,16 @@ export default function Content() {
861861
{' '}
862862
- Demo of Blog Feed component
863863
</li>
864+
<li>
865+
<Link
866+
to="/examples/member-path-selector"
867+
>
868+
Member Path - Path Selector
869+
</Link>
870+
{' '}
871+
&mdash;
872+
Demo for path selector component on member path page
873+
</li>
864874
</ul>
865875
</div>
866876
);

src/shared/components/Contentful/AppComponent/index.jsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Leaderboard from 'containers/tco/Leaderboard';
1212
import RecruitCRMJobs from 'containers/Gigs/RecruitCRMJobs';
1313
import EmailSubscribeForm from 'containers/EmailSubscribeForm';
1414
import GSheet from 'containers/GSheet';
15+
import PathSelector from 'components/MemberPath/PathSelector';
1516

1617

1718
const { fireErrorMessage } = errors;
@@ -43,6 +44,14 @@ export function AppComponentSwitch(appComponent) {
4344
if (appComponent.fields.type === 'GSheet') {
4445
return <GSheet {...appComponent.fields.props} key={appComponent.sys.id} />;
4546
}
47+
if (appComponent.fields.type === 'MemberPath') {
48+
return (
49+
<PathSelector
50+
{...appComponent.fields.props}
51+
key={appComponent.sys.id}
52+
/>
53+
);
54+
}
4655
fireErrorMessage(`Unsupported app component type ${appComponent.fields.type}`, '');
4756
return null;
4857
}

src/shared/components/Dashboard/GigsFeed/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default function GigsFeed({
2020
<span styleName="title">GIGS</span>
2121
<a
2222
styleName="allLink"
23-
href={`${config.URL.COMMUNITY_APP}/gigs`}
23+
href={`${config.URL.BASE}/gigs`}
2424
target="_blank"
2525
rel="noreferrer"
2626
>View all <span>gigs</span>
@@ -31,7 +31,7 @@ export default function GigsFeed({
3131
: gigs.message ? <span>{gigs.message}</span> : gigs.map(gig => (
3232
<div styleName="row" key={`dashboard-gigs-feed-${gig.externalId}`}>
3333
<a
34-
href={`${config.URL.COMMUNITY_APP}/gigs/${gig.externalId}`}
34+
href={`${config.URL.BASE}/gigs/${gig.externalId}`}
3535
target="_blank"
3636
rel="noreferrer"
3737
>{gig.title}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import PT from 'prop-types';
2+
import React, { useEffect, useState } from 'react';
3+
import cn from 'classnames';
4+
import ArrowLeftIcon from 'assets/images/member-path/icon-left.svg';
5+
import ArrowRightIcon from 'assets/images/member-path/icon-right.svg';
6+
import styles from './styles.scss';
7+
8+
const colorStyles = [styles.purple, styles.blue, styles.teal, styles.orange];
9+
10+
export default function PathSelector({
11+
data,
12+
animationTime,
13+
}) {
14+
const [activeItemIndex, setActiveItemIndex] = useState(0);
15+
const [timer, setTimer] = useState(null);
16+
17+
useEffect(
18+
() => {
19+
setTimer(setInterval(() => {
20+
setActiveItemIndex(itemIndex => (itemIndex + 1) % data.items.length);
21+
},
22+
animationTime));
23+
return () => {
24+
if (timer) {
25+
clearInterval(timer);
26+
}
27+
};
28+
},
29+
[],
30+
);
31+
const stopTimer = () => {
32+
if (timer) {
33+
clearInterval(timer);
34+
setTimer(null);
35+
}
36+
};
37+
38+
const handleOptionSelect = index => () => {
39+
setActiveItemIndex(index);
40+
// Stop the animation if user selects an item
41+
stopTimer();
42+
};
43+
44+
const handlePrevButton = () => {
45+
setActiveItemIndex(activeItemIndex - 1 < 0 ? data.items.length - 1 : activeItemIndex - 1);
46+
// Stop the animation if user selects an item
47+
stopTimer();
48+
};
49+
50+
const handleNextButton = () => {
51+
setActiveItemIndex((activeItemIndex + 1) % data.items.length);
52+
// Stop the animation if user selects an item
53+
stopTimer();
54+
};
55+
56+
const items = data.items.map((item, index) => (
57+
<button
58+
key={`path-selector-${item.title}`}
59+
type="button"
60+
className={cn(
61+
styles.option,
62+
colorStyles[index % colorStyles.length],
63+
{ [styles.active]: activeItemIndex === index },
64+
)
65+
}
66+
onClick={handleOptionSelect(index)}
67+
>
68+
<img
69+
className={styles.icon}
70+
src={item.iconURL}
71+
alt={item.title}
72+
/>
73+
<img
74+
className={styles.activeIcon}
75+
src={item.activeIconURL}
76+
alt={item.title}
77+
/>
78+
<span>{item.title}</span>
79+
</button>
80+
));
81+
82+
return (
83+
<div className={styles.container}>
84+
<div className={styles.header}>
85+
<h2 className={styles.title}>{data.title}</h2>
86+
<div className={styles.options}>
87+
<ArrowLeftIcon
88+
className={styles.arrowIcon}
89+
onClick={handlePrevButton}
90+
/>
91+
{items}
92+
<ArrowRightIcon
93+
className={styles.arrowIcon}
94+
onClick={handleNextButton}
95+
/>
96+
</div>
97+
</div>
98+
<div className={cn(styles.content, colorStyles[activeItemIndex % colorStyles.length])}>
99+
<div className={styles.contentText}>
100+
<span>{data.items[activeItemIndex].contentText}</span>
101+
</div>
102+
<a
103+
href={data.items[activeItemIndex].btnURL}
104+
target="_blank"
105+
rel="noopener noreferrer"
106+
className={styles.contentButton}
107+
>
108+
{data.items[activeItemIndex].btnText}
109+
</a>
110+
</div>
111+
</div>
112+
);
113+
}
114+
115+
PathSelector.defaultProps = {
116+
animationTime: 3000,
117+
};
118+
119+
PathSelector.propTypes = {
120+
data: PT.shape({
121+
items: PT.arrayOf(PT.shape({
122+
title: PT.string,
123+
iconURL: PT.string,
124+
activeIconURL: PT.string,
125+
contentText: PT.string,
126+
btnText: PT.string,
127+
btnURL: PT.string,
128+
btnNewTab: PT.bool,
129+
})),
130+
title: PT.string,
131+
}).isRequired,
132+
animationTime: PT.number,
133+
};

0 commit comments

Comments
 (0)