diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.js index 786531801837..16fdacd8964a 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.js @@ -9,33 +9,49 @@ 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'; 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 = (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.delegateAccountID) { + const delegateUserDetails = lodashGet(props.personalDetailsList, props.delegateAccountID, {}); + const delegateUserDisplayName = delegateUserDetails.displayName ? delegateUserDetails.displayName.trim() : ''; + userDisplayName = `${delegateUserDisplayName} (${props.translate('reportAction.asCopilot')} ${userDisplayName})`; + userLogin = delegateUserDetails.login; + userAvatar = delegateUserDetails.avatar; + userAccountID = props.delegateAccountID; + } + const renderTooltipContent = useCallback( () => ( - - {String(userDetails.displayName).trim() ? userDetails.displayName : ''} - + {userDisplayName} - {String(userDetails.login || '').trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''} + {(userLogin || '').trim() && !_.isEqual(userLogin, userDisplayName) ? Str.removeSMSDomain(userLogin) : ''} ), - [userDetails.avatar, userDetails.displayName, userDetails.login, userDetails.accountID], + [userAvatar, userDisplayName, userLogin, userAccountID], ); - if (!userDetails.displayName && !userDetails.login) { + if (!userDisplayName && !userLogin) { return props.children; } @@ -46,8 +62,11 @@ UserDetailsTooltip.propTypes = propTypes; UserDetailsTooltip.defaultProps = defaultProps; UserDetailsTooltip.displayName = 'UserDetailsTooltip'; -export default withOnyx({ - personalDetailsList: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, -})(UserDetailsTooltip); +export default compose( + withLocalize, + withOnyx({ + personalDetailsList: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, + }), +)(UserDetailsTooltip); diff --git a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js index 4d34c73ef1ba..0bf0f5f9b7cb 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,19 @@ const propTypes = { children: PropTypes.node.isRequired, /** List of personalDetails (keyed by accountID) */ personalDetailsList: PropTypes.objectOf(personalDetailsPropType), + + /** The accountID of the copilot who took this action on behalf of the user */ + delegateAccountID: PropTypes.number, + + /** Localization props */ + ...withLocalizePropTypes, }; const defaultProps = { accountID: '', fallbackUserDetails: {displayName: '', login: '', avatar: ''}, personalDetailsList: {}, + delegateAccountID: 0, }; export {propTypes, defaultProps}; diff --git a/src/languages/en.js b/src/languages/en.js index 192d9954e5ff..cfc11029fbec 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -299,6 +299,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 d54fa5110117..f1104899d3d7 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -298,6 +298,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 65558110ba45..010295c0b0d3 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 accountID of the copilot who took this action on behalf of the user */ + delegateAccountID: PropTypes.number, + ...windowDimensionsPropTypes, /** localization props */ @@ -75,6 +78,7 @@ const defaultProps = { isSingleLine: false, source: '', style: [], + delegateAccountID: 0, }; function ReportActionItemFragment(props) { @@ -145,7 +149,10 @@ function ReportActionItemFragment(props) { } case 'TEXT': return ( - + { function ReportActionItemSingle(props) { const actorEmail = lodashGet(props.action, 'actorEmail', '').replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); const actorAccountID = props.action.actorAccountID; - const {avatar, displayName, pendingFields} = props.personalDetailsList[actorAccountID] || {}; - const avatarSource = UserUtils.getAvatar(avatar, actorAccountID); + 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.delegateAccountID) { + const delegateDetails = props.personalDetailsList[props.action.delegateAccountID]; + const delegateDisplayName = delegateDetails.displayName; + displayName = `${delegateDisplayName} (${props.translate('reportAction.asCopilot')} ${displayName})`; + avatar = delegateDetails.avatar; + } + + 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, @@ -90,7 +101,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)} accessibilityLabel={actorEmail} accessibilityRole="button" > @@ -104,7 +115,10 @@ function ReportActionItemSingle(props) { noMargin /> ) : ( - + showUserDetails(actorAccountID)} + onPress={() => showUserDetails(props.action.delegateAccountID ? props.action.delegateAccountID : actorAccountID)} accessibilityLabel={actorEmail} accessibilityRole="button" > @@ -133,6 +147,7 @@ function ReportActionItemSingle(props) { fragment={fragment} isAttachment={props.action.isAttachment} isLoading={props.action.isLoading} + delegateAccountID={props.action.delegateAccountID} isSingleLine /> ))}