Skip to content

Commit 0fa7461

Browse files
authored
Merge pull request #5100 from topcoder-platform/develop
Release 2020-10-13
2 parents 50094ec + 12adaec commit 0fa7461

File tree

35 files changed

+995
-25
lines changed

35 files changed

+995
-25
lines changed

.circleci/config.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,15 +236,15 @@ workflows:
236236
context : org-global
237237
filters:
238238
branches:
239-
only:
240-
- develop
239+
only:
240+
- hot-fix
241241
# This is alternate dev env for parallel testing
242242
- "build-qa":
243243
context : org-global
244244
filters:
245245
branches:
246246
only:
247-
- develop
247+
- listing-develop-sync
248248
# This is beta env for production soft releases
249249
- "build-prod-beta":
250250
context : org-global
@@ -260,6 +260,7 @@ workflows:
260260
branches:
261261
only:
262262
- develop
263+
- listing-develop-sync
263264
# Production builds are exectuted
264265
# when PR is merged to the master
265266
# Don't change anything in this configuration

__tests__/shared/reducers/challenge-listing/sidebar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const defaultReducer = require('reducers/challenge-listing/sidebar').default;
22

33
const expectedState = {
4-
activeBucket: 'all',
4+
activeBucket: 'openForRegistration',
55
};
66

77
function testReducer(reducer) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@
140140
"tc-accounts": "git+https://github.com/appirio-tech/accounts-app.git#dev",
141141
"tc-core-library-js": "github:appirio-tech/tc-core-library-js#v2.6.3",
142142
"tc-ui": "^1.0.12",
143-
"topcoder-react-lib": "1000.24.6",
143+
"topcoder-react-lib": "1.0.8",
144144
"topcoder-react-ui-kit": "2.0.1",
145145
"topcoder-react-utils": "0.7.8",
146146
"turndown": "^4.0.2",

src/server/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import cdnRouter from './routes/cdn';
2727
import mailChimpRouter from './routes/mailchimp';
2828
import mockDocuSignFactory from './__mocks__/docu-sign-mock';
2929
import recruitCRMRouter from './routes/recruitCRM';
30+
import mmLeaderboardRouter from './routes/mmLeaderboard';
3031

3132
/* Dome API for topcoder communities */
3233
import tcCommunitiesDemoApi from './tc-communities';
@@ -135,6 +136,7 @@ async function onExpressJsSetup(server) {
135136
server.use('/api/cdn', cdnRouter);
136137
server.use('/api/mailchimp', mailChimpRouter);
137138
server.use('/api/recruit', recruitCRMRouter);
139+
server.use('/api/mml', mmLeaderboardRouter);
138140

139141
// serve demo api
140142
server.use(

src/server/routes/mmLeaderboard.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* The routes related to MMLeaderboard integration
3+
*/
4+
5+
import express from 'express';
6+
import MMLService from '../services/mmLeaderboard';
7+
8+
const cors = require('cors');
9+
10+
const routes = express.Router();
11+
12+
// Enables CORS on those routes according config above
13+
// ToDo configure CORS for set of our trusted domains
14+
routes.use(cors());
15+
routes.options('*', cors());
16+
17+
routes.get('/:id', (req, res, next) => new MMLService().getLeaderboard(req, res, next));
18+
19+
export default routes;

src/server/services/mmLeaderboard.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* eslint-disable class-methods-use-this */
2+
/**
3+
* Server-side functions necessary for effective integration with MMLeaderboard
4+
*/
5+
import { services } from 'topcoder-react-lib';
6+
7+
const { api, submissions } = services;
8+
9+
/**
10+
* Auxiliary class that handles communication with MMLeaderboard
11+
*/
12+
export default class MMLService {
13+
/**
14+
* getLeaderboard endpoint.
15+
* @return {Promise}
16+
* @param {Object} the request.
17+
*/
18+
async getLeaderboard(req, res, next) {
19+
try {
20+
const m2mToken = await api.getTcM2mToken();
21+
const subSrv = submissions.getService(m2mToken);
22+
const reviewIds = await subSrv.getScanReviewIds();
23+
const v5api = api.getApiV5(m2mToken);
24+
const subs = await v5api.get(`/submissions?challengeId=${req.params.id}&page=1&perPage=500`);
25+
return res.send({
26+
id: req.params.id,
27+
subs: await subs.json(),
28+
reviewIds,
29+
});
30+
} catch (err) {
31+
return next(err);
32+
}
33+
}
34+
}

src/server/tc-communities/blockchain/metadata.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
"tags": ["Blockchain", "Ethereum"]
66
}]
77
},
8+
"challengeListing": {
9+
"ignoreCommunityFilterByDefault": true
10+
},
811
"communityId": "blockchain",
912
"communityName": "Blockchain Community",
1013
"groupIds": ["20000010"],

src/server/tc-communities/cognitive/metadata.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
}]
77
},
88
"challengeListing": {
9+
"ignoreCommunityFilterByDefault": true,
910
"openChallengesInNewTabs": false
1011
},
1112
"communityId": "cognitive",

src/shared/actions/mmLeaderboard.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { redux } from 'topcoder-react-utils';
2+
import Service from 'services/mmLeaderboard';
3+
import _ from 'lodash';
4+
5+
/**
6+
* Fetch init
7+
*/
8+
function getMMLeaderboardInit(id) {
9+
return { id };
10+
}
11+
12+
/**
13+
* Fetch done
14+
*/
15+
async function getMMLeaderboardDone(id) {
16+
const ss = new Service();
17+
const res = await ss.getMMLeaderboard(id);
18+
let data = [];
19+
if (res) {
20+
const groupedData = _.groupBy(res.subs, 'createdBy');
21+
_.each(groupedData, (subs, handle) => {
22+
// filter member subs from reviewIds
23+
const filteredSubs = _.map(subs, (sub) => {
24+
// eslint-disable-next-line no-param-reassign
25+
sub.review = _.filter(sub.review, r => res.reviewIds.indexOf(r.typeId) === -1);
26+
return sub;
27+
});
28+
const sortedSubs = _.orderBy(filteredSubs, ['updated'], ['desc']);
29+
const scores = _.orderBy(_.compact(sortedSubs[0].review), ['updated'], ['desc']);
30+
data.push({
31+
createdBy: handle,
32+
updated: sortedSubs[0].submittedDate,
33+
id: sortedSubs[0].id,
34+
score: scores && scores.length ? scores[0].score : '...',
35+
});
36+
});
37+
data = _.orderBy(data, [d => (Number(d.score) ? Number(d.score) : 0)], ['desc']).map((r, i) => ({
38+
...r,
39+
rank: i + 1,
40+
score: r.score % 1 ? Number(r.score).toFixed(5) : r.score,
41+
}));
42+
}
43+
return {
44+
id,
45+
data,
46+
};
47+
}
48+
49+
export default redux.createActions({
50+
MMLEADERBOARD: {
51+
GET_MML_INIT: getMMLeaderboardInit,
52+
GET_MML_DONE: getMMLeaderboardDone,
53+
},
54+
});

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import React from 'react';
1010
import { errors } from 'topcoder-react-lib';
1111
import Leaderboard from 'containers/tco/Leaderboard';
1212
import RecruitCRMJobs from 'containers/Gigs/RecruitCRMJobs';
13+
import EmailSubscribeForm from 'containers/EmailSubscribeForm';
14+
1315

1416
const { fireErrorMessage } = errors;
1517

@@ -34,6 +36,9 @@ export function AppComponentSwitch(appComponent) {
3436
if (appComponent.fields.type === 'RecruitCRM-Jobs') {
3537
return <RecruitCRMJobs {...appComponent.fields.props} key={appComponent.sys.id} />;
3638
}
39+
if (appComponent.fields.type === 'EmailSubscribeForm') {
40+
return <EmailSubscribeForm {...appComponent.fields.props} key={appComponent.sys.id} />;
41+
}
3742
fireErrorMessage('Unsupported app component type from contentful', '');
3843
return null;
3944
}

src/shared/components/Gigs/GigDetails/index.jsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export default function GigDetails(props) {
4343
}
4444
let skills = getCustomField(job.custom_fields, 'Technologies Required');
4545
if (skills !== 'n/a') skills = skills.split(',').join(', ');
46+
const hPerW = getCustomField(job.custom_fields, 'Hours per week');
47+
const compens = job.min_annual_salary === job.max_annual_salary ? job.max_annual_salary : `${job.min_annual_salary} - ${job.max_annual_salary}`;
4648

4749
return (
4850
<div styleName="container">
@@ -70,7 +72,7 @@ export default function GigDetails(props) {
7072
<IconMoney />
7173
<div styleName="infos-data">
7274
Compensation
73-
<strong>${job.min_annual_salary} - ${job.max_annual_salary} / {getSalaryType(job.salary_type)}</strong>
75+
<strong>${compens} / {getSalaryType(job.salary_type)}</strong>
7476
</div>
7577
</div>
7678
<div styleName="infos-item">
@@ -84,7 +86,7 @@ export default function GigDetails(props) {
8486
<IconHours />
8587
<div styleName="infos-data">
8688
Hours
87-
<strong>{getCustomField(job.custom_fields, 'Hours per week')} hours / week</strong>
89+
<strong>{hPerW === 'n/a' ? hPerW : `${hPerW} hours / week`}</strong>
8890
</div>
8991
</div>
9092
<div styleName="infos-item">
@@ -108,7 +110,10 @@ export default function GigDetails(props) {
108110
* Topcoder does not provide visa sponsorship nor will we work with Staffing Agencies.
109111
</strong>
110112
<strong>
111-
** Topcoder and Wipro employees are not eligible for Gig work opportunities. Do not apply and send questions to <a href="mailto:support@topcoder.com">support@topcoder.com</a>.
113+
** USA Visa Holders - Please consult an attorney before applying to any Topcoder Gig. Some visa statuses will or will not allow you to conduct freelance work with Topcoder.
114+
</strong>
115+
<strong>
116+
*** Topcoder and Wipro employees are not eligible for Gig work opportunities. Do not apply and send questions to <a href="mailto:support@topcoder.com">support@topcoder.com</a>.
112117
</strong>
113118
</div>
114119
<div styleName="cta-buttons">

0 commit comments

Comments
 (0)