From 388e4d300deb15728819ead090a2aec03a6d4fa1 Mon Sep 17 00:00:00 2001 From: RishiRajSahu Date: Tue, 2 Feb 2021 13:38:19 +0530 Subject: [PATCH 01/15] Added description for TaaS redirection button --- .circleci/config.yml | 2 +- .../TaasProjectWelcome/TaasProjectWelcome.jsx | 9 +++-- .../TaasProjectWelcome.scss | 36 ++++++++++++++++--- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a32f2f31f..913b48dfb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -128,7 +128,7 @@ workflows: - build-dev filters: branches: - only: ['dev'] + only: ['dev', 'feature/add_msg_for_taas_projects'] - deployTest01: context : org-global diff --git a/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.jsx b/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.jsx index 59c6c6e9a..cfe6fba45 100644 --- a/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.jsx +++ b/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.jsx @@ -5,8 +5,13 @@ import './TaasProjectWelcome.scss' const TaasProjectWelcome = ({ projectId }) => { const url = `${TAAS_APP_URL}/myteams/${projectId}` return ( -
- Go to your Talent Team +
+
+

This is a Talent as a Service project. Click this button to navigate to a TaaS focused experience where you can get information specific to your TaaS team.

+
+
+ Go to your Talent Team +
) } diff --git a/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.scss b/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.scss index e0ed62c21..2e30473f3 100644 --- a/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.scss +++ b/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.scss @@ -5,11 +5,39 @@ align-items: center; display: flex; justify-content: center; - height: 400px; + height: 100px; :global(.tc-btn-lg) { - height: 70px; - line-height: 68px; - font-size: 30px; + height: 50px; + line-height: 48px; + font-size: 20px; } + } + +.text-container { + @include stand-alone-item-shadow; + background-color: $tc-white; + border-radius: $card-border-radius; + margin-top: 4 * $base-unit; + padding: 5 * $base-unit; + + @media screen and (max-width: $screen-md - 1px) { + border-radius: 0; + } + + p { + @include roboto; + font-size: 15px; + margin-top: 3 * $base-unit; + line-height: 25px; + + b { + font-weight: bold; + } + + i { + font-style: italic; + } + } +} \ No newline at end of file From e8aab36c5987b3dacefefdcdf876b7609df411a9 Mon Sep 17 00:00:00 2001 From: yoution Date: Mon, 1 Mar 2021 23:36:39 +0800 Subject: [PATCH 02/15] fix: issue #4249 --- src/actions/loadUser.js | 24 +++++++++++++++---- src/api/users.js | 17 +++++++++++++ src/config/constants.js | 5 ++++ src/reducers/loadUser.js | 5 ++++ .../system/components/ChangeEmailForm.jsx | 5 ++-- .../system/components/SystemSettingsForm.jsx | 18 ++++++++++---- .../system/components/SystemSettingsForm.scss | 14 +++++++++++ .../containers/SystemSettingsContainer.jsx | 13 ++++++++-- 8 files changed, 87 insertions(+), 14 deletions(-) diff --git a/src/actions/loadUser.js b/src/actions/loadUser.js index b70c3eb88..0669fb51a 100644 --- a/src/actions/loadUser.js +++ b/src/actions/loadUser.js @@ -3,6 +3,8 @@ import { ACCOUNTS_APP_CONNECTOR_URL, LOAD_USER_SUCCESS, LOAD_USER_FAILURE, + LOAD_USER_CREDENTIAL, + LOAD_USER_CREDENTIAL_FAILURE, LOAD_ORG_CONFIG_SUCCESS, LOAD_ORG_CONFIG_FAILURE, ROLE_ADMINISTRATOR, @@ -16,7 +18,7 @@ import { ROLE_PRESALES, ROLE_PROJECT_MANAGER, ROLE_SOLUTION_ARCHITECT } from '../config/constants' import { getFreshToken, configureConnector, decodeToken } from 'tc-auth-lib' -import { getUserProfile } from '../api/users' +import { getUserProfile, getCredential } from '../api/users' import { fetchGroups } from '../api/groups' import { getOrgConfig } from '../api/orgConfig' import { EventTypes } from 'redux-segment' @@ -26,6 +28,18 @@ configureConnector({ frameId: 'tc-accounts-iframe' }) +export function getUserCredential(userId) { + return (dispatch) => { + return dispatch({ + type: LOAD_USER_CREDENTIAL, + payload: getCredential(userId) + }).catch((err) => { + console.log(err) + dispatch({ type: LOAD_USER_CREDENTIAL_FAILURE }) + }) + } +} + export function loadUser() { return ((dispatch, getState) => { const state = getState() @@ -125,9 +139,9 @@ export function loadUserSuccess(dispatch, token) { loadGroups(dispatch, currentUser.userId) }) .catch((err) => { - // if we fail to load user's profile, still dispatch user load success - // ideally it shouldn't happen, but if it is, we can render the page - // without profile information + // if we fail to load user's profile, still dispatch user load success + // ideally it shouldn't happen, but if it is, we can render the page + // without profile information console.log(err) dispatch({ type: LOAD_USER_SUCCESS, user : currentUser }) }) @@ -161,7 +175,7 @@ function loadGroups(dispatch, userId) { } }) .catch((err) => { - // if we fail to load groups + // if we fail to load groups console.log(err) }) } diff --git a/src/api/users.js b/src/api/users.js index 68a85159a..88b025020 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -17,6 +17,23 @@ export function getUserProfile(handle) { }) } + +/** + * Gets credential for the specified user id. + * + * NOTE: Only admins are authorized to use the underlying endpoint. + * + * @param {Number} userId The user id + * @return {Promise} Resolves to the linked accounts array. + */ +export function getCredential(userId) { + return axios.get(`${TC_API_URL}/v3/users/${userId}?fields=credential`) + .then(resp => { + return _.get(resp.data, 'result.content', {}) + }) +} + + /** * Update user profile * diff --git a/src/config/constants.js b/src/config/constants.js index c62adbaa8..da025d899 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -7,6 +7,11 @@ import { getCookie } from '../helpers/cookie' export const LOAD_USER_SUCCESS = 'LOAD_USER_SUCCESS' export const LOAD_USER_FAILURE = 'LOAD_USER_FAILURE' +export const LOAD_USER_CREDENTIAL = 'LOAD_USER_CREDENTIAL' +export const LOAD_USER_CREDENTIAL_SUCCESS = 'LOAD_USER_CREDENTIAL_SUCCESS' +export const LOAD_USER_CREDENTIAL_FAILURE = 'LOAD_USER_CREDENTIAL_FAILURE' + + // Load organization configs export const LOAD_ORG_CONFIG_SUCCESS = 'LOAD_ORG_CONFIG_SUCCESS' export const LOAD_ORG_CONFIG_FAILURE = 'LOAD_ORG_CONFIG_FAILURE' diff --git a/src/reducers/loadUser.js b/src/reducers/loadUser.js index 20e1a85d4..c9e9e5f1d 100644 --- a/src/reducers/loadUser.js +++ b/src/reducers/loadUser.js @@ -2,6 +2,7 @@ import _ from 'lodash' import { LOAD_USER_SUCCESS, LOAD_USER_FAILURE, + LOAD_USER_CREDENTIAL_SUCCESS, LOAD_ORG_CONFIG_SUCCESS, LOAD_ORG_CONFIG_FAILURE, SAVE_PROFILE_PHOTO_SUCCESS, @@ -18,6 +19,10 @@ export const initialState = { export default function(state = initialState, action) { switch (action.type) { + case LOAD_USER_CREDENTIAL_SUCCESS: + return Object.assign({}, state, { + credential: action.payload.credential + }) case LOAD_USER_SUCCESS: return Object.assign({}, state, { isLoading : false, diff --git a/src/routes/settings/routes/system/components/ChangeEmailForm.jsx b/src/routes/settings/routes/system/components/ChangeEmailForm.jsx index 717881b99..1ae89495b 100644 --- a/src/routes/settings/routes/system/components/ChangeEmailForm.jsx +++ b/src/routes/settings/routes/system/components/ChangeEmailForm.jsx @@ -98,7 +98,7 @@ class ChangeEmailForm extends React.Component { } render() { - const { settings, checkingEmail, checkedEmail, isEmailAvailable, isEmailChanging, emailSubmitted} = this.props + const {disabled, settings, checkingEmail, checkedEmail, isEmailAvailable, isEmailChanging, emailSubmitted} = this.props const { currentEmail, isValid, isFocused } = this.state const currentEmailAvailable = checkedEmail === currentEmail && isEmailAvailable const isCheckingCurrentEmail = checkingEmail === currentEmail @@ -140,7 +140,7 @@ class ChangeEmailForm extends React.Component { validationErrors={{ isEmail: 'Provide a correct email' }} - disabled={isEmailChanging || !hasPermission(PERMISSIONS.UPDATE_USER_EMAIL)} + disabled={disabled ||isEmailChanging || !hasPermission(PERMISSIONS.UPDATE_USER_EMAIL)} ref={(ref) => this.emailRef = ref} /> { isFocused && isCheckingCurrentEmail && ( @@ -174,6 +174,7 @@ class ChangeEmailForm extends React.Component { ChangeEmailForm.propTypes = { email: PropTypes.string, + disabled: PropTypes.bool, onSubmit: PropTypes.func.isRequired, checkingEmail: PropTypes.string, checkedEmail: PropTypes.string, diff --git a/src/routes/settings/routes/system/components/SystemSettingsForm.jsx b/src/routes/settings/routes/system/components/SystemSettingsForm.jsx index a2c6143ee..29f8fe6e7 100644 --- a/src/routes/settings/routes/system/components/SystemSettingsForm.jsx +++ b/src/routes/settings/routes/system/components/SystemSettingsForm.jsx @@ -9,7 +9,7 @@ const TCFormFields = FormsyForm.Fields class SystemSettingsForm extends Component { render() { - const { changePassword, checkEmailAvailability, changeEmail, systemSettings, resetPassword } = this.props + const { changePassword, checkEmailAvailability, changeEmail, systemSettings, resetPassword, usingSsoService } = this.props return (
@@ -40,20 +40,28 @@ class SystemSettingsForm extends Component { checkEmailAvailability={checkEmailAvailability} onSubmit={(email) => changeEmail(email)} {...systemSettings} + disabled={usingSsoService? true: systemSettings.disabled === true} /> + + {usingSsoService ?
+ Since you joined Topcoder using your <SSO Service> account, + any email updates will need to be handled by logging in to + your <SSO Service> account. +
: null}
-
+ {!usingSsoService ? +
Retrieve or change your password -
+
: null} -
+ {!usingSsoService ?
changePassword(data)} onReset={() => resetPassword()} {...systemSettings} /> -
+
: null}
) } diff --git a/src/routes/settings/routes/system/components/SystemSettingsForm.scss b/src/routes/settings/routes/system/components/SystemSettingsForm.scss index b5d6d54a7..8221af529 100644 --- a/src/routes/settings/routes/system/components/SystemSettingsForm.scss +++ b/src/routes/settings/routes/system/components/SystemSettingsForm.scss @@ -4,6 +4,19 @@ display: flex; flex-direction: column; padding-bottom: 30px; + + .error-message { + @include roboto-medium; + + display: block; + border-radius: 5px; + background-color: $tc-red-10; + color: $tc-red-110; + font-size: 15px; + padding: 15px; + margin: 15px 40px; + line-height: 20px; + } } .username { @@ -41,6 +54,7 @@ .input-container { flex-grow: 1; + @media screen and (max-width: $screen-md - 1px) { width: 100%; } diff --git a/src/routes/settings/routes/system/containers/SystemSettingsContainer.jsx b/src/routes/settings/routes/system/containers/SystemSettingsContainer.jsx index ff57ac633..2f1a40757 100644 --- a/src/routes/settings/routes/system/containers/SystemSettingsContainer.jsx +++ b/src/routes/settings/routes/system/containers/SystemSettingsContainer.jsx @@ -7,6 +7,7 @@ import { connect } from 'react-redux' import spinnerWhileLoading from '../../../../../components/LoadingSpinner' import SettingsPanel from '../../../components/SettingsPanel' import { checkEmailAvailability, changeEmail, changePassword, getSystemSettings, resetPassword } from '../../../actions' +import { getUserCredential } from '../../../../../actions/loadUser' import { requiresAuthentication } from '../../../../../components/AuthenticatedComponent' import SystemSettingsForm from '../components/SystemSettingsForm' import './SystemSettingsContainer.scss' @@ -16,7 +17,13 @@ const FormEnhanced = enhance(SystemSettingsForm) class SystemSettingsContainer extends Component { componentDidMount() { - this.props.getSystemSettings() + const { + getSystemSettings, + getUserCredential, + user + } = this.props + getSystemSettings() + getUserCredential(user.userId) } render() { @@ -41,11 +48,13 @@ const SystemSettingsContainerWithAuth = requiresAuthentication(SystemSettingsCon const mapStateToProps = ({ settings, loadUser }) => ({ systemSettings: settings.system, - user: loadUser.user + user: loadUser.user, + usingSsoService: _.get(loadUser, 'credential.hasPassword', false) === false, }) const mapDispatchToProps = { getSystemSettings, + getUserCredential, checkEmailAvailability, changeEmail, changePassword, From fef90c5f1fefcd6f36148313bc8ec5c21e96bfd7 Mon Sep 17 00:00:00 2001 From: yoution Date: Tue, 2 Mar 2021 00:20:34 +0800 Subject: [PATCH 03/15] fix: issue-4301 --- src/components/TeamManagement/AutocompleteInput.jsx | 10 +++++++++- .../TeamManagement/AutocompleteInputContainer.jsx | 13 ++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/components/TeamManagement/AutocompleteInput.jsx b/src/components/TeamManagement/AutocompleteInput.jsx index d670dfc90..fadc7370c 100644 --- a/src/components/TeamManagement/AutocompleteInput.jsx +++ b/src/components/TeamManagement/AutocompleteInput.jsx @@ -16,7 +16,8 @@ class AutocompleteInput extends React.Component { const { placeholder, selectedMembers, - disabled + disabled, + inputValue } = this.props return ( @@ -27,6 +28,7 @@ class AutocompleteInput extends React.Component { showDropdownIndicator={false} createOption placeholder={placeholder} + inputValue={inputValue} value={selectedMembers} onInputChange={this.props.onInputChange} onChange={this.props.onUpdate} @@ -41,6 +43,7 @@ class AutocompleteInput extends React.Component { AutocompleteInput.defaultProps = { placeholder: 'Enter one or more user handles', selectedMembers: [], + inputValue: '', disabled: false } @@ -70,6 +73,11 @@ AutocompleteInput.propTypes = { * The flag if component is disabled */ disabled: PropTypes.bool, + + /** + * The inputValue for the input field + */ + inputValue: PropTypes.string, } export default AutocompleteInput diff --git a/src/components/TeamManagement/AutocompleteInputContainer.jsx b/src/components/TeamManagement/AutocompleteInputContainer.jsx index 8bf201179..2f8c732ee 100644 --- a/src/components/TeamManagement/AutocompleteInputContainer.jsx +++ b/src/components/TeamManagement/AutocompleteInputContainer.jsx @@ -11,6 +11,10 @@ class AutocompleteInputContainer extends React.Component { constructor(props) { super(props) this.debounceTimer = null + this.state = { + // field input value + inputValue: '' + } this.clearUserSuggestions = this.clearUserSuggestions.bind(this) } @@ -27,7 +31,11 @@ class AutocompleteInputContainer extends React.Component { } } - onInputChange(inputValue) { + onInputChange(inputValue, reason) { + // for keeping inputValue + if (reason.action === 'input-blur' || reason.action === 'menu-close') { + return + } const indexOfSpace = inputValue.indexOf(' ') const indexOfSemiColon = inputValue.indexOf(';') @@ -36,6 +44,7 @@ class AutocompleteInputContainer extends React.Component { return '' } + this.setState({inputValue}) if (indexOfSpace >= 1 || indexOfSemiColon >= 1 ) { inputValue = inputValue.substring(0, inputValue.length -1 ) this.onUpdate([...this.props.selectedMembers, {label: inputValue, value: inputValue}]) @@ -69,9 +78,11 @@ class AutocompleteInputContainer extends React.Component { render() { const { placeholder, currentUser, selectedMembers, disabled } = this.props + const {inputValue} = this.state return ( Date: Tue, 2 Mar 2021 17:07:43 +0800 Subject: [PATCH 04/15] fix: issue #4300 --- src/projects/detail/components/BillingAccountField/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/projects/detail/components/BillingAccountField/index.js b/src/projects/detail/components/BillingAccountField/index.js index f906a2927..12789085c 100644 --- a/src/projects/detail/components/BillingAccountField/index.js +++ b/src/projects/detail/components/BillingAccountField/index.js @@ -1,4 +1,5 @@ import React from 'react' +import moment from 'moment' import {HOC as hoc} from 'formsy-react' import Select from '../../../../components/Select/Select' @@ -14,7 +15,7 @@ import styles from './styles.module.scss' * @returns {{ label: string, value: number }} option for Select */ const buildOption = (billingAccountObj) => ({ - label: `${billingAccountObj.name} (${billingAccountObj.tcBillingAccountId})`, + label: `${billingAccountObj.name} (${billingAccountObj.tcBillingAccountId}) - ${moment(billingAccountObj.endDate).format('DD MMM YYYY')}`, value: billingAccountObj.tcBillingAccountId }) From 93698dc03ec0a1b466dbf0f78384e7218e15cf41 Mon Sep 17 00:00:00 2001 From: narekcat Date: Tue, 2 Mar 2021 16:12:31 +0400 Subject: [PATCH 05/15] fix: issue 4316 --- src/components/Select/Select.jsx | 1 + src/projects/detail/components/BillingAccountField/index.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Select/Select.jsx b/src/components/Select/Select.jsx index 92f300a7e..34e03dd45 100644 --- a/src/components/Select/Select.jsx +++ b/src/components/Select/Select.jsx @@ -36,6 +36,7 @@ const Select = (props) => { createOptionPosition="first" className={containerclass} classNamePrefix="react-select" + isClearable /> ) } diff --git a/src/projects/detail/components/BillingAccountField/index.js b/src/projects/detail/components/BillingAccountField/index.js index f906a2927..73f6b6611 100644 --- a/src/projects/detail/components/BillingAccountField/index.js +++ b/src/projects/detail/components/BillingAccountField/index.js @@ -72,7 +72,7 @@ class BillingAccountField extends React.Component { handleChange(value) { this.setState({ selectedBillingAccount: value }) - this.props.setValue(value.value) + this.props.setValue(value ? value.value : null) } render() { @@ -89,6 +89,7 @@ class BillingAccountField extends React.Component { value={this.state.selectedBillingAccount} options={this.state.billingAccounts} isDisabled={this.state.billingAccounts.length === 0} + showDropdownIndicator /> {/* Hide this link because we haven't implemented a required page in SFDC yet */} {/*
From df328ec7aa6033852c101aaca53da731c8d7a7cb Mon Sep 17 00:00:00 2001 From: yoution Date: Tue, 2 Mar 2021 21:30:23 +0800 Subject: [PATCH 06/15] fix: issue #4315 --- config/constants/dev.js | 1 + config/constants/master.js | 1 + config/constants/qa.js | 1 + src/config/constants.js | 1 + .../detail/components/BillingAccountField/index.js | 9 ++++----- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/config/constants/dev.js b/config/constants/dev.js index d8c3e285f..5776dd80a 100644 --- a/config/constants/dev.js +++ b/config/constants/dev.js @@ -38,6 +38,7 @@ module.exports = { FILE_PICKER_ACCEPT: process.env.FILE_PICKER_ACCEPT_DEV, SALESFORCE_PROJECT_LEAD_LINK: 'https://c.cs18.visual.force.com/apex/ConnectLead?connectProjectId=', + SALESFORCE_BILLING_ACCOUNT_LINK: 'https://c.cs18.visual.force.com/apex/baredirect?id=', CONNECT_SEGMENT_KEY: process.env.DEV_SEGMENT_KEY, PREDIX_PROGRAM_ID : 3448, diff --git a/config/constants/master.js b/config/constants/master.js index 924643813..a594a3545 100644 --- a/config/constants/master.js +++ b/config/constants/master.js @@ -39,6 +39,7 @@ module.exports = { FILE_PICKER_ACCEPT: process.env.FILE_PICKER_ACCEPT_PROD, SALESFORCE_PROJECT_LEAD_LINK: 'https://topcoder.my.salesforce.com/apex/ConnectLead?connectProjectId=', + SALESFORCE_BILLING_ACCOUNT_LINK: 'https://topcoder.my.salesforce.com/apex/baredirect?id=', CONNECT_SEGMENT_KEY: process.env.PROD_SEGMENT_KEY, PREDIX_PROGRAM_ID : 3448, IBM_COGNITIVE_PROGRAM_ID : 3449, diff --git a/config/constants/qa.js b/config/constants/qa.js index 0d94ada46..31d32cce2 100644 --- a/config/constants/qa.js +++ b/config/constants/qa.js @@ -38,6 +38,7 @@ module.exports = { FILE_PICKER_ACCEPT: process.env.FILE_PICKER_ACCEPT_QA, SALESFORCE_PROJECT_LEAD_LINK: 'https://c.cs18.visual.force.com/apex/ConnectLead?connectProjectId=', + SALESFORCE_BILLING_ACCOUNT_LINK: 'https://c.cs18.visual.force.com/apex/baredirect?id=', CONNECT_SEGMENT_KEY: process.env.QA_SEGMENT_KEY, PREDIX_PROGRAM_ID : 3448, IBM_COGNITIVE_PROGRAM_ID : 3449, diff --git a/src/config/constants.js b/src/config/constants.js index c62adbaa8..c404fc4cb 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -738,6 +738,7 @@ export const TC_API_URL = `https://api.${DOMAIN}` export const DIRECT_PROJECT_URL = `https://www.${DOMAIN}/direct/projectOverview?formData.projectId=` export const WORK_MANAGER_APP = `https://challenges.${DOMAIN}/projects` export const SALESFORCE_PROJECT_LEAD_LINK = process.env.SALESFORCE_PROJECT_LEAD_LINK +export const SALESFORCE_BILLING_ACCOUNT_LINK = process.env.SALESFORCE_BILLING_ACCOUNT_LINK export const TC_NOTIFICATION_URL = process.env.TC_NOTIFICATION_URL || `${TC_API_URL}/v5/notifications` // Uncomment if you run TC Notifications locally // export const TC_NOTIFICATION_URL = 'http://localstho:4000/v5/notifications' diff --git a/src/projects/detail/components/BillingAccountField/index.js b/src/projects/detail/components/BillingAccountField/index.js index f906a2927..e31c27cd3 100644 --- a/src/projects/detail/components/BillingAccountField/index.js +++ b/src/projects/detail/components/BillingAccountField/index.js @@ -3,7 +3,7 @@ import {HOC as hoc} from 'formsy-react' import Select from '../../../../components/Select/Select' import {fetchBillingAccounts} from '../../../../api/billingAccounts' -// import {SALESFORCE_PROJECT_LEAD_LINK} from '../../../../config/constants' +import {SALESFORCE_BILLING_ACCOUNT_LINK} from '../../../../config/constants' import styles from './styles.module.scss' @@ -90,17 +90,16 @@ class BillingAccountField extends React.Component { options={this.state.billingAccounts} isDisabled={this.state.billingAccounts.length === 0} /> - {/* Hide this link because we haven't implemented a required page in SFDC yet */} - {/*
+ {this.state.selectedBillingAccount ? */} +
: null }
) } From 94ab43cbcf2e739bda6d1c58eb61c2e224ee5339 Mon Sep 17 00:00:00 2001 From: yoution Date: Wed, 3 Mar 2021 22:32:43 +0800 Subject: [PATCH 07/15] fix issue #4249 --- src/config/constants.js | 1 + src/reducers/loadUser.js | 11 ++++++ .../system/components/ChangeEmailForm.jsx | 6 ++-- .../system/components/SystemSettingsForm.jsx | 35 +++++++++++-------- .../containers/SystemSettingsContainer.jsx | 3 +- 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/config/constants.js b/src/config/constants.js index da025d899..13ed9c6f0 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -8,6 +8,7 @@ export const LOAD_USER_SUCCESS = 'LOAD_USER_SUCCESS' export const LOAD_USER_FAILURE = 'LOAD_USER_FAILURE' export const LOAD_USER_CREDENTIAL = 'LOAD_USER_CREDENTIAL' +export const LOAD_USER_CREDENTIAL_PENDING = 'LOAD_USER_CREDENTIAL_PENDING' export const LOAD_USER_CREDENTIAL_SUCCESS = 'LOAD_USER_CREDENTIAL_SUCCESS' export const LOAD_USER_CREDENTIAL_FAILURE = 'LOAD_USER_CREDENTIAL_FAILURE' diff --git a/src/reducers/loadUser.js b/src/reducers/loadUser.js index c9e9e5f1d..376d1345a 100644 --- a/src/reducers/loadUser.js +++ b/src/reducers/loadUser.js @@ -2,7 +2,9 @@ import _ from 'lodash' import { LOAD_USER_SUCCESS, LOAD_USER_FAILURE, + LOAD_USER_CREDENTIAL_PENDING, LOAD_USER_CREDENTIAL_SUCCESS, + LOAD_USER_CREDENTIAL_FAILURE, LOAD_ORG_CONFIG_SUCCESS, LOAD_ORG_CONFIG_FAILURE, SAVE_PROFILE_PHOTO_SUCCESS, @@ -19,10 +21,19 @@ export const initialState = { export default function(state = initialState, action) { switch (action.type) { + case LOAD_USER_CREDENTIAL_PENDING: + return Object.assign({}, state, { + isLoadingCredential: true, + }) case LOAD_USER_CREDENTIAL_SUCCESS: return Object.assign({}, state, { + isLoadingCredential: false, credential: action.payload.credential }) + case LOAD_USER_CREDENTIAL_FAILURE: + return Object.assign({}, state, { + isLoadingCredential: false, + }) case LOAD_USER_SUCCESS: return Object.assign({}, state, { isLoading : false, diff --git a/src/routes/settings/routes/system/components/ChangeEmailForm.jsx b/src/routes/settings/routes/system/components/ChangeEmailForm.jsx index 1ae89495b..9025826d4 100644 --- a/src/routes/settings/routes/system/components/ChangeEmailForm.jsx +++ b/src/routes/settings/routes/system/components/ChangeEmailForm.jsx @@ -98,7 +98,7 @@ class ChangeEmailForm extends React.Component { } render() { - const {disabled, settings, checkingEmail, checkedEmail, isEmailAvailable, isEmailChanging, emailSubmitted} = this.props + const {usingSsoService, settings, checkingEmail, checkedEmail, isEmailAvailable, isEmailChanging, emailSubmitted} = this.props const { currentEmail, isValid, isFocused } = this.state const currentEmailAvailable = checkedEmail === currentEmail && isEmailAvailable const isCheckingCurrentEmail = checkingEmail === currentEmail @@ -140,7 +140,7 @@ class ChangeEmailForm extends React.Component { validationErrors={{ isEmail: 'Provide a correct email' }} - disabled={disabled ||isEmailChanging || !hasPermission(PERMISSIONS.UPDATE_USER_EMAIL)} + disabled={usingSsoService || isEmailChanging || !hasPermission(PERMISSIONS.UPDATE_USER_EMAIL)} ref={(ref) => this.emailRef = ref} /> { isFocused && isCheckingCurrentEmail && ( @@ -174,7 +174,7 @@ class ChangeEmailForm extends React.Component { ChangeEmailForm.propTypes = { email: PropTypes.string, - disabled: PropTypes.bool, + usingSsoService: PropTypes.bool, onSubmit: PropTypes.func.isRequired, checkingEmail: PropTypes.string, checkedEmail: PropTypes.string, diff --git a/src/routes/settings/routes/system/components/SystemSettingsForm.jsx b/src/routes/settings/routes/system/components/SystemSettingsForm.jsx index 29f8fe6e7..5870ee742 100644 --- a/src/routes/settings/routes/system/components/SystemSettingsForm.jsx +++ b/src/routes/settings/routes/system/components/SystemSettingsForm.jsx @@ -40,28 +40,33 @@ class SystemSettingsForm extends Component { checkEmailAvailability={checkEmailAvailability} onSubmit={(email) => changeEmail(email)} {...systemSettings} - disabled={usingSsoService? true: systemSettings.disabled === true} + usingSsoService={usingSsoService} /> - {usingSsoService ?
- Since you joined Topcoder using your <SSO Service> account, - any email updates will need to be handled by logging in to - your <SSO Service> account. -
: null} + {usingSsoService && ( +
+ Since you joined Topcoder using your <SSO Service> account, + any email updates will need to be handled by logging in to + your <SSO Service> account. +
+ )} - {!usingSsoService ? + {!usingSsoService&& (
Retrieve or change your password -
: null} + + )} - {!usingSsoService ?
- changePassword(data)} - onReset={() => resetPassword()} - {...systemSettings} - /> -
: null} + {!usingSsoService && ( +
+ changePassword(data)} + onReset={() => resetPassword()} + {...systemSettings} + /> +
+ )} ) } diff --git a/src/routes/settings/routes/system/containers/SystemSettingsContainer.jsx b/src/routes/settings/routes/system/containers/SystemSettingsContainer.jsx index 2f1a40757..201be6729 100644 --- a/src/routes/settings/routes/system/containers/SystemSettingsContainer.jsx +++ b/src/routes/settings/routes/system/containers/SystemSettingsContainer.jsx @@ -12,7 +12,7 @@ import { requiresAuthentication } from '../../../../../components/AuthenticatedC import SystemSettingsForm from '../components/SystemSettingsForm' import './SystemSettingsContainer.scss' -const enhance = spinnerWhileLoading(props => !props.systemSettings.isLoading) +const enhance = spinnerWhileLoading(props => !props.systemSettings.isLoading && !props.isLoadingCredential) const FormEnhanced = enhance(SystemSettingsForm) class SystemSettingsContainer extends Component { @@ -49,6 +49,7 @@ const SystemSettingsContainerWithAuth = requiresAuthentication(SystemSettingsCon const mapStateToProps = ({ settings, loadUser }) => ({ systemSettings: settings.system, user: loadUser.user, + isLoadingCredential: loadUser.isLoadingCredential, usingSsoService: _.get(loadUser, 'credential.hasPassword', false) === false, }) From a23bc24db2f35f743b472262a7aa2df5c7c858af Mon Sep 17 00:00:00 2001 From: yoution Date: Thu, 4 Mar 2021 08:34:13 +0800 Subject: [PATCH 08/15] fix: issue #4315 --- .../components/BillingAccountField/index.js | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/projects/detail/components/BillingAccountField/index.js b/src/projects/detail/components/BillingAccountField/index.js index e31c27cd3..6075ceb0a 100644 --- a/src/projects/detail/components/BillingAccountField/index.js +++ b/src/projects/detail/components/BillingAccountField/index.js @@ -90,16 +90,18 @@ class BillingAccountField extends React.Component { options={this.state.billingAccounts} isDisabled={this.state.billingAccounts.length === 0} /> - {this.state.selectedBillingAccount ? + )} ) } From e9361c3eda5bba14d6401c626beaf04309df5398 Mon Sep 17 00:00:00 2001 From: yoution Date: Thu, 4 Mar 2021 08:50:47 +0800 Subject: [PATCH 09/15] fix: issue #4300 --- src/projects/detail/components/BillingAccountField/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/projects/detail/components/BillingAccountField/index.js b/src/projects/detail/components/BillingAccountField/index.js index 12789085c..400b5222c 100644 --- a/src/projects/detail/components/BillingAccountField/index.js +++ b/src/projects/detail/components/BillingAccountField/index.js @@ -15,7 +15,7 @@ import styles from './styles.module.scss' * @returns {{ label: string, value: number }} option for Select */ const buildOption = (billingAccountObj) => ({ - label: `${billingAccountObj.name} (${billingAccountObj.tcBillingAccountId}) - ${moment(billingAccountObj.endDate).format('DD MMM YYYY')}`, + label: `${billingAccountObj.name} (${billingAccountObj.tcBillingAccountId}) ${billingAccountObj.endDate ? ' - '+ moment(billingAccountObj.endDate).format('DD MMM YYYY'): ''}`, value: billingAccountObj.tcBillingAccountId }) From 04261344530fbb9130a3459e0840853196a067f9 Mon Sep 17 00:00:00 2001 From: yoution Date: Thu, 4 Mar 2021 11:30:40 +0800 Subject: [PATCH 10/15] Revert "fix: issue-4301" This reverts commit fef90c5f1fefcd6f36148313bc8ec5c21e96bfd7. --- src/components/TeamManagement/AutocompleteInput.jsx | 10 +--------- .../TeamManagement/AutocompleteInputContainer.jsx | 13 +------------ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/components/TeamManagement/AutocompleteInput.jsx b/src/components/TeamManagement/AutocompleteInput.jsx index fadc7370c..d670dfc90 100644 --- a/src/components/TeamManagement/AutocompleteInput.jsx +++ b/src/components/TeamManagement/AutocompleteInput.jsx @@ -16,8 +16,7 @@ class AutocompleteInput extends React.Component { const { placeholder, selectedMembers, - disabled, - inputValue + disabled } = this.props return ( @@ -28,7 +27,6 @@ class AutocompleteInput extends React.Component { showDropdownIndicator={false} createOption placeholder={placeholder} - inputValue={inputValue} value={selectedMembers} onInputChange={this.props.onInputChange} onChange={this.props.onUpdate} @@ -43,7 +41,6 @@ class AutocompleteInput extends React.Component { AutocompleteInput.defaultProps = { placeholder: 'Enter one or more user handles', selectedMembers: [], - inputValue: '', disabled: false } @@ -73,11 +70,6 @@ AutocompleteInput.propTypes = { * The flag if component is disabled */ disabled: PropTypes.bool, - - /** - * The inputValue for the input field - */ - inputValue: PropTypes.string, } export default AutocompleteInput diff --git a/src/components/TeamManagement/AutocompleteInputContainer.jsx b/src/components/TeamManagement/AutocompleteInputContainer.jsx index 2f8c732ee..8bf201179 100644 --- a/src/components/TeamManagement/AutocompleteInputContainer.jsx +++ b/src/components/TeamManagement/AutocompleteInputContainer.jsx @@ -11,10 +11,6 @@ class AutocompleteInputContainer extends React.Component { constructor(props) { super(props) this.debounceTimer = null - this.state = { - // field input value - inputValue: '' - } this.clearUserSuggestions = this.clearUserSuggestions.bind(this) } @@ -31,11 +27,7 @@ class AutocompleteInputContainer extends React.Component { } } - onInputChange(inputValue, reason) { - // for keeping inputValue - if (reason.action === 'input-blur' || reason.action === 'menu-close') { - return - } + onInputChange(inputValue) { const indexOfSpace = inputValue.indexOf(' ') const indexOfSemiColon = inputValue.indexOf(';') @@ -44,7 +36,6 @@ class AutocompleteInputContainer extends React.Component { return '' } - this.setState({inputValue}) if (indexOfSpace >= 1 || indexOfSemiColon >= 1 ) { inputValue = inputValue.substring(0, inputValue.length -1 ) this.onUpdate([...this.props.selectedMembers, {label: inputValue, value: inputValue}]) @@ -78,11 +69,9 @@ class AutocompleteInputContainer extends React.Component { render() { const { placeholder, currentUser, selectedMembers, disabled } = this.props - const {inputValue} = this.state return ( Date: Thu, 4 Mar 2021 11:38:15 +0800 Subject: [PATCH 11/15] fix: issue #4301 --- src/components/Select/Select.jsx | 1 + .../TeamManagement/AutocompleteInput.jsx | 17 ++++++++++++++++- .../AutocompleteInputContainer.jsx | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/components/Select/Select.jsx b/src/components/Select/Select.jsx index 92f300a7e..daca59239 100644 --- a/src/components/Select/Select.jsx +++ b/src/components/Select/Select.jsx @@ -26,6 +26,7 @@ const Select = (props) => { {...props} createOptionPosition="first" className={containerclass} + ref={props.createSelectRef} classNamePrefix="react-select" /> ) diff --git a/src/components/TeamManagement/AutocompleteInput.jsx b/src/components/TeamManagement/AutocompleteInput.jsx index d670dfc90..006466628 100644 --- a/src/components/TeamManagement/AutocompleteInput.jsx +++ b/src/components/TeamManagement/AutocompleteInput.jsx @@ -16,14 +16,18 @@ class AutocompleteInput extends React.Component { const { placeholder, selectedMembers, - disabled + createSelectRef, + disabled, + onBlur } = this.props return (