Skip to content

Commit d49c623

Browse files
authored
Merge pull request #327 from topcoder-platform/feat/traits-v5-upgrade
feat: upgrade to use v5 member api
2 parents 71f3963 + 39265c8 commit d49c623

File tree

14 files changed

+157
-153
lines changed

14 files changed

+157
-153
lines changed

.circleci/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
- attach_workspace:
2929
at: .
3030
- run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
31-
- run: npm publish
31+
- run: npm publish --tag test-release
3232
# dont change anything
3333
workflows:
3434
version: 2

__tests__/__snapshots__/index.js.snap

+2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,9 @@ Object {
174174
"updatePasswordDone": [Function],
175175
"updatePasswordInit": [Function],
176176
"updateProfileDone": [Function],
177+
"updateProfileDoneV5": [Function],
177178
"updateProfileInit": [Function],
179+
"updateProfileInitV5": [Function],
178180
"uploadPhotoDone": [Function],
179181
"uploadPhotoInit": [Function],
180182
"verifyMemberNewEmailDone": [Function],

__tests__/actions/__snapshots__/profile.js.snap

+2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ Object {
4444
"updatePasswordDone": [Function],
4545
"updatePasswordInit": [Function],
4646
"updateProfileDone": [Function],
47+
"updateProfileDoneV5": [Function],
4748
"updateProfileInit": [Function],
49+
"updateProfileInitV5": [Function],
4850
"uploadPhotoDone": [Function],
4951
"uploadPhotoInit": [Function],
5052
"verifyMemberNewEmailDone": [Function],

__tests__/actions/auth.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const MOCK_GROUPS_REQ_URL = 'https://api.topcoder-dev.com/v5/groups?memberId=12345&membershipType=user';
2-
const MOCK_PROFILE_REQ_URL = 'https://api.topcoder-dev.com/v3/members/username12345';
2+
const MOCK_PROFILE_REQ_URL = 'https://api.topcoder-dev.com/v5/members/username12345';
33

44
jest.mock('isomorphic-fetch', () => jest.fn(url => Promise.resolve({
55
ok: true,
@@ -10,7 +10,7 @@ jest.mock('isomorphic-fetch', () => jest.fn(url => Promise.resolve({
1010
content = ['Group1', 'Group2'];
1111
break;
1212
case MOCK_PROFILE_REQ_URL:
13-
content = { result: { content: { userId: 12345 }, status: 200 } };
13+
content = Promise.resolve({ userId: 12345 });
1414
break;
1515
default: throw new Error('Unexpected URL!');
1616
}

__tests__/actions/profile.js

-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ const linkedAccounts = [{
1818

1919
// Mock services
2020
const mockMembersService = {
21-
getPresignedUrl: jest.fn().mockReturnValue(Promise.resolve()),
22-
uploadFileToS3: jest.fn().mockReturnValue(Promise.resolve()),
2321
updateMemberPhoto: jest.fn().mockReturnValue(Promise.resolve('url-of-photo')),
2422
updateMemberProfile: jest.fn().mockReturnValue(Promise.resolve(profile)),
2523
addSkill: jest.fn().mockReturnValue(Promise.resolve({ skills: [skill] })),
@@ -47,8 +45,6 @@ test('Module exports', () => expect(actions).toMatchSnapshot());
4745
test('profile.uploadPhotoDone', async () => {
4846
const actionResult = await redux.resolveAction(actions.profile.uploadPhotoDone(handle, tokenV3));
4947
expect(actionResult).toMatchSnapshot();
50-
expect(mockMembersService.getPresignedUrl).toBeCalled();
51-
expect(mockMembersService.uploadFileToS3).toBeCalled();
5248
expect(mockMembersService.updateMemberPhoto).toBeCalled();
5349
});
5450

docs/services.members.md

+6-34
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ members via API V3.
2525
* [.addSkill(handle, skillTagId)](#module_services.members..MembersService+addSkill) ⇒ <code>Promise</code>
2626
* [.hideSkill(handle, skillTagId)](#module_services.members..MembersService+hideSkill) ⇒ <code>Promise</code>
2727
* [.updateMemberProfile(profile)](#module_services.members..MembersService+updateMemberProfile) ⇒ <code>Promise</code>
28-
* [.getPresignedUrl(userHandle, file)](#module_services.members..MembersService+getPresignedUrl) ⇒ <code>Promise</code>
29-
* [.updateMemberPhoto(S3Response)](#module_services.members..MembersService+updateMemberPhoto) ⇒ <code>Promise</code>
30-
* [.uploadFileToS3(presignedUrlResponse)](#module_services.members..MembersService+uploadFileToS3) ⇒ <code>Promise</code>
28+
* [.updateMemberPhoto(userHandle, file)](#module_services.members..MembersService+updateMemberPhoto) ⇒ <code>Promise</code>
3129
* [.verifyMemberNewEmail(handle, emailVerifyToken)](#module_services.members..MembersService+verifyMemberNewEmail) ⇒ <code>Promise</code>
3230

3331
<a name="module_services.members.getService"></a>
@@ -65,9 +63,7 @@ Service class.
6563
* [.addSkill(handle, skillTagId)](#module_services.members..MembersService+addSkill) ⇒ <code>Promise</code>
6664
* [.hideSkill(handle, skillTagId)](#module_services.members..MembersService+hideSkill) ⇒ <code>Promise</code>
6765
* [.updateMemberProfile(profile)](#module_services.members..MembersService+updateMemberProfile) ⇒ <code>Promise</code>
68-
* [.getPresignedUrl(userHandle, file)](#module_services.members..MembersService+getPresignedUrl) ⇒ <code>Promise</code>
69-
* [.updateMemberPhoto(S3Response)](#module_services.members..MembersService+updateMemberPhoto) ⇒ <code>Promise</code>
70-
* [.uploadFileToS3(presignedUrlResponse)](#module_services.members..MembersService+uploadFileToS3) ⇒ <code>Promise</code>
66+
* [.updateMemberPhoto(userHandle, file)](#module_services.members..MembersService+updateMemberPhoto) ⇒ <code>Promise</code>
7167
* [.verifyMemberNewEmail(handle, emailVerifyToken)](#module_services.members..MembersService+verifyMemberNewEmail) ⇒ <code>Promise</code>
7268

7369
<a name="new_module_services.members..MembersService_new"></a>
@@ -256,42 +252,18 @@ Updates member profile.
256252
| --- | --- | --- |
257253
| profile | <code>Object</code> | The profile to update. |
258254

259-
<a name="module_services.members..MembersService+getPresignedUrl"></a>
260-
261-
#### membersService.getPresignedUrl(userHandle, file) ⇒ <code>Promise</code>
262-
Gets presigned url for member photo file.
263-
264-
**Kind**: instance method of [<code>MembersService</code>](#module_services.members..MembersService)
265-
**Returns**: <code>Promise</code> - Resolves to the api response content
266-
267-
| Param | Type | Description |
268-
| --- | --- | --- |
269-
| userHandle | <code>String</code> | The user handle |
270-
| file | <code>File</code> | The file to get its presigned url |
271-
272255
<a name="module_services.members..MembersService+updateMemberPhoto"></a>
273256

274-
#### membersService.updateMemberPhoto(S3Response) ⇒ <code>Promise</code>
275-
Updates member photo.
257+
#### membersService.updateMemberPhoto(userHandle, file) ⇒ <code>Promise</code>
258+
Uploads and updates member photo.
276259

277260
**Kind**: instance method of [<code>MembersService</code>](#module_services.members..MembersService)
278261
**Returns**: <code>Promise</code> - Resolves to the api response content
279262

280263
| Param | Type | Description |
281264
| --- | --- | --- |
282-
| S3Response | <code>Object</code> | The response from uploadFileToS3() function. |
283-
284-
<a name="module_services.members..MembersService+uploadFileToS3"></a>
285-
286-
#### membersService.uploadFileToS3(presignedUrlResponse) ⇒ <code>Promise</code>
287-
Uploads file to S3.
288-
289-
**Kind**: instance method of [<code>MembersService</code>](#module_services.members..MembersService)
290-
**Returns**: <code>Promise</code> - Resolves to the api response content
291-
292-
| Param | Type | Description |
293-
| --- | --- | --- |
294-
| presignedUrlResponse | <code>Object</code> | The presigned url response from getPresignedUrl() function. |
265+
| userHandle | <code>String</code> | The user handle |
266+
| file | <code>File</code> | The file to be uploaded |
295267

296268
<a name="module_services.members..MembersService+verifyMemberNewEmail"></a>
297269

package.json

+1-1
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": "1.2.4",
34+
"version": "1000.28.8",
3535
"dependencies": {
3636
"auth0-js": "^6.8.4",
3737
"config": "^3.2.0",

src/actions/auth.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55

66
import { createActions } from 'redux-actions';
77
import { decodeToken } from '@topcoder-platform/tc-auth-lib';
8-
import { getApiV3, getApiV5 } from '../services/api';
8+
import { getApiV5 } from '../services/api';
99
import { setErrorIcon, ERROR_ICON_TYPES } from '../utils/errors';
1010
import { getService } from '../services/groups';
11+
import { handleApiResponse } from '../utils/tc';
1112

1213
/**
1314
* Helper method that checks for HTTP error response v5 and throws Error in this case.
@@ -41,11 +42,10 @@ async function checkErrorV5(res) {
4142
function loadProfileDone(userTokenV3) {
4243
if (!userTokenV3) return Promise.resolve(null);
4344
const user = decodeToken(userTokenV3);
44-
const apiV3 = getApiV3(userTokenV3);
4545
const apiV5 = getApiV5(userTokenV3);
4646
return Promise.all([
47-
apiV3.get(`/members/${user.handle}`)
48-
.then(res => res.json()).then(res => (res.result.status === 200 ? res.result.content : {})),
47+
apiV5.get(`/members/${user.handle}`)
48+
.then(handleApiResponse),
4949
apiV5.get(`/groups?memberId=${user.userId}&membershipType=user`)
5050
.then(checkErrorV5).then(res => res.result || []),
5151
]).then(([profile, groups]) => ({ ...profile, groups }));

src/actions/profile.js

+22-3
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,7 @@ function uploadPhotoInit() {}
216216
*/
217217
function uploadPhotoDone(handle, tokenV3, file) {
218218
const service = getMembersService(tokenV3);
219-
return service.getPresignedUrl(handle, file)
220-
.then(res => service.uploadFileToS3(res))
221-
.then(res => service.updateMemberPhoto(res))
219+
return service.updateMemberPhoto(handle, file)
222220
.then(photoURL => ({ handle, photoURL }));
223221
}
224222

@@ -248,6 +246,25 @@ function updateProfileDone(profile, tokenV3) {
248246
return service.updateMemberProfile(profile);
249247
}
250248

249+
/**
250+
* @static
251+
* @desc Creates an action that signals beginning of updating user's profile.
252+
* @return {Action}
253+
*/
254+
function updateProfileInitV5() {}
255+
256+
/**
257+
* @static
258+
* @desc Creates an action that updates user's profile.
259+
* @param {String} profile Topcoder user profile.
260+
* @param {String} tokenV5 Topcoder auth token v5.
261+
* @return {Action}
262+
*/
263+
function updateProfileDoneV5(profile, handle, tokenV3) {
264+
const service = getMembersService(tokenV3);
265+
return service.updateMemberProfileV5(profile, handle);
266+
}
267+
251268
/**
252269
* @static
253270
* @desc Creates an action that signals beginning of adding user's skill.
@@ -485,6 +502,8 @@ export default createActions({
485502
DELETE_PHOTO_DONE: updateProfileDone,
486503
UPDATE_PROFILE_INIT: updateProfileInit,
487504
UPDATE_PROFILE_DONE: updateProfileDone,
505+
UPDATE_PROFILE_INIT_V5: updateProfileInitV5,
506+
UPDATE_PROFILE_DONE_V5: updateProfileDoneV5,
488507
ADD_SKILL_INIT: addSkillInit,
489508
ADD_SKILL_DONE: addSkillDone,
490509
HIDE_SKILL_INIT: hideSkillInit,

src/reducers/auth.js

+15
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,21 @@ function create(initialState) {
106106
},
107107
};
108108
},
109+
[profileActions.profile.updateProfileDoneV5]: (state, { payload, error }) => {
110+
if (error) {
111+
return state;
112+
}
113+
if (!state.profile || state.profile.handle !== payload.handle) {
114+
return state;
115+
}
116+
return {
117+
...state,
118+
profile: {
119+
...state.profile,
120+
...payload,
121+
},
122+
};
123+
},
109124
}, _.defaults(initialState, {
110125
authenticating: true,
111126
profile: null,

src/reducers/profile.js

+45
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,49 @@ function onUpdateProfileDone(state, { payload, error }) {
266266
};
267267
}
268268

269+
/**
270+
* Handles PROFILE/UPDATE_PROFILE_DONE_V5 action.
271+
* @param {Object} state
272+
* @param {Object} action Payload will be JSON from api call
273+
* @return {Object} New state
274+
*/
275+
function onUpdateProfileDoneV5(state, { payload, error }) {
276+
const newState = { ...state, updatingProfile: false };
277+
278+
if (payload.isEmailConflict) {
279+
return {
280+
...newState,
281+
isEmailConflict: true,
282+
updateProfileSuccess: false,
283+
};
284+
}
285+
286+
if (error) {
287+
logger.error('Failed to update user profile', payload);
288+
fireErrorMessage('ERROR: Failed to update user profile!');
289+
return {
290+
...newState,
291+
updateProfileSuccess: false,
292+
};
293+
}
294+
295+
if (!newState.info || newState.info.handle !== payload.handle) {
296+
return {
297+
...newState,
298+
updateProfileSuccess: true,
299+
};
300+
}
301+
302+
return {
303+
...newState,
304+
info: {
305+
...newState.info,
306+
...payload,
307+
},
308+
updateProfileSuccess: true,
309+
};
310+
}
311+
269312
/**
270313
* Handles PROFILE/ADD_SKILL_DONE action.
271314
* @param {Object} state
@@ -530,6 +573,8 @@ function create(initialState) {
530573
[a.deletePhotoDone]: onDeletePhotoDone,
531574
[a.updateProfileInit]: state => ({ ...state, updatingProfile: true }),
532575
[a.updateProfileDone]: onUpdateProfileDone,
576+
[a.updateProfileInitV5]: state => ({ ...state, updatingProfile: true }),
577+
[a.updateProfileDoneV5]: onUpdateProfileDoneV5,
533578
[a.addSkillInit]: state => ({ ...state, addingSkill: true }),
534579
[a.addSkillDone]: onAddSkillDone,
535580
[a.hideSkillInit]: state => ({ ...state, hidingSkill: true }),

0 commit comments

Comments
 (0)