Skip to content

Commit adbac5a

Browse files
Merge pull request #1 from topcoder-platform/integration-v5-challenge-api
Integration v5 challenge api
2 parents 0df81e4 + f81a302 commit adbac5a

File tree

25 files changed

+372
-197
lines changed

25 files changed

+372
-197
lines changed

__tests__/__snapshots__/index.js.snap

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ Object {
111111
"getSubtrackChallengesInit": [Function],
112112
"getUserMarathonDone": [Function],
113113
"getUserMarathonInit": [Function],
114+
"getUserResourcesDone": [Function],
115+
"getUserResourcesInit": [Function],
114116
"getUserSrmDone": [Function],
115117
"getUserSrmInit": [Function],
116118
},
@@ -223,9 +225,9 @@ Object {
223225
"setEndDate": [Function],
224226
"setReviewOpportunityType": [Function],
225227
"setStartDate": [Function],
226-
"setSubtracks": [Function],
227228
"setTags": [Function],
228229
"setText": [Function],
230+
"setTypes": [Function],
229231
},
230232
},
231233
"errors": Object {
@@ -370,9 +372,10 @@ Object {
370372
},
371373
"tc": Object {
372374
"COMPETITION_TRACKS": Object {
373-
"DATA_SCIENCE": "data_science",
374-
"DESIGN": "design",
375-
"DEVELOP": "develop",
375+
"DATA_SCIENCE": "Data Science",
376+
"DESIGN": "Design",
377+
"DEVELOP": "Development",
378+
"QA": "Quality Assurance",
376379
},
377380
"REVIEW_OPPORTUNITY_TYPES": Object {
378381
"Contest Review": "Review",

__tests__/actions/auth.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
const MOCK_GROUPS_REQ_URL = 'https://api.topcoder-dev.com/v3/groups?memberId=12345&membershipType=user';
1+
const MOCK_GROUPS_REQ_URL = 'https://api.topcoder-dev.com/v5/groups?memberId=12345&membershipType=user';
22
const MOCK_PROFILE_REQ_URL = 'https://api.topcoder-dev.com/v3/members/username12345';
33

44
jest.mock('isomorphic-fetch', () => jest.fn(url => Promise.resolve({
5+
ok: true,
56
json: () => {
67
let content;
78
switch (url) {
8-
case MOCK_GROUPS_REQ_URL: content = ['Group1', 'Group2']; break;
9-
case MOCK_PROFILE_REQ_URL: content = { userId: 12345 }; break;
9+
case MOCK_GROUPS_REQ_URL:
10+
content = ['Group1', 'Group2'];
11+
break;
12+
case MOCK_PROFILE_REQ_URL:
13+
content = { result: { content: { userId: 12345 }, status: 200 } };
14+
break;
1015
default: throw new Error('Unexpected URL!');
1116
}
12-
return {
13-
result: { content, status: 200 },
14-
};
17+
return content;
1518
},
1619
})));
1720

__tests__/utils/challenge/filter.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
setText, setTags, setSubtracks, setStartDate,
2+
setText, setTags, setTypes, setStartDate,
33
} from '../../../src/utils/challenge/filter';
44

55
describe('challenge filter', () => {
@@ -22,12 +22,12 @@ describe('challenge filter', () => {
2222
expect(res).toEqual({});
2323
});
2424

25-
test('setSubtracks', () => {
26-
res = setSubtracks({});
25+
test('setTypes', () => {
26+
res = setTypes({});
2727
expect(res).toEqual({});
28-
res = setSubtracks({}, 'subtracks');
29-
expect(res).toEqual({ subtracks: 'subtracks' });
30-
res = setSubtracks({ subtracks: 'subtracks' });
28+
res = setTypes({}, 'types');
29+
expect(res).toEqual({ types: 'types' });
30+
res = setTypes({ types: 'types' });
3131
expect(res).toEqual({});
3232
});
3333

config/test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module.exports = {
22
API: {
33
V2: 'https://api.topcoder-dev.com/v2',
44
V3: 'https://api.topcoder-dev.com/v3',
5+
V5: 'https://api.topcoder-dev.com/v5',
56
},
67
dummyConfigKey: 'Dummy config value',
78
SECRET: {

docs/challenge.filter.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ users are participating.
7070
* [.setEndDate(state, date)](#module_challenge.filter.setEndDate) ⇒ <code>Object</code>
7171
* [.setReviewOpportunityType(state, reviewOpportunityType)](#module_challenge.filter.setReviewOpportunityType) ⇒ <code>Object</code>
7272
* [.setStartDate(state, date)](#module_challenge.filter.setStartDate) ⇒ <code>Object</code>
73-
* [.setSubtracks(state, subtracks)](#module_challenge.filter.setSubtracks) ⇒ <code>Object</code>
73+
* [.setTypes(state, types)](#module_challenge.filter.setTypes) ⇒ <code>Object</code>
7474
* [.setTags(state, tags)](#module_challenge.filter.setTags) ⇒ <code>Object</code>
7575
* [.setText(state, text)](#module_challenge.filter.setText) ⇒ <code>Object</code>
7676
* _inner_
@@ -198,17 +198,17 @@ Clones the state and sets the start date.
198198
| state | <code>Object</code> | |
199199
| date | <code>String</code> | ISO date string. |
200200

201-
<a name="module_challenge.filter.setSubtracks"></a>
201+
<a name="module_challenge.filter.setTypes"></a>
202202

203-
### challenge.filter.setSubtracks(state, subtracks) ⇒ <code>Object</code>
204-
Clones the state and sets the subtracks.
203+
### challenge.filter.setTypes(state, types) ⇒ <code>Object</code>
204+
Clones the state and sets the challenge types.
205205

206206
**Kind**: static method of [<code>challenge.filter</code>](#module_challenge.filter)
207207

208208
| Param | Type |
209209
| --- | --- |
210210
| state | <code>Object</code> |
211-
| subtracks | <code>Array</code> |
211+
| types | <code>Array</code> |
212212

213213
<a name="module_challenge.filter.setTags"></a>
214214

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"lint:js": "./node_modules/.bin/eslint --ext .js,.jsx .",
3232
"test": "npm run lint && npm run jest"
3333
},
34-
"version": "1000.19.22",
34+
"version": "1000.19.51",
3535
"dependencies": {
3636
"auth0-js": "^6.8.4",
3737
"config": "^3.2.0",

src/actions/auth.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { createActions } from 'redux-actions';
77
import { decodeToken } from 'tc-accounts';
8-
import { getApi } from '../services/api';
8+
import { getApiV3, getApiV5 } from '../services/api';
99

1010
/**
1111
* @static
@@ -16,12 +16,14 @@ import { getApi } from '../services/api';
1616
function loadProfileDone(userTokenV3) {
1717
if (!userTokenV3) return Promise.resolve(null);
1818
const user = decodeToken(userTokenV3);
19-
const api = getApi('V3', userTokenV3);
19+
const apiV3 = getApiV3(userTokenV3);
20+
const apiV5 = getApiV5(userTokenV3);
2021
return Promise.all([
21-
api.get(`/members/${user.handle}`)
22+
apiV3.get(`/members/${user.handle}`)
2223
.then(res => res.json()).then(res => (res.result.status === 200 ? res.result.content : {})),
23-
api.get(`/groups?memberId=${user.userId}&membershipType=user`)
24-
.then(res => res.json()).then(res => (res.result.status === 200 ? res.result.content : [])),
24+
apiV5.get(`/groups?memberId=${user.userId}&membershipType=user`)
25+
.then(res => (res.ok ? res.json() : new Error(res.statusText)))
26+
.then(res => (res.message ? new Error(res.message) : res)),
2527
]).then(([profile, groups]) => ({ ...profile, groups }));
2628
}
2729

src/actions/challenge.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import _ from 'lodash';
88
import { config } from 'topcoder-react-utils';
99
import { createActions } from 'redux-actions';
10+
import { decodeToken } from 'tc-accounts';
1011
import { getService as getChallengesService } from '../services/challenges';
1112
import { getService as getSubmissionService } from '../services/submissions';
1213
import { getService as getMemberService } from '../services/members';
@@ -103,16 +104,20 @@ function getSubmissionsInit(challengeId) {
103104
* @desc Creates an action that loads user's submissions to the specified
104105
* challenge.
105106
* @param {String} challengeId Challenge ID.
106-
* @param {String} tokenV2 Topcoder auth token v2.
107+
* @param {String} tokenV3 Topcoder auth token v3.
107108
* @return {Action}
108109
*/
109-
function getSubmissionsDone(challengeId, tokenV2) {
110-
return getApi('V2', tokenV2)
111-
.fetch(`/challenges/submissions/${challengeId}/mySubmissions`)
112-
.then(response => response.json())
113-
.then(response => ({
110+
function getSubmissionsDone(challengeId, tokenV3) {
111+
const user = decodeToken(tokenV3);
112+
const submissionsService = getSubmissionService(tokenV3);
113+
const filters = {
114+
challengeId,
115+
memberId: user.userId,
116+
};
117+
return submissionsService.getSubmissions(filters)
118+
.then(submissions => ({
114119
challengeId: _.toString(challengeId),
115-
submissions: response.submissions,
120+
submissions,
116121
}))
117122
.catch((error) => {
118123
const err = { challengeId: _.toString(challengeId), error };
@@ -289,13 +294,13 @@ function fetchCheckpointsDone(tokenV2, challengeId) {
289294
response.checkpointResults[index].expanded = false;
290295
});
291296
return {
292-
challengeId: Number(challengeId),
297+
challengeId: String(challengeId),
293298
checkpoints: response,
294299
};
295300
})
296301
.catch(error => ({
297302
error,
298-
challengeId: Number(challengeId),
303+
challengeId: String(challengeId),
299304
}));
300305
}
301306

src/actions/members.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,30 @@ async function getUserMarathonDone(
357357
}));
358358
}
359359

360+
/**
361+
* @static
362+
* @desc Create an action that fetch user registered challenge's resources.
363+
* @param {String} memberId Member id.
364+
* @param {String} uuid Operation UUID.
365+
* @return {Action}
366+
*/
367+
async function getUserResourcesInit(memberId, uuid) {
368+
return { memberId, uuid };
369+
}
370+
371+
/**
372+
* @static
373+
* @desc Create an action that fetch user registered challenge's resources.
374+
* @param {String} handle Member handle.
375+
* @param {String} uuid Operation UUID.
376+
* @return {Action}
377+
*/
378+
async function getUserResourcesDone(memberId, tokenV3, uuid) {
379+
const resources = await getService(tokenV3).getUserResources(memberId);
380+
381+
return { resources, uuid };
382+
}
383+
360384
export default createActions({
361385
MEMBERS: {
362386
DROP: drop,
@@ -380,5 +404,7 @@ export default createActions({
380404
GET_USER_SRM_DONE: getUserSRMDone,
381405
GET_USER_MARATHON_INIT: getUserMarathonInit,
382406
GET_USER_MARATHON_DONE: getUserMarathonDone,
407+
GET_USER_RESOURCES_INIT: getUserResourcesInit,
408+
GET_USER_RESOURCES_DONE: getUserResourcesDone,
383409
},
384410
});

src/actions/smp.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function deleteSubmissionInit() {}
2222
* @return {Action}
2323
*/
2424
function deleteSubmissionDone(tokenV3, submissionId) {
25-
return getApi('V3', tokenV3).delete(`/submissions/${submissionId}`)
25+
return getApi('V5', tokenV3).delete(`/submissions/${submissionId}`)
2626
.then(() => submissionId);
2727
}
2828

src/actions/terms.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function getTermsInit(arg) {
3232
* @return {Action}
3333
*/
3434
function getTermsDone(entity, tokens, mockAgreed) {
35-
const service = getService(tokens.tokenV2);
35+
const service = getService(tokens.tokenV3);
3636
let termsPromise;
3737

3838
// if mockAgreed=true passed, then we create an array of 10 true which we pass to the
@@ -44,7 +44,7 @@ function getTermsDone(entity, tokens, mockAgreed) {
4444

4545
switch (entity.type) {
4646
case 'challenge': {
47-
termsPromise = service.getChallengeTerms(entity.id, mockAgreedArray);
47+
termsPromise = service.getChallengeTerms(entity.terms, mockAgreedArray);
4848
break;
4949
}
5050
case 'community': {
@@ -59,7 +59,7 @@ function getTermsDone(entity, tokens, mockAgreed) {
5959
throw new Error(`Entity type '${entity.type}' is not supported by getTermsDone.`);
6060
}
6161

62-
return termsPromise.then(res => ({ entity, terms: res.terms }));
62+
return termsPromise.then(res => ({ entity, terms: res }));
6363
}
6464

6565
/**
@@ -152,11 +152,11 @@ function getTermDetailsInit(termId) {
152152
* @static
153153
* @desc Creates an action that fetches details of the specified term.
154154
* @param {Number|String} termId
155-
* @param {String} tokenV2
155+
* @param {String} tokenV3
156156
* @return {Action}
157157
*/
158-
function getTermDetailsDone(termId, tokenV2) {
159-
const service = getService(tokenV2);
158+
function getTermDetailsDone(termId, tokenV3) {
159+
const service = getService(tokenV3);
160160
return service.getTermDetails(termId).then(details => ({ termId, details }));
161161
}
162162

@@ -175,11 +175,11 @@ function getDocuSignUrlInit(templateId) {
175175
* @desc Creates an action that generates the url of DoduSign term
176176
* @param {Number|String} templateId id of document template to sign
177177
* @param {String} returnUrl callback url after finishing singing
178-
* @param {String} tokenV2 auth token
178+
* @param {String} tokenV3 auth token
179179
* @return {Action}
180180
*/
181-
function getDocuSignUrlDone(templateId, returnUrl, tokenV2) {
182-
const service = getService(tokenV2);
181+
function getDocuSignUrlDone(templateId, returnUrl, tokenV3) {
182+
const service = getService(tokenV3);
183183
return service.getDocuSignUrl(templateId, returnUrl)
184184
.then(resp => ({ templateId, docuSignUrl: resp.recipientViewUrl }));
185185
}
@@ -198,11 +198,11 @@ function agreeTermInit(termId) {
198198
* @static
199199
* @desc Creates an action that agrees to a term.
200200
* @param {Number|String} termId id of term
201-
* @param {String} tokenV2 auth token
201+
* @param {String} tokenV3 auth token
202202
* @return {Action}
203203
*/
204-
function agreeTermDone(termId, tokenV2) {
205-
const service = getService(tokenV2);
204+
function agreeTermDone(termId, tokenV3) {
205+
const service = getService(tokenV3);
206206
return service.agreeTerm(termId).then(resp => ({ termId, success: resp.success }));
207207
}
208208

src/reducers/challenge.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { fireErrorMessage } from '../utils/errors';
1818

1919
import mySubmissionsManagement from './my-submissions-management';
2020

21+
import { COMPETITION_TRACKS } from '../utils/tc';
22+
2123
/**
2224
* Handles CHALLENGE/GET_DETAILS_INIT action.
2325
* @param {Object} state
@@ -171,7 +173,7 @@ function onFetchCheckpointsDone(state, action) {
171173
loadingCheckpoints: false,
172174
};
173175
}
174-
if (state.details && state.details.id === action.payload.challengeId) {
176+
if (state.details && state.details.legacyId === action.payload.challengeId) {
175177
return {
176178
...state,
177179
checkpoints: action.payload.checkpoints,
@@ -465,15 +467,25 @@ export function factory(options = {}) {
465467
challengeId,
466468
tokens.tokenV3,
467469
tokens.tokenV2,
468-
)).then((details) => {
469-
const track = _.get(details, 'payload.track', '').toLowerCase();
470-
const checkpointsPromise = track === 'design' ? (
471-
redux.resolveAction(actions.challenge.fetchCheckpointsDone(tokens.tokenV2, challengeId))
472-
) : null;
473-
const resultsPromise = _.get(details, 'payload.status', '') === 'Completed' ? (
474-
redux.resolveAction(actions.challenge.loadResultsDone(tokens, challengeId, track))
470+
)).then((res) => {
471+
const challengeDetails = _.get(res, 'payload', {});
472+
const track = _.get(challengeDetails, 'track', '');
473+
let checkpointsPromise = null;
474+
if (track === COMPETITION_TRACKS.DESIGN) {
475+
const p = _.get(challengeDetails, 'phases', [])
476+
.filter(x => x.name === 'Checkpoint Review');
477+
if (p.length && !p[0].isOpen) {
478+
checkpointsPromise = redux.resolveAction(
479+
actions.challenge.fetchCheckpointsDone(tokens.tokenV2, challengeDetails.legacyId),
480+
);
481+
}
482+
}
483+
const resultsPromise = challengeDetails.status === 'Completed' ? (
484+
redux.resolveAction(
485+
actions.challenge.loadResultsDone(tokens, challengeId, track.toLowerCase()),
486+
)
475487
) : null;
476-
return Promise.all([details, checkpointsPromise, resultsPromise]);
488+
return Promise.all([res, checkpointsPromise, resultsPromise]);
477489
}).then(([details, checkpoints, results]) => {
478490
state = {
479491
...state,

0 commit comments

Comments
 (0)