Skip to content

Commit e04f229

Browse files
author
Ubuntu
committed
update profile and skills to v5
1 parent 2a01da8 commit e04f229

File tree

8 files changed

+117
-26
lines changed

8 files changed

+117
-26
lines changed

__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
}

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

+21
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,25 @@ function updateProfileDone(profile, tokenV3) {
246246
return service.updateMemberProfile(profile);
247247
}
248248

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+
249268
/**
250269
* @static
251270
* @desc Creates an action that signals beginning of adding user's skill.
@@ -483,6 +502,8 @@ export default createActions({
483502
DELETE_PHOTO_DONE: updateProfileDone,
484503
UPDATE_PROFILE_INIT: updateProfileInit,
485504
UPDATE_PROFILE_DONE: updateProfileDone,
505+
UPDATE_PROFILE_INIT_V5: updateProfileInitV5,
506+
UPDATE_PROFILE_DONE_V5: updateProfileDoneV5,
486507
ADD_SKILL_INIT: addSkillInit,
487508
ADD_SKILL_DONE: addSkillDone,
488509
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 }),

src/services/members.js

+26-20
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ class MembersService {
4545
* @return {Promise} Resolves to the data object.
4646
*/
4747
async getMemberInfo(handle) {
48-
const res = await this.private.api.get(`/members/${handle}`);
49-
return getApiResponsePayload(res);
48+
const res = await this.private.apiV5.get(`/members/${handle}`);
49+
return handleApiResponse(res);
5050
}
5151

5252
/**
@@ -75,8 +75,8 @@ class MembersService {
7575
* @return {Promise} Resolves to the stats object.
7676
*/
7777
async getSkills(handle) {
78-
const res = await this.private.api.get(`/members/${handle}/skills`);
79-
return getApiResponsePayload(res);
78+
const res = await this.private.apiV5.get(`/members/${handle}/skills`);
79+
return handleApiResponse(res);
8080
}
8181

8282
/**
@@ -188,16 +188,12 @@ class MembersService {
188188
*/
189189
async addSkill(handle, skillTagId) {
190190
const body = {
191-
param: {
192-
skills: {
193-
[skillTagId]: {
194-
hidden: false,
195-
},
196-
},
191+
[skillTagId]: {
192+
hidden: false,
197193
},
198194
};
199-
const res = await this.private.api.patchJson(`/members/${handle}/skills`, body);
200-
return getApiResponsePayload(res);
195+
const res = await this.private.apiV5.patchJson(`/members/${handle}/skills`, body);
196+
return handleApiResponse(res);
201197
}
202198

203199
/**
@@ -208,19 +204,15 @@ class MembersService {
208204
*/
209205
async hideSkill(handle, skillTagId) {
210206
const body = {
211-
param: {
212-
skills: {
213-
[skillTagId]: {
214-
hidden: true,
215-
},
216-
},
207+
[skillTagId]: {
208+
hidden: true,
217209
},
218210
};
219-
const res = await this.private.api.fetch(`/members/${handle}/skills`, {
211+
const res = await this.private.apiV5.fetch(`/members/${handle}/skills`, {
220212
body: JSON.stringify(body),
221213
method: 'PATCH',
222214
});
223-
return getApiResponsePayload(res);
215+
return handleApiResponse(res);
224216
}
225217

226218
/**
@@ -237,6 +229,20 @@ class MembersService {
237229
return getApiResponsePayload(res);
238230
}
239231

232+
/**
233+
* Updates member profile.
234+
* @param {Object} profile The profile to update.
235+
* @return {Promise} Resolves to the api response content
236+
*/
237+
async updateMemberProfileV5(profile, handle) {
238+
const url = profile.verifyUrl ? `/members/${handle}?verifyUrl=${profile.verifyUrl}` : `/members/${handle}`;
239+
const res = await this.private.apiV5.putJson(url, profile.verifyUrl ? _.omit(profile, ['verifyUrl']) : profile);
240+
if (profile.verifyUrl && res.status === 409) {
241+
return Promise.resolve(Object.assign({}, profile, { isEmailConflict: true }));
242+
}
243+
return handleApiResponse(res);
244+
}
245+
240246
/**
241247
* Updates member photo.
242248
* @param {String} userHandle The user handle

0 commit comments

Comments
 (0)