From 4a2ce600efa86ed7e312c944d8108ff0d4353a36 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 17 Oct 2024 16:24:42 +0700 Subject: [PATCH 1/4] fix: in offline approver selected is not greyed out --- src/libs/WorkflowUtils.ts | 7 +++ .../approvals/ApprovalWorkflowEditor.tsx | 52 +++++++++++++------ src/types/onyx/ApprovalWorkflow.ts | 7 ++- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts index 67655e0f472b..fccda6bb3629 100644 --- a/src/libs/WorkflowUtils.ts +++ b/src/libs/WorkflowUtils.ts @@ -125,6 +125,7 @@ function convertPolicyEmployeesToApprovalWorkflows({employees, defaultApprover, email, avatar: personalDetailsByEmail[email]?.avatar, displayName: personalDetailsByEmail[email]?.displayName ?? email, + pendingFields: personalDetailsByEmail[email]?.pendingFields, }; if (!approvalWorkflows[submitsTo]) { @@ -234,6 +235,9 @@ function convertApprovalWorkflowToPolicyEmployees({ email: approver.email, forwardsTo, pendingAction, + pendingFields: { + forwardsTo: pendingAction, + }, }; }); @@ -250,6 +254,9 @@ function convertApprovalWorkflowToPolicyEmployees({ ...(updatedEmployeeList[email] ? updatedEmployeeList[email] : {email}), submitsTo, pendingAction, + pendingFields: { + submitsTo: pendingAction, + }, }; }); diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx index 2b7abca0f3b3..4ebd61929504 100644 --- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx +++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx @@ -7,6 +7,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItem from '@components/MenuItem'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; @@ -18,6 +19,7 @@ import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {ApprovalWorkflowOnyx, Policy} from '@src/types/onyx'; import type {Approver} from '@src/types/onyx/ApprovalWorkflow'; +import type {PendingAction} from '@src/types/onyx/OnyxCommon'; type ApprovalWorkflowEditorProps = { /** The approval workflow to display */ @@ -43,6 +45,22 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic [approverCount, toLocaleOrdinal, translate], ); + const getApprovalPendingAction = useCallback( + (index: number) => { + let pendingAction: PendingAction | undefined; + if (index === 0) { + approvalWorkflow?.members?.forEach((member) => { + pendingAction = pendingAction ?? member.pendingFields?.submitsTo; + }); + return pendingAction; + } + const previousApprover = approvalWorkflow?.approvers.at(index - 1); + const previousMember = approvalWorkflow?.members?.find((member) => member?.email === previousApprover?.email); + return previousMember?.pendingFields?.forwardsTo; + }, + [approvalWorkflow], + ); + const members = useMemo(() => { if (approvalWorkflow.isDefault) { return translate('workspace.common.everyone'); @@ -134,22 +152,24 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic : undefined; return ( - editApprover(approverIndex)} - shouldShowRightIcon - hintText={hintText} - shouldRenderHintAsHTML - brickRoadIndicator={errorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - errorText={errorText} - shouldRenderErrorAsHTML - /> + + editApprover(approverIndex)} + shouldShowRightIcon + hintText={hintText} + shouldRenderHintAsHTML + brickRoadIndicator={errorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + errorText={errorText} + shouldRenderErrorAsHTML + /> + ); })} diff --git a/src/types/onyx/ApprovalWorkflow.ts b/src/types/onyx/ApprovalWorkflow.ts index 7b643ce12883..bafb1c78a8de 100644 --- a/src/types/onyx/ApprovalWorkflow.ts +++ b/src/types/onyx/ApprovalWorkflow.ts @@ -2,7 +2,7 @@ import type {ValueOf} from 'type-fest'; import type {AvatarSource} from '@libs/UserUtils'; import type CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; -import type {OnyxValueWithOfflineFeedback} from './OnyxCommon'; +import type {OnyxValueWithOfflineFeedback, PendingFields} from './OnyxCommon'; /** * Approver in the approval workflow @@ -55,6 +55,11 @@ type Member = { * Avatar URL of the current user from their personal details */ avatar?: AvatarSource; + + /** + * Pending states for offline updates + */ + pendingFields?: PendingFields<'submitsTo' | 'forwardsTo'>; }; /** From d2653c6c32949912aa4e22b2b46040fee4f23935 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 21 Oct 2024 10:32:34 +0700 Subject: [PATCH 2/4] fix lint --- src/libs/WorkflowUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts index fccda6bb3629..3a43c0bc4eca 100644 --- a/src/libs/WorkflowUtils.ts +++ b/src/libs/WorkflowUtils.ts @@ -125,7 +125,7 @@ function convertPolicyEmployeesToApprovalWorkflows({employees, defaultApprover, email, avatar: personalDetailsByEmail[email]?.avatar, displayName: personalDetailsByEmail[email]?.displayName ?? email, - pendingFields: personalDetailsByEmail[email]?.pendingFields, + pendingFields: employee.pendingFields, }; if (!approvalWorkflows[submitsTo]) { From 34b97b8e6484cdb33925a01fe08c56efa67b74cb Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 21 Oct 2024 11:23:34 +0700 Subject: [PATCH 3/4] fix: reset pendingFields --- src/libs/actions/Workflow.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts index de3824386536..7da3807f6bd3 100644 --- a/src/libs/actions/Workflow.ts +++ b/src/libs/actions/Workflow.ts @@ -182,7 +182,7 @@ function updateApprovalWorkflow(policyID: string, approvalWorkflow: ApprovalWork onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - employeeList: Object.fromEntries(Object.keys(updatedEmployees).map((key) => [key, {pendingAction: null}])), + employeeList: Object.fromEntries(Object.keys(updatedEmployees).map((key) => [key, {pendingAction: null, pendingFields: null}])), }, }, ]; From 3f8fe77d52b2470fe80f536cec2e9290b2887f47 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 23 Oct 2024 14:32:31 +0700 Subject: [PATCH 4/4] fix unit test --- tests/unit/WorkflowUtilsTest.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/unit/WorkflowUtilsTest.ts b/tests/unit/WorkflowUtilsTest.ts index 1e4638fb915f..effc35f2609d 100644 --- a/tests/unit/WorkflowUtilsTest.ts +++ b/tests/unit/WorkflowUtilsTest.ts @@ -397,8 +397,8 @@ describe('WorkflowUtils', () => { const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'create'}); expect(convertedEmployees).toEqual({ - '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', submitsTo: '1@example.com'}), - '2@example.com': buildPolicyEmployee(2, {submitsTo: '1@example.com'}), + '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}), + '2@example.com': buildPolicyEmployee(2, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}), }); }); @@ -412,12 +412,12 @@ describe('WorkflowUtils', () => { const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'create'}); expect(convertedEmployees).toEqual({ - '1@example.com': buildPolicyEmployee(1, {forwardsTo: '2@example.com'}), - '2@example.com': buildPolicyEmployee(2, {forwardsTo: '3@example.com'}), - '3@example.com': buildPolicyEmployee(3, {forwardsTo: ''}), - '4@example.com': buildPolicyEmployee(4, {submitsTo: '1@example.com'}), - '5@example.com': buildPolicyEmployee(5, {submitsTo: '1@example.com'}), - '6@example.com': buildPolicyEmployee(6, {submitsTo: '1@example.com'}), + '1@example.com': buildPolicyEmployee(1, {forwardsTo: '2@example.com', pendingFields: {forwardsTo: 'add'}}), + '2@example.com': buildPolicyEmployee(2, {forwardsTo: '3@example.com', pendingFields: {forwardsTo: 'add'}}), + '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', pendingFields: {forwardsTo: 'add'}}), + '4@example.com': buildPolicyEmployee(4, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}), + '5@example.com': buildPolicyEmployee(5, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}), + '6@example.com': buildPolicyEmployee(6, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}), }); }); @@ -431,12 +431,12 @@ describe('WorkflowUtils', () => { const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'remove'}); expect(convertedEmployees).toEqual({ - '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', pendingAction: 'update'}), - '2@example.com': buildPolicyEmployee(2, {forwardsTo: '', pendingAction: 'update'}), - '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', pendingAction: 'update'}), - '4@example.com': buildPolicyEmployee(4, {submitsTo: '', pendingAction: 'update'}), - '5@example.com': buildPolicyEmployee(5, {submitsTo: '', pendingAction: 'update'}), - '6@example.com': buildPolicyEmployee(6, {submitsTo: '', pendingAction: 'update'}), + '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}), + '2@example.com': buildPolicyEmployee(2, {forwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}), + '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}), + '4@example.com': buildPolicyEmployee(4, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}), + '5@example.com': buildPolicyEmployee(5, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}), + '6@example.com': buildPolicyEmployee(6, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}), }); }); });