From fe36ce9d912456fbaccc512d4343755cf6e88c8c Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Tue, 13 Feb 2024 21:16:28 +0100 Subject: [PATCH 01/64] Update archive messages for threads --- src/components/ArchivedReportFooter.tsx | 7 +++++-- src/languages/en.ts | 11 ++++++----- src/libs/ReportUtils.ts | 11 +++++++++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/components/ArchivedReportFooter.tsx b/src/components/ArchivedReportFooter.tsx index 083c8340baa6..c86fa42ea9fb 100644 --- a/src/components/ArchivedReportFooter.tsx +++ b/src/components/ArchivedReportFooter.tsx @@ -11,6 +11,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetailsList, Report, ReportAction} from '@src/types/onyx'; import Banner from './Banner'; +import { getCurrentUserAccountID } from '@libs/actions/Report'; type ArchivedReportFooterOnyxProps = { /** The reason this report was archived */ @@ -31,8 +32,9 @@ function ArchivedReportFooter({report, reportClosedAction, personalDetails = {}} const originalMessage = reportClosedAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED ? reportClosedAction.originalMessage : null; const archiveReason = originalMessage?.reason ?? CONST.REPORT.ARCHIVE_REASON.DEFAULT; - let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[report?.ownerAccountID ?? 0]); - + const actorPersonalDetails = personalDetails?.[reportClosedAction?.actorAccountID ?? 0]; + let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(actorPersonalDetails); + let oldDisplayName: string | undefined; if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) { const newAccountID = originalMessage?.newAccountID; @@ -56,6 +58,7 @@ function ArchivedReportFooter({report, reportClosedAction, personalDetails = {}} displayName: `${displayName}`, oldDisplayName: `${oldDisplayName}`, policyName: `${policyName}`, + shouldUseYou: actorPersonalDetails?.accountID === getCurrentUserAccountID(), }) : translate(`reportArchiveReasons.${archiveReason}`); diff --git a/src/languages/en.ts b/src/languages/en.ts index f24b0e3e2438..f1755a1a6b1b 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -508,13 +508,14 @@ export default { reportArchiveReasons: { [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'This chat room has been archived.', [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}: ReportArchiveReasonsClosedParams) => - `This workspace chat is no longer active because ${displayName} closed their account.`, + `This chat is no longer active because ${displayName} closed their account.`, [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}: ReportArchiveReasonsMergedParams) => - `This workspace chat is no longer active because ${oldDisplayName} has merged their account with ${displayName}.`, - [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName}: ReportArchiveReasonsRemovedFromPolicyParams) => - `This workspace chat is no longer active because ${displayName} is no longer a member of the ${policyName} workspace.`, + `This chat is no longer active because ${oldDisplayName} has merged their account with ${displayName}.`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName, shouldUseYou}: ReportArchiveReasonsRemovedFromPolicyParams) => + shouldUseYou ? `This chat is no longer active because you are no longer a member of the ${policyName} workspace.` + : `This chat is no longer active because ${displayName} is no longer a member of the ${policyName} workspace.`, [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}: ReportArchiveReasonsPolicyDeletedParams) => - `This workspace chat is no longer active because ${policyName} is no longer an active workspace.`, + `This chat is no longer active because ${policyName} is no longer an active workspace.`, }, writeCapabilityPage: { label: 'Who can post', diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 26280f95447d..48f853633bc1 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2444,7 +2444,11 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu const parentReportAction = ReportActionsUtils.getParentReportAction(report); if (isChatThread(report)) { if (!isEmptyObject(parentReportAction) && ReportActionsUtils.isTransactionThread(parentReportAction)) { - return getTransactionReportName(parentReportAction); + formattedName = getTransactionReportName(parentReportAction); + if (isArchivedRoom(report)) { + formattedName += ` (${Localize.translateLocal('common.archived')})`; + } + return formattedName; } const isAttachment = ReportActionsUtils.isReportActionAttachment(!isEmptyObject(parentReportAction) ? parentReportAction : null); @@ -2462,6 +2466,9 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu if (isAdminRoom(report) || isUserCreatedPolicyRoom(report)) { return getAdminRoomInvitedParticipants(parentReportAction, parentReportActionMessage); } + if (parentReportActionMessage && isArchivedRoom(report)) { + return `${parentReportActionMessage} (${Localize.translateLocal('common.archived')})`; + } return parentReportActionMessage || Localize.translateLocal('parentReportAction.deletedMessage'); } @@ -3615,7 +3622,7 @@ function buildTransactionThread(reportAction: OnyxEntry, moneyRequ getTransactionReportName(reportAction), undefined, getReport(moneyRequestReportID)?.policyID ?? CONST.POLICY.OWNER_EMAIL_FAKE, - CONST.POLICY.OWNER_ACCOUNT_ID_FAKE, + getReport(moneyRequestReportID)?.ownerAccountID ?? CONST.POLICY.OWNER_ACCOUNT_ID_FAKE, false, '', undefined, From 0cd9f91e0bf12bdb03c56cc4e1fc8b9e97dd265f Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Tue, 13 Feb 2024 21:19:19 +0100 Subject: [PATCH 02/64] fix type error --- src/languages/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/languages/types.ts b/src/languages/types.ts index c9442c6560a3..59c6119b781c 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -90,6 +90,7 @@ type ReportArchiveReasonsMergedParams = { type ReportArchiveReasonsRemovedFromPolicyParams = { displayName: string; policyName: string; + shouldUseYou: boolean; }; type ReportArchiveReasonsPolicyDeletedParams = { From bb19a7bf7071b63710cf0b8b51f0b3870323f381 Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Wed, 14 Feb 2024 01:03:27 +0100 Subject: [PATCH 03/64] undo unecessary change --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 48f853633bc1..efaecd0fe476 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -3622,7 +3622,7 @@ function buildTransactionThread(reportAction: OnyxEntry, moneyRequ getTransactionReportName(reportAction), undefined, getReport(moneyRequestReportID)?.policyID ?? CONST.POLICY.OWNER_EMAIL_FAKE, - getReport(moneyRequestReportID)?.ownerAccountID ?? CONST.POLICY.OWNER_ACCOUNT_ID_FAKE, + CONST.POLICY.OWNER_ACCOUNT_ID_FAKE, false, '', undefined, From 5c3061b59b9c3c91b14c9cd31bb74bf294f4e957 Mon Sep 17 00:00:00 2001 From: Ren Jones <153645623+ren-jones@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:26:11 -0600 Subject: [PATCH 04/64] Create Set-time-zone.md New account settings article --- .../account-settings/Set-time-zone.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docs/articles/expensify-classic/settings/account-settings/Set-time-zone.md diff --git a/docs/articles/expensify-classic/settings/account-settings/Set-time-zone.md b/docs/articles/expensify-classic/settings/account-settings/Set-time-zone.md new file mode 100644 index 000000000000..600f6c92092e --- /dev/null +++ b/docs/articles/expensify-classic/settings/account-settings/Set-time-zone.md @@ -0,0 +1,20 @@ +--- +title: Set time zone +description: Set your time zone in Expensify +--- +
+ +You can manually set your time zone or allow Expensify to automatically set your time zone based on your location. + +{% include info.html %} +Some actions you take in Expensify are timestamped. To ensure the most accurate time is captured, you’ll want to make sure your time zone matches your current location. If you select the automatic time zone option, your time zone will automatically reflect your current location. If you manually set your time zone, you must manually update the time zone when traveling. {% include end-info.html %} + +*Note: This process is currently not available from the mobile app and must be completed from the Expensify website.* + +1. Hover over Settings, then click **Account**. +2. Click the **Preferences** tab. +3. Scroll down to the Time Zone section and select your time zone preferences. + - Automatic time zone: To allow Expensify to automatically set your time zone based on your location, select the Set my time zone automatically checkbox. + - Manual time zone: To manually select your time zone, select your time zone from the list. + +
From 233f66d4e83182a2a8b50ba4b62ffdbaac67c435 Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Sun, 25 Feb 2024 22:19:25 +0100 Subject: [PATCH 05/64] prettier --- src/components/ArchivedReportFooter.tsx | 4 ++-- src/languages/en.ts | 8 ++++---- src/libs/ReportUtils.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/ArchivedReportFooter.tsx b/src/components/ArchivedReportFooter.tsx index c86fa42ea9fb..9713e40136a2 100644 --- a/src/components/ArchivedReportFooter.tsx +++ b/src/components/ArchivedReportFooter.tsx @@ -4,6 +4,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import {getCurrentUserAccountID} from '@libs/actions/Report'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -11,7 +12,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetailsList, Report, ReportAction} from '@src/types/onyx'; import Banner from './Banner'; -import { getCurrentUserAccountID } from '@libs/actions/Report'; type ArchivedReportFooterOnyxProps = { /** The reason this report was archived */ @@ -34,7 +34,7 @@ function ArchivedReportFooter({report, reportClosedAction, personalDetails = {}} const archiveReason = originalMessage?.reason ?? CONST.REPORT.ARCHIVE_REASON.DEFAULT; const actorPersonalDetails = personalDetails?.[reportClosedAction?.actorAccountID ?? 0]; let displayName = PersonalDetailsUtils.getDisplayNameOrDefault(actorPersonalDetails); - + let oldDisplayName: string | undefined; if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED) { const newAccountID = originalMessage?.newAccountID; diff --git a/src/languages/en.ts b/src/languages/en.ts index f506e8e4f0e9..17c66ab0df47 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -516,13 +516,13 @@ export default { }, reportArchiveReasons: { [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'This chat room has been archived.', - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}: ReportArchiveReasonsClosedParams) => - `This chat is no longer active because ${displayName} closed their account.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}: ReportArchiveReasonsClosedParams) => `This chat is no longer active because ${displayName} closed their account.`, [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}: ReportArchiveReasonsMergedParams) => `This chat is no longer active because ${oldDisplayName} has merged their account with ${displayName}.`, [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName, shouldUseYou}: ReportArchiveReasonsRemovedFromPolicyParams) => - shouldUseYou ? `This chat is no longer active because you are no longer a member of the ${policyName} workspace.` - : `This chat is no longer active because ${displayName} is no longer a member of the ${policyName} workspace.`, + shouldUseYou + ? `This chat is no longer active because you are no longer a member of the ${policyName} workspace.` + : `This chat is no longer active because ${displayName} is no longer a member of the ${policyName} workspace.`, [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}: ReportArchiveReasonsPolicyDeletedParams) => `This chat is no longer active because ${policyName} is no longer an active workspace.`, }, diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index fa6113e543aa..d88091e298b4 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2522,7 +2522,7 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu formattedName = getTransactionReportName(parentReportAction); if (isArchivedRoom(report)) { formattedName += ` (${Localize.translateLocal('common.archived')})`; - } + } return formattedName; } @@ -2547,7 +2547,7 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } if (parentReportActionMessage && isArchivedRoom(report)) { return `${parentReportActionMessage} (${Localize.translateLocal('common.archived')})`; - } + } return parentReportActionMessage; } From 17efb7c1a14cdec4ba13798311df47a22a998777 Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Sun, 25 Feb 2024 22:23:56 +0100 Subject: [PATCH 06/64] fix typescript error --- src/languages/en.ts | 2 +- src/languages/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 17c66ab0df47..861c63b3b1b4 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -519,7 +519,7 @@ export default { [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}: ReportArchiveReasonsClosedParams) => `This chat is no longer active because ${displayName} closed their account.`, [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}: ReportArchiveReasonsMergedParams) => `This chat is no longer active because ${oldDisplayName} has merged their account with ${displayName}.`, - [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName, shouldUseYou}: ReportArchiveReasonsRemovedFromPolicyParams) => + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName, shouldUseYou = false}: ReportArchiveReasonsRemovedFromPolicyParams) => shouldUseYou ? `This chat is no longer active because you are no longer a member of the ${policyName} workspace.` : `This chat is no longer active because ${displayName} is no longer a member of the ${policyName} workspace.`, diff --git a/src/languages/types.ts b/src/languages/types.ts index 90765e38595e..ed993f79f171 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -90,7 +90,7 @@ type ReportArchiveReasonsMergedParams = { type ReportArchiveReasonsRemovedFromPolicyParams = { displayName: string; policyName: string; - shouldUseYou: boolean; + shouldUseYou?: boolean; }; type ReportArchiveReasonsPolicyDeletedParams = { From 3e1b02f03c16f0c2babac64d95293653521e5cde Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Sun, 25 Feb 2024 22:30:15 +0100 Subject: [PATCH 07/64] spanish translation --- src/languages/es.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index c9ff087d0de7..802908d8c182 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -509,14 +509,15 @@ export default { }, reportArchiveReasons: { [CONST.REPORT.ARCHIVE_REASON.DEFAULT]: 'Esta sala de chat ha sido eliminada.', - [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}: ReportArchiveReasonsClosedParams) => - `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha cerrado su cuenta.`, + [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_CLOSED]: ({displayName}: ReportArchiveReasonsClosedParams) => `Este chat esta desactivado porque ${displayName} ha cerrado su cuenta.`, [CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED]: ({displayName, oldDisplayName}: ReportArchiveReasonsMergedParams) => - `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}: ReportArchiveReasonsRemovedFromPolicyParams) => - `Este chat de espacio de trabajo esta desactivado porque ${displayName} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, + `Este chat esta desactivado porque ${oldDisplayName} ha combinado su cuenta con ${displayName}.`, + [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName, shouldUseYou = false}: ReportArchiveReasonsRemovedFromPolicyParams) => + shouldUseYou + ? `Este chat esta desactivado porque ha dejado de ser miembro del espacio de trabajo ${policyName}.` + : `Este chat esta desactivado porque ${displayName} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}: ReportArchiveReasonsPolicyDeletedParams) => - `Este chat de espacio de trabajo esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, + `Este chat esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, }, writeCapabilityPage: { label: 'Quién puede postear', From 045018839066bad4e66de063d579d2f81e3de340 Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Sun, 25 Feb 2024 23:03:01 +0100 Subject: [PATCH 08/64] correct spanish translation --- src/languages/es.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index 802908d8c182..a0da53859fba 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -514,7 +514,7 @@ export default { `Este chat esta desactivado porque ${oldDisplayName} ha combinado su cuenta con ${displayName}.`, [CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY]: ({displayName, policyName, shouldUseYou = false}: ReportArchiveReasonsRemovedFromPolicyParams) => shouldUseYou - ? `Este chat esta desactivado porque ha dejado de ser miembro del espacio de trabajo ${policyName}.` + ? `Este chat ya no está activo porque ya no eres miembro del espacio de trabajo ${policyName}.` : `Este chat esta desactivado porque ${displayName} ha dejado de ser miembro del espacio de trabajo ${policyName}.`, [CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED]: ({policyName}: ReportArchiveReasonsPolicyDeletedParams) => `Este chat esta desactivado porque el espacio de trabajo ${policyName} se ha eliminado.`, From fb2d496d39de7e58722b7570cfbc392dfb2f4671 Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Mon, 26 Feb 2024 00:38:26 +0100 Subject: [PATCH 09/64] fix failing test --- tests/unit/SidebarTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/SidebarTest.js b/tests/unit/SidebarTest.js index 6a813ef1fa8c..09f979d0dd98 100644 --- a/tests/unit/SidebarTest.js +++ b/tests/unit/SidebarTest.js @@ -132,7 +132,7 @@ describe('Sidebar', () => { const hintMessagePreviewText = Localize.translateLocal('accessibilityHints.lastChatMessagePreview'); const messagePreviewTexts = screen.queryAllByLabelText(hintMessagePreviewText); expect(lodashGet(messagePreviewTexts, [0, 'props', 'children'])).toBe( - 'This workspace chat is no longer active because Vikings Policy is no longer an active workspace.', + 'This chat is no longer active because Vikings Policy is no longer an active workspace.', ); }) ); From df4cb033a6393ff457bc08afb4f19a01d406968d Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Mon, 26 Feb 2024 01:08:07 +0100 Subject: [PATCH 10/64] prettier --- tests/unit/SidebarTest.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/unit/SidebarTest.js b/tests/unit/SidebarTest.js index 09f979d0dd98..de44d858654f 100644 --- a/tests/unit/SidebarTest.js +++ b/tests/unit/SidebarTest.js @@ -131,9 +131,7 @@ describe('Sidebar', () => { const hintMessagePreviewText = Localize.translateLocal('accessibilityHints.lastChatMessagePreview'); const messagePreviewTexts = screen.queryAllByLabelText(hintMessagePreviewText); - expect(lodashGet(messagePreviewTexts, [0, 'props', 'children'])).toBe( - 'This chat is no longer active because Vikings Policy is no longer an active workspace.', - ); + expect(lodashGet(messagePreviewTexts, [0, 'props', 'children'])).toBe('This chat is no longer active because Vikings Policy is no longer an active workspace.'); }) ); }); From 5fe99d543c912dd1a62a4ce33ad1d217257d6779 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Tue, 5 Mar 2024 15:32:11 +0100 Subject: [PATCH 11/64] initial settings --- src/ROUTES.ts | 4 ++ src/SCREENS.ts | 1 + src/languages/en.ts | 1 + .../API/parameters/SetPolicyRequiresTag.ts | 6 ++ src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 + .../AppNavigator/ModalStackNavigators.tsx | 1 + .../CENTRAL_PANE_TO_RHP_MAPPING.ts | 1 + .../TAB_TO_CENTRAL_PANE_MAPPING.ts | 1 + src/libs/Navigation/linkingConfig/config.ts | 3 + src/libs/Navigation/types.ts | 3 + src/libs/actions/Policy.ts | 55 ++++++++++++++++ .../workspace/tags/WorkspaceTagsPage.tsx | 24 ++++++- .../tags/WorkspaceTagsSettingsPage.tsx | 64 +++++++++++++++++++ 14 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 src/libs/API/parameters/SetPolicyRequiresTag.ts create mode 100644 src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index cfc287ba2cdc..30d6a7698bb5 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -550,6 +550,10 @@ const ROUTES = { route: 'workspace/:policyID/tags', getRoute: (policyID: string) => `workspace/${policyID}/tags` as const, }, + WORKSPACE_TAGS_SETTINGS: { + route: 'workspace/:policyID/tags/settings', + getRoute: (policyID: string) => `workspace/${policyID}/tags/settings` as const, + }, // Referral program promotion REFERRAL_DETAILS_MODAL: { route: 'referral/:contentType', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 2369fe435feb..8ffdbcfb1f5c 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -215,6 +215,7 @@ const SCREENS = { INVITE_MESSAGE: 'Workspace_Invite_Message', CATEGORIES: 'Workspace_Categories', TAGS: 'Workspace_Tags', + TAGS_SETTINGS: 'Tags_Settings', CURRENCY: 'Workspace_Profile_Currency', WORKFLOWS: 'Workspace_Workflows', WORKFLOWS_APPROVER: 'Workspace_Workflows_Approver', diff --git a/src/languages/en.ts b/src/languages/en.ts index 0a52cca62ef5..0026e2449beb 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1779,6 +1779,7 @@ export default { title: "You haven't created any tags", subtitle: 'Add a tag to track projects, locations, departments, and more.', }, + genericFailureMessage: 'An error occurred while updating the tag, please try again.', }, emptyWorkspace: { title: 'Create a workspace', diff --git a/src/libs/API/parameters/SetPolicyRequiresTag.ts b/src/libs/API/parameters/SetPolicyRequiresTag.ts new file mode 100644 index 000000000000..b8c2e71e7e3b --- /dev/null +++ b/src/libs/API/parameters/SetPolicyRequiresTag.ts @@ -0,0 +1,6 @@ +type SetPolicyRequiresTag = { + policyID: string; + requiresTag: boolean; +}; + +export default SetPolicyRequiresTag; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 679379c8089a..00af2d615bf1 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -153,4 +153,5 @@ export type {default as SetWorkspaceAutoReportingParams} from './SetWorkspaceAut export type {default as SetWorkspaceAutoReportingFrequencyParams} from './SetWorkspaceAutoReportingFrequencyParams'; export type {default as SetWorkspaceAutoReportingMonthlyOffsetParams} from './SetWorkspaceAutoReportingMonthlyOffsetParams'; export type {default as SetWorkspaceApprovalModeParams} from './SetWorkspaceApprovalModeParams'; +export type {default as SetPolicyRequiresTag} from './SetPolicyRequiresTag'; export type {default as SwitchToOldDotParams} from './SwitchToOldDotParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index cacbfebdc120..983afbfeadc1 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -116,6 +116,7 @@ const WRITE_COMMANDS = { CREATE_WORKSPACE_FROM_IOU_PAYMENT: 'CreateWorkspaceFromIOUPayment', SET_WORKSPACE_CATEGORIES_ENABLED: 'SetWorkspaceCategoriesEnabled', SET_WORKSPACE_REQUIRES_CATEGORY: 'SetWorkspaceRequiresCategory', + SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag', CREATE_TASK: 'CreateTask', CANCEL_TASK: 'CancelTask', EDIT_TASK_ASSIGNEE: 'EditTaskAssignee', @@ -265,6 +266,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.CREATE_WORKSPACE_FROM_IOU_PAYMENT]: Parameters.CreateWorkspaceFromIOUPaymentParams; [WRITE_COMMANDS.SET_WORKSPACE_CATEGORIES_ENABLED]: Parameters.SetWorkspaceCategoriesEnabledParams; [WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams; + [WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag; [WRITE_COMMANDS.CREATE_TASK]: Parameters.CreateTaskParams; [WRITE_COMMANDS.CANCEL_TASK]: Parameters.CancelTaskParams; [WRITE_COMMANDS.EDIT_TASK_ASSIGNEE]: Parameters.EditTaskAssigneeParams; diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index 545641957c9a..f8646a47324b 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -251,6 +251,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../pages/workspace/WorkspaceProfileCurrencyPage').default as React.ComponentType, [SCREENS.WORKSPACE.CATEGORY_SETTINGS]: () => require('../../../pages/workspace/categories/CategorySettingsPage').default as React.ComponentType, [SCREENS.WORKSPACE.CATEGORIES_SETTINGS]: () => require('../../../pages/workspace/categories/WorkspaceCategoriesSettingsPage').default as React.ComponentType, + [SCREENS.WORKSPACE.TAGS_SETTINGS]: () => require('../../../pages/workspace/tags/WorkspaceTagsSettingsPage').default as React.ComponentType, [SCREENS.REIMBURSEMENT_ACCOUNT]: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default as React.ComponentType, [SCREENS.GET_ASSISTANCE]: () => require('../../../pages/GetAssistancePage').default as React.ComponentType, [SCREENS.SETTINGS.TWO_FACTOR_AUTH]: () => require('../../../pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage').default as React.ComponentType, diff --git a/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts b/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts index 7959999ee813..eff4f9ae1a95 100755 --- a/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts @@ -7,6 +7,7 @@ const CENTRAL_PANE_TO_RHP_MAPPING: Partial> = [SCREENS.WORKSPACE.MEMBERS]: [SCREENS.WORKSPACE.INVITE, SCREENS.WORKSPACE.INVITE_MESSAGE], [SCREENS.WORKSPACE.WORKFLOWS]: [SCREENS.WORKSPACE.WORKFLOWS_APPROVER, SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY, SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET], [SCREENS.WORKSPACE.CATEGORIES]: [SCREENS.WORKSPACE.CATEGORY_SETTINGS, SCREENS.WORKSPACE.CATEGORIES_SETTINGS], + [SCREENS.WORKSPACE.TAGS]: [SCREENS.WORKSPACE.TAGS_SETTINGS], }; export default CENTRAL_PANE_TO_RHP_MAPPING; diff --git a/src/libs/Navigation/linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING.ts b/src/libs/Navigation/linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING.ts index f4316009b70b..98bb217fabf0 100755 --- a/src/libs/Navigation/linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/TAB_TO_CENTRAL_PANE_MAPPING.ts @@ -14,6 +14,7 @@ const TAB_TO_CENTRAL_PANE_MAPPING: Record = { SCREENS.WORKSPACE.TRAVEL, SCREENS.WORKSPACE.MEMBERS, SCREENS.WORKSPACE.CATEGORIES, + SCREENS.WORKSPACE.TAGS, ], }; diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 3ceb3c1ac7df..90206fed3ebe 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -280,6 +280,9 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.CATEGORIES_SETTINGS]: { path: ROUTES.WORKSPACE_CATEGORIES_SETTINGS.route, }, + [SCREENS.WORKSPACE.TAGS_SETTINGS]: { + path: ROUTES.WORKSPACE_TAGS_SETTINGS.route, + }, [SCREENS.REIMBURSEMENT_ACCOUNT]: { path: ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.route, exact: true, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 6ffbb3a358b0..6eef56a2f134 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -200,6 +200,9 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.CATEGORIES_SETTINGS]: { policyID: string; }; + [SCREENS.WORKSPACE.TAGS_SETTINGS]: { + policyID: string; + }; [SCREENS.GET_ASSISTANCE]: { backTo: Routes; }; diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 313c4deb9934..547c067100ee 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -2473,6 +2473,60 @@ function setWorkspaceRequiresCategory(policyID: string, requiresCategory: boolea API.write('SetWorkspaceRequiresCategory', parameters, onyxData); } +function setPolicyRequiresTag(policyID: string, requiresTag: boolean) { + const onyxData: OnyxData = { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + requiresTag, + errors: { + requiresTag: null, + }, + pendingFields: { + requiresTag: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + errors: { + requiresTag: null, + }, + pendingFields: { + requiresTag: null, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + requiresTag: !requiresTag, + errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + pendingFields: { + requiresTag: null, + }, + }, + }, + ], + }; + + const parameters = { + policyID, + requiresTag, + }; + + API.write('SetPolicyRequiresTag', parameters, onyxData); +} + function clearCategoryErrors(policyID: string, categoryName: string) { const category = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`]?.[categoryName]; @@ -2536,4 +2590,5 @@ export { setWorkspaceCategoryEnabled, setWorkspaceRequiresCategory, clearCategoryErrors, + setPolicyRequiresTag, }; diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index c82740eff361..a57c044beec2 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -3,6 +3,7 @@ import React, {useMemo, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; +import Button from '@components/Button'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -16,11 +17,13 @@ import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import type {CentralPaneNavigatorParamList} from '@navigation/types'; import AdminPolicyAccessOrNotFoundWrapper from '@pages/workspace/AdminPolicyAccessOrNotFoundWrapper'; import PaidPolicyAccessOrNotFoundWrapper from '@pages/workspace/PaidPolicyAccessOrNotFoundWrapper'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; @@ -93,6 +96,22 @@ function WorkspaceTagsPage({policyTags, route}: WorkspaceTagsPageProps) { ); + const navigateToTagsSettings = () => { + Navigation.navigate(ROUTES.WORKSPACE_TAGS_SETTINGS.getRoute(route.params.policyID)); + }; + + const settingsButton = ( + +