diff --git a/src/api/users.js b/src/api/users.js index 1be70383d..abf3d6830 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -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} user profile data */ export function getUserProfile(handle) { @@ -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} 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', {}) @@ -35,9 +40,9 @@ export function updateUserProfile(handle, updatedProfile) { /** * Get member traits - * + * * @param {String} handle member handle - * + * * @returns {Promise} member traits */ export const getMemberTraits = (handle) => { @@ -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} member traits */ export const updateMemberTraits = (handle, updatedTraits) => { @@ -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} member traits */ export const createMemberTraits = (handle, traits) => { @@ -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} photo URL */ export const updateMemberPhoto = (handle, data) => { @@ -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} data of pre-signed URL + * + * @returns {Promise} 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} response body */ export const checkEmailValidity = (email) => { @@ -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} 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} response body */ export const resetPassword = (email) => { diff --git a/src/routes/settings/actions/index.js b/src/routes/settings/actions/index.js index 2ef9f0126..8025c8384 100644 --- a/src/routes/settings/actions/index.js +++ b/src/routes/settings/actions/index.js @@ -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' @@ -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 => { @@ -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, @@ -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) ) diff --git a/src/routes/settings/reducers/index.js b/src/routes/settings/reducers/index.js index 105747c16..d78609ea1 100644 --- a/src/routes/settings/reducers/index.js +++ b/src/routes/settings/reducers/index.js @@ -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 } diff --git a/src/routes/settings/routes/system/components/ChangeEmailForm.jsx b/src/routes/settings/routes/system/components/ChangeEmailForm.jsx index 38204f7b4..c4dce38a4 100644 --- a/src/routes/settings/routes/system/components/ChangeEmailForm.jsx +++ b/src/routes/settings/routes/system/components/ChangeEmailForm.jsx @@ -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 /> -
- To change the email please get in touch with support -
{ isFocused && isCheckingCurrentEmail && (
Verifying email