From 59c508b4cf4bc15b0f202afec691e23289402178 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 13:58:45 -0500 Subject: [PATCH 01/42] feat: pass a new parameter to the requires tags api --- src/libs/API/parameters/SetPolicyRequiresTag.ts | 1 + src/libs/actions/Policy/Tag.ts | 4 +++- src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx | 4 ++-- tests/actions/PolicyTagTest.ts | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libs/API/parameters/SetPolicyRequiresTag.ts b/src/libs/API/parameters/SetPolicyRequiresTag.ts index b8c2e71e7e3..fa1531a60f5 100644 --- a/src/libs/API/parameters/SetPolicyRequiresTag.ts +++ b/src/libs/API/parameters/SetPolicyRequiresTag.ts @@ -1,5 +1,6 @@ type SetPolicyRequiresTag = { policyID: string; + tagListIndex: number; requiresTag: boolean; }; diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 7760f29d670..88efe6fa905 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -1,5 +1,6 @@ import type {NullishDeep, OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; +import {tag} from 'type-fest/source/opaque'; import * as API from '@libs/API'; import type {EnablePolicyTagsParams, OpenPolicyTagsPageParams, SetPolicyTagsEnabled} from '@libs/API/parameters'; import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; @@ -531,7 +532,7 @@ function renamePolicyTaglist(policyID: string, policyTagListName: {oldName: stri API.write(WRITE_COMMANDS.RENAME_POLICY_TAG_LIST, parameters, onyxData); } -function setPolicyRequiresTag(policyID: string, requiresTag: boolean) { +function setPolicyRequiresTag(policyID: string, requiresTag: boolean, tagListIndex: number) { const onyxData: OnyxData = { optimisticData: [ { @@ -577,6 +578,7 @@ function setPolicyRequiresTag(policyID: string, requiresTag: boolean) { const parameters = { policyID, + tagListIndex, requiresTag, }; diff --git a/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx index 15e9e605e8d..cc0fb918b46 100644 --- a/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx @@ -36,9 +36,9 @@ function WorkspaceTagsSettingsPage({route, policyTags}: WorkspaceTagsSettingsPag const hasEnabledOptions = OptionsListUtils.hasEnabledOptions(Object.values(policyTags ?? {}).flatMap(({tags}) => Object.values(tags))); const updateWorkspaceRequiresTag = useCallback( (value: boolean) => { - Tag.setPolicyRequiresTag(route.params.policyID, value); + Tag.setPolicyRequiresTag(route.params.policyID, value, policyTagLists[0].orderWeight); }, - [route.params.policyID], + [route.params.policyID, policyTagLists], ); return ( diff --git a/tests/actions/PolicyTagTest.ts b/tests/actions/PolicyTagTest.ts index ad473633d87..aaa92bf9924 100644 --- a/tests/actions/PolicyTagTest.ts +++ b/tests/actions/PolicyTagTest.ts @@ -34,7 +34,7 @@ describe('actions/Policy', () => { return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) .then(() => { - Tag.setPolicyRequiresTag(fakePolicy.id, true); + Tag.setPolicyRequiresTag(fakePolicy.id, true, 0); return waitForBatchedUpdates(); }) .then( @@ -81,7 +81,7 @@ describe('actions/Policy', () => { return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) .then(() => { - Tag.setPolicyRequiresTag(fakePolicy.id, false); + Tag.setPolicyRequiresTag(fakePolicy.id, false, 0); return waitForBatchedUpdates(); }) .then( @@ -129,7 +129,7 @@ describe('actions/Policy', () => { return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) .then(() => { mockFetch?.fail?.(); - Tag.setPolicyRequiresTag(fakePolicy.id, false); + Tag.setPolicyRequiresTag(fakePolicy.id, false, 0); return waitForBatchedUpdates(); }) From 6a2c8ee8bd391aee795ea0c8b079bfd369e14fc1 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 14:08:14 -0500 Subject: [PATCH 02/42] chore: add new constant --- src/CONST.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index de4e3305edd..d2b5302bed8 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1665,6 +1665,9 @@ const CONST = { // Often referred to as "collect" workspaces TEAM: 'team', }, + TAG: { + REQUIRED: 'required', + }, ROLE: { ADMIN: 'admin', AUDITOR: 'auditor', From 336c036647095f45afd83c12be454df28cd88d0e Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 14:08:34 -0500 Subject: [PATCH 03/42] feat: add the toggle button --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 1b91777a22a..0c5d99b173a 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -21,12 +21,14 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import * as ErrorUtils from '@libs/ErrorUtils'; import localeCompare from '@libs/LocaleCompare'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import type {SettingsNavigatorParamList} from '@navigation/types'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import * as Tag from '@userActions/Policy/Tag'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -245,6 +247,17 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { shouldShowRightIcon /> + + Tag.setPolicyRequiresTag(policyID, on, route.params.orderWeight ?? 0)} + pendingAction={currentPolicyTag.pendingFields?.required} + errors={ErrorUtils.getLatestErrorField(policyTags, CONST.POLICY.TAG.REQUIRED)} + disabled={tagList.length === 0} + /> + {isLoading && ( Date: Sun, 2 Jun 2024 14:22:17 -0500 Subject: [PATCH 04/42] chore: disable the switch if all tags are not active --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 0c5d99b173a..915ca5f0bf9 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -255,7 +255,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { onToggle={(on) => Tag.setPolicyRequiresTag(policyID, on, route.params.orderWeight ?? 0)} pendingAction={currentPolicyTag.pendingFields?.required} errors={ErrorUtils.getLatestErrorField(policyTags, CONST.POLICY.TAG.REQUIRED)} - disabled={tagList.length === 0} + disabled={!Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} /> {isLoading && ( From 95c360b40b1638bc423ee2d6387db04249929bb7 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 14:42:55 -0500 Subject: [PATCH 05/42] fix: remove unnecessary import --- src/libs/actions/Policy/Tag.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 88efe6fa905..3bfa46adfcb 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -1,6 +1,5 @@ import type {NullishDeep, OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import {tag} from 'type-fest/source/opaque'; import * as API from '@libs/API'; import type {EnablePolicyTagsParams, OpenPolicyTagsPageParams, SetPolicyTagsEnabled} from '@libs/API/parameters'; import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; From 75b21ebd298073b00fdfbe6c90d9cd6f5fefb0fa Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 16:15:55 -0500 Subject: [PATCH 06/42] fix: UI copy and error message --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 915ca5f0bf9..bc9033fd44f 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -249,12 +249,12 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { Tag.setPolicyRequiresTag(policyID, on, route.params.orderWeight ?? 0)} pendingAction={currentPolicyTag.pendingFields?.required} - errors={ErrorUtils.getLatestErrorField(policyTags, CONST.POLICY.TAG.REQUIRED)} + errors={currentPolicyTag.errors} disabled={!Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} /> From 39f7fac94a3c662c854a55ebc479baba17aef7fe Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 16:16:39 -0500 Subject: [PATCH 07/42] fix: component position --- .../workspace/tags/WorkspaceViewTagsPage.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index bc9033fd44f..cf6afbbaab6 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -236,17 +236,6 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { cancelText={translate('common.cancel')} danger /> - - - tag.enabled)} /> + + + {isLoading && ( Date: Sun, 2 Jun 2024 16:17:02 -0500 Subject: [PATCH 08/42] chore: remove unused error util --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index cf6afbbaab6..c021cc49c66 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -21,7 +21,6 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; -import * as ErrorUtils from '@libs/ErrorUtils'; import localeCompare from '@libs/LocaleCompare'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; From e1246a810fb9cd23807330844a1e36bf95bc33ed Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 16:46:16 -0500 Subject: [PATCH 09/42] fix: swap the API to call --- .../API/parameters/SetPolicyRequiresTag.ts | 7 ---- .../API/parameters/SetPolicyTagsRequired.ts | 7 ++++ src/libs/API/parameters/index.ts | 2 +- src/libs/API/types.ts | 4 +- src/libs/actions/Policy/Tag.ts | 42 +++++++++---------- .../workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- 6 files changed, 31 insertions(+), 33 deletions(-) delete mode 100644 src/libs/API/parameters/SetPolicyRequiresTag.ts create mode 100644 src/libs/API/parameters/SetPolicyTagsRequired.ts diff --git a/src/libs/API/parameters/SetPolicyRequiresTag.ts b/src/libs/API/parameters/SetPolicyRequiresTag.ts deleted file mode 100644 index fa1531a60f5..00000000000 --- a/src/libs/API/parameters/SetPolicyRequiresTag.ts +++ /dev/null @@ -1,7 +0,0 @@ -type SetPolicyRequiresTag = { - policyID: string; - tagListIndex: number; - requiresTag: boolean; -}; - -export default SetPolicyRequiresTag; diff --git a/src/libs/API/parameters/SetPolicyTagsRequired.ts b/src/libs/API/parameters/SetPolicyTagsRequired.ts new file mode 100644 index 00000000000..8defd4a8084 --- /dev/null +++ b/src/libs/API/parameters/SetPolicyTagsRequired.ts @@ -0,0 +1,7 @@ +type SetPolicyTagsRequired = { + policyID: string; + tagListIndex: number; + requireTagList: boolean; +}; + +export default SetPolicyTagsRequired; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 68097a20112..8ef37b8fc36 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -171,7 +171,7 @@ export type {default as SetWorkspaceAutoReportingMonthlyOffsetParams} from './Se export type {default as SetWorkspaceApprovalModeParams} from './SetWorkspaceApprovalModeParams'; export type {default as SetWorkspacePayerParams} from './SetWorkspacePayerParams'; export type {default as SetWorkspaceReimbursementParams} from './SetWorkspaceReimbursementParams'; -export type {default as SetPolicyRequiresTag} from './SetPolicyRequiresTag'; +export type {default as SetPolicyTagsRequired} from './SetPolicyTagsRequired'; export type {default as RenamePolicyTaglist} from './RenamePolicyTaglist'; export type {default as SwitchToOldDotParams} from './SwitchToOldDotParams'; export type {default as TrackExpenseParams} from './TrackExpenseParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 897b300f047..53917dc633b 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -133,7 +133,7 @@ const WRITE_COMMANDS = { RENAME_POLICY_TAG: 'RenamePolicyTag', SET_WORKSPACE_REQUIRES_CATEGORY: 'SetWorkspaceRequiresCategory', DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories', - SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag', + SET_POLICY_TAGS_REQUIRED: 'SetPolicyTagsRequired', RENAME_POLICY_TAG_LIST: 'RenamePolicyTaglist', DELETE_POLICY_TAGS: 'DeletePolicyTags', CREATE_TASK: 'CreateTask', @@ -338,7 +338,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY]: Parameters.RenameWorkspaceCategoriesParams; [WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams; [WRITE_COMMANDS.DELETE_WORKSPACE_CATEGORIES]: Parameters.DeleteWorkspaceCategoriesParams; - [WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag; + [WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED]: Parameters.SetPolicyTagsRequired; [WRITE_COMMANDS.RENAME_POLICY_TAG_LIST]: Parameters.RenamePolicyTaglist; [WRITE_COMMANDS.CREATE_POLICY_TAG]: Parameters.CreatePolicyTagsParams; [WRITE_COMMANDS.RENAME_POLICY_TAG]: Parameters.RenamePolicyTagsParams; diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 3bfa46adfcb..6df6b1660d0 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -1,7 +1,7 @@ import type {NullishDeep, OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import * as API from '@libs/API'; -import type {EnablePolicyTagsParams, OpenPolicyTagsPageParams, SetPolicyTagsEnabled} from '@libs/API/parameters'; +import type {EnablePolicyTagsParams, OpenPolicyTagsPageParams, SetPolicyTagsEnabled, SetPolicyTagsRequired} from '@libs/API/parameters'; import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import getIsNarrowLayout from '@libs/getIsNarrowLayout'; @@ -531,17 +531,19 @@ function renamePolicyTaglist(policyID: string, policyTagListName: {oldName: stri API.write(WRITE_COMMANDS.RENAME_POLICY_TAG_LIST, parameters, onyxData); } -function setPolicyRequiresTag(policyID: string, requiresTag: boolean, tagListIndex: number) { +function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIndex: number) { + const policyTag = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[tagListIndex] ?? {}; + const onyxData: OnyxData = { optimisticData: [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { - requiresTag, - errors: {requiresTag: null}, - pendingFields: { - requiresTag: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + [policyTag.name]: { + required: requiresTag, + errors: null, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, }, }, }, @@ -549,13 +551,11 @@ function setPolicyRequiresTag(policyID: string, requiresTag: boolean, tagListInd successData: [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { - errors: { - requiresTag: null, - }, - pendingFields: { - requiresTag: null, + [policyTag.name]: { + errors: null, + pendingAction: null, }, }, }, @@ -563,31 +563,29 @@ function setPolicyRequiresTag(policyID: string, requiresTag: boolean, tagListInd failureData: [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { - requiresTag: !requiresTag, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), - pendingFields: { - requiresTag: null, + [policyTag.name]: { + required: policyTag.required, }, }, }, ], }; - const parameters = { + const parameters: SetPolicyTagsRequired = { policyID, tagListIndex, - requiresTag, + requireTagList: requiresTag, }; - API.write(WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG, parameters, onyxData); + API.write(WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED, parameters, onyxData); } export { openPolicyTagsPage, buildOptimisticPolicyRecentlyUsedTags, - setPolicyRequiresTag, + setPolicyTagsRequired, renamePolicyTaglist, enablePolicyTags, createPolicyTag, diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index c021cc49c66..93e0699514a 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -240,7 +240,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { title={translate('common.required')} switchAccessibilityLabel={translate('common.required')} isActive={Boolean(policyTagList?.required)} - onToggle={(on) => Tag.setPolicyRequiresTag(policyID, on, route.params.orderWeight ?? 0)} + onToggle={(on) => Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight ?? 0)} pendingAction={currentPolicyTag.pendingFields?.required} errors={currentPolicyTag.errors} disabled={!Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} From da8ca41c17f6d43dff76df66d8ddb758e583e3be Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 17:06:33 -0500 Subject: [PATCH 10/42] fix: add back the command to make all tags required --- src/libs/actions/Policy/Tag.ts | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 6df6b1660d0..8a49e260c7d 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -531,6 +531,58 @@ function renamePolicyTaglist(policyID: string, policyTagListName: {oldName: stri API.write(WRITE_COMMANDS.RENAME_POLICY_TAG_LIST, 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(WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG, parameters, onyxData); +} + function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIndex: number) { const policyTag = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[tagListIndex] ?? {}; @@ -585,6 +637,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn export { openPolicyTagsPage, buildOptimisticPolicyRecentlyUsedTags, + setPolicyRequiresTag, setPolicyTagsRequired, renamePolicyTaglist, enablePolicyTags, From ec97f633704026764af6c8cedaa0d7d478543717 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 17:13:46 -0500 Subject: [PATCH 11/42] chore: add back the API param type --- src/libs/API/parameters/SetPolicyRequiresTag.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/libs/API/parameters/SetPolicyRequiresTag.ts diff --git a/src/libs/API/parameters/SetPolicyRequiresTag.ts b/src/libs/API/parameters/SetPolicyRequiresTag.ts new file mode 100644 index 00000000000..b8c2e71e7e3 --- /dev/null +++ b/src/libs/API/parameters/SetPolicyRequiresTag.ts @@ -0,0 +1,6 @@ +type SetPolicyRequiresTag = { + policyID: string; + requiresTag: boolean; +}; + +export default SetPolicyRequiresTag; From 18e3d274871fb3852a8eccfd99d0b27391a117bb Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 17:16:01 -0500 Subject: [PATCH 12/42] chore: add back the API command --- src/libs/API/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 53917dc633b..fa1b4d3f568 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -134,6 +134,7 @@ const WRITE_COMMANDS = { SET_WORKSPACE_REQUIRES_CATEGORY: 'SetWorkspaceRequiresCategory', DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories', SET_POLICY_TAGS_REQUIRED: 'SetPolicyTagsRequired', + SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag', RENAME_POLICY_TAG_LIST: 'RenamePolicyTaglist', DELETE_POLICY_TAGS: 'DeletePolicyTags', CREATE_TASK: 'CreateTask', @@ -338,6 +339,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY]: Parameters.RenameWorkspaceCategoriesParams; [WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams; [WRITE_COMMANDS.DELETE_WORKSPACE_CATEGORIES]: Parameters.DeleteWorkspaceCategoriesParams; + [WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag; [WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED]: Parameters.SetPolicyTagsRequired; [WRITE_COMMANDS.RENAME_POLICY_TAG_LIST]: Parameters.RenamePolicyTaglist; [WRITE_COMMANDS.CREATE_POLICY_TAG]: Parameters.CreatePolicyTagsParams; From ffd3507cda3aec5fb3e4972b9e6426156c6af019 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 17:16:50 -0500 Subject: [PATCH 13/42] chore: export the parameter type --- src/libs/API/parameters/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 8ef37b8fc36..af703694e21 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -171,6 +171,7 @@ export type {default as SetWorkspaceAutoReportingMonthlyOffsetParams} from './Se export type {default as SetWorkspaceApprovalModeParams} from './SetWorkspaceApprovalModeParams'; export type {default as SetWorkspacePayerParams} from './SetWorkspacePayerParams'; export type {default as SetWorkspaceReimbursementParams} from './SetWorkspaceReimbursementParams'; +export type {default as SetPolicyRequiresTag} from './SetPolicyRequiresTag'; export type {default as SetPolicyTagsRequired} from './SetPolicyTagsRequired'; export type {default as RenamePolicyTaglist} from './RenamePolicyTaglist'; export type {default as SwitchToOldDotParams} from './SwitchToOldDotParams'; From 21c49fe92b29f81ba5d3a20a9063a68e30e66cd4 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 17:17:07 -0500 Subject: [PATCH 14/42] fix: add back the old API call --- src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx index cc0fb918b46..15e9e605e8d 100644 --- a/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx @@ -36,9 +36,9 @@ function WorkspaceTagsSettingsPage({route, policyTags}: WorkspaceTagsSettingsPag const hasEnabledOptions = OptionsListUtils.hasEnabledOptions(Object.values(policyTags ?? {}).flatMap(({tags}) => Object.values(tags))); const updateWorkspaceRequiresTag = useCallback( (value: boolean) => { - Tag.setPolicyRequiresTag(route.params.policyID, value, policyTagLists[0].orderWeight); + Tag.setPolicyRequiresTag(route.params.policyID, value); }, - [route.params.policyID, policyTagLists], + [route.params.policyID], ); return ( From b477d14f6df180c21c40d91fa2809a13e346da0e Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 17:20:55 -0500 Subject: [PATCH 15/42] fix: remove extra parameters --- tests/actions/PolicyTagTest.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/actions/PolicyTagTest.ts b/tests/actions/PolicyTagTest.ts index aaa92bf9924..ad473633d87 100644 --- a/tests/actions/PolicyTagTest.ts +++ b/tests/actions/PolicyTagTest.ts @@ -34,7 +34,7 @@ describe('actions/Policy', () => { return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) .then(() => { - Tag.setPolicyRequiresTag(fakePolicy.id, true, 0); + Tag.setPolicyRequiresTag(fakePolicy.id, true); return waitForBatchedUpdates(); }) .then( @@ -81,7 +81,7 @@ describe('actions/Policy', () => { return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) .then(() => { - Tag.setPolicyRequiresTag(fakePolicy.id, false, 0); + Tag.setPolicyRequiresTag(fakePolicy.id, false); return waitForBatchedUpdates(); }) .then( @@ -129,7 +129,7 @@ describe('actions/Policy', () => { return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) .then(() => { mockFetch?.fail?.(); - Tag.setPolicyRequiresTag(fakePolicy.id, false, 0); + Tag.setPolicyRequiresTag(fakePolicy.id, false); return waitForBatchedUpdates(); }) From 3a450df850f8c04aea29d488b3ac400a337c0136 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Sun, 2 Jun 2024 23:18:23 -0500 Subject: [PATCH 16/42] fix: remove null --- src/libs/actions/Policy/Tag.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 8a49e260c7d..e02824a0324 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -594,7 +594,6 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn value: { [policyTag.name]: { required: requiresTag, - errors: null, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, }, }, From 276f6e3ccab9b61184923c4c8688b4f537c4e701 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Mon, 3 Jun 2024 13:04:00 -0500 Subject: [PATCH 17/42] fix: errors null location --- src/libs/actions/Policy/Tag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index e02824a0324..55f5a2a369c 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -595,6 +595,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn [policyTag.name]: { required: requiresTag, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + errors: null, }, }, }, @@ -605,7 +606,6 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { [policyTag.name]: { - errors: null, pendingAction: null, }, }, From 53a95143bf6e9977ff21a6958ee6de116e3c8e66 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Mon, 3 Jun 2024 13:07:15 -0500 Subject: [PATCH 18/42] chore: remove redundant variable --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 93e0699514a..dadb2c1ab67 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -66,10 +66,9 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { setSelectedTags({}); }, [isFocused]); - const policyTagList = useMemo(() => PolicyUtils.getTagLists(policyTags).find((policyTag) => policyTag.name === currentTagListName), [currentTagListName, policyTags]); const tagList = useMemo( () => - Object.values(policyTagList?.tags ?? {}) + Object.values(currentPolicyTag?.tags ?? {}) .sort((tagA, tagB) => localeCompare(tagA.name, tagB.name)) .map((tag) => ({ value: tag.name, @@ -82,7 +81,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { isDisabled: tag.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, rightElement: , })), - [policyTagList, selectedTags, translate], + [currentPolicyTag, selectedTags, translate], ); const tagListKeyedByName = useMemo( @@ -239,7 +238,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight ?? 0)} pendingAction={currentPolicyTag.pendingFields?.required} errors={currentPolicyTag.errors} From abcfc1e1eef4a3744abaea71695bf34837beec35 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Mon, 3 Jun 2024 13:08:49 -0500 Subject: [PATCH 19/42] chore: remove zero --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index dadb2c1ab67..b9488587ac3 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -239,7 +239,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { title={translate('common.required')} switchAccessibilityLabel={translate('common.required')} isActive={Boolean(currentPolicyTag?.required)} - onToggle={(on) => Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight ?? 0)} + onToggle={(on) => Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight)} pendingAction={currentPolicyTag.pendingFields?.required} errors={currentPolicyTag.errors} disabled={!Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} From 8b777f11221410ff117cb8e43137f09213ab4024 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Mon, 3 Jun 2024 13:10:20 -0500 Subject: [PATCH 20/42] chore: use pendingFields --- src/libs/actions/Policy/Tag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 55f5a2a369c..d3f0ca3127f 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -594,7 +594,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn value: { [policyTag.name]: { required: requiresTag, - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + pendingFields: {required: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}, errors: null, }, }, From e2e37f255558f369708a5cb7cef3c91259a17b6f Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Mon, 3 Jun 2024 13:12:54 -0500 Subject: [PATCH 21/42] chore: remove a const that is not used --- src/CONST.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index d2b5302bed8..de4e3305edd 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1665,9 +1665,6 @@ const CONST = { // Often referred to as "collect" workspaces TEAM: 'team', }, - TAG: { - REQUIRED: 'required', - }, ROLE: { ADMIN: 'admin', AUDITOR: 'auditor', From 55cd7bbaf2c050dc162997afefafd876a7dc968d Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Mon, 3 Jun 2024 13:23:07 -0500 Subject: [PATCH 22/42] don't lock required switch when the switch is on --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index b9488587ac3..79360f3b408 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -242,7 +242,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { onToggle={(on) => Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight)} pendingAction={currentPolicyTag.pendingFields?.required} errors={currentPolicyTag.errors} - disabled={!Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} + disabled={!currentPolicyTag?.required && !Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} /> Date: Mon, 3 Jun 2024 15:36:05 -0500 Subject: [PATCH 23/42] chore: add generic error --- src/libs/actions/Policy/Tag.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index d3f0ca3127f..a343f7fc1a1 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -618,6 +618,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn value: { [policyTag.name]: { required: policyTag.required, + errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), }, }, }, From 7e5a4dbe5182e7f9c046ea313a12ff9630576cf3 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Tue, 4 Jun 2024 19:10:14 -0500 Subject: [PATCH 24/42] chore: add error fields --- src/libs/actions/Policy/Tag.ts | 4 +++- src/types/onyx/PolicyTag.ts | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index a343f7fc1a1..087dd908390 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -618,7 +618,9 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn value: { [policyTag.name]: { required: policyTag.required, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + errorFields: { + required: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + }, }, }, }, diff --git a/src/types/onyx/PolicyTag.ts b/src/types/onyx/PolicyTag.ts index 40bac23dc4f..7afea4324a9 100644 --- a/src/types/onyx/PolicyTag.ts +++ b/src/types/onyx/PolicyTag.ts @@ -37,6 +37,9 @@ type PolicyTagList = Record< /** A list of errors keyed by microtime */ errors?: OnyxCommon.Errors; + + /** Error objects keyed by field name containing errors keyed by microtime */ + errorFields?: OnyxCommon.ErrorFields; }> >; From aa2127adad35e4fc1d80c3861abb21ec48096f09 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 00:08:32 -0500 Subject: [PATCH 25/42] chore: clear pending fields --- src/libs/actions/Policy/Tag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 087dd908390..7cc50449e7e 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -606,7 +606,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { [policyTag.name]: { - pendingAction: null, + pendingFields: null, }, }, }, From cdd4b49111dbbfea1c87cf83945bdd75e4967211 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 00:11:00 -0500 Subject: [PATCH 26/42] fix: clear pending field --- src/libs/actions/Policy/Tag.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 7cc50449e7e..011de8d6ce6 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -161,6 +161,7 @@ function createPolicyTag(policyID: string, tagName: string) { tags: { [newTagName]: { errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), + pendingFields: null, }, }, }, From 144ed2637b8d33adc77b1c7057909f2d82bcf058 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 00:20:18 -0500 Subject: [PATCH 27/42] fix: display error from the error field --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 79360f3b408..c44f39c082d 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -241,7 +241,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { isActive={Boolean(currentPolicyTag?.required)} onToggle={(on) => Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight)} pendingAction={currentPolicyTag.pendingFields?.required} - errors={currentPolicyTag.errors} + errors={currentPolicyTag?.errorFields?.required ?? undefined} disabled={!currentPolicyTag?.required && !Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} /> From fbbca9d81825ca412b821f3d32c784df7cfd350b Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 00:28:32 -0500 Subject: [PATCH 28/42] clear the error --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index c44f39c082d..9f7407d5b34 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -242,6 +242,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { onToggle={(on) => Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight)} pendingAction={currentPolicyTag.pendingFields?.required} errors={currentPolicyTag?.errorFields?.required ?? undefined} + onCloseError={() => Tag.clearPolicyTagErrors(policyID, 'required')} disabled={!currentPolicyTag?.required && !Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} /> From fe47bb733f96fc9e0b1e0912cd2912071eb0fcc6 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 13:38:16 -0700 Subject: [PATCH 29/42] use action instead of fields Co-authored-by: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> --- src/libs/actions/Policy/Tag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 011de8d6ce6..3016f60025c 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -161,7 +161,7 @@ function createPolicyTag(policyID: string, tagName: string) { tags: { [newTagName]: { errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), - pendingFields: null, + pendingAction: null, }, }, }, From 4a5851d8993fc529ba949731b92266002dde71c2 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 13:38:40 -0700 Subject: [PATCH 30/42] clear fields Co-authored-by: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> --- src/libs/actions/Policy/Tag.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 3016f60025c..b669e9c1ef4 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -619,6 +619,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn value: { [policyTag.name]: { required: policyTag.required, + pendingFields: {required: null}, errorFields: { required: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), }, From 1f083ef39db8ce1654fd7c3401e94b08cd6fe0da Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 13:40:26 -0700 Subject: [PATCH 31/42] clear the required field Co-authored-by: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> --- src/libs/actions/Policy/Tag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index b669e9c1ef4..b29c9fbd5d4 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -607,7 +607,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { [policyTag.name]: { - pendingFields: null, + pendingFields: {required: null}, }, }, }, From 9752216e38417a5f7eaf1bcb21246ec1d7411774 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 13:45:01 -0700 Subject: [PATCH 32/42] fix: clear specific error field Co-authored-by: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> --- src/libs/actions/Policy/Tag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index b29c9fbd5d4..ec68b09c257 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -596,7 +596,7 @@ function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIn [policyTag.name]: { required: requiresTag, pendingFields: {required: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}, - errors: null, + errorFields: {required: null}, }, }, }, From 86685bd813777ae13e7bd0d5fbb80a6d96c8133a Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 15:59:24 -0500 Subject: [PATCH 33/42] chore: define a function to clear a field error from policy tag list --- src/libs/actions/Policy/Tag.ts | 11 +++++++++++ src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index ec68b09c257..c5759078f15 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -360,6 +360,16 @@ function clearPolicyTagErrors(policyID: string, tagName: string) { }); } +function clearPolicyTagListError(policyID: string, tagListName: string, errorField: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { + [tagListName]: { + errorFields: { + [errorField]: null, + }, + }, + }); +} + function renamePolicyTag(policyID: string, policyTag: {oldName: string; newName: string}) { const tagListName = Object.keys(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})[0]; const oldTagName = policyTag.oldName; @@ -648,6 +658,7 @@ export { createPolicyTag, renamePolicyTag, clearPolicyTagErrors, + clearPolicyTagListError, deletePolicyTags, setWorkspaceTagEnabled, }; diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 9f7407d5b34..fd8b17a3864 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -276,7 +276,9 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { customListHeader={getCustomListHeader()} shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} - onDismissError={(item) => Tag.clearPolicyTagErrors(policyID, item.value)} + onDismissError={(item) => { + Tag.clearPolicyTagListError(policyID, item.value, 'required'); + }} /> )} From b4422fb62bd679369d72c3b9c7ed9dbdcef237bf Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 16:05:23 -0500 Subject: [PATCH 34/42] refactor: get orderWeight instead of the tag name --- src/libs/actions/Policy/Tag.ts | 6 ++++-- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index c5759078f15..e46dc729db0 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -360,9 +360,11 @@ function clearPolicyTagErrors(policyID: string, tagName: string) { }); } -function clearPolicyTagListError(policyID: string, tagListName: string, errorField: string) { +function clearPolicyTagListError(policyID: string, tagListIndex: number, errorField: string) { + const policyTag = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[tagListIndex] ?? {}; + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { - [tagListName]: { + [policyTag.name]: { errorFields: { [errorField]: null, }, diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index fd8b17a3864..07c4700738c 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -242,7 +242,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { onToggle={(on) => Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight)} pendingAction={currentPolicyTag.pendingFields?.required} errors={currentPolicyTag?.errorFields?.required ?? undefined} - onCloseError={() => Tag.clearPolicyTagErrors(policyID, 'required')} + onCloseError={() => Tag.clearPolicyTagListError(policyID, route.params.orderWeight, 'required')} disabled={!currentPolicyTag?.required && !Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)} /> From 4fc37fb2dd8ade17cec6c68ae1ad86a8059a0c15 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 16:06:15 -0500 Subject: [PATCH 35/42] fix: the function parameter --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 07c4700738c..33350676e27 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -276,8 +276,8 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { customListHeader={getCustomListHeader()} shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} - onDismissError={(item) => { - Tag.clearPolicyTagListError(policyID, item.value, 'required'); + onDismissError={() => { + Tag.clearPolicyTagListError(policyID, route.params.orderWeight, 'required'); }} /> )} From 7229be7c3dc182c972b19886ce76c4b263736850 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Wed, 5 Jun 2024 22:00:08 -0500 Subject: [PATCH 36/42] chore: make clearPolicyTagErrors take tag list index --- src/libs/actions/Policy/Tag.ts | 4 ++-- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index e46dc729db0..27eef648b29 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -330,8 +330,8 @@ function deletePolicyTags(policyID: string, tagsToDelete: string[]) { API.write(WRITE_COMMANDS.DELETE_POLICY_TAGS, parameters, onyxData); } -function clearPolicyTagErrors(policyID: string, tagName: string) { - const tagListName = Object.keys(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})[0]; +function clearPolicyTagErrors(policyID: string, tagName: string, tagListIndex: number) { + const tagListName = Object.keys(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})[tagListIndex]; const tag = allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`]?.[tagListName].tags?.[tagName]; if (!tag) { return; diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 33350676e27..878d6c2130a 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -276,8 +276,8 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { customListHeader={getCustomListHeader()} shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} - onDismissError={() => { - Tag.clearPolicyTagListError(policyID, route.params.orderWeight, 'required'); + onDismissError={(item) => { + Tag.clearPolicyTagErrors(policyID, item.value, item.orderWeight ?? 0); }} /> )} From 70f7c6bfd3a4b8c16450dc3ae0126f8f20d68222 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Thu, 6 Jun 2024 08:06:38 -0700 Subject: [PATCH 37/42] fix: use orderWeight from route params Co-authored-by: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 878d6c2130a..fbe695c7ec2 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -277,7 +277,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} onDismissError={(item) => { - Tag.clearPolicyTagErrors(policyID, item.value, item.orderWeight ?? 0); + Tag.clearPolicyTagErrors(policyID, item.value, route.params.orderWeight); }} /> )} From 1ca0837a84f7c67137abedf4fc1d901194de6714 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Thu, 6 Jun 2024 11:27:39 -0500 Subject: [PATCH 38/42] chore: pass missing argument to the clear error function --- src/pages/workspace/tags/TagSettingsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/TagSettingsPage.tsx b/src/pages/workspace/tags/TagSettingsPage.tsx index a4f6940814d..bfe6246faf6 100644 --- a/src/pages/workspace/tags/TagSettingsPage.tsx +++ b/src/pages/workspace/tags/TagSettingsPage.tsx @@ -118,7 +118,7 @@ function TagSettingsPage({route, policyTags, navigation}: TagSettingsPageProps) errors={ErrorUtils.getLatestErrorMessageField(currentPolicyTag)} pendingAction={currentPolicyTag.pendingFields?.enabled} errorRowStyles={styles.mh5} - onClose={() => Tag.clearPolicyTagErrors(route.params.policyID, route.params.tagName)} + onClose={() => Tag.clearPolicyTagErrors(route.params.policyID, route.params.tagName, route.params.orderWeight)} > From 83bca4b9901eafe8773273c511eea3aa31efc5dc Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Thu, 6 Jun 2024 13:49:02 -0500 Subject: [PATCH 39/42] fix: pass the missing argument to the function to clear the error --- src/pages/workspace/tags/WorkspaceTagsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index f70e6b9ba5a..2bd1d67e031 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -350,7 +350,7 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { customListHeader={getCustomListHeader()} shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} - onDismissError={(item) => Tag.clearPolicyTagErrors(policyID, item.value)} + onDismissError={(item) => Tag.clearPolicyTagErrors(policyID, item.value, item.orderWeight ?? 0)} listHeaderContent={isSmallScreenWidth ? getHeaderText() : null} showScrollIndicator={false} /> From cdd4365571dd060421d82aba3b518bfe718f5fdd Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Fri, 7 Jun 2024 08:50:10 -0700 Subject: [PATCH 40/42] only clear policy tag error when the items renders are policy tags Co-authored-by: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> --- src/pages/workspace/tags/WorkspaceTagsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index ab08bb53d86..35c4dfa19e2 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -350,7 +350,7 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { customListHeader={getCustomListHeader()} shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} - onDismissError={(item) => Tag.clearPolicyTagErrors(policyID, item.value, item.orderWeight ?? 0)} + onDismissError={(item) => !isMultiLevelTags && Tag.clearPolicyTagErrors(policyID, item.value, 0)} listHeaderContent={isSmallScreenWidth ? getHeaderText() : null} showScrollIndicator={false} /> From 050471f53217d764ea776fb95b0372cca5421e65 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Fri, 7 Jun 2024 11:21:59 -0500 Subject: [PATCH 41/42] fix: lint issue --- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index fbe695c7ec2..0678b334471 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -238,7 +238,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight)} pendingAction={currentPolicyTag.pendingFields?.required} errors={currentPolicyTag?.errorFields?.required ?? undefined} From bef9b951315524cbaf3fec678d9637c949416772 Mon Sep 17 00:00:00 2001 From: Hayata Suenaga Date: Fri, 7 Jun 2024 19:43:53 -0500 Subject: [PATCH 42/42] return of policy tag name is undefined --- src/libs/actions/Policy/Tag.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 4410c644064..a8607ca8f5f 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -363,6 +363,10 @@ function clearPolicyTagErrors(policyID: string, tagName: string, tagListIndex: n function clearPolicyTagListError(policyID: string, tagListIndex: number, errorField: string) { const policyTag = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[tagListIndex] ?? {}; + if (!policyTag.name) { + return; + } + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { [policyTag.name]: { errorFields: { @@ -626,6 +630,10 @@ function setPolicyRequiresTag(policyID: string, requiresTag: boolean) { function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIndex: number) { const policyTag = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[tagListIndex] ?? {}; + if (!policyTag.name) { + return; + } + const onyxData: OnyxData = { optimisticData: [ {