From 10b76ad2cbe32ac9862f2852dcb47d74949fc46c Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 13 Jun 2023 20:21:33 -0700 Subject: [PATCH 1/6] Show the Copilot details if a delegate is set in a report action --- src/components/UserDetailsTooltip/index.js | 31 ++++++++++++++++--- .../userDetailsTooltipPropTypes.js | 12 +++++++ src/languages/en.js | 3 ++ src/languages/es.js | 3 ++ .../home/report/ReportActionItemFragment.js | 6 +++- .../home/report/ReportActionItemSingle.js | 22 +++++++++++-- 6 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.js index 493b40a0a5e1..c921eb748b26 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.js @@ -9,25 +9,41 @@ import Tooltip from '../Tooltip'; import {propTypes, defaultProps} from './userDetailsTooltipPropTypes'; import styles from '../../styles/styles'; import ONYXKEYS from '../../ONYXKEYS'; +import withLocalize from '../withLocalize'; +import compose from '../../libs/compose'; function UserDetailsTooltip(props) { const userDetails = lodashGet(props.personalDetailsList, props.accountID, props.fallbackUserDetails); + let userDisplayName = String(userDetails.displayName).trim() ? userDetails.displayName : ''; + let userLogin = String(userDetails.login).trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''; + let userAvatar = userDetails.avatar; + + // We replace the actor's email, name, and avatar with the Copilot manually for now. This will be improved upon when + // the Copilot feature is implemented. + if (props.delegate) { + const delegateUserDetails = lodashGet(props.personalDetails, props.delegate, {}); + const delegateUserDisplayName = String(delegateUserDetails.displayName).trim() ? delegateUserDetails.displayName : ''; + userDisplayName = `${delegateUserDisplayName} (${props.translate('reportAction.asCopilot')} ${userDisplayName})`; + userLogin = delegateUserDetails.login; + userAvatar = delegateUserDetails.avatar; + } + const renderTooltipContent = useCallback( () => ( - {String(userDetails.displayName).trim() ? userDetails.displayName : ''} + {userDisplayName} - {String(userDetails.login).trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''} + {userLogin} ), @@ -45,8 +61,13 @@ UserDetailsTooltip.propTypes = propTypes; UserDetailsTooltip.defaultProps = defaultProps; UserDetailsTooltip.displayName = 'UserDetailsTooltip'; -export default withOnyx({ +export default compose( + withLocalize, + withOnyx({ personalDetailsList: { key: ONYXKEYS.PERSONAL_DETAILS_LIST, }, -})(UserDetailsTooltip); + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS, + }, +}))(UserDetailsTooltip); diff --git a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js index 4d34c73ef1ba..c33fdcc331ff 100644 --- a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js +++ b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import personalDetailsPropType from '../../pages/personalDetailsPropType'; +import {withLocalizePropTypes} from '../withLocalize'; const propTypes = { /** User's Account ID */ @@ -17,12 +18,23 @@ const propTypes = { children: PropTypes.node.isRequired, /** List of personalDetails (keyed by accountID) */ personalDetailsList: PropTypes.objectOf(personalDetailsPropType), + + /** List of personalDetails (keyed by login) */ + personalDetails: PropTypes.objectOf(personalDetailsPropType), + + /** The email of the copilot who took this action on behalf of the user */ + delegate: PropTypes.string, + + /** Localization props */ + ...withLocalizePropTypes }; const defaultProps = { accountID: '', fallbackUserDetails: {displayName: '', login: '', avatar: ''}, personalDetailsList: {}, + personalDetails: {}, + delegate: '', }; export {propTypes, defaultProps}; diff --git a/src/languages/en.js b/src/languages/en.js index ed205f6576a0..17cce8920161 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -296,6 +296,9 @@ export default { sayHello: 'Say hello!', usePlusButton: '\n\nYou can also use the + button below to send or request money!', }, + reportAction: { + asCopilot: 'as copilot for', + }, mentionSuggestions: { hereAlternateText: 'Notify everyone online in this room', }, diff --git a/src/languages/es.js b/src/languages/es.js index e2a48a37f5f9..ef0b89e8fe5f 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -295,6 +295,9 @@ export default { sayHello: '¡Saluda!', usePlusButton: '\n\n¡También puedes usar el botón + de abajo para enviar o pedir dinero!', }, + reportAction: { + asCopilot: 'como copiloto de', + }, mentionSuggestions: { hereAlternateText: 'Notificar a todos los que estén en linea de esta sala', }, diff --git a/src/pages/home/report/ReportActionItemFragment.js b/src/pages/home/report/ReportActionItemFragment.js index 07b00590306e..184e56d913ee 100644 --- a/src/pages/home/report/ReportActionItemFragment.js +++ b/src/pages/home/report/ReportActionItemFragment.js @@ -57,6 +57,9 @@ const propTypes = { // Additional styles to add after local styles style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + /** The email of the copilot who took this action on behalf of the user */ + delegate: PropTypes.string, + ...windowDimensionsPropTypes, /** localization props */ @@ -75,6 +78,7 @@ const defaultProps = { isSingleLine: false, source: '', style: [], + delegate: '', }; const ReportActionItemFragment = (props) => { @@ -145,7 +149,7 @@ const ReportActionItemFragment = (props) => { } case 'TEXT': return ( - + { }; const ReportActionItemSingle = (props) => { - const actorEmail = props.action.actorEmail.replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); - const {accountID, avatar, displayName, pendingFields} = props.personalDetails[actorEmail] || {}; + let actorEmail = props.action.actorEmail.replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); + let {avatar, displayName} = props.personalDetails[actorEmail] || {}; + const {accountID, pendingFields} = props.personalDetails[actorEmail] || {}; + + // We replace the actor's email, name, and avatar with the Copilot manually for now. This will be improved upon when + // the Copilot feature is implemented. + if (props.action.delegate) { + const delegateDetails = props.personalDetails[props.action.delegate]; + const delegateDisplayName = delegateDetails.displayName + actorEmail = delegateDetails.login; + displayName = `${delegateDisplayName} (${props.translate('reportAction.asCopilot')} ${displayName})`; + avatar = delegateDetails.avatar; + } + const avatarSource = UserUtils.getAvatar(avatar, actorEmail); // Since the display name for a report action message is delivered with the report history as an array of fragments @@ -100,7 +112,10 @@ const ReportActionItemSingle = (props) => { noMargin /> ) : ( - + { fragment={fragment} isAttachment={props.action.isAttachment} isLoading={props.action.isLoading} + delegate={props.action.delegate} isSingleLine /> ))} From 5c56c2bd2831a5334d80368258aa265e471c8b1d Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 14 Jun 2023 13:06:12 -0700 Subject: [PATCH 2/6] Lint JS Code --- src/components/UserDetailsTooltip/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.js index c921eb748b26..bdbdedc51e1b 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.js @@ -47,10 +47,10 @@ function UserDetailsTooltip(props) { ), - [userDetails.avatar, userDetails.displayName, userDetails.login], + [userAvatar, userDisplayName, userLogin], ); - if (!userDetails.displayName && !userDetails.login) { + if (!userDisplayName && !userLogin) { return props.children; } From c7d7b63a8dbbcd59fa2a382296abbc2d6a1837ff Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 14 Jun 2023 16:04:32 -0700 Subject: [PATCH 3/6] Prettier --- src/components/UserDetailsTooltip/index.js | 23 ++++++++----------- .../userDetailsTooltipPropTypes.js | 2 +- .../home/report/ReportActionItemFragment.js | 5 +++- .../home/report/ReportActionItemSingle.js | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.js index 25b2941ecf1b..872846027957 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.js @@ -39,13 +39,9 @@ function UserDetailsTooltip(props) { /> - - {userDisplayName} - + {userDisplayName} - - {userLogin} - + {userLogin} ), [userAvatar, userDisplayName, userLogin], @@ -65,10 +61,11 @@ UserDetailsTooltip.displayName = 'UserDetailsTooltip'; export default compose( withLocalize, withOnyx({ - personalDetailsList: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS, - }, -}))(UserDetailsTooltip); + personalDetailsList: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS, + }, + }), +)(UserDetailsTooltip); diff --git a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js index c33fdcc331ff..fee4004cc0e2 100644 --- a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js +++ b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js @@ -26,7 +26,7 @@ const propTypes = { delegate: PropTypes.string, /** Localization props */ - ...withLocalizePropTypes + ...withLocalizePropTypes, }; const defaultProps = { diff --git a/src/pages/home/report/ReportActionItemFragment.js b/src/pages/home/report/ReportActionItemFragment.js index 0240f269ae07..3e9f19866c90 100644 --- a/src/pages/home/report/ReportActionItemFragment.js +++ b/src/pages/home/report/ReportActionItemFragment.js @@ -149,7 +149,10 @@ function ReportActionItemFragment(props) { } case 'TEXT': return ( - + Date: Thu, 15 Jun 2023 14:25:52 -0700 Subject: [PATCH 4/6] use accountIID instead of email --- src/components/UserDetailsTooltip/index.js | 13 ++++++------ .../userDetailsTooltipPropTypes.js | 10 +++------ .../home/report/ReportActionItemFragment.js | 8 +++---- .../home/report/ReportActionItemSingle.js | 21 +++++++++---------- 4 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.js index 872846027957..664f679979e5 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.js @@ -18,15 +18,17 @@ function UserDetailsTooltip(props) { let userDisplayName = String(userDetails.displayName).trim() ? userDetails.displayName : ''; let userLogin = String(userDetails.login).trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''; let userAvatar = userDetails.avatar; + let userAccountID = props.accountID; // We replace the actor's email, name, and avatar with the Copilot manually for now. This will be improved upon when // the Copilot feature is implemented. - if (props.delegate) { - const delegateUserDetails = lodashGet(props.personalDetails, props.delegate, {}); + if (props.delegateAccountID) { + const delegateUserDetails = lodashGet(props.personalDetailsList, props.delegateAccountID, {}); const delegateUserDisplayName = String(delegateUserDetails.displayName).trim() ? delegateUserDetails.displayName : ''; userDisplayName = `${delegateUserDisplayName} (${props.translate('reportAction.asCopilot')} ${userDisplayName})`; userLogin = delegateUserDetails.login; userAvatar = delegateUserDetails.avatar; + userAccountID = props.delegateAccountID; } const renderTooltipContent = useCallback( @@ -35,7 +37,7 @@ function UserDetailsTooltip(props) { @@ -44,7 +46,7 @@ function UserDetailsTooltip(props) { {userLogin} ), - [userAvatar, userDisplayName, userLogin], + [userAvatar, userDisplayName, userLogin, userAccountID], ); if (!userDisplayName && !userLogin) { @@ -64,8 +66,5 @@ export default compose( personalDetailsList: { key: ONYXKEYS.PERSONAL_DETAILS_LIST, }, - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS, - }, }), )(UserDetailsTooltip); diff --git a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js index fee4004cc0e2..0bf0f5f9b7cb 100644 --- a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js +++ b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js @@ -19,11 +19,8 @@ const propTypes = { /** List of personalDetails (keyed by accountID) */ personalDetailsList: PropTypes.objectOf(personalDetailsPropType), - /** List of personalDetails (keyed by login) */ - personalDetails: PropTypes.objectOf(personalDetailsPropType), - - /** The email of the copilot who took this action on behalf of the user */ - delegate: PropTypes.string, + /** The accountID of the copilot who took this action on behalf of the user */ + delegateAccountID: PropTypes.number, /** Localization props */ ...withLocalizePropTypes, @@ -33,8 +30,7 @@ const defaultProps = { accountID: '', fallbackUserDetails: {displayName: '', login: '', avatar: ''}, personalDetailsList: {}, - personalDetails: {}, - delegate: '', + delegateAccountID: 0, }; export {propTypes, defaultProps}; diff --git a/src/pages/home/report/ReportActionItemFragment.js b/src/pages/home/report/ReportActionItemFragment.js index 2156ec44fb61..010295c0b0d3 100644 --- a/src/pages/home/report/ReportActionItemFragment.js +++ b/src/pages/home/report/ReportActionItemFragment.js @@ -57,8 +57,8 @@ const propTypes = { // Additional styles to add after local styles style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), - /** The email of the copilot who took this action on behalf of the user */ - delegate: PropTypes.string, + /** The accountID of the copilot who took this action on behalf of the user */ + delegateAccountID: PropTypes.number, ...windowDimensionsPropTypes, @@ -78,7 +78,7 @@ const defaultProps = { isSingleLine: false, source: '', style: [], - delegate: '', + delegateAccountID: 0, }; function ReportActionItemFragment(props) { @@ -151,7 +151,7 @@ function ReportActionItemFragment(props) { return ( { }; function ReportActionItemSingle(props) { - let actorEmail = lodashGet(props.action, 'actorEmail', '').replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); + const actorEmail = lodashGet(props.action, 'actorEmail', '').replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); const actorAccountID = props.action.actorAccountID; - let {avatar, displayName} = props.personalDetailsList[actorEmail] || {}; - const {pendingFields} = props.personalDetailsList[actorEmail] || {}; + let {avatar, displayName} = props.personalDetailsList[actorAccountID] || {}; + const {pendingFields} = props.personalDetailsList[actorAccountID] || {}; // We replace the actor's email, name, and avatar with the Copilot manually for now. This will be improved upon when // the Copilot feature is implemented. - if (props.action.delegate) { - const delegateDetails = props.personalDetails[props.action.delegate]; + if (props.action.delegateAccountID) { + const delegateDetails = props.personalDetailsList[props.action.delegateAccountID]; const delegateDisplayName = delegateDetails.displayName; - actorEmail = delegateDetails.login; displayName = `${delegateDisplayName} (${props.translate('reportAction.asCopilot')} ${displayName})`; avatar = delegateDetails.avatar; } - const avatarSource = UserUtils.getAvatar(avatar, actorAccountID); + const avatarSource = UserUtils.getAvatar(avatar, props.action.delegateAccountID ? props.action.delegateAccountID : actorAccountID); // Since the display name for a report action message is delivered with the report history as an array of fragments // we'll need to take the displayName from personal details and have it be in the same format for now. Eventually, @@ -101,7 +100,7 @@ function ReportActionItemSingle(props) { style={[styles.alignSelfStart, styles.mr3]} onPressIn={ControlSelection.block} onPressOut={ControlSelection.unblock} - onPress={() => showUserDetails(actorAccountID)} + onPress={() => showUserDetails(props.action.delegateAccountID ? props.action.delegateAccountID : actorAccountID)} > {props.shouldShowSubscriptAvatar ? ( @@ -115,7 +114,7 @@ function ReportActionItemSingle(props) { ) : ( showUserDetails(actorAccountID)} + onPress={() => showUserDetails(props.action.delegateAccountID ? props.action.delegateAccountID : actorAccountID)} > {_.map(personArray, (fragment, index) => ( ))} From 57156229bd16e1178f72c658ea2faca33b4fb48f Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Thu, 15 Jun 2023 14:40:56 -0700 Subject: [PATCH 5/6] Fix string thing --- src/components/UserDetailsTooltip/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.js index 664f679979e5..e52c7156fb13 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.js @@ -15,7 +15,7 @@ import * as UserUtils from '../../libs/UserUtils'; function UserDetailsTooltip(props) { const userDetails = lodashGet(props.personalDetailsList, props.accountID, props.fallbackUserDetails); - let userDisplayName = String(userDetails.displayName).trim() ? userDetails.displayName : ''; + let userDisplayName = userDetails.displayName ? userDetails.displayName.trim() : ''; let userLogin = String(userDetails.login).trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''; let userAvatar = userDetails.avatar; let userAccountID = props.accountID; @@ -24,7 +24,7 @@ function UserDetailsTooltip(props) { // the Copilot feature is implemented. if (props.delegateAccountID) { const delegateUserDetails = lodashGet(props.personalDetailsList, props.delegateAccountID, {}); - const delegateUserDisplayName = String(delegateUserDetails.displayName).trim() ? delegateUserDetails.displayName : ''; + const delegateUserDisplayName = delegateUserDetails.displayName ? delegateUserDetails.displayName.trim() : ''; userDisplayName = `${delegateUserDisplayName} (${props.translate('reportAction.asCopilot')} ${userDisplayName})`; userLogin = delegateUserDetails.login; userAvatar = delegateUserDetails.avatar; From 77464ae442a6f9745dd839d9cb5770e7b1d03b48 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 19 Jun 2023 13:05:51 -0700 Subject: [PATCH 6/6] Remove unneccessary String() call --- src/components/UserDetailsTooltip/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.js index fc96553843e1..16fdacd8964a 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.js @@ -16,7 +16,7 @@ import * as UserUtils from '../../libs/UserUtils'; function UserDetailsTooltip(props) { const userDetails = lodashGet(props.personalDetailsList, props.accountID, props.fallbackUserDetails); let userDisplayName = userDetails.displayName ? userDetails.displayName.trim() : ''; - let userLogin = String(userDetails.login).trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''; + let userLogin = (userDetails.login || '').trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''; let userAvatar = userDetails.avatar; let userAccountID = props.accountID; @@ -44,7 +44,7 @@ function UserDetailsTooltip(props) { {userDisplayName} - {String(userLogin || '').trim() && !_.isEqual(userLogin, userDisplayName) ? Str.removeSMSDomain(userLogin) : ''} + {(userLogin || '').trim() && !_.isEqual(userLogin, userDisplayName) ? Str.removeSMSDomain(userLogin) : ''} ),