From 2681e039d0e7972cf3a88ffcc7b30d91b336a61b Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Sat, 19 Feb 2022 07:57:49 -0800 Subject: [PATCH 01/47] Create report action const for ARCHIVE_REASON report action --- src/CONST/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CONST/index.js b/src/CONST/index.js index a6ed085bd523..6e83dd535e1d 100755 --- a/src/CONST/index.js +++ b/src/CONST/index.js @@ -216,9 +216,10 @@ const CONST = { ACTIONS: { LIMIT: 50, TYPE: { - IOU: 'IOU', ADDCOMMENT: 'ADDCOMMENT', + ARCHIVE_REASON: 'ARCHIVE_REASON', CREATED: 'CREATED', + IOU: 'IOU', RENAMED: 'RENAMED', }, }, From a9a454bb0981e94965d50ab6a7eac7820dacdada Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Sat, 19 Feb 2022 08:01:49 -0800 Subject: [PATCH 02/47] Update isArchivedRoom to account for policy expense chats --- src/libs/reportUtils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index 509275bb420b..9f1de577a1fc 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -142,12 +142,13 @@ function findLastAccessedReport(reports, ignoreDefaultRooms) { /** * Whether the provided report is an archived room * @param {Object} report + * @param {String} report.chatType * @param {Number} report.stateNum * @param {Number} report.statusNum * @returns {Boolean} */ function isArchivedRoom(report) { - if (!isDefaultRoom(report)) { + if (!isChatRoom(report) && !isPolicyExpenseChat(report)) { return false; } From 2faf3d2b1f2db0bf7c85a559fb654ab46f3397c6 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Sat, 19 Feb 2022 09:06:44 -0800 Subject: [PATCH 03/47] Create ArchivedReportFooter component --- src/components/ArchivedReportFooter.js | 39 ++++++++++++++++++++++++++ src/styles/StyleUtils.js | 3 +- src/styles/themes/default.js | 1 + 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/components/ArchivedReportFooter.js diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js new file mode 100644 index 000000000000..195aab94f95c --- /dev/null +++ b/src/components/ArchivedReportFooter.js @@ -0,0 +1,39 @@ +import React from 'react'; +import {Pressable, View} from 'react-native'; +import PropTypes from 'prop-types'; +import Icon from './Icon'; +import * as Expensicons from './Icon/Expensicons'; +import Text from './Text'; +import Tooltip from './Tooltip'; +import styles from '../styles/styles'; +import * as StyleUtils from '../styles/StyleUtils'; +import getButtonState from '../libs/getButtonState'; + +const propTypes = { + /** The reason this report was archived. */ + archivedReason: PropTypes.string.isRequired, +}; + +const ArchivedReportFooter = props => ( + + + {/* TODO: translate archivedReason */} + {props.archivedReason} + + { /* TODO: What does clicking the ! icon do? */ }}> + {({pressed, hovered}) => ( + + )} + + + + +); + +ArchivedReportFooter.propTypes = propTypes; +ArchivedReportFooter.displayName = 'ArchivedReportFooter'; + +export default ArchivedReportFooter; diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index 25c9bc91c1c2..dd5b846bd430 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -226,9 +226,8 @@ function getButtonBackgroundColorStyle(buttonState = CONST.BUTTON_STATES.DEFAULT function getIconFillColor(buttonState = CONST.BUTTON_STATES.DEFAULT) { switch (buttonState) { case CONST.BUTTON_STATES.ACTIVE: - return themeColors.text; case CONST.BUTTON_STATES.PRESSED: - return themeColors.heading; + return themeColors.iconHovered; case CONST.BUTTON_STATES.COMPLETE: return themeColors.iconSuccessFill; case CONST.BUTTON_STATES.DEFAULT: diff --git a/src/styles/themes/default.js b/src/styles/themes/default.js index 25bec7f37717..b5cf7a058ca4 100644 --- a/src/styles/themes/default.js +++ b/src/styles/themes/default.js @@ -14,6 +14,7 @@ export default { border: colors.gray2, borderFocus: colors.blue, icon: colors.gray3, + iconHovered: colors.dark, iconSuccessFill: colors.green, iconReversed: colors.white, textSupporting: colors.gray4, From dbb991d4e45e3474ce7cee513745b3d9125b97ac Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Sat, 19 Feb 2022 09:46:55 -0800 Subject: [PATCH 04/47] Look for last archived reason in ReportActionCompose --- src/CONST/index.js | 5 +- src/components/ArchivedReportFooter.js | 44 ++- src/pages/home/report/ReportActionCompose.js | 389 ++++++++++--------- 3 files changed, 231 insertions(+), 207 deletions(-) diff --git a/src/CONST/index.js b/src/CONST/index.js index 6e83dd535e1d..10600791c526 100755 --- a/src/CONST/index.js +++ b/src/CONST/index.js @@ -217,12 +217,15 @@ const CONST = { LIMIT: 50, TYPE: { ADDCOMMENT: 'ADDCOMMENT', - ARCHIVE_REASON: 'ARCHIVE_REASON', + ARCHIVED: 'ARCHIVED', CREATED: 'CREATED', IOU: 'IOU', RENAMED: 'RENAMED', }, }, + ARCHIVE_REASON: { + MANUALLY_DELETED: 'manuallyDeleted', + }, ERROR: { INACCESSIBLE_REPORT: 'Report not found', }, diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 195aab94f95c..f495d64cb060 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -8,32 +8,40 @@ import Tooltip from './Tooltip'; import styles from '../styles/styles'; import * as StyleUtils from '../styles/StyleUtils'; import getButtonState from '../libs/getButtonState'; +import withLocalize, {withLocalizePropTypes} from './withLocalize'; const propTypes = { /** The reason this report was archived. */ archivedReason: PropTypes.string.isRequired, + + ...withLocalizePropTypes, }; -const ArchivedReportFooter = props => ( - - - {/* TODO: translate archivedReason */} - {props.archivedReason} - - { /* TODO: What does clicking the ! icon do? */ }}> - {({pressed, hovered}) => ( - - )} - - +const ArchivedReportFooter = (props) => { + // const getTranslationKeyForArchivedReason = () => {}; + // const message = props.translate(getTranslationKeyForArchivedReason(props.archivedReason)); + const message = props.translate('reportActionCompose.roomIsArchived'); + return ( + + + {/* TODO: translate archivedReason */} + {message} + + { /* TODO: What does clicking the ! icon do? */ }}> + {({pressed, hovered}) => ( + + )} + + + - -); + ); +}; ArchivedReportFooter.propTypes = propTypes; ArchivedReportFooter.displayName = 'ArchivedReportFooter'; -export default ArchivedReportFooter; +export default withLocalize(ArchivedReportFooter); diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index c25817ed821a..f4c012bb1b39 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -44,6 +44,7 @@ import * as User from '../../../libs/actions/User'; import Tooltip from '../../../components/Tooltip'; import EmojiPicker from '../../../components/EmojiPicker'; import VirtualKeyboard from '../../../libs/VirtualKeyboard'; +import ArchivedReportFooter from '../../../components/ArchivedReportFooter'; const propTypes = { @@ -226,10 +227,6 @@ class ReportActionCompose extends React.Component { * @return {String} */ getInputPlaceholder() { - if (ReportUtils.isArchivedRoom(this.props.report)) { - return this.props.translate('reportActionCompose.roomIsArchived'); - } - if (ReportUtils.chatIncludesConcierge(this.props.report) && User.isBlockedFromConcierge(this.props.blockedFromConcierge)) { return this.props.translate('reportActionCompose.blockedFromConcierge'); } @@ -406,7 +403,15 @@ class ReportActionCompose extends React.Component { const isComposeDisabled = this.props.isDrawerOpen && this.props.isSmallScreenWidth; const isBlockedFromConcierge = ReportUtils.chatIncludesConcierge(this.props.report) && User.isBlockedFromConcierge(this.props.blockedFromConcierge); const inputPlaceholder = this.getInputPlaceholder(); - const isArchivedChatRoom = ReportUtils.isArchivedRoom(this.props.report); + const isArchivedRoom = ReportUtils.isArchivedRoom(this.props.report); + + // TODO: loop from back and get latest archived reason (only if room is archived) + let archivedReason = ''; + if (isArchivedRoom) { + // TODO: use TYPE.ARCHIVED instead of TYPE.ARCHIVED_REASON + const lastArchivedActionIndex = _.findLastIndex(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.ARCHIVED); + archivedReason = lastArchivedActionIndex >= 0 ? this.props.reportActions[lastArchivedActionIndex] : CONST.REPORT.ARCHIVE_REASON.MANUALLY_DELETED; + } return ( {shouldShowReportRecipientLocalTime && } - - { - this.submitForm(); - Report.addAction(this.props.reportID, '', file); - this.setTextInputShouldClear(false); - }} - > - {({displayFileInModal}) => ( - <> - - {({openPicker}) => ( + {isArchivedRoom + ? + : ( + <> + + { + this.submitForm(); + Report.addAction(this.props.reportID, '', file); + this.setTextInputShouldClear(false); + }} + > + {({displayFileInModal}) => ( <> - - - { - e.preventDefault(); - this.setMenuVisibility(true); - }} - style={styles.chatItemAttachButton} - underlayColor={themeColors.componentBG} - disabled={isBlockedFromConcierge || isArchivedChatRoom} - > - - - - - this.setMenuVisibility(false)} - onItemSelected={() => this.setMenuVisibility(false)} - anchorPosition={styles.createMenuPositionReportActionCompose} - animationIn="fadeInUp" - animationOut="fadeOutDown" - menuItems={[ - ...(!hasExcludedIOUEmails - && Permissions.canUseIOU(this.props.betas) ? [ - hasMultipleParticipants - ? { - icon: Expensicons.Receipt, - text: this.props.translate('iou.splitBill'), - onSelected: () => { - Navigation.navigate( - ROUTES.getIouSplitRoute( - this.props.reportID, - ), - ); + + {({openPicker}) => ( + <> + + + { + e.preventDefault(); + this.setMenuVisibility(true); + }} + style={styles.chatItemAttachButton} + underlayColor={themeColors.componentBG} + disabled={isBlockedFromConcierge || isArchivedRoom} + > + + + + + this.setMenuVisibility(false)} + onItemSelected={() => this.setMenuVisibility(false)} + anchorPosition={styles.createMenuPositionReportActionCompose} + animationIn="fadeInUp" + animationOut="fadeOutDown" + menuItems={[ + ...(!hasExcludedIOUEmails + && Permissions.canUseIOU(this.props.betas) ? [ + hasMultipleParticipants + ? { + icon: Expensicons.Receipt, + text: this.props.translate('iou.splitBill'), + onSelected: () => { + Navigation.navigate( + ROUTES.getIouSplitRoute( + this.props.reportID, + ), + ); + }, + } + : { + icon: Expensicons.MoneyCircle, + text: this.props.translate('iou.requestMoney'), + onSelected: () => { + Navigation.navigate( + ROUTES.getIouRequestRoute( + this.props.reportID, + ), + ); + }, + }, + ] : []), + ...(!hasExcludedIOUEmails && Permissions.canUseIOUSend(this.props.betas) && !hasMultipleParticipants ? [ + { + icon: Expensicons.Send, + text: this.props.translate('iou.sendMoney'), + onSelected: () => { + Navigation.navigate( + ROUTES.getIOUSendRoute( + this.props.reportID, + ), + ); + }, }, - } - : { - icon: Expensicons.MoneyCircle, - text: this.props.translate('iou.requestMoney'), + ] : []), + { + icon: Expensicons.Paperclip, + text: this.props.translate('reportActionCompose.addAttachment'), onSelected: () => { - Navigation.navigate( - ROUTES.getIouRequestRoute( - this.props.reportID, - ), - ); + openPicker({ + onPicked: (file) => { + displayFileInModal({file}); + }, + }); }, }, - ] : []), - ...(!hasExcludedIOUEmails && Permissions.canUseIOUSend(this.props.betas) && !hasMultipleParticipants ? [ - { - icon: Expensicons.Send, - text: this.props.translate('iou.sendMoney'), - onSelected: () => { - Navigation.navigate( - ROUTES.getIOUSendRoute( - this.props.reportID, - ), - ); - }, - }, - ] : []), - { - icon: Expensicons.Paperclip, - text: this.props.translate('reportActionCompose.addAttachment'), - onSelected: () => { - openPicker({ - onPicked: (file) => { - displayFileInModal({file}); - }, - }); - }, - }, - ]} + ]} + /> + + )} + + { + if (!isOriginComposer) { + return; + } + + this.setState({isDraggingOver: true}); + }} + onDragOver={(e, isOriginComposer) => { + if (!isOriginComposer) { + return; + } + + this.setState({isDraggingOver: true}); + }} + onDragLeave={() => this.setState({isDraggingOver: false})} + onDrop={(e) => { + e.preventDefault(); + + const file = lodashGet(e, ['dataTransfer', 'files', 0]); + if (!file) { + return; + } + + displayFileInModal({file}); + this.setState({isDraggingOver: false}); + }} + style={[styles.textInputCompose, styles.flex4]} + defaultValue={this.props.comment} + maxLines={16} // This is the same that slack has + onFocus={() => this.setIsFocused(true)} + onBlur={() => this.setIsFocused(false)} + onPasteFile={file => displayFileInModal({file})} + shouldClear={this.state.textInputShouldClear} + onClear={() => this.setTextInputShouldClear(false)} + isDisabled={isComposeDisabled || isBlockedFromConcierge} + selection={this.state.selection} + onSelectionChange={this.onSelectionChange} /> + )} - - { - if (!isOriginComposer) { - return; - } - - this.setState({isDraggingOver: true}); - }} - onDragOver={(e, isOriginComposer) => { - if (!isOriginComposer) { - return; - } - - this.setState({isDraggingOver: true}); - }} - onDragLeave={() => this.setState({isDraggingOver: false})} - onDrop={(e) => { - e.preventDefault(); - - const file = lodashGet(e, ['dataTransfer', 'files', 0]); - if (!file) { - return; - } - - displayFileInModal({file}); - this.setState({isDraggingOver: false}); - }} - style={[styles.textInputCompose, styles.flex4]} - defaultValue={this.props.comment} - maxLines={16} // This is the same that slack has - onFocus={() => this.setIsFocused(true)} - onBlur={() => this.setIsFocused(false)} - onPasteFile={file => displayFileInModal({file})} - shouldClear={this.state.textInputShouldClear} - onClear={() => this.setTextInputShouldClear(false)} - isDisabled={isComposeDisabled || isBlockedFromConcierge || isArchivedChatRoom} - selection={this.state.selection} - onSelectionChange={this.onSelectionChange} + + this.focus(true)} + onEmojiSelected={this.addEmojiToTextBox} + onBeforeShowEmojiPicker={() => this.textInput.blur()} /> + + + + + + + + + {this.props.network.isOffline ? ( + + + + + {this.props.translate('reportActionCompose.youAppearToBeOffline')} + + + + ) : } + + ) + } - - )} - - this.focus(true)} - onEmojiSelected={this.addEmojiToTextBox} - onBeforeShowEmojiPicker={() => this.textInput.blur()} - /> - - - - - - - - - {this.props.network.isOffline ? ( - - - - - {this.props.translate('reportActionCompose.youAppearToBeOffline')} - - - - ) : } ); } From 40ac7990cb09f4cfe6f468dfe2ef65a889e43c57 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 16:22:54 -0800 Subject: [PATCH 05/47] Use CLOSED reportAction instead of ARCHIVE_REASON --- src/CONST/index.js | 4 ++-- src/pages/home/report/ReportActionCompose.js | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/CONST/index.js b/src/CONST/index.js index 10600791c526..8932f8578a8a 100755 --- a/src/CONST/index.js +++ b/src/CONST/index.js @@ -217,14 +217,14 @@ const CONST = { LIMIT: 50, TYPE: { ADDCOMMENT: 'ADDCOMMENT', - ARCHIVED: 'ARCHIVED', + CLOSED: 'CLOSED', CREATED: 'CREATED', IOU: 'IOU', RENAMED: 'RENAMED', }, }, ARCHIVE_REASON: { - MANUALLY_DELETED: 'manuallyDeleted', + MANUALLY_ARCHIVED: 'manuallyArchived', }, ERROR: { INACCESSIBLE_REPORT: 'Report not found', diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index f4c012bb1b39..44535bf4f518 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -405,12 +405,10 @@ class ReportActionCompose extends React.Component { const inputPlaceholder = this.getInputPlaceholder(); const isArchivedRoom = ReportUtils.isArchivedRoom(this.props.report); - // TODO: loop from back and get latest archived reason (only if room is archived) let archivedReason = ''; if (isArchivedRoom) { - // TODO: use TYPE.ARCHIVED instead of TYPE.ARCHIVED_REASON - const lastArchivedActionIndex = _.findLastIndex(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.ARCHIVED); - archivedReason = lastArchivedActionIndex >= 0 ? this.props.reportActions[lastArchivedActionIndex] : CONST.REPORT.ARCHIVE_REASON.MANUALLY_DELETED; + const lastClosedActionIndex = _.findLastIndex(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); + archivedReason = lastClosedActionIndex >= 0 ? this.props.reportActions[lastClosedActionIndex].originalMessage.reason : CONST.REPORT.ARCHIVE_REASON.MANUALLY_ARCHIVED; } return ( From 20715e26e89b11d8f9541bc2981488e7eb3db607 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 16:23:39 -0800 Subject: [PATCH 06/47] Simplify component to only include the one hoverable element --- src/components/ArchivedReportFooter.js | 37 +++++++++++--------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index f495d64cb060..bc2a9dcf5337 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -1,10 +1,10 @@ import React from 'react'; -import {Pressable, View} from 'react-native'; +import {View} from 'react-native'; import PropTypes from 'prop-types'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; +import Hoverable from './Hoverable'; import Text from './Text'; -import Tooltip from './Tooltip'; import styles from '../styles/styles'; import * as StyleUtils from '../styles/StyleUtils'; import getButtonState from '../libs/getButtonState'; @@ -12,32 +12,27 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize'; const propTypes = { /** The reason this report was archived. */ - archivedReason: PropTypes.string.isRequired, + archiveReason: PropTypes.string.isRequired, ...withLocalizePropTypes, }; const ArchivedReportFooter = (props) => { - // const getTranslationKeyForArchivedReason = () => {}; - // const message = props.translate(getTranslationKeyForArchivedReason(props.archivedReason)); + // const getTranslationKeyForArchiveReason = () => {}; + // const message = props.translate(getTranslationKeyForArchiveReason(props.archiveReason)); const message = props.translate('reportActionCompose.roomIsArchived'); return ( - - - {/* TODO: translate archivedReason */} - {message} - - { /* TODO: What does clicking the ! icon do? */ }}> - {({pressed, hovered}) => ( - - )} - - - - + + {isHovered => ( + + {message} + + + )} + ); }; From ab3877994a937b0791e18af9a481c8ee188b078d Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 16:31:06 -0800 Subject: [PATCH 07/47] Use reportArchiveReasons translation key --- src/components/ArchivedReportFooter.js | 5 +---- src/languages/en.js | 4 +++- src/languages/es.js | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index bc2a9dcf5337..6e7db9723d38 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -18,14 +18,11 @@ const propTypes = { }; const ArchivedReportFooter = (props) => { - // const getTranslationKeyForArchiveReason = () => {}; - // const message = props.translate(getTranslationKeyForArchiveReason(props.archiveReason)); - const message = props.translate('reportActionCompose.roomIsArchived'); return ( {isHovered => ( - {message} + {props.translate(`reportArchiveReasons.${props.archiveReason}`)} `It's ${time} for ${user}`, edited: '(edited)', emoji: 'Emoji', @@ -182,6 +181,9 @@ export default { areTyping: 'are typing...', multipleUsers: 'Multiple users', }, + reportArchiveReasons: { + manuallyArchived: 'This chat room has been archived.', + }, sidebarScreen: { fabAction: 'New chat', newChat: 'New chat', diff --git a/src/languages/es.js b/src/languages/es.js index 6a6750ec3dce..be06fa8a6d8c 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -152,7 +152,6 @@ export default { blockedFromConcierge: 'Comunicación no permitida', youAppearToBeOffline: 'Parece que estás desconectado.', fileUploadFailed: 'Subida fallida. El archivo no es compatible.', - roomIsArchived: 'Esta sala de chat ha sido eliminada', localTime: ({user, time}) => `Son las ${time} para ${user}`, edited: '(editado)', emoji: 'Emoji', From efa7db0eec2899766f73b26ca71a3d956113861c Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 16:36:30 -0800 Subject: [PATCH 08/47] Pre-emptively add translations for other archive reasons --- src/languages/en.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/languages/en.js b/src/languages/en.js index 509d1f9d4a28..02dc87b4bbf0 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -182,7 +182,11 @@ export default { multipleUsers: 'Multiple users', }, reportArchiveReasons: { + accountClosed: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, + accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged with ${newLogin}.`, manuallyArchived: 'This chat room has been archived.', + removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, + policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, }, sidebarScreen: { fabAction: 'New chat', From a53c4ea327d0cc65c8e0dd3e357f30f5eb85ab62 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 16:44:55 -0800 Subject: [PATCH 09/47] Add known spanish translations --- src/languages/es.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/languages/es.js b/src/languages/es.js index be06fa8a6d8c..fb50bca6a03f 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -181,6 +181,13 @@ export default { areTyping: 'están escribiendo...', multipleUsers: 'Varios usuarios', }, + reportArchiveReasons: { + // accountClosed: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, + // accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged with ${newLogin}.`, + manuallyArchived: 'Esta sala de chat ha sido eliminada.', + // removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, + // policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, + }, sidebarScreen: { fabAction: 'Nuevo chat', newChat: 'Nuevo chat', From 36b80d367e9cf8e1c73d3eb2d456a0ce77605700 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 17:04:05 -0800 Subject: [PATCH 10/47] Move chat footer rendering logic to ReportScreen --- src/pages/home/ReportScreen.js | 33 +- src/pages/home/report/ReportActionCompose.js | 393 +++++++++---------- src/pages/home/report/ReportActionsView.js | 2 +- src/styles/styles.js | 18 +- 4 files changed, 219 insertions(+), 227 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 3dc006c423e3..1e97762a2d7f 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -19,6 +19,7 @@ import SwipeableView from '../../components/SwipeableView'; import CONST from '../../CONST'; import FullScreenLoadingIndicator from '../../components/FullscreenLoadingIndicator'; import reportActionPropTypes from './report/reportActionPropTypes'; +import ArchivedReportFooter from '../../components/ArchivedReportFooter'; const propTypes = { /** Navigation route context info provided by react navigation */ @@ -163,6 +164,14 @@ class ReportScreen extends React.Component { } const reportID = getReportID(this.props.route); + + const isArchivedRoom = ReportUtils.isArchivedRoom(this.props.report); + let archiveReason = ''; + if (isArchivedRoom) { + const lastClosedActionIndex = _.findLastIndex(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); + archiveReason = lastClosedActionIndex >= 0 ? this.props.reportActions[lastClosedActionIndex].originalMessage.reason : CONST.REPORT.ARCHIVE_REASON.MANUALLY_ARCHIVED; + } + return ( )} - {this.props.session.shouldShowComposeInput && ( - Keyboard.dismiss()}> - - + {(isArchivedRoom || this.props.session.shouldShowComposeInput) && ( + + {isArchivedRoom + ? + : ( + Keyboard.dismiss()}> + + + )} + )} diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 44535bf4f518..e14766310e3e 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -403,223 +403,200 @@ class ReportActionCompose extends React.Component { const isComposeDisabled = this.props.isDrawerOpen && this.props.isSmallScreenWidth; const isBlockedFromConcierge = ReportUtils.chatIncludesConcierge(this.props.report) && User.isBlockedFromConcierge(this.props.blockedFromConcierge); const inputPlaceholder = this.getInputPlaceholder(); - const isArchivedRoom = ReportUtils.isArchivedRoom(this.props.report); - - let archivedReason = ''; - if (isArchivedRoom) { - const lastClosedActionIndex = _.findLastIndex(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); - archivedReason = lastClosedActionIndex >= 0 ? this.props.reportActions[lastClosedActionIndex].originalMessage.reason : CONST.REPORT.ARCHIVE_REASON.MANUALLY_ARCHIVED; - } - return ( - + {shouldShowReportRecipientLocalTime && } - {isArchivedRoom - ? - : ( - <> - - { - this.submitForm(); - Report.addAction(this.props.reportID, '', file); - this.setTextInputShouldClear(false); - }} - > - {({displayFileInModal}) => ( + + { + this.submitForm(); + Report.addAction(this.props.reportID, '', file); + this.setTextInputShouldClear(false); + }} + > + {({displayFileInModal}) => ( + <> + + {({openPicker}) => ( <> - - {({openPicker}) => ( - <> - - - { - e.preventDefault(); - this.setMenuVisibility(true); - }} - style={styles.chatItemAttachButton} - underlayColor={themeColors.componentBG} - disabled={isBlockedFromConcierge || isArchivedRoom} - > - - - - - this.setMenuVisibility(false)} - onItemSelected={() => this.setMenuVisibility(false)} - anchorPosition={styles.createMenuPositionReportActionCompose} - animationIn="fadeInUp" - animationOut="fadeOutDown" - menuItems={[ - ...(!hasExcludedIOUEmails - && Permissions.canUseIOU(this.props.betas) ? [ - hasMultipleParticipants - ? { - icon: Expensicons.Receipt, - text: this.props.translate('iou.splitBill'), - onSelected: () => { - Navigation.navigate( - ROUTES.getIouSplitRoute( - this.props.reportID, - ), - ); - }, - } - : { - icon: Expensicons.MoneyCircle, - text: this.props.translate('iou.requestMoney'), - onSelected: () => { - Navigation.navigate( - ROUTES.getIouRequestRoute( - this.props.reportID, - ), - ); - }, - }, - ] : []), - ...(!hasExcludedIOUEmails && Permissions.canUseIOUSend(this.props.betas) && !hasMultipleParticipants ? [ - { - icon: Expensicons.Send, - text: this.props.translate('iou.sendMoney'), - onSelected: () => { - Navigation.navigate( - ROUTES.getIOUSendRoute( - this.props.reportID, - ), - ); - }, - }, - ] : []), - { - icon: Expensicons.Paperclip, - text: this.props.translate('reportActionCompose.addAttachment'), - onSelected: () => { - openPicker({ - onPicked: (file) => { - displayFileInModal({file}); - }, - }); - }, + + + { + e.preventDefault(); + this.setMenuVisibility(true); + }} + style={styles.chatItemAttachButton} + underlayColor={themeColors.componentBG} + disabled={isBlockedFromConcierge || isArchivedRoom} + > + + + + + this.setMenuVisibility(false)} + onItemSelected={() => this.setMenuVisibility(false)} + anchorPosition={styles.createMenuPositionReportActionCompose} + animationIn="fadeInUp" + animationOut="fadeOutDown" + menuItems={[ + ...(!hasExcludedIOUEmails && Permissions.canUseIOU(this.props.betas) ? [ + hasMultipleParticipants + ? { + icon: Expensicons.Receipt, + text: this.props.translate('iou.splitBill'), + onSelected: () => { + Navigation.navigate( + ROUTES.getIouSplitRoute( + this.props.reportID, + ), + ); + }, + } : { + icon: Expensicons.MoneyCircle, + text: this.props.translate('iou.requestMoney'), + onSelected: () => { + Navigation.navigate( + ROUTES.getIouRequestRoute( + this.props.reportID, + ), + ); }, - ]} - /> - - )} - - { - if (!isOriginComposer) { - return; - } - - this.setState({isDraggingOver: true}); - }} - onDragOver={(e, isOriginComposer) => { - if (!isOriginComposer) { - return; - } - - this.setState({isDraggingOver: true}); - }} - onDragLeave={() => this.setState({isDraggingOver: false})} - onDrop={(e) => { - e.preventDefault(); - - const file = lodashGet(e, ['dataTransfer', 'files', 0]); - if (!file) { - return; - } - - displayFileInModal({file}); - this.setState({isDraggingOver: false}); - }} - style={[styles.textInputCompose, styles.flex4]} - defaultValue={this.props.comment} - maxLines={16} // This is the same that slack has - onFocus={() => this.setIsFocused(true)} - onBlur={() => this.setIsFocused(false)} - onPasteFile={file => displayFileInModal({file})} - shouldClear={this.state.textInputShouldClear} - onClear={() => this.setTextInputShouldClear(false)} - isDisabled={isComposeDisabled || isBlockedFromConcierge} - selection={this.state.selection} - onSelectionChange={this.onSelectionChange} + }, + ] : []), + ...(!hasExcludedIOUEmails && Permissions.canUseIOUSend(this.props.betas) && !hasMultipleParticipants ? [ + { + icon: Expensicons.Send, + text: this.props.translate('iou.sendMoney'), + onSelected: () => { + Navigation.navigate( + ROUTES.getIOUSendRoute( + this.props.reportID, + ), + ); + }, + }, + ] : []), + { + icon: Expensicons.Paperclip, + text: this.props.translate('reportActionCompose.addAttachment'), + onSelected: () => { + openPicker({ + onPicked: (file) => { + displayFileInModal({file}); + }, + }); + }, + }, + ]} /> - )} - - this.focus(true)} - onEmojiSelected={this.addEmojiToTextBox} - onBeforeShowEmojiPicker={() => this.textInput.blur()} - /> - - - - - - - - - {this.props.network.isOffline ? ( - - - - - {this.props.translate('reportActionCompose.youAppearToBeOffline')} - - - - ) : } - - ) - } + + { + if (!isOriginComposer) { + return; + } + + this.setState({isDraggingOver: true}); + }} + onDragOver={(e, isOriginComposer) => { + if (!isOriginComposer) { + return; + } + + this.setState({isDraggingOver: true}); + }} + onDragLeave={() => this.setState({isDraggingOver: false})} + onDrop={(e) => { + e.preventDefault(); + const file = lodashGet(e, ['dataTransfer', 'files', 0]); + if (!file) { + return; + } + + displayFileInModal({file}); + this.setState({isDraggingOver: false}); + }} + style={[styles.textInputCompose, styles.flex4]} + defaultValue={this.props.comment} + maxLines={16} // This is the same that slack has + onFocus={() => this.setIsFocused(true)} + onBlur={() => this.setIsFocused(false)} + onPasteFile={file => displayFileInModal({file})} + shouldClear={this.state.textInputShouldClear} + onClear={() => this.setTextInputShouldClear(false)} + isDisabled={isComposeDisabled || isBlockedFromConcierge} + selection={this.state.selection} + onSelectionChange={this.onSelectionChange} + /> + + )} + + this.focus(true)} + onEmojiSelected={this.addEmojiToTextBox} + onBeforeShowEmojiPicker={() => this.textInput.blur()} + /> + + + + + + + + + {this.props.network.isOffline ? ( + + + + + {this.props.translate('reportActionCompose.youAppearToBeOffline')} + + + + ) : } ); } diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index b7da95451c17..da2a392866a4 100755 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -320,7 +320,7 @@ class ReportActionsView extends React.Component { const minimumReportActionHeight = styles.chatItem.paddingTop + styles.chatItem.paddingBottom + variables.fontSizeNormalHeight; const availableHeight = this.props.windowHeight - - (styles.chatItemCompose.minHeight + variables.contentHeaderHeight); + - (styles.chatFooter.minHeight + variables.contentHeaderHeight); return Math.ceil(availableHeight / minimumReportActionHeight); } diff --git a/src/styles/styles.js b/src/styles/styles.js index efa5ab09f0f6..2034416ffa2e 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1301,15 +1301,6 @@ const styles = { lineHeight: 20, }, - chatItemCompose: { - minHeight: 65, - marginBottom: 5, - paddingLeft: 20, - paddingRight: 20, - display: 'flex', - backgroundColor: themeColors.appBG, - }, - chatItemComposeWithFirstRow: { minHeight: 90, }, @@ -1329,6 +1320,15 @@ const styles = { minHeight: variables.componentSizeNormal, }, + chatFooter: { + minHeight: 65, + marginBottom: 5, + paddingLeft: 20, + paddingRight: 20, + display: 'flex', + backgroundColor: themeColors.appBG, + }, + textInputCompose: addOutlineWidth({ backgroundColor: themeColors.componentBG, borderColor: themeColors.border, From 844cc8608c0a613446aa32372e0b2afe7acb3a85 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 17:05:47 -0800 Subject: [PATCH 11/47] Get rid of unnecessary arrow function in render --- src/pages/home/ReportScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 1e97762a2d7f..3bac7ab998ba 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -197,7 +197,7 @@ class ReportScreen extends React.Component { {isArchivedRoom ? : ( - Keyboard.dismiss()}> + Date: Tue, 22 Feb 2022 17:07:19 -0800 Subject: [PATCH 12/47] Remove outdate use of isArchivedRoom from ReportActionCompose --- src/pages/home/report/ReportActionCompose.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index e14766310e3e..828872348ed5 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -437,7 +437,7 @@ class ReportActionCompose extends React.Component { }} style={styles.chatItemAttachButton} underlayColor={themeColors.componentBG} - disabled={isBlockedFromConcierge || isArchivedRoom} + disabled={isBlockedFromConcierge} > From 1b45be44359ab1d5d4534ada9f14371ca4bee995 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 17:08:54 -0800 Subject: [PATCH 13/47] Simplify diff for reviewers --- src/pages/home/report/ReportActionCompose.js | 47 ++++++++++---------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 828872348ed5..0a614a5cd451 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -451,30 +451,31 @@ class ReportActionCompose extends React.Component { animationIn="fadeInUp" animationOut="fadeOutDown" menuItems={[ - ...(!hasExcludedIOUEmails && Permissions.canUseIOU(this.props.betas) ? [ - hasMultipleParticipants - ? { - icon: Expensicons.Receipt, - text: this.props.translate('iou.splitBill'), - onSelected: () => { - Navigation.navigate( - ROUTES.getIouSplitRoute( - this.props.reportID, - ), - ); + ...(!hasExcludedIOUEmails + && Permissions.canUseIOU(this.props.betas) ? [ + hasMultipleParticipants + ? { + icon: Expensicons.Receipt, + text: this.props.translate('iou.splitBill'), + onSelected: () => { + Navigation.navigate( + ROUTES.getIouSplitRoute( + this.props.reportID, + ), + ); + }, + } : { + icon: Expensicons.MoneyCircle, + text: this.props.translate('iou.requestMoney'), + onSelected: () => { + Navigation.navigate( + ROUTES.getIouRequestRoute( + this.props.reportID, + ), + ); + }, }, - } : { - icon: Expensicons.MoneyCircle, - text: this.props.translate('iou.requestMoney'), - onSelected: () => { - Navigation.navigate( - ROUTES.getIouRequestRoute( - this.props.reportID, - ), - ); - }, - }, - ] : []), + ] : []), ...(!hasExcludedIOUEmails && Permissions.canUseIOUSend(this.props.betas) && !hasMultipleParticipants ? [ { icon: Expensicons.Send, From 7308254b38b7c9a0f7f5f0828dfe9db4e8c4f448 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 17:47:29 -0800 Subject: [PATCH 14/47] Clean up component style --- src/components/ArchivedReportFooter.js | 23 +++++++++++++++++------ src/styles/styles.js | 4 ++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 6e7db9723d38..97812cd02f2c 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -19,14 +19,25 @@ const propTypes = { const ArchivedReportFooter = (props) => { return ( - + {isHovered => ( - + + {/* TODO: pass displayName, policyName, and other parameters to translate() */} {props.translate(`reportArchiveReasons.${props.archiveReason}`)} - + + + )} diff --git a/src/styles/styles.js b/src/styles/styles.js index 2034416ffa2e..d602e8d1e917 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -320,6 +320,10 @@ const styles = { color: colors.red, }, + borderRadiusNormal: { + borderRadius: variables.componentBorderRadiusNormal, + }, + button: { backgroundColor: themeColors.buttonDefaultBG, borderRadius: variables.componentBorderRadiusNormal, From b6e2a5db93d318c830e780d0a5a11a6261b8054e Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Feb 2022 18:17:16 -0800 Subject: [PATCH 15/47] Add support for bold text in footer --- src/components/ArchivedReportFooter.js | 11 +++++++-- src/languages/en.js | 8 +++--- src/pages/home/ReportScreen.js | 26 +++++++++++--------- src/pages/home/report/ReportActionCompose.js | 2 -- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 97812cd02f2c..6a4bddf343c3 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -1,9 +1,11 @@ import React from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; +import CONST from '../CONST'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import Hoverable from './Hoverable'; +import RenderHTML from './RenderHTML'; import Text from './Text'; import styles from '../styles/styles'; import * as StyleUtils from '../styles/StyleUtils'; @@ -30,8 +32,13 @@ const ArchivedReportFooter = (props) => { isHovered ? styles.activeComponentBG : styles.hoveredComponentBG, ]} > - {/* TODO: pass displayName, policyName, and other parameters to translate() */} - {props.translate(`reportArchiveReasons.${props.archiveReason}`)} + { + props.archiveReason === CONST.REPORT.ARCHIVE_REASON.MANUALLY_ARCHIVED + ? {props.translate(`reportArchiveReasons.${props.archiveReason}`)} + + // TODO: pass displayName, policyName, and other parameters to translate() + : + } `This workspace chat is no longer active because ${login} closed their account.`, - accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged with ${newLogin}.`, + accountClosed: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, + accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged with ${newLogin}.`, manuallyArchived: 'This chat room has been archived.', - removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, - policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, + removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, + policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, }, sidebarScreen: { fabAction: 'New chat', diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 3bac7ab998ba..c8173571ca22 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -194,18 +194,20 @@ class ReportScreen extends React.Component { )} {(isArchivedRoom || this.props.session.shouldShowComposeInput) && ( - {isArchivedRoom - ? - : ( - - - - )} + { + isArchivedRoom + ? + : ( + + + + ) + } )} diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 0a614a5cd451..504047f7cd23 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -44,8 +44,6 @@ import * as User from '../../../libs/actions/User'; import Tooltip from '../../../components/Tooltip'; import EmojiPicker from '../../../components/EmojiPicker'; import VirtualKeyboard from '../../../libs/VirtualKeyboard'; -import ArchivedReportFooter from '../../../components/ArchivedReportFooter'; - const propTypes = { /** Beta features list */ From f9b6a666232dd571def018813ae6aa3d8a50477c Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 23 Feb 2022 09:15:53 -0800 Subject: [PATCH 16/47] Fix JS style --- src/components/ArchivedReportFooter.js | 6 ++---- src/pages/home/report/ReportActionCompose.js | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 6a4bddf343c3..d097c1437248 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -19,8 +19,7 @@ const propTypes = { ...withLocalizePropTypes, }; -const ArchivedReportFooter = (props) => { - return ( +const ArchivedReportFooter = (props) => ( {isHovered => ( { )} - ); -}; +); ArchivedReportFooter.propTypes = propTypes; ArchivedReportFooter.displayName = 'ArchivedReportFooter'; diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 6ca91755e4ba..05ece1aef793 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -554,7 +554,7 @@ class ReportActionCompose extends React.Component { )} this.focus(true)} onEmojiSelected={this.addEmojiToTextBox} /> From facde6a02ae1e60372536ea218d0f6b271c4a766 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 23 Feb 2022 13:37:10 -0800 Subject: [PATCH 17/47] Fix JS style (again) --- src/components/ArchivedReportFooter.js | 52 +++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index d097c1437248..75de509a406d 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -19,34 +19,34 @@ const propTypes = { ...withLocalizePropTypes, }; -const ArchivedReportFooter = (props) => ( - - {isHovered => ( - - { - props.archiveReason === CONST.REPORT.ARCHIVE_REASON.MANUALLY_ARCHIVED - ? {props.translate(`reportArchiveReasons.${props.archiveReason}`)} +const ArchivedReportFooter = props => ( + + {isHovered => ( + + { + props.archiveReason === CONST.REPORT.ARCHIVE_REASON.MANUALLY_ARCHIVED + ? {props.translate(`reportArchiveReasons.${props.archiveReason}`)} - // TODO: pass displayName, policyName, and other parameters to translate() - : - } - - - + // TODO: pass displayName, policyName, and other parameters to translate() + : + } + + - )} - + + )} + ); ArchivedReportFooter.propTypes = propTypes; From 2bcb7a191f81cd840a41ae5f82be95a5db9c89a2 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 23 Feb 2022 13:46:39 -0800 Subject: [PATCH 18/47] Rename MANUALLY_ARCHIVED to DEFAULT --- src/CONST/index.js | 2 +- src/components/ArchivedReportFooter.js | 9 +++++++-- src/languages/en.js | 2 +- src/languages/es.js | 2 +- src/pages/home/ReportScreen.js | 6 +++--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/CONST/index.js b/src/CONST/index.js index 911c337423c9..59af812ba081 100755 --- a/src/CONST/index.js +++ b/src/CONST/index.js @@ -224,7 +224,7 @@ const CONST = { }, }, ARCHIVE_REASON: { - MANUALLY_ARCHIVED: 'manuallyArchived', + DEFAULT: 'default', }, ERROR: { INACCESSIBLE_REPORT: 'Report not found', diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 75de509a406d..462aecc57944 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -14,11 +14,15 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize'; const propTypes = { /** The reason this report was archived. */ - archiveReason: PropTypes.string.isRequired, + archiveReason: PropTypes.string, ...withLocalizePropTypes, }; +const defaultProps = { + archiveReason: CONST.REPORT.ARCHIVE_REASON.DEFAULT, +}; + const ArchivedReportFooter = props => ( {isHovered => ( @@ -32,7 +36,7 @@ const ArchivedReportFooter = props => ( ]} > { - props.archiveReason === CONST.REPORT.ARCHIVE_REASON.MANUALLY_ARCHIVED + props.archiveReason === CONST.REPORT.ARCHIVE_REASON.DEFAULT ? {props.translate(`reportArchiveReasons.${props.archiveReason}`)} // TODO: pass displayName, policyName, and other parameters to translate() @@ -50,6 +54,7 @@ const ArchivedReportFooter = props => ( ); ArchivedReportFooter.propTypes = propTypes; +ArchivedReportFooter.defaultProps = defaultProps; ArchivedReportFooter.displayName = 'ArchivedReportFooter'; export default withLocalize(ArchivedReportFooter); diff --git a/src/languages/en.js b/src/languages/en.js index e79c58519d73..bb1478e77308 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -184,7 +184,7 @@ export default { reportArchiveReasons: { accountClosed: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged with ${newLogin}.`, - manuallyArchived: 'This chat room has been archived.', + default: 'This chat room has been archived.', removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, }, diff --git a/src/languages/es.js b/src/languages/es.js index fb50bca6a03f..fbc9164af74a 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -184,7 +184,7 @@ export default { reportArchiveReasons: { // accountClosed: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, // accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged with ${newLogin}.`, - manuallyArchived: 'Esta sala de chat ha sido eliminada.', + default: 'Esta sala de chat ha sido eliminada.', // removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, // policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, }, diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index c8173571ca22..88d8c7639201 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -3,6 +3,7 @@ import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import {Keyboard, View} from 'react-native'; import _ from 'underscore'; +import lodashFindLast from 'lodash/findLast'; import styles from '../../styles/styles'; import ScreenWrapper from '../../components/ScreenWrapper'; import HeaderView from './HeaderView'; @@ -166,10 +167,9 @@ class ReportScreen extends React.Component { const reportID = getReportID(this.props.route); const isArchivedRoom = ReportUtils.isArchivedRoom(this.props.report); - let archiveReason = ''; + let archiveReason; if (isArchivedRoom) { - const lastClosedActionIndex = _.findLastIndex(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); - archiveReason = lastClosedActionIndex >= 0 ? this.props.reportActions[lastClosedActionIndex].originalMessage.reason : CONST.REPORT.ARCHIVE_REASON.MANUALLY_ARCHIVED; + archiveReason = lodashFindLast(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); } return ( From 11a5fc170f9fdd8de408c41f75d64bd625bff06e Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 1 Mar 2022 16:01:35 -0800 Subject: [PATCH 19/47] Update translations --- src/languages/en.js | 2 +- src/languages/es.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 804f78152365..fcd62c6fb4f9 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -183,7 +183,7 @@ export default { }, reportArchiveReasons: { accountClosed: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, - accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged with ${newLogin}.`, + accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged their account with ${newLogin}.`, default: 'This chat room has been archived.', removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, diff --git a/src/languages/es.js b/src/languages/es.js index 3c1baa0debaa..c7c35d229300 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -182,11 +182,11 @@ export default { multipleUsers: 'Varios usuarios', }, reportArchiveReasons: { - // accountClosed: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, - // accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged with ${newLogin}.`, + accountClosed: ({login}) => `Este chat de espacio de trabajo esta desactivado porque ${login} ha cerrado su cuenta`, + accountMerged: ({oldLogin, newLogin}) => `Este chat de espacio de trabajo esta desactivado porque ${oldLogin} ha combinado su cuenta con ${newLogin}`, default: 'Esta sala de chat ha sido eliminada.', - // removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, - // policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, + removedFromPolicy: ({policyName, login}) => `Este chat de espacio de trabajo esta desactivado porque ${login} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, + policyDeleted: ({policyName}) => `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, }, sidebarScreen: { fabAction: 'Nuevo chat', From 550c3ce0a9f7e92fbe5f6ef9af30e663ab4fdba5 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 1 Mar 2022 16:07:53 -0800 Subject: [PATCH 20/47] Move icon to left of reason --- src/components/ArchivedReportFooter.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 462aecc57944..d798e1692417 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -29,12 +29,17 @@ const ArchivedReportFooter = props => ( + + + { props.archiveReason === CONST.REPORT.ARCHIVE_REASON.DEFAULT ? {props.translate(`reportArchiveReasons.${props.archiveReason}`)} @@ -42,12 +47,6 @@ const ArchivedReportFooter = props => ( // TODO: pass displayName, policyName, and other parameters to translate() : } - - - )} From b77c48c274bd46e1f31a3a8b00592626ef203659 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 1 Mar 2022 16:14:31 -0800 Subject: [PATCH 21/47] Update growl to have exclamation on left as well --- src/components/GrowlNotification/index.js | 2 +- src/styles/styles.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/GrowlNotification/index.js b/src/components/GrowlNotification/index.js index d5d8659d307b..dcdafff51324 100644 --- a/src/components/GrowlNotification/index.js +++ b/src/components/GrowlNotification/index.js @@ -92,10 +92,10 @@ class GrowlNotification extends Component { + {this.state.bodyText} - diff --git a/src/styles/styles.js b/src/styles/styles.js index 801f7dc62747..7b1e5db4d7b3 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -2124,6 +2124,7 @@ const styles = { width: '90%', lineHeight: variables.fontSizeNormalHeight, color: themeColors.textReversed, + ...spacing.ml4, }, blockquote: { From a54474d75b40e08769c665ad2c21be4e06373331 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 1 Mar 2022 16:36:53 -0800 Subject: [PATCH 22/47] Use constants as translation keys --- src/CONST.js | 4 ++++ src/languages/en.js | 12 +++++++----- src/languages/es.js | 12 +++++++----- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index b51da3c07da6..0a3b7a8f00fb 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -222,6 +222,10 @@ const CONST = { }, ARCHIVE_REASON: { DEFAULT: 'default', + ACCOUNT_CLOSED: 'accountClosed', + ACCOUNT_MERGED: 'accountMerged', + REMOVED_FROM_POLICY: 'removedFromPolicy', + POLICY_DELETED: 'policyDeleted', }, ERROR: { INACCESSIBLE_REPORT: 'Report not found', diff --git a/src/languages/en.js b/src/languages/en.js index fcd62c6fb4f9..1dcae631aa43 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -1,3 +1,5 @@ +import CONST from '../CONST'; + /* eslint-disable max-len */ export default { common: { @@ -182,11 +184,11 @@ export default { multipleUsers: 'Multiple users', }, reportArchiveReasons: { - accountClosed: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, - accountMerged: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged their account with ${newLogin}.`, - default: 'This chat room has been archived.', - removedFromPolicy: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, - policyDeleted: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, + [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'This chat room has been archived.', + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged their account with ${newLogin}.`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, + [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, }, sidebarScreen: { fabAction: 'New chat', diff --git a/src/languages/es.js b/src/languages/es.js index c7c35d229300..575a5ba8d578 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -1,3 +1,5 @@ +import CONST from '../CONST'; + /* eslint-disable max-len */ export default { common: { @@ -182,11 +184,11 @@ export default { multipleUsers: 'Varios usuarios', }, reportArchiveReasons: { - accountClosed: ({login}) => `Este chat de espacio de trabajo esta desactivado porque ${login} ha cerrado su cuenta`, - accountMerged: ({oldLogin, newLogin}) => `Este chat de espacio de trabajo esta desactivado porque ${oldLogin} ha combinado su cuenta con ${newLogin}`, - default: 'Esta sala de chat ha sido eliminada.', - removedFromPolicy: ({policyName, login}) => `Este chat de espacio de trabajo esta desactivado porque ${login} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, - policyDeleted: ({policyName}) => `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, + [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'Esta sala de chat ha sido eliminada.', + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({login}) => `Este chat de espacio de trabajo esta desactivado porque ${login} ha cerrado su cuenta`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({oldLogin, newLogin}) => `Este chat de espacio de trabajo esta desactivado porque ${oldLogin} ha combinado su cuenta con ${newLogin}`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({policyName, login}) => `Este chat de espacio de trabajo esta desactivado porque ${login} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, + [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, }, sidebarScreen: { fabAction: 'Nuevo chat', From 30999a5c792de34c04f17be7057bd6f5dd39032d Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 1 Mar 2022 16:41:41 -0800 Subject: [PATCH 23/47] Add alert log if no closed action is found for archived room --- src/pages/home/ReportScreen.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 88d8c7639201..10c03fa60056 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import {Keyboard, View} from 'react-native'; import _ from 'underscore'; import lodashFindLast from 'lodash/findLast'; +import Log from '../../libs/Log'; import styles from '../../styles/styles'; import ScreenWrapper from '../../components/ScreenWrapper'; import HeaderView from './HeaderView'; @@ -170,6 +171,7 @@ class ReportScreen extends React.Component { let archiveReason; if (isArchivedRoom) { archiveReason = lodashFindLast(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); + Log.alert(`No closed action found for archived room w/ reportID ${this.props.route.params.reportID}`); } return ( From 352efe8e73f8872efe4daa74c4743e9f195f6205 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 1 Mar 2022 16:54:03 -0800 Subject: [PATCH 24/47] Create reusable Banner component --- src/components/Banner.js | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/components/Banner.js diff --git a/src/components/Banner.js b/src/components/Banner.js new file mode 100644 index 000000000000..9c67174f0386 --- /dev/null +++ b/src/components/Banner.js @@ -0,0 +1,56 @@ +import React, {memo} from 'react'; +import PropTypes from 'prop-types'; +import {View} from 'react-native'; +import Hoverable from './Hoverable'; +import Icon from './Icon'; +import * as Expensicons from './Icon/Expensicons'; +import RenderHTML from './RenderHTML'; +import Text from './Text'; +import styles from '../styles/styles'; +import * as StyleUtils from '../styles/StyleUtils'; +import getButtonState from '../libs/getButtonState'; + +const propTypes = { + /** Text to display in the banner. */ + text: PropTypes.string.isRequired, + + /** Should this component render the text as HTML? */ + shouldRenderHTML: PropTypes.bool, +}; + +const defaultProps = { + shouldRenderHTML: false, +}; + +const Banner = props => ( + + {isHovered => ( + + + + + { + props.shouldRenderHTML + ? + : {props.text} + } + + )} + +); + +Banner.propTypes = propTypes; +Banner.defaultProps = defaultProps; +Banner.displayName = 'Banner'; + +export default memo(Banner); From 603bff8d5e6ea50242a055154c94c2664862053f Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 1 Mar 2022 17:09:08 -0800 Subject: [PATCH 25/47] Add storybook story for reusable Banner component --- .storybook/preview.js | 2 ++ src/stories/Banner.stories.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/stories/Banner.stories.js diff --git a/.storybook/preview.js b/.storybook/preview.js index 835171bd408d..05f9ba07e740 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -4,6 +4,7 @@ import '../assets/css/fonts.css'; import ComposeProviders from '../src/components/ComposeProviders'; import OnyxProvider from '../src/components/OnyxProvider'; import {LocaleContextProvider} from '../src/components/withLocalize'; +import HTMLEngineProvider from '../src/components/HTMLEngineProvider'; import ONYXKEYS from '../src/ONYXKEYS'; Onyx.init({ @@ -16,6 +17,7 @@ const decorators = [ components={[ OnyxProvider, LocaleContextProvider, + HTMLEngineProvider, ]} > diff --git a/src/stories/Banner.stories.js b/src/stories/Banner.stories.js new file mode 100644 index 000000000000..247489d49711 --- /dev/null +++ b/src/stories/Banner.stories.js @@ -0,0 +1,34 @@ +import React from 'react'; +import Banner from '../components/Banner'; + +/** + * We use the Component Story Format for writing stories. Follow the docs here: + * + * https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format + */ +const story = { + title: 'Components/Banner', + component: Banner, +}; + +// eslint-disable-next-line react/jsx-props-no-spreading +const Template = args => ; + +// Arguments can be passed to the component by binding +// See: https://storybook.js.org/docs/react/writing-stories/introduction#using-args +const InfoBanner = Template.bind({}); +InfoBanner.args = { + text: 'This is an informational banner', +}; + +const HTMLBanner = Template.bind({}); +HTMLBanner.args = { + text: 'This is a informational banner containing HTML', + shouldRenderHTML: true, +}; + +export default story; +export { + InfoBanner, + HTMLBanner, +}; From 906e969816761e4ed9dfb477fbd14e092ce20cbc Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 1 Mar 2022 17:14:54 -0800 Subject: [PATCH 26/47] Use reusable Banner component in ArchivedReportFooter --- src/components/ArchivedReportFooter.js | 41 ++++---------------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index d798e1692417..cb94d34c921a 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -1,15 +1,7 @@ import React from 'react'; -import {View} from 'react-native'; import PropTypes from 'prop-types'; import CONST from '../CONST'; -import Icon from './Icon'; -import * as Expensicons from './Icon/Expensicons'; -import Hoverable from './Hoverable'; -import RenderHTML from './RenderHTML'; -import Text from './Text'; -import styles from '../styles/styles'; -import * as StyleUtils from '../styles/StyleUtils'; -import getButtonState from '../libs/getButtonState'; +import Banner from './Banner'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; const propTypes = { @@ -23,33 +15,12 @@ const defaultProps = { archiveReason: CONST.REPORT.ARCHIVE_REASON.DEFAULT, }; +// TODO: pass displayName, policyName, and other parameters to translate() const ArchivedReportFooter = props => ( - - {isHovered => ( - - - - - { - props.archiveReason === CONST.REPORT.ARCHIVE_REASON.DEFAULT - ? {props.translate(`reportArchiveReasons.${props.archiveReason}`)} - - // TODO: pass displayName, policyName, and other parameters to translate() - : - } - - )} - + ); ArchivedReportFooter.propTypes = propTypes; From 8996bf7f3744597f3ef9594a796b08154db0c94a Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 9 Mar 2022 09:48:43 -0800 Subject: [PATCH 27/47] Fix ArchivedReportFooter shouldRenderHTML --- src/components/ArchivedReportFooter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index cb94d34c921a..e68a851a622b 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -19,7 +19,7 @@ const defaultProps = { const ArchivedReportFooter = props => ( ); From 2edb2ca6c18f3b6b18cee0e9b7a512bab6e565a6 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 9 Mar 2022 11:01:57 -0800 Subject: [PATCH 28/47] Save draft state with displayName but not policyName --- src/components/ArchivedReportFooter.js | 52 ++++++++++++++++++++++---- src/languages/en.js | 6 +-- src/languages/es.js | 6 +-- src/pages/home/ReportScreen.js | 12 ++++-- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index e68a851a622b..53944215b052 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -1,13 +1,27 @@ +import _ from 'underscore'; import React from 'react'; import PropTypes from 'prop-types'; +import {withOnyx} from 'react-native-onyx'; import CONST from '../CONST'; import Banner from './Banner'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import compose from '../libs/compose'; +import * as ReportUtils from '../libs/reportUtils'; +import personalDetailsPropType from '../pages/personalDetailsPropType'; +import ONYXKEYS from '../ONYXKEYS'; const propTypes = { /** The reason this report was archived. */ archiveReason: PropTypes.string, + /** The archived report */ + report: PropTypes.shape({ + /** Participants associated with the report */ + participants: PropTypes.arrayOf(PropTypes.string), + }).isRequired, + + personalDetails: PropTypes.objectOf(personalDetailsPropType).isRequired, + ...withLocalizePropTypes, }; @@ -15,16 +29,38 @@ const defaultProps = { archiveReason: CONST.REPORT.ARCHIVE_REASON.DEFAULT, }; -// TODO: pass displayName, policyName, and other parameters to translate() -const ArchivedReportFooter = props => ( - -); +const ArchivedReportFooter = (props) => { + // TODO: move https://github.com/Expensify/Web-Expensify/pull/33104/files logic to front-end so we can get the policy name here. + + // TODO: account for manually archived policy rooms + const archiveReason = ReportUtils.isPolicyExpenseChat(props.report) + ? props.archiveReason + : CONST.REPORT.ARCHIVE_REASON.DEFAULT; + // TODO: verify this isn't a problem when used on archived rooms – owner of chat reports is __FAKE__ + const displayName = _.has(props.personalDetails, props.report.ownerEmail) + ? props.personalDetails[props.report.ownerEmail].displayName + : props.report.ownerEmail; + return ( + + ); +}; ArchivedReportFooter.propTypes = propTypes; ArchivedReportFooter.defaultProps = defaultProps; ArchivedReportFooter.displayName = 'ArchivedReportFooter'; -export default withLocalize(ArchivedReportFooter); +export default compose( + withLocalize, + withOnyx({ + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS, + }, + }), +)(ArchivedReportFooter); diff --git a/src/languages/en.js b/src/languages/en.js index aa61ecb91536..628b1182d566 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -186,9 +186,9 @@ export default { }, reportArchiveReasons: { [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'This chat room has been archived.', - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({login}) => `This workspace chat is no longer active because ${login} closed their account.`, - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({oldLogin, newLogin}) => `This workspace chat is no longer active because ${oldLogin} has merged their account with ${newLogin}.`, - [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({policyName, login}) => `This workspace chat is no longer active because ${login} is no longer a member of the ${policyName} workspace.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}) => `This workspace chat is no longer active because ${displayName} closed their account.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}) => `This workspace chat is no longer active because ${oldDisplayName} has merged their account with ${displayName}.`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}) => `This workspace chat is no longer active because ${displayName} is no longer a member of the ${policyName} workspace.`, [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, }, sidebarScreen: { diff --git a/src/languages/es.js b/src/languages/es.js index f4a01328f051..2a72a2de5221 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -186,9 +186,9 @@ export default { }, reportArchiveReasons: { [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'Esta sala de chat ha sido eliminada.', - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({login}) => `Este chat de espacio de trabajo esta desactivado porque ${login} ha cerrado su cuenta`, - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({oldLogin, newLogin}) => `Este chat de espacio de trabajo esta desactivado porque ${oldLogin} ha combinado su cuenta con ${newLogin}`, - [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({policyName, login}) => `Este chat de espacio de trabajo esta desactivado porque ${login} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha cerrado su cuenta`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}) => `Este chat de espacio de trabajo esta desactivado porque ${oldDisplayName} ha combinado su cuenta con ${displayName}`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, }, sidebarScreen: { diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 10c03fa60056..a9b305fec780 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -171,7 +171,9 @@ class ReportScreen extends React.Component { let archiveReason; if (isArchivedRoom) { archiveReason = lodashFindLast(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); - Log.alert(`No closed action found for archived room w/ reportID ${this.props.route.params.reportID}`); + if (!archiveReason) { + Log.alert(`No closed action found for archived room w/ reportID ${this.props.route.params.reportID}`); + } } return ( @@ -198,8 +200,12 @@ class ReportScreen extends React.Component { { isArchivedRoom - ? - : ( + ? ( + + ) : ( Date: Thu, 17 Mar 2022 14:57:04 -0700 Subject: [PATCH 29/47] Load policyName in ArchivedReportFooter --- src/components/ArchivedReportFooter.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 53944215b052..fd911797c2ea 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -1,3 +1,4 @@ +import lodashGet from 'lodash/get'; import _ from 'underscore'; import React from 'react'; import PropTypes from 'prop-types'; @@ -11,17 +12,30 @@ import personalDetailsPropType from '../pages/personalDetailsPropType'; import ONYXKEYS from '../ONYXKEYS'; const propTypes = { - /** The reason this report was archived. */ + /** The reason this report was archived */ archiveReason: PropTypes.string, /** The archived report */ report: PropTypes.shape({ /** Participants associated with the report */ participants: PropTypes.arrayOf(PropTypes.string), + + /** The policy this report is attached to */ + policyID: PropTypes.string, }).isRequired, + /** Personal details of all users */ personalDetails: PropTypes.objectOf(personalDetailsPropType).isRequired, + /** The list of policies the user has access to. */ + policies: PropTypes.objectOf(PropTypes.shape({ + /** The ID of the policy */ + ID: PropTypes.string, + + /** The name of the policy */ + name: PropTypes.string, + })).isRequired, + ...withLocalizePropTypes, }; @@ -30,8 +44,7 @@ const defaultProps = { }; const ArchivedReportFooter = (props) => { - // TODO: move https://github.com/Expensify/Web-Expensify/pull/33104/files logic to front-end so we can get the policy name here. - + const policyName = lodashGet(props.policies, `policy_${props.report.policyID}.name`); // TODO: account for manually archived policy rooms const archiveReason = ReportUtils.isPolicyExpenseChat(props.report) ? props.archiveReason @@ -45,7 +58,7 @@ const ArchivedReportFooter = (props) => { text={props.translate(`reportArchiveReasons.${archiveReason}`, { displayName, oldDisplayName: props.oldDisplayName, - policyName: props.policyName, + policyName, })} shouldRenderHTML={archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT} /> @@ -62,5 +75,8 @@ export default compose( personalDetails: { key: ONYXKEYS.PERSONAL_DETAILS, }, + policies: { + key: ONYXKEYS.COLLECTION.POLICY, + }, }), )(ArchivedReportFooter); From 3833270ceb94028c7ec1b566311ac2e9e56db562 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Thu, 17 Mar 2022 14:59:39 -0700 Subject: [PATCH 30/47] Remove TODOs related to archived policy rooms --- src/components/ArchivedReportFooter.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index fd911797c2ea..431a079f16cb 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -45,11 +45,9 @@ const defaultProps = { const ArchivedReportFooter = (props) => { const policyName = lodashGet(props.policies, `policy_${props.report.policyID}.name`); - // TODO: account for manually archived policy rooms const archiveReason = ReportUtils.isPolicyExpenseChat(props.report) ? props.archiveReason : CONST.REPORT.ARCHIVE_REASON.DEFAULT; - // TODO: verify this isn't a problem when used on archived rooms – owner of chat reports is __FAKE__ const displayName = _.has(props.personalDetails, props.report.ownerEmail) ? props.personalDetails[props.report.ownerEmail].displayName : props.report.ownerEmail; From eadf175c889e2bc8ef73f3a6543a096972d89030 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Thu, 17 Mar 2022 15:11:40 -0700 Subject: [PATCH 31/47] fix bad merge in storybook --- .storybook/preview.js | 1 - 1 file changed, 1 deletion(-) diff --git a/.storybook/preview.js b/.storybook/preview.js index dec7cf26ec03..65508e6bed71 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -5,7 +5,6 @@ import ComposeProviders from '../src/components/ComposeProviders'; import HTMLEngineProvider from '../src/components/HTMLEngineProvider'; import OnyxProvider from '../src/components/OnyxProvider'; import {LocaleContextProvider} from '../src/components/withLocalize'; -import HTMLEngineProvider from '../src/components/HTMLEngineProvider'; import ONYXKEYS from '../src/ONYXKEYS'; Onyx.init({ From b6ebc7df2ee43d059d0386d22dc76a007f1a04a9 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Thu, 17 Mar 2022 18:00:49 -0700 Subject: [PATCH 32/47] Implement accountMerged archive reason --- src/components/ArchivedReportFooter.js | 30 ++++++++++++++++---------- src/pages/home/ReportScreen.js | 8 +++---- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 431a079f16cb..a5fc7d602cf4 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -7,13 +7,18 @@ import CONST from '../CONST'; import Banner from './Banner'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import compose from '../libs/compose'; -import * as ReportUtils from '../libs/reportUtils'; import personalDetailsPropType from '../pages/personalDetailsPropType'; import ONYXKEYS from '../ONYXKEYS'; const propTypes = { /** The reason this report was archived */ - archiveReason: PropTypes.string, + reportClosedAction: PropTypes.shape({ + message: PropTypes.shape({ + reason: PropTypes.string.isRequired, + oldLogin: PropTypes.string, + newLogin: PropTypes.string, + }).isRequired, + }).isRequired, /** The archived report */ report: PropTypes.shape({ @@ -39,23 +44,26 @@ const propTypes = { ...withLocalizePropTypes, }; -const defaultProps = { - archiveReason: CONST.REPORT.ARCHIVE_REASON.DEFAULT, -}; - const ArchivedReportFooter = (props) => { + const archiveReason = lodashGet(props.reportClosedAction, 'message.reason', CONST.REPORT.ARCHIVE_REASON.DEFAULT); const policyName = lodashGet(props.policies, `policy_${props.report.policyID}.name`); - const archiveReason = ReportUtils.isPolicyExpenseChat(props.report) - ? props.archiveReason - : CONST.REPORT.ARCHIVE_REASON.DEFAULT; - const displayName = _.has(props.personalDetails, props.report.ownerEmail) + let displayName = _.has(props.personalDetails, props.report.ownerEmail) ? props.personalDetails[props.report.ownerEmail].displayName : props.report.ownerEmail; + + let oldDisplayName; + if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) { + const newLogin = props.reportClosedAction.message.newLogin; + const oldLogin = props.reportClosedAction.message.oldLogin; + displayName = lodashGet(props.personalDetails, `${newLogin}.displayName`, newLogin); + oldDisplayName = lodashGet(props.personalDetails, `${oldLogin}.displayName`, oldLogin); + } + return ( action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); - if (!archiveReason) { + reportClosedAction = lodashFindLast(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); + if (!reportClosedAction) { Log.alert(`No closed action found for archived room w/ reportID ${this.props.route.params.reportID}`); } } @@ -202,7 +202,7 @@ class ReportScreen extends React.Component { isArchivedRoom ? ( ) : ( From e2b8a2c3c9ef0b850e80c082cbb4b8f632e8d532 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Thu, 17 Mar 2022 18:05:56 -0700 Subject: [PATCH 33/47] Fix JS style --- src/components/ArchivedReportFooter.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index a5fc7d602cf4..c266ba2d88b4 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -47,9 +47,7 @@ const propTypes = { const ArchivedReportFooter = (props) => { const archiveReason = lodashGet(props.reportClosedAction, 'message.reason', CONST.REPORT.ARCHIVE_REASON.DEFAULT); const policyName = lodashGet(props.policies, `policy_${props.report.policyID}.name`); - let displayName = _.has(props.personalDetails, props.report.ownerEmail) - ? props.personalDetails[props.report.ownerEmail].displayName - : props.report.ownerEmail; + let displayName = lodashGet(props.personalDetails, `${props.report.ownerEmail}.displayName`, props.report.ownerEmail); let oldDisplayName; if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) { @@ -72,7 +70,6 @@ const ArchivedReportFooter = (props) => { }; ArchivedReportFooter.propTypes = propTypes; -ArchivedReportFooter.defaultProps = defaultProps; ArchivedReportFooter.displayName = 'ArchivedReportFooter'; export default compose( From 44d5cebab4888fc3eceeae504f3fcd14b4e3c57f Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Thu, 17 Mar 2022 18:08:59 -0700 Subject: [PATCH 34/47] Add missing prop comments --- src/components/ArchivedReportFooter.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index c266ba2d88b4..ca7260920ac5 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -13,9 +13,15 @@ import ONYXKEYS from '../ONYXKEYS'; const propTypes = { /** The reason this report was archived */ reportClosedAction: PropTypes.shape({ + /** Message attached to the report closed action */ message: PropTypes.shape({ + /** The reason the report was closed */ reason: PropTypes.string.isRequired, + + /** (For accountMerged reason only), the email of the previous owner of this report. */ oldLogin: PropTypes.string, + + /** (For accountMerged reason only), the email of the account the previous owner was merged into */ newLogin: PropTypes.string, }).isRequired, }).isRequired, From 920df83663354dc99bb4878a65cdc63c516517f8 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Thu, 17 Mar 2022 18:26:11 -0700 Subject: [PATCH 35/47] Remove unused import --- src/components/ArchivedReportFooter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index ca7260920ac5..c886d752e8d0 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -1,5 +1,4 @@ import lodashGet from 'lodash/get'; -import _ from 'underscore'; import React from 'react'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; From 2772192fc6b4a85ae1a0aa592314e636d91750f3 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Mar 2022 18:34:15 -0700 Subject: [PATCH 36/47] ActionName not type and originalMessage not message --- src/components/ArchivedReportFooter.js | 4 ++-- src/pages/home/ReportScreen.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index c886d752e8d0..dfd49947bff0 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -13,7 +13,7 @@ const propTypes = { /** The reason this report was archived */ reportClosedAction: PropTypes.shape({ /** Message attached to the report closed action */ - message: PropTypes.shape({ + originalMessage: PropTypes.shape({ /** The reason the report was closed */ reason: PropTypes.string.isRequired, @@ -50,7 +50,7 @@ const propTypes = { }; const ArchivedReportFooter = (props) => { - const archiveReason = lodashGet(props.reportClosedAction, 'message.reason', CONST.REPORT.ARCHIVE_REASON.DEFAULT); + const archiveReason = lodashGet(props.reportClosedAction, 'originalMessage.reason', CONST.REPORT.ARCHIVE_REASON.DEFAULT); const policyName = lodashGet(props.policies, `policy_${props.report.policyID}.name`); let displayName = lodashGet(props.personalDetails, `${props.report.ownerEmail}.displayName`, props.report.ownerEmail); diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index e48c1fffb5af..a008239d2af4 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -170,7 +170,7 @@ class ReportScreen extends React.Component { const isArchivedRoom = ReportUtils.isArchivedRoom(this.props.report); let reportClosedAction; if (isArchivedRoom) { - reportClosedAction = lodashFindLast(this.props.reportActions, action => action.type === CONST.REPORT.ACTIONS.TYPE.CLOSED); + reportClosedAction = lodashFindLast(this.props.reportActions, action => action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED); if (!reportClosedAction) { Log.alert(`No closed action found for archived room w/ reportID ${this.props.route.params.reportID}`); } From 7b6718d66d51c9f6d7958697980f1ef7f9dce4a5 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Mar 2022 18:37:45 -0700 Subject: [PATCH 37/47] Add HTML in spanish translations --- src/languages/es.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/languages/es.js b/src/languages/es.js index 100055171449..9861c4898dda 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -192,10 +192,10 @@ export default { }, reportArchiveReasons: { [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'Esta sala de chat ha sido eliminada.', - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha cerrado su cuenta`, - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}) => `Este chat de espacio de trabajo esta desactivado porque ${oldDisplayName} ha combinado su cuenta con ${displayName}`, - [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, - [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha cerrado su cuenta.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}) => `Este chat de espacio de trabajo esta desactivado porque ${oldDisplayName} ha combinado su cuenta con ${displayName}.`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, + [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, }, sidebarScreen: { fabAction: 'Nuevo chat', From 8d4fff2e14500e6db28bce4f79ae16b3003e9087 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Mar 2022 21:06:52 -0700 Subject: [PATCH 38/47] Use originalMessage instead of message --- src/components/ArchivedReportFooter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index dfd49947bff0..e95fb5c2cb67 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -56,8 +56,8 @@ const ArchivedReportFooter = (props) => { let oldDisplayName; if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) { - const newLogin = props.reportClosedAction.message.newLogin; - const oldLogin = props.reportClosedAction.message.oldLogin; + const newLogin = props.reportClosedAction.originalMessage.newLogin; + const oldLogin = props.reportClosedAction.originalMessage.oldLogin; displayName = lodashGet(props.personalDetails, `${newLogin}.displayName`, newLogin); oldDisplayName = lodashGet(props.personalDetails, `${oldLogin}.displayName`, oldLogin); } From 86f78507ba278f3562233d8e5851d0ddcc0c6141 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Mar 2022 21:07:28 -0700 Subject: [PATCH 39/47] Remove false alarm --- src/pages/home/ReportScreen.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index a008239d2af4..a090dce5d838 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -171,9 +171,6 @@ class ReportScreen extends React.Component { let reportClosedAction; if (isArchivedRoom) { reportClosedAction = lodashFindLast(this.props.reportActions, action => action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED); - if (!reportClosedAction) { - Log.alert(`No closed action found for archived room w/ reportID ${this.props.route.params.reportID}`); - } } return ( From 77a32df9b5150d02d9a4fb4bc1eaadab5aa52609 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Mar 2022 21:12:46 -0700 Subject: [PATCH 40/47] Add LoginUtil to sanitize merged_0@ prefix --- src/libs/{LoginUtil.js => LoginUtils.js} | 13 ++++++++++- src/libs/ValidationUtils.js | 4 ++-- src/libs/actions/PersonalDetails.js | 25 +++++++++++---------- src/libs/actions/Report.js | 5 +++-- src/pages/RequestCallPage.js | 2 +- src/pages/settings/AddSecondaryLoginPage.js | 2 +- src/pages/signin/LoginForm.js | 2 +- 7 files changed, 33 insertions(+), 20 deletions(-) rename src/libs/{LoginUtil.js => LoginUtils.js} (53%) diff --git a/src/libs/LoginUtil.js b/src/libs/LoginUtils.js similarity index 53% rename from src/libs/LoginUtil.js rename to src/libs/LoginUtils.js index e8346b2bfc54..932cfe0866de 100644 --- a/src/libs/LoginUtil.js +++ b/src/libs/LoginUtils.js @@ -1,5 +1,15 @@ import CONST from '../CONST'; +/** + * Remove the MERGED_0@ prefix from merged account emails. + * + * @param {String} email + * @returns {String} + */ +function getEmailWithoutMergedAccountPrefix(email) { + return email.replace(/^MERGED_0@/, ''); +} + /** * Remove the special chars from the phone number * @param {String} phone @@ -9,6 +19,7 @@ function getPhoneNumberWithoutSpecialChars(phone) { return phone.replace(CONST.REGEX.SPECIAL_CHARS_WITHOUT_NEWLINE, ''); } -export default { +export { + getEmailWithoutMergedAccountPrefix, getPhoneNumberWithoutSpecialChars, }; diff --git a/src/libs/ValidationUtils.js b/src/libs/ValidationUtils.js index 9780edb065f9..83ce6b2c816f 100644 --- a/src/libs/ValidationUtils.js +++ b/src/libs/ValidationUtils.js @@ -2,7 +2,7 @@ import moment from 'moment'; import _ from 'underscore'; import CONST from '../CONST'; import * as CardUtils from './CardUtils'; -import LoginUtil from './LoginUtil'; +import * as LoginUtils from './LoginUtils'; /** * Implements the Luhn Algorithm, a checksum formula used to validate credit card @@ -291,7 +291,7 @@ function isPositiveInteger(input) { * @returns {Boolean} */ function isNumericWithSpecialChars(input) { - return /^\+?\d*$/.test(LoginUtil.getPhoneNumberWithoutSpecialChars(input)); + return /^\+?\d*$/.test(LoginUtils.getPhoneNumberWithoutSpecialChars(input)); } /** diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 4dbaa0ab700a..07df4456056d 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -8,6 +8,7 @@ import CONST from '../../CONST'; import NetworkConnection from '../NetworkConnection'; import * as API from '../API'; import NameValuePair from './NameValuePair'; +import * as LoginUtils from '../LoginUtils'; import * as ReportUtils from '../reportUtils'; import * as OptionsListUtils from '../OptionsListUtils'; import Growl from '../Growl'; @@ -87,20 +88,20 @@ function formatPersonalDetails(personalDetailsList) { // This method needs to be SUPER PERFORMANT because it can be called with a massive list of logins depending on the policies that someone belongs to // eslint-disable-next-line rulesdir/prefer-underscore-method - Object.keys(personalDetailsList).forEach((login) => { - const personalDetailsResponse = personalDetailsList[login]; + Object.entries(personalDetailsList).forEach(([login, details]) => { + const sanitizedLogin = LoginUtils.getEmailWithoutMergedAccountPrefix(login); // Form the details into something that has all the data in an easy to use format. - const avatar = getAvatar(personalDetailsResponse, login); - const displayName = getDisplayName(login, personalDetailsResponse); - const pronouns = personalDetailsResponse.pronouns || ''; - const timezone = personalDetailsResponse.timeZone || CONST.DEFAULT_TIME_ZONE; - const firstName = personalDetailsResponse.firstName || ''; - const lastName = personalDetailsResponse.lastName || ''; - const payPalMeAddress = personalDetailsResponse.expensify_payPalMeAddress || ''; - const phoneNumber = personalDetailsResponse.phoneNumber || ''; - formattedResult[login] = { - login, + const avatar = getAvatar(details, sanitizedLogin); + const displayName = getDisplayName(sanitizedLogin, details); + const pronouns = details.pronouns || ''; + const timezone = details.timeZone || CONST.DEFAULT_TIME_ZONE; + const firstName = details.firstName || ''; + const lastName = details.lastName || ''; + const payPalMeAddress = details.expensify_payPalMeAddress || ''; + const phoneNumber = details.phoneNumber || ''; + formattedResult[sanitizedLogin] = { + login: sanitizedLogin, avatar, displayName, firstName, diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index c1a21d187f3a..3aaf22887757 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -20,6 +20,7 @@ import Timing from './Timing'; import * as API from '../API'; import CONST from '../../CONST'; import Log from '../Log'; +import * as LoginUtils from '../LoginUtils'; import * as ReportUtils from '../reportUtils'; import * as OptionsListUtils from '../OptionsListUtils'; import Timers from '../Timers'; @@ -156,7 +157,7 @@ function getChatReportName(fullReport, chatType) { // For a basic policy room or a Policy Expense chat, return its original name if (ReportUtils.isUserCreatedPolicyRoom({chatType}) || ReportUtils.isPolicyExpenseChat({chatType})) { - return fullReport.reportName; + return LoginUtils.getEmailWithoutMergedAccountPrefix(fullReport.reportName); } const {sharedReportList} = fullReport; @@ -214,7 +215,7 @@ function getSimplifiedReportObject(report) { reportID: report.reportID, reportName, chatType, - ownerEmail: lodashGet(report, ['ownerEmail'], ''), + ownerEmail: LoginUtils.getEmailWithoutMergedAccountPrefix(lodashGet(report, ['ownerEmail'], '')), policyID: lodashGet(report, ['reportNameValuePairs', 'expensify_policyID'], ''), unreadActionCount: getUnreadActionCount(report), maxSequenceNumber: lodashGet(report, 'reportActionCount', 0), diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js index f0d3a9b2b36c..a2c89df5bf67 100644 --- a/src/pages/RequestCallPage.js +++ b/src/pages/RequestCallPage.js @@ -27,7 +27,7 @@ import Section from '../components/Section'; import KeyboardAvoidingView from '../components/KeyboardAvoidingView'; import * as Illustrations from '../components/Icon/Illustrations'; import * as Expensicons from '../components/Icon/Expensicons'; -import LoginUtil from '../libs/LoginUtil'; +import * as LoginUtils from '../libs/LoginUtils'; import * as ValidationUtils from '../libs/ValidationUtils'; import * as PersonalDetails from '../libs/actions/PersonalDetails'; import * as User from '../libs/actions/User'; diff --git a/src/pages/settings/AddSecondaryLoginPage.js b/src/pages/settings/AddSecondaryLoginPage.js index b496cfd812d1..d5758e579575 100755 --- a/src/pages/settings/AddSecondaryLoginPage.js +++ b/src/pages/settings/AddSecondaryLoginPage.js @@ -20,7 +20,7 @@ import compose from '../../libs/compose'; import FixedFooter from '../../components/FixedFooter'; import TextInput from '../../components/TextInput'; import userPropTypes from './userPropTypes'; -import LoginUtil from '../../libs/LoginUtil'; +import * as LoginUtils from '../../libs/LoginUtils'; const propTypes = { /* Onyx Props */ diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index 2b9340d98d4a..7d784e5cbd07 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -16,7 +16,7 @@ import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize import getEmailKeyboardType from '../../libs/getEmailKeyboardType'; import TextInput from '../../components/TextInput'; import * as ValidationUtils from '../../libs/ValidationUtils'; -import LoginUtil from '../../libs/LoginUtil'; +import * as LoginUtils from '../../libs/LoginUtils'; import withToggleVisibilityView, {toggleVisibilityViewPropTypes} from '../../components/withToggleVisibilityView'; const propTypes = { From bd85b1b051a4a3e6777ffe69edb70c3e104d0a0b Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Mar 2022 21:27:44 -0700 Subject: [PATCH 41/47] Fix lint errors --- src/pages/RequestCallPage.js | 4 ++-- src/pages/home/ReportScreen.js | 1 - src/pages/settings/AddSecondaryLoginPage.js | 4 ++-- src/pages/signin/LoginForm.js | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js index a2c89df5bf67..5dbbcb892d1d 100644 --- a/src/pages/RequestCallPage.js +++ b/src/pages/RequestCallPage.js @@ -150,7 +150,7 @@ class RequestCallPage extends Component { policyID: policyForCall.id, firstName: this.state.firstName, lastName: this.state.lastName, - phoneNumber: LoginUtil.getPhoneNumberWithoutSpecialChars(this.state.phoneNumber), + phoneNumber: LoginUtils.getPhoneNumberWithoutSpecialChars(this.state.phoneNumber), phoneNumberExtension: this.state.phoneExtension, }); } @@ -172,7 +172,7 @@ class RequestCallPage extends Component { * @returns {String} */ getPhoneNumberError() { - const phoneNumber = LoginUtil.getPhoneNumberWithoutSpecialChars(this.state.phoneNumber); + const phoneNumber = LoginUtils.getPhoneNumberWithoutSpecialChars(this.state.phoneNumber); if (_.isEmpty(this.state.phoneNumber.trim()) || !Str.isValidPhone(phoneNumber)) { return this.props.translate('messages.errorMessageInvalidPhone'); } diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index a090dce5d838..ae4acbdd4820 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import {Keyboard, View} from 'react-native'; import _ from 'underscore'; import lodashFindLast from 'lodash/findLast'; -import Log from '../../libs/Log'; import styles from '../../styles/styles'; import ScreenWrapper from '../../components/ScreenWrapper'; import HeaderView from './HeaderView'; diff --git a/src/pages/settings/AddSecondaryLoginPage.js b/src/pages/settings/AddSecondaryLoginPage.js index d5758e579575..7a15526de572 100755 --- a/src/pages/settings/AddSecondaryLoginPage.js +++ b/src/pages/settings/AddSecondaryLoginPage.js @@ -72,7 +72,7 @@ class AddSecondaryLoginPage extends Component { */ submitForm() { const login = this.formType === CONST.LOGIN_TYPE.PHONE - ? LoginUtil.getPhoneNumberWithoutSpecialChars(this.state.login) + ? LoginUtils.getPhoneNumberWithoutSpecialChars(this.state.login) : this.state.login; User.setSecondaryLoginAndNavigate(login, this.state.password); } @@ -84,7 +84,7 @@ class AddSecondaryLoginPage extends Component { */ validateForm() { const login = this.formType === CONST.LOGIN_TYPE.PHONE - ? LoginUtil.getPhoneNumberWithoutSpecialChars(this.state.login) + ? LoginUtils.getPhoneNumberWithoutSpecialChars(this.state.login) : this.state.login; const validationMethod = this.formType === CONST.LOGIN_TYPE.PHONE ? Str.isValidPhone : Str.isValidEmail; diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index 7d784e5cbd07..0805c6ffe5c3 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -115,7 +115,7 @@ class LoginForm extends React.Component { return; } - const phoneLogin = LoginUtil.getPhoneNumberWithoutSpecialChars(login); + const phoneLogin = LoginUtils.getPhoneNumberWithoutSpecialChars(login); const isValidPhoneLogin = Str.isValidPhone(phoneLogin); if (!Str.isValidEmail(login) && !isValidPhoneLogin) { From 94ec3e42e8e9dd3b06bd78df41679389eb309517 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Mar 2022 21:42:45 -0700 Subject: [PATCH 42/47] Make reportClosedAction optional because its not there for the first render --- src/components/ArchivedReportFooter.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index e95fb5c2cb67..c63bcd31eedb 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -23,7 +23,7 @@ const propTypes = { /** (For accountMerged reason only), the email of the account the previous owner was merged into */ newLogin: PropTypes.string, }).isRequired, - }).isRequired, + }), /** The archived report */ report: PropTypes.shape({ @@ -49,6 +49,12 @@ const propTypes = { ...withLocalizePropTypes, }; +const defaultProps = { + reportClosedAction: { + originalMessage: CONST.REPORT.ARCHIVE_REASON.DEFAULT, + }, +}; + const ArchivedReportFooter = (props) => { const archiveReason = lodashGet(props.reportClosedAction, 'originalMessage.reason', CONST.REPORT.ARCHIVE_REASON.DEFAULT); const policyName = lodashGet(props.policies, `policy_${props.report.policyID}.name`); @@ -75,6 +81,7 @@ const ArchivedReportFooter = (props) => { }; ArchivedReportFooter.propTypes = propTypes; +ArchivedReportFooter.defaultProps = defaultProps; ArchivedReportFooter.displayName = 'ArchivedReportFooter'; export default compose( From d067f1948399d01c58a49f69e1712ca75f0d1454 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Tue, 22 Mar 2022 22:11:38 -0700 Subject: [PATCH 43/47] Remove unused props --- src/components/ArchivedReportFooter.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index c63bcd31eedb..2878ff12d3d1 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -27,9 +27,6 @@ const propTypes = { /** The archived report */ report: PropTypes.shape({ - /** Participants associated with the report */ - participants: PropTypes.arrayOf(PropTypes.string), - /** The policy this report is attached to */ policyID: PropTypes.string, }).isRequired, @@ -39,9 +36,6 @@ const propTypes = { /** The list of policies the user has access to. */ policies: PropTypes.objectOf(PropTypes.shape({ - /** The ID of the policy */ - ID: PropTypes.string, - /** The name of the policy */ name: PropTypes.string, })).isRequired, From 117241b651b48a5696665f6183de8785eee89236 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 23 Mar 2022 11:23:24 -0700 Subject: [PATCH 44/47] Fix originalMessage.reason default prop --- src/components/ArchivedReportFooter.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 2878ff12d3d1..0d4b7ba2c385 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -45,7 +45,9 @@ const propTypes = { const defaultProps = { reportClosedAction: { - originalMessage: CONST.REPORT.ARCHIVE_REASON.DEFAULT, + originalMessage: { + reason: CONST.REPORT.ARCHIVE_REASON.DEFAULT, + }, }, }; From 8d5d53a3b2d9e59cc136dbecca550d27944816b6 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 23 Mar 2022 11:34:54 -0700 Subject: [PATCH 45/47] Use onyx collection key constant --- src/components/ArchivedReportFooter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 0d4b7ba2c385..7d1b626dc608 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -53,7 +53,7 @@ const defaultProps = { const ArchivedReportFooter = (props) => { const archiveReason = lodashGet(props.reportClosedAction, 'originalMessage.reason', CONST.REPORT.ARCHIVE_REASON.DEFAULT); - const policyName = lodashGet(props.policies, `policy_${props.report.policyID}.name`); + const policyName = lodashGet(props.policies, `${ONYXKEYS.COLLECTION.POLICY}${props.report.policyID}.name`); let displayName = lodashGet(props.personalDetails, `${props.report.ownerEmail}.displayName`, props.report.ownerEmail); let oldDisplayName; From 8e5442cefcbbe190edf9a3cce31a26c36c98c4b2 Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 23 Mar 2022 11:52:03 -0700 Subject: [PATCH 46/47] Use state and status constants --- src/CONST.js | 7 +++++++ src/libs/reportUtils.js | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/CONST.js b/src/CONST.js index 7ca3c964e0d6..5d40051ac074 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -253,6 +253,13 @@ const CONST = { PROCESSING: 1, SUBMITTED: 2, }, + STATUS: { + OPEN: 0, + SUBMITTED: 1, + CLOSED: 2, + APPROVED: 3, + REIMBURSED: 4, + }, NOTIFICATION_PREFERENCE: { MUTE: 'mute', DAILY: 'daily', diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index b862909192e5..984167390629 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -172,7 +172,7 @@ function isArchivedRoom(report) { return false; } - return report.statusNum === 2 && report.stateNum === 2; + return report.statusNum === CONST.REPORT.STATUS.CLOSED && report.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED; } /** From 811379bd997653c43740db5cd90192d5c457510f Mon Sep 17 00:00:00 2001 From: Rory Abraham Date: Wed, 23 Mar 2022 13:45:13 -0700 Subject: [PATCH 47/47] Take HTML out of translation files --- src/components/ArchivedReportFooter.js | 6 +++--- src/languages/en.js | 8 ++++---- src/languages/es.js | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/ArchivedReportFooter.js b/src/components/ArchivedReportFooter.js index 7d1b626dc608..d423fa0d4e22 100644 --- a/src/components/ArchivedReportFooter.js +++ b/src/components/ArchivedReportFooter.js @@ -67,9 +67,9 @@ const ArchivedReportFooter = (props) => { return ( ${displayName}`, + oldDisplayName: `${oldDisplayName}`, + policyName: `${policyName}`, })} shouldRenderHTML={archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT} /> diff --git a/src/languages/en.js b/src/languages/en.js index 0d3337c60daf..5672f5131e1e 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -192,10 +192,10 @@ export default { }, reportArchiveReasons: { [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'This chat room has been archived.', - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}) => `This workspace chat is no longer active because ${displayName} closed their account.`, - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}) => `This workspace chat is no longer active because ${oldDisplayName} has merged their account with ${displayName}.`, - [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}) => `This workspace chat is no longer active because ${displayName} is no longer a member of the ${policyName} workspace.`, - [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}) => `This workspace chat is no longer active because ${displayName} closed their account.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}) => `This workspace chat is no longer active because ${oldDisplayName} has merged their account with ${displayName}.`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}) => `This workspace chat is no longer active because ${displayName} is no longer a member of the ${policyName} workspace.`, + [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, }, sidebarScreen: { fabAction: 'New chat', diff --git a/src/languages/es.js b/src/languages/es.js index 9861c4898dda..ac933e5eab49 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -192,10 +192,10 @@ export default { }, reportArchiveReasons: { [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'Esta sala de chat ha sido eliminada.', - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha cerrado su cuenta.`, - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}) => `Este chat de espacio de trabajo esta desactivado porque ${oldDisplayName} ha combinado su cuenta con ${displayName}.`, - [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, - [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha cerrado su cuenta.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}) => `Este chat de espacio de trabajo esta desactivado porque ${oldDisplayName} ha combinado su cuenta con ${displayName}.`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}) => `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, + [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}) => `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, }, sidebarScreen: { fabAction: 'Nuevo chat',