Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 35 additions & 30 deletions src/api/users.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import _ from 'lodash'
import { axiosInstance as axios } from './requestInterceptor'
import { TC_API_URL, RESET_PASSWORD_URL } from '../config/constants'
import querystring from 'querystring'

/**
* Get a user based on it's handle/username
*
*
* @param {String} handle user handle
*
*
* @returns {Promise<Object>} user profile data
*/
export function getUserProfile(handle) {
Expand All @@ -18,15 +19,19 @@ export function getUserProfile(handle) {

/**
* Update user profile
*
*
* @param {String} handle user handle
* @param {Object} updatedProfile updated user data
*
* @param {Object} [queryParams] optional query params
*
* @returns {Promise<Object>} user profile data
*/
export function updateUserProfile(handle, updatedProfile) {
return axios.put(`${TC_API_URL}/v3/members/${handle}/`, {
param: updatedProfile
export function updateUserProfile(handle, updatedProfile, queryParams = {}) {
let query = querystring.stringify(queryParams)
query = query ? `?${query}` : ''

return axios.put(`${TC_API_URL}/v3/members/${handle}/${query}`, {
param: updatedProfile
})
.then(resp => {
return _.get(resp.data, 'result.content', {})
Expand All @@ -35,9 +40,9 @@ export function updateUserProfile(handle, updatedProfile) {

/**
* Get member traits
*
*
* @param {String} handle member handle
*
*
* @returns {Promise<Array>} member traits
*/
export const getMemberTraits = (handle) => {
Expand All @@ -47,10 +52,10 @@ export const getMemberTraits = (handle) => {

/**
* Update member traits
*
*
* @param {String} handle member handle
* @param {Array} updatedTraits list of updated traits
*
*
* @returns {Promise<Array>} member traits
*/
export const updateMemberTraits = (handle, updatedTraits) => {
Expand All @@ -62,10 +67,10 @@ export const updateMemberTraits = (handle, updatedTraits) => {

/**
* Create member traits
*
*
* @param {String} handle member handle
* @param {Array} traits list of traits to create
*
*
* @returns {Promise<Array>} member traits
*/
export const createMemberTraits = (handle, traits) => {
Expand All @@ -77,12 +82,12 @@ export const createMemberTraits = (handle, traits) => {

/**
* Update member photo
*
*
* @param {String} handle member handle
* @param {Object} data params to update photo
* @param {String} data.contentType photo file content type
* @param {String} data.token token provided by pre signed URL
*
*
* @returns {Promise<String>} photo URL
*/
export const updateMemberPhoto = (handle, data) => {
Expand All @@ -94,26 +99,26 @@ export const updateMemberPhoto = (handle, data) => {

/**
* Get pre-signed URL for member photo
*
*
* @param {String} handle member handle
* @param {File} file file to upload
*
* @returns {Promise<Object>} data of pre-signed URL
*
* @returns {Promise<Object>} data of pre-signed URL
*/
export const getPreSignedUrl = (handle, file) => {
return axios.post(`${TC_API_URL}/v3/members/${handle}/photoUploadUrl`, {
param: {
contentType: file.type
}
return axios.post(`${TC_API_URL}/v3/members/${handle}/photoUploadUrl`, {
param: {
contentType: file.type
}
})
.then(resp => _.get(resp.data, 'result.content', {}))
}

/**
* Check if email is available to be used for a user
*
*
* @param {String} email email to validate
*
*
* @returns {Promise<Object>} response body
*/
export const checkEmailValidity = (email) => {
Expand All @@ -123,24 +128,24 @@ export const checkEmailValidity = (email) => {

/**
* Update user password
*
*
* @param {Number} userId user id
* @param {Object} credential user credentials old and new one
*
*
* @returns {Promise<Object>} response body
*/
export const updatePassword = (userId, credential) => {
return axios.patch(`${TC_API_URL}/v3/users/${userId}`, {
param: { credential }
return axios.patch(`${TC_API_URL}/v3/users/${userId}`, {
param: { credential }
})
.then(resp => _.get(resp.data, 'result.content', {}))
}

/**
* Send reset password email to the user
*
*
* @param {String} email user email
*
*
* @returns {Promise<Object>} response body
*/
export const resetPassword = (email) => {
Expand Down
16 changes: 12 additions & 4 deletions src/routes/settings/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
RESET_PASSWORD_SUCCESS,
RESET_PASSWORD_FAILURE,
CLEAR_PROFILE_SETTINGS_PHOTO,
CONNECT_DOMAIN,
} from '../../../config/constants'
import settingsService from '../services/settings'
import * as memberService from '../../../api/users'
Expand Down Expand Up @@ -67,9 +68,11 @@ export const checkEmailAvailability = (email) => (dispatch) => {
memberService.checkEmailValidity(email)
.then(data => {
const isEmailAvailable = _.get(data, 'valid')
const reason = _.get(data, 'reason')

dispatch({
type: CHECK_EMAIL_AVAILABILITY_SUCCESS,
payload: {email, isEmailAvailable}
payload: {email, isEmailAvailable, reason}
})
})
.catch(err => {
Expand All @@ -93,7 +96,12 @@ export const changeEmail = (email) => (dispatch, getState) => {
// as we used `omit` above we have a new object and can directly update it
newProfile.email = email

memberService.updateUserProfile(handle, newProfile)
const queryParams = {
successUrl: `${CONNECT_DOMAIN}/settings/account/email-verification/success`,
failUrl: `${CONNECT_DOMAIN}/settings/account/email-verification/failure`
}

memberService.updateUserProfile(handle, newProfile, queryParams)
.then(data => {
dispatch({
type: CHANGE_EMAIL_SUCCESS,
Expand Down Expand Up @@ -205,13 +213,13 @@ export const saveProfileSettings = (settings) => (dispatch, getState) => {
// some traits could have categoryName as null
// for such traits we have to use POST method instead of PUT or we will get
// error 404 for such traits
traits.filter((trait) => trait.categoryName),
traits.filter((trait) => trait.categoryName),
'traitId'
)
const updatedTraits = applyProfileSettingsToTraits(traits, settings)

// we will only update on server traits which can be updated on the settings page
const traitsForServer = updatedTraits.filter((trait) =>
const traitsForServer = updatedTraits.filter((trait) =>
// TODO Revert to 'connect_info' again when PROD supports it
_.includes(['basic_info', customerTraitId], trait.traitId)
)
Expand Down
2 changes: 1 addition & 1 deletion src/routes/settings/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export default (state = initialState, action) => {
checkingEmail: null,
checkedEmail: action.payload.email,
isEmailAvailable: action.payload.isEmailAvailable,
checkingEmailError: null
checkingEmailError: action.payload.isEmailAvailable ? null : action.payload.reason
} : state.system
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,7 @@ class ChangeEmailForm extends React.Component {
}}
disabled={isEmailChanging}
ref={(ref) => this.emailRef = ref}
/* disable email field for now, as backend doesn't support returnUrl yet
and verification link which is sent to email leads to Community app, instead of Connect app for now */
disabled
/>
<div className="email-hint">
To change the email please <a href="mailto:support@topcoder.com">get in touch with support</a>
</div>
{ isFocused && isCheckingCurrentEmail && (
<div className="field-status">
Verifying email
Expand Down