From 948e1f7f0724a6789f2d59e6fff7d4be0692454d Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 10 Jul 2024 15:25:44 +0200 Subject: [PATCH 01/17] fix hold/unhold logic --- src/libs/ReportUtils.ts | 5 +++-- src/pages/ReportDetailsPage.tsx | 17 +++++++++++------ .../report/ContextMenu/ContextMenuActions.tsx | 6 ++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index fb3bebd75274..e8d5697de64b 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2823,12 +2823,13 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const isApprover = isMoneyRequestReport(moneyRequestReport) && moneyRequestReport?.managerID !== null && currentUserPersonalDetails?.accountID === moneyRequestReport?.managerID; const isOnHold = TransactionUtils.isOnHold(transaction); const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction); + const isClosed = isClosedReport(moneyRequestReport); const canModifyStatus = !isTrackExpenseMoneyReport && (isPolicyAdmin || isActionOwner || isApprover); const isDeletedParentAction = isEmptyObject(parentReportAction) || ReportActionsUtils.isDeletedAction(parentReportAction); - const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction; - const canHoldRequest = canHoldOrUnholdRequest && !isOnHold && (isRequestHoldCreator || (!isRequestIOU && canModifyStatus)) && !isScanning && !!transaction?.reimbursable; + const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction && !isClosed; + const canHoldRequest = canHoldOrUnholdRequest && !isOnHold && (isRequestIOU || canModifyStatus) && !isScanning && !!transaction?.reimbursable; const canUnholdRequest = !!(canHoldOrUnholdRequest && isOnHold && (isRequestHoldCreator || (!isRequestIOU && canModifyStatus))) && !!transaction?.reimbursable; return {canHoldRequest, canUnholdRequest}; diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index a585f9c94d67..6726e5d36540 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -171,7 +171,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD // 2. MoneyReport case if (caseID === CASES.MONEY_REPORT) { if (!reportActions || !transactionThreadReport?.parentReportActionID) { - return null; + return undefined; } return reportActions.find((action) => action.reportActionID === transactionThreadReport.parentReportActionID); } @@ -512,9 +512,14 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD ? ReportActionsUtils.getOriginalMessage(requestParentReportAction)?.IOUTransactionID ?? '' : ''; - const canHoldUnholdReportAction = ReportUtils.canHoldUnholdReportAction(parentReportAction); - const shouldShowHoldAction = - caseID !== CASES.MONEY_REPORT && (canHoldUnholdReportAction.canHoldRequest || canHoldUnholdReportAction.canUnholdRequest) && !ReportUtils.isArchivedRoom(parentReport); + let holdReportAction: OnyxTypes.ReportAction | undefined; + if (caseID == CASES.MONEY_REQUEST) { + holdReportAction = parentReportAction; + } else if (caseID == CASES.MONEY_REPORT) { + holdReportAction = requestParentReportAction; + } + const canHoldUnholdReportAction = ReportUtils.canHoldUnholdReportAction(holdReportAction); + const shouldShowHoldAction = (canHoldUnholdReportAction.canHoldRequest || canHoldUnholdReportAction.canUnholdRequest) && !ReportUtils.isArchivedRoom(parentReport); const canJoin = ReportUtils.canJoinChat(report, parentReportAction, policy); @@ -526,7 +531,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD } if (isExpenseReport && shouldShowHoldAction) { - result.push(PromotedActions.hold({isTextHold: canHoldUnholdReportAction.canHoldRequest, reportAction: parentReportAction})); + result.push(PromotedActions.hold({isTextHold: canHoldUnholdReportAction.canHoldRequest, reportAction: holdReportAction})); } if (report) { @@ -536,7 +541,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD result.push(PromotedActions.share(report)); return result; - }, [report, parentReportAction, canJoin, isExpenseReport, shouldShowHoldAction, canHoldUnholdReportAction.canHoldRequest]); + }, [report, holdReportAction, canJoin, isExpenseReport, shouldShowHoldAction, canHoldUnholdReportAction.canHoldRequest]); const nameSectionExpenseIOU = ( diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index 218c382fd776..42bd26ac6dbd 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -260,8 +260,7 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.unholdExpense', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction) => - type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canEditReportAction(reportAction) && ReportUtils.canHoldUnholdReportAction(reportAction).canUnholdRequest, + shouldShow: (type, reportAction) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(reportAction).canUnholdRequest, onPress: (closePopover, {reportAction}) => { if (closePopover) { hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction)); @@ -277,8 +276,7 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.hold', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction) => - type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canEditReportAction(reportAction) && ReportUtils.canHoldUnholdReportAction(reportAction).canHoldRequest, + shouldShow: (type, reportAction) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(reportAction).canHoldRequest, onPress: (closePopover, {reportAction}) => { if (closePopover) { hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction)); From e43ffe0e7617aaa49566c647d4026e9f0e6ffbf2 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Thu, 11 Jul 2024 10:51:34 +0200 Subject: [PATCH 02/17] fix lint errors --- src/pages/ReportDetailsPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 6726e5d36540..d324800baa7f 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -513,9 +513,9 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD : ''; let holdReportAction: OnyxTypes.ReportAction | undefined; - if (caseID == CASES.MONEY_REQUEST) { + if (caseID === CASES.MONEY_REQUEST) { holdReportAction = parentReportAction; - } else if (caseID == CASES.MONEY_REPORT) { + } else if (caseID === CASES.MONEY_REPORT) { holdReportAction = requestParentReportAction; } const canHoldUnholdReportAction = ReportUtils.canHoldUnholdReportAction(holdReportAction); From 1384fe1b59316c3e61d401f10da26969180c247d Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:07:12 +0200 Subject: [PATCH 03/17] fix isPolicyAdmin not being properly implemented in ReportUtils check --- src/libs/ReportUtils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e8d5697de64b..35a008cdeb45 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2821,11 +2821,12 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) typeof currentUserPersonalDetails?.accountID === 'number' && parentReportAction.actorAccountID === currentUserPersonalDetails?.accountID; const isApprover = isMoneyRequestReport(moneyRequestReport) && moneyRequestReport?.managerID !== null && currentUserPersonalDetails?.accountID === moneyRequestReport?.managerID; + const isAdmin = isPolicyAdmin(moneyRequestReport.policyID ?? '-1', allPolicies); const isOnHold = TransactionUtils.isOnHold(transaction); const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction); const isClosed = isClosedReport(moneyRequestReport); - const canModifyStatus = !isTrackExpenseMoneyReport && (isPolicyAdmin || isActionOwner || isApprover); + const canModifyStatus = !isTrackExpenseMoneyReport && (isAdmin || isActionOwner || isApprover); const isDeletedParentAction = isEmptyObject(parentReportAction) || ReportActionsUtils.isDeletedAction(parentReportAction); const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction && !isClosed; From ade4976c6cb38c724ea228e0d78728fda3f09700 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:13:53 +0200 Subject: [PATCH 04/17] fix prettier --- src/libs/ReportUtils.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f92cfadb229e..914c4a2082bf 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2829,7 +2829,9 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction && !isClosed; const canHoldRequest = canHoldOrUnholdRequest && !isOnHold && (isRequestIOU || canModifyStatus) && !isScanning && !!transaction?.reimbursable; - const canUnholdRequest = !!(canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && (isRequestHoldCreator || (!isRequestIOU && canModifyStatus))) && !!transaction?.reimbursable; + const canUnholdRequest = + !!(canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && (isRequestHoldCreator || (!isRequestIOU && canModifyStatus))) && + !!transaction?.reimbursable; return {canHoldRequest, canUnholdRequest}; } From c8dce56a27ca755c0b8d41b94020aaa6a1da61e7 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:25:24 +0200 Subject: [PATCH 05/17] fix lint errors after merge --- src/pages/ReportDetailsPage.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 6dc207cf743c..cea6358fe7cb 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -183,8 +183,6 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD return report; }, [caseID, parentReport, report]); - const moneyRequestAction = transactionThreadReportID ? requestParentReportAction : parentReportAction; - const canModifyTask = Task.canModifyTask(report, session?.accountID ?? -1); const shouldShowTaskDeleteButton = isTaskReport && @@ -525,8 +523,9 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD } else if (caseID === CASES.MONEY_REPORT) { holdReportAction = requestParentReportAction; } + const canHoldUnholdReportAction = ReportUtils.canHoldUnholdReportAction(holdReportAction); - const shouldShowHoldAction = (canHoldUnholdReportAction.canHoldRequest || canHoldUnholdReportAction.canUnholdRequest) && !ReportUtils.isArchivedRoom(parentReport); + const shouldShowHoldAction = (canHoldUnholdReportAction.canHoldRequest || canHoldUnholdReportAction.canUnholdRequest) && !ReportUtils.isArchivedRoom(transactionThreadReportID ? report : parentReport, parentReportNameValuePairs); const canJoin = ReportUtils.canJoinChat(report, parentReportAction, policy); From c4289b496243c65c9cceff7795c75433927e75e3 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:26:30 +0200 Subject: [PATCH 06/17] clean up code --- src/pages/ReportDetailsPage.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index cea6358fe7cb..73a2011c3d12 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -525,7 +525,9 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD } const canHoldUnholdReportAction = ReportUtils.canHoldUnholdReportAction(holdReportAction); - const shouldShowHoldAction = (canHoldUnholdReportAction.canHoldRequest || canHoldUnholdReportAction.canUnholdRequest) && !ReportUtils.isArchivedRoom(transactionThreadReportID ? report : parentReport, parentReportNameValuePairs); + const shouldShowHoldAction = + (canHoldUnholdReportAction.canHoldRequest || canHoldUnholdReportAction.canUnholdRequest) && + !ReportUtils.isArchivedRoom(transactionThreadReportID ? report : parentReport, parentReportNameValuePairs); const canJoin = ReportUtils.canJoinChat(report, parentReportAction, policy); From 1259a4a7a59a7afadc9c31c51202438760908821 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:11:37 +0200 Subject: [PATCH 07/17] correct logic for hold/unhold for ContextMenu action --- .../BaseReportActionContextMenu.tsx | 42 ++++++++++++++++++- .../report/ContextMenu/ContextMenuActions.tsx | 18 ++++---- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index 5ab38cbf2e7e..d4a1e3b2b9c6 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -5,7 +5,7 @@ import {InteractionManager, View} from 'react-native'; // eslint-disable-next-line no-restricted-imports import type {GestureResponderEvent, Text as RNText, View as ViewType} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx, withOnyx} from 'react-native-onyx'; import type {ContextMenuItemHandle} from '@components/ContextMenuItem'; import ContextMenuItem from '@components/ContextMenuItem'; import FocusTrapForModal from '@components/FocusTrap/FocusTrapForModal'; @@ -14,6 +14,7 @@ import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; +import usePaginatedReportActions from '@hooks/usePaginatedReportActions'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -135,13 +136,49 @@ function BaseReportActionContextMenu({ return reportActions[reportActionID]; }, [reportActions, reportActionID]); + const childReport = ReportUtils.getReport(reportAction?.childReportID ?? '-1'); + const parentReportAction = ReportActionsUtils.getReportAction(childReport?.parentReportID ?? '', childReport?.parentReportActionID ?? ''); + + const {reportActions: reportActionsPaginated} = usePaginatedReportActions(childReport?.reportID ?? '-1'); + + const transactionThreadReportID = useMemo( + () => ReportActionsUtils.getOneTransactionThreadReportID(childReport?.reportID ?? '-1', reportActionsPaginated ?? [], isOffline), + [childReport?.reportID, reportActionsPaginated, isOffline], + ); + + const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`); + + const isMoneyRequestReport = useMemo(() => ReportUtils.isMoneyRequestReport(childReport), [childReport]); + const isInvoiceReport = useMemo(() => ReportUtils.isInvoiceReport(childReport), [childReport]); + + const requestParentReportAction = useMemo(() => { + if (isMoneyRequestReport || isInvoiceReport) { + if (!reportActionsPaginated || !transactionThreadReport?.parentReportActionID) { + return undefined; + } + return reportActionsPaginated.find((action) => action.reportActionID === transactionThreadReport.parentReportActionID); + } + return parentReportAction; + }, [parentReportAction, reportActionsPaginated, transactionThreadReport?.parentReportActionID, isMoneyRequestReport, isInvoiceReport]); + + const isMoneyRequest = useMemo(() => ReportUtils.isMoneyRequest(childReport), [childReport]); + const isTrackExpenseReport = ReportUtils.isTrackExpenseReport(childReport); + const isSingleTransactionView = isMoneyRequest || isTrackExpenseReport; + + let holdReportAction: ReportAction | undefined; + if (isSingleTransactionView) { + holdReportAction = parentReportAction; + } else if (isMoneyRequestReport || isInvoiceReport) { + holdReportAction = requestParentReportAction; + } + const originalReportID = useMemo(() => ReportUtils.getOriginalReportID(reportID, reportAction), [reportID, reportAction]); const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); let filteredContextMenuActions = ContextMenuActions.filter( (contextAction) => !disabledActions.includes(contextAction) && - contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline, isMini), + contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline, isMini, holdReportAction), ); if (isMini) { @@ -248,6 +285,7 @@ function BaseReportActionContextMenu({ interceptAnonymousUser, openOverflowMenu, setIsEmojiPickerActive, + holdReportAction, }; if ('renderContent' in contextAction) { diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index b5e4d44d7514..708cb3495800 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -66,6 +66,7 @@ type ShouldShow = ( isUnreadChat: boolean, isOffline: boolean, isMini: boolean, + holdReportAction: OnyxEntry | undefined, ) => boolean; type ContextMenuActionPayload = { @@ -83,6 +84,7 @@ type ContextMenuActionPayload = { event?: GestureResponderEvent | MouseEvent | KeyboardEvent; setIsEmojiPickerActive?: (state: boolean) => void; anchorRef?: MutableRefObject; + holdReportAction: OnyxEntry | undefined; }; type OnPress = (closePopover: boolean, payload: ContextMenuActionPayload, selection?: string, reportID?: string, draftMessage?: string) => void; @@ -262,15 +264,15 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.unholdExpense', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(reportAction).canUnholdRequest, - onPress: (closePopover, {reportAction}) => { + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, holdReportAction) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(holdReportAction).canHoldRequest, + onPress: (closePopover, {holdReportAction}) => { if (closePopover) { - hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction)); + hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(holdReportAction)); return; } // No popover to hide, call changeMoneyRequestHoldStatus immediately - ReportUtils.changeMoneyRequestHoldStatus(reportAction); + ReportUtils.changeMoneyRequestHoldStatus(holdReportAction); }, getDescription: () => {}, }, @@ -278,15 +280,15 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.hold', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(reportAction).canHoldRequest, - onPress: (closePopover, {reportAction}) => { + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, holdReportAction) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(holdReportAction).canHoldRequest, + onPress: (closePopover, {holdReportAction}) => { if (closePopover) { - hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction)); + hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(holdReportAction)); return; } // No popover to hide, call changeMoneyRequestHoldStatus immediately - ReportUtils.changeMoneyRequestHoldStatus(reportAction); + ReportUtils.changeMoneyRequestHoldStatus(holdReportAction); }, getDescription: () => {}, }, From dbf242158fb4fdaeec108dcbfc2bfdeef3b43c83 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:12:09 +0200 Subject: [PATCH 08/17] fix prettier --- .../home/report/ContextMenu/BaseReportActionContextMenu.tsx | 2 +- src/pages/home/report/ContextMenu/ContextMenuActions.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index d4a1e3b2b9c6..549d06f85ce2 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -13,8 +13,8 @@ import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import useStyleUtils from '@hooks/useStyleUtils'; import usePaginatedReportActions from '@hooks/usePaginatedReportActions'; +import useStyleUtils from '@hooks/useStyleUtils'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index 708cb3495800..6e7605511424 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -264,7 +264,8 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.unholdExpense', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, holdReportAction) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(holdReportAction).canHoldRequest, + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, holdReportAction) => + type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(holdReportAction).canHoldRequest, onPress: (closePopover, {holdReportAction}) => { if (closePopover) { hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(holdReportAction)); @@ -280,7 +281,8 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.hold', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, holdReportAction) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(holdReportAction).canHoldRequest, + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, holdReportAction) => + type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(holdReportAction).canHoldRequest, onPress: (closePopover, {holdReportAction}) => { if (closePopover) { hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(holdReportAction)); From 7dba3b978fa4364f6a6d7c28bcd6209136c52cd4 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:57:44 +0200 Subject: [PATCH 09/17] refactor code for latest main hold logic changes --- src/pages/ReportDetailsPage.tsx | 2 +- .../BaseReportActionContextMenu.tsx | 17 ++++--------- .../report/ContextMenu/ContextMenuActions.tsx | 24 +++++++++---------- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index c177f33bcf12..669d9fac7ffa 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -828,4 +828,4 @@ export default withReportOrNotFound()( key: ONYXKEYS.SESSION, }, })(ReportDetailsPage), -); \ No newline at end of file +); diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index a7cfb664e97f..44372b11cf32 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -161,17 +161,8 @@ function BaseReportActionContextMenu({ return parentReportAction; }, [parentReportAction, reportActionsPaginated, transactionThreadReport?.parentReportActionID, isMoneyRequestReport, isInvoiceReport]); - const isMoneyRequest = useMemo(() => ReportUtils.isMoneyRequest(childReport), [childReport]); - const isTrackExpenseReport = ReportUtils.isTrackExpenseReport(childReport); - const isSingleTransactionView = isMoneyRequest || isTrackExpenseReport; - - let holdReportAction: ReportAction | undefined; - if (isSingleTransactionView) { - holdReportAction = parentReportAction; - } else if (isMoneyRequestReport || isInvoiceReport) { - holdReportAction = requestParentReportAction; - } - + const moneyRequestAction = transactionThreadReportID ? requestParentReportAction : parentReportAction; + const sourceID = ReportUtils.getSourceIDFromReportAction(reportAction); const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`); @@ -182,7 +173,7 @@ function BaseReportActionContextMenu({ let filteredContextMenuActions = ContextMenuActions.filter( (contextAction) => !disabledActions.includes(contextAction) && - contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline, isMini, holdReportAction), + contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline, isMini, moneyRequestAction), ); if (isMini) { @@ -289,7 +280,7 @@ function BaseReportActionContextMenu({ interceptAnonymousUser, openOverflowMenu, setIsEmojiPickerActive, - holdReportAction, + moneyRequestAction, }; if ('renderContent' in contextAction) { diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index 50c4925e7c45..bf0730df076f 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -66,7 +66,7 @@ type ShouldShow = ( isUnreadChat: boolean, isOffline: boolean, isMini: boolean, - holdReportAction: OnyxEntry | undefined, + moneyRequestAction: ReportAction | undefined, ) => boolean; type ContextMenuActionPayload = { @@ -84,7 +84,7 @@ type ContextMenuActionPayload = { event?: GestureResponderEvent | MouseEvent | KeyboardEvent; setIsEmojiPickerActive?: (state: boolean) => void; anchorRef?: MutableRefObject; - holdReportAction: OnyxEntry | undefined; + moneyRequestAction: ReportAction | undefined; }; type OnPress = (closePopover: boolean, payload: ContextMenuActionPayload, selection?: string, reportID?: string, draftMessage?: string) => void; @@ -265,16 +265,16 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.unholdExpense', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, holdReportAction) => - type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(holdReportAction).canHoldRequest, - onPress: (closePopover, {holdReportAction}) => { + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, moneyRequestAction) => + type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(moneyRequestAction).canHoldRequest, + onPress: (closePopover, {moneyRequestAction}) => { if (closePopover) { - hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(holdReportAction)); + hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction)); return; } // No popover to hide, call changeMoneyRequestHoldStatus immediately - ReportUtils.changeMoneyRequestHoldStatus(holdReportAction); + ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction); }, getDescription: () => {}, }, @@ -282,16 +282,16 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.hold', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, holdReportAction) => - type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(holdReportAction).canHoldRequest, - onPress: (closePopover, {holdReportAction}) => { + shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, moneyRequestAction) => + type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(moneyRequestAction).canHoldRequest, + onPress: (closePopover, {moneyRequestAction}) => { if (closePopover) { - hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(holdReportAction)); + hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction)); return; } // No popover to hide, call changeMoneyRequestHoldStatus immediately - ReportUtils.changeMoneyRequestHoldStatus(holdReportAction); + ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction); }, getDescription: () => {}, }, From 6730a11a1b01dd0ab49e7c8a9727b7cd24ac624d Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 31 Jul 2024 13:58:34 +0200 Subject: [PATCH 10/17] clean up context menu related components --- .../BaseReportActionContextMenu.tsx | 31 +------------------ .../report/ContextMenu/ContextMenuActions.tsx | 22 ++++++------- 2 files changed, 11 insertions(+), 42 deletions(-) diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index 44372b11cf32..7a191d7bff03 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -13,7 +13,6 @@ import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import usePaginatedReportActions from '@hooks/usePaginatedReportActions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -136,33 +135,6 @@ function BaseReportActionContextMenu({ return reportActions[reportActionID]; }, [reportActions, reportActionID]); - const childReport = ReportUtils.getReport(reportAction?.childReportID ?? '-1'); - const parentReportAction = ReportActionsUtils.getReportAction(childReport?.parentReportID ?? '', childReport?.parentReportActionID ?? ''); - - const {reportActions: reportActionsPaginated} = usePaginatedReportActions(childReport?.reportID ?? '-1'); - - const transactionThreadReportID = useMemo( - () => ReportActionsUtils.getOneTransactionThreadReportID(childReport?.reportID ?? '-1', reportActionsPaginated ?? [], isOffline), - [childReport?.reportID, reportActionsPaginated, isOffline], - ); - - const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`); - - const isMoneyRequestReport = useMemo(() => ReportUtils.isMoneyRequestReport(childReport), [childReport]); - const isInvoiceReport = useMemo(() => ReportUtils.isInvoiceReport(childReport), [childReport]); - - const requestParentReportAction = useMemo(() => { - if (isMoneyRequestReport || isInvoiceReport) { - if (!reportActionsPaginated || !transactionThreadReport?.parentReportActionID) { - return undefined; - } - return reportActionsPaginated.find((action) => action.reportActionID === transactionThreadReport.parentReportActionID); - } - return parentReportAction; - }, [parentReportAction, reportActionsPaginated, transactionThreadReport?.parentReportActionID, isMoneyRequestReport, isInvoiceReport]); - - const moneyRequestAction = transactionThreadReportID ? requestParentReportAction : parentReportAction; - const sourceID = ReportUtils.getSourceIDFromReportAction(reportAction); const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`); @@ -173,7 +145,7 @@ function BaseReportActionContextMenu({ let filteredContextMenuActions = ContextMenuActions.filter( (contextAction) => !disabledActions.includes(contextAction) && - contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline, isMini, moneyRequestAction), + contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline, isMini), ); if (isMini) { @@ -280,7 +252,6 @@ function BaseReportActionContextMenu({ interceptAnonymousUser, openOverflowMenu, setIsEmojiPickerActive, - moneyRequestAction, }; if ('renderContent' in contextAction) { diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index bf0730df076f..921ec324fced 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -66,7 +66,6 @@ type ShouldShow = ( isUnreadChat: boolean, isOffline: boolean, isMini: boolean, - moneyRequestAction: ReportAction | undefined, ) => boolean; type ContextMenuActionPayload = { @@ -84,7 +83,6 @@ type ContextMenuActionPayload = { event?: GestureResponderEvent | MouseEvent | KeyboardEvent; setIsEmojiPickerActive?: (state: boolean) => void; anchorRef?: MutableRefObject; - moneyRequestAction: ReportAction | undefined; }; type OnPress = (closePopover: boolean, payload: ContextMenuActionPayload, selection?: string, reportID?: string, draftMessage?: string) => void; @@ -265,16 +263,16 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.unholdExpense', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, moneyRequestAction) => - type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(moneyRequestAction).canHoldRequest, - onPress: (closePopover, {moneyRequestAction}) => { + shouldShow: (type, reportAction) => + type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canEditReportAction(reportAction) && ReportUtils.canHoldUnholdReportAction(reportAction).canUnholdRequest, + onPress: (closePopover, {reportAction}) => { if (closePopover) { - hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction)); + hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction)); return; } // No popover to hide, call changeMoneyRequestHoldStatus immediately - ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction); + ReportUtils.changeMoneyRequestHoldStatus(reportAction); }, getDescription: () => {}, }, @@ -282,16 +280,16 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.hold', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, isOffline, isMini, moneyRequestAction) => - type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canHoldUnholdReportAction(moneyRequestAction).canHoldRequest, - onPress: (closePopover, {moneyRequestAction}) => { + shouldShow: (type, reportAction) => + type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canEditReportAction(reportAction) && ReportUtils.canHoldUnholdReportAction(reportAction).canHoldRequest, + onPress: (closePopover, {reportAction}) => { if (closePopover) { - hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction)); + hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction)); return; } // No popover to hide, call changeMoneyRequestHoldStatus immediately - ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction); + ReportUtils.changeMoneyRequestHoldStatus(reportAction); }, getDescription: () => {}, }, From e5c06b8117c53ea5de346ed2ab346d239cf69d1e Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:41:42 +0200 Subject: [PATCH 11/17] unify logic for when hold action is shown in report details and context menu --- .../BaseReportActionContextMenu.tsx | 58 ++++++++++++++++++- .../report/ContextMenu/ContextMenuActions.tsx | 51 ++++++++++++---- 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index 7a191d7bff03..a3199b4e43eb 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -13,6 +13,7 @@ import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import usePaginatedReportActions from '@hooks/usePaginatedReportActions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -139,13 +140,67 @@ function BaseReportActionContextMenu({ const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`); + // HOLD START + + const childReport = ReportUtils.getReport(reportAction?.childReportID ?? '-1'); + const parentReportAction = ReportActionsUtils.getReportAction(childReport?.parentReportID ?? '', childReport?.parentReportActionID ?? ''); + const {reportActions: paginatedReportActions} = usePaginatedReportActions(childReport?.reportID ?? '-1'); + + const transactionThreadReportID = useMemo( + () => ReportActionsUtils.getOneTransactionThreadReportID(childReport?.reportID ?? '-1', paginatedReportActions ?? [], isOffline), + [childReport?.reportID, paginatedReportActions, isOffline], + ); + + const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`); + + const isMoneyRequestReport = useMemo(() => ReportUtils.isMoneyRequestReport(childReport), [childReport]); + const isInvoiceReport = useMemo(() => ReportUtils.isInvoiceReport(childReport), [childReport]); + + const requestParentReportAction = useMemo(() => { + if (isMoneyRequestReport || isInvoiceReport) { + if (!paginatedReportActions || !transactionThreadReport?.parentReportActionID) { + return undefined; + } + return paginatedReportActions.find((action) => action.reportActionID === transactionThreadReport.parentReportActionID); + } + return parentReportAction; + }, [parentReportAction, isMoneyRequestReport, isInvoiceReport, paginatedReportActions, transactionThreadReport?.parentReportActionID]); + + const moneyRequestAction = transactionThreadReportID ? requestParentReportAction : parentReportAction; + + const [parentReportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${childReport?.parentReportID ?? '-1'}`); + const parentReport = ReportUtils.getReport(childReport?.parentReportID ?? '-1'); + + const isMoneyRequest = useMemo(() => ReportUtils.isMoneyRequest(childReport), [childReport]); + const isTrackExpenseReport = ReportUtils.isTrackExpenseReport(childReport); + const isSingleTransactionView = isMoneyRequest || isTrackExpenseReport; + const isMoneyRequestOrReport = isMoneyRequestReport || isInvoiceReport || isSingleTransactionView; + + const areHoldRequirementsMet = isMoneyRequestOrReport && !ReportUtils.isArchivedRoom(transactionThreadReportID ? childReport : parentReport, parentReportNameValuePairs); + + // HOLD END + const originalReportID = useMemo(() => ReportUtils.getOriginalReportID(reportID, reportAction), [reportID, reportAction]); const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); let filteredContextMenuActions = ContextMenuActions.filter( (contextAction) => !disabledActions.includes(contextAction) && - contextAction.shouldShow(type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID, isPinnedChat, isUnreadChat, !!isOffline, isMini), + contextAction.shouldShow( + type, + reportAction, + isArchivedRoom, + betas, + anchor, + isChronosReport, + reportID, + isPinnedChat, + isUnreadChat, + !!isOffline, + isMini, + moneyRequestAction, + areHoldRequirementsMet, + ), ); if (isMini) { @@ -252,6 +307,7 @@ function BaseReportActionContextMenu({ interceptAnonymousUser, openOverflowMenu, setIsEmojiPickerActive, + moneyRequestAction, }; if ('renderContent' in contextAction) { diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index 921ec324fced..57d23974ab14 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -66,6 +66,8 @@ type ShouldShow = ( isUnreadChat: boolean, isOffline: boolean, isMini: boolean, + moneyRequestAction: ReportAction | undefined, + areHoldRequirementsMet: boolean, ) => boolean; type ContextMenuActionPayload = { @@ -83,6 +85,7 @@ type ContextMenuActionPayload = { event?: GestureResponderEvent | MouseEvent | KeyboardEvent; setIsEmojiPickerActive?: (state: boolean) => void; anchorRef?: MutableRefObject; + moneyRequestAction: ReportAction | undefined; }; type OnPress = (closePopover: boolean, payload: ContextMenuActionPayload, selection?: string, reportID?: string, draftMessage?: string) => void; @@ -261,18 +264,31 @@ const ContextMenuActions: ContextMenuAction[] = [ }, { isAnonymousAction: false, - textTranslateKey: 'iou.unholdExpense', + textTranslateKey: 'iou.unhold', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction) => - type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canEditReportAction(reportAction) && ReportUtils.canHoldUnholdReportAction(reportAction).canUnholdRequest, - onPress: (closePopover, {reportAction}) => { + shouldShow: ( + type, + reportAction, + isArchivedRoom, + betas, + anchor, + isChronosReport, + reportID, + isPinnedChat, + isUnreadChat, + isOffline, + isMini, + moneyRequestAction, + areHoldRequirementsMet, + ) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && areHoldRequirementsMet && ReportUtils.canHoldUnholdReportAction(moneyRequestAction).canUnholdRequest, + onPress: (closePopover, {moneyRequestAction}) => { if (closePopover) { - hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction)); + hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction)); return; } // No popover to hide, call changeMoneyRequestHoldStatus immediately - ReportUtils.changeMoneyRequestHoldStatus(reportAction); + ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction); }, getDescription: () => {}, }, @@ -280,16 +296,29 @@ const ContextMenuActions: ContextMenuAction[] = [ isAnonymousAction: false, textTranslateKey: 'iou.hold', icon: Expensicons.Stopwatch, - shouldShow: (type, reportAction) => - type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && ReportUtils.canEditReportAction(reportAction) && ReportUtils.canHoldUnholdReportAction(reportAction).canHoldRequest, - onPress: (closePopover, {reportAction}) => { + shouldShow: ( + type, + reportAction, + isArchivedRoom, + betas, + anchor, + isChronosReport, + reportID, + isPinnedChat, + isUnreadChat, + isOffline, + isMini, + moneyRequestAction, + areHoldRequirementsMet, + ) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && areHoldRequirementsMet && ReportUtils.canHoldUnholdReportAction(moneyRequestAction).canHoldRequest, + onPress: (closePopover, {moneyRequestAction}) => { if (closePopover) { - hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(reportAction)); + hideContextMenu(false, () => ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction)); return; } // No popover to hide, call changeMoneyRequestHoldStatus immediately - ReportUtils.changeMoneyRequestHoldStatus(reportAction); + ReportUtils.changeMoneyRequestHoldStatus(moneyRequestAction); }, getDescription: () => {}, }, From 4e9194089792f889d9f628325cfb12aac1528177 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:43:10 +0200 Subject: [PATCH 12/17] remove unused comments --- .../home/report/ContextMenu/BaseReportActionContextMenu.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index a3199b4e43eb..309adce9a7f2 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -140,8 +140,6 @@ function BaseReportActionContextMenu({ const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`); - // HOLD START - const childReport = ReportUtils.getReport(reportAction?.childReportID ?? '-1'); const parentReportAction = ReportActionsUtils.getReportAction(childReport?.parentReportID ?? '', childReport?.parentReportActionID ?? ''); const {reportActions: paginatedReportActions} = usePaginatedReportActions(childReport?.reportID ?? '-1'); @@ -178,8 +176,6 @@ function BaseReportActionContextMenu({ const areHoldRequirementsMet = isMoneyRequestOrReport && !ReportUtils.isArchivedRoom(transactionThreadReportID ? childReport : parentReport, parentReportNameValuePairs); - // HOLD END - const originalReportID = useMemo(() => ReportUtils.getOriginalReportID(reportID, reportAction), [reportID, reportAction]); const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); From 9c97c2c452ff81ce6c61e5013b31201004ce265f Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:37:27 +0200 Subject: [PATCH 13/17] fix can hold logic for IOUs and self-held expenses --- src/libs/ReportUtils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 47d4b7ada8b3..82b402be34b6 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2872,11 +2872,10 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const transactionID = moneyRequestReport ? ReportActionsUtils.getOriginalMessage(reportAction)?.IOUTransactionID : 0; const transaction = allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] ?? ({} as Transaction); - const parentReport = getReportOrDraftReport(String(moneyRequestReport.parentReportID)); const parentReportAction = ReportActionsUtils.getParentReportAction(moneyRequestReport); - const isRequestIOU = parentReport?.type === 'iou'; - const isRequestHoldCreator = isHoldCreator(transaction, moneyRequestReport?.reportID) && isRequestIOU; + const isRequestIOU = isIOUReport(moneyRequestReport); + const isRequestHoldCreator = isActionCreator(reportAction) && isRequestIOU; const isTrackExpenseMoneyReport = isTrackExpenseReport(moneyRequestReport); const isActionOwner = typeof parentReportAction?.actorAccountID === 'number' && @@ -2889,12 +2888,13 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const isClosed = isClosedReport(moneyRequestReport); const canModifyStatus = !isTrackExpenseMoneyReport && (isAdmin || isActionOwner || isApprover); + const canModifyUnholdStatus = !isTrackExpenseMoneyReport && (isAdmin || isApprover || isHoldCreator(transaction, moneyRequestReport?.reportID)); const isDeletedParentAction = isEmptyObject(parentReportAction) || ReportActionsUtils.isDeletedAction(parentReportAction); const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction && !isClosed; const canHoldRequest = canHoldOrUnholdRequest && !isOnHold && (isRequestIOU || canModifyStatus) && !isScanning && !!transaction?.reimbursable; const canUnholdRequest = - !!(canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && (isRequestHoldCreator || (!isRequestIOU && canModifyStatus))) && + !!(canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && (isRequestHoldCreator || (!isRequestIOU && canModifyUnholdStatus))) && !!transaction?.reimbursable; return {canHoldRequest, canUnholdRequest}; From 9bbd7a7ee6c2d4e5198064f907c983e19c1dbfad Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 9 Aug 2024 12:03:35 +0200 Subject: [PATCH 14/17] fix isHoldCreator not working properly for money requests --- src/libs/ReportUtils.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a1967a64659c..3e2e7bdf705b 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2899,7 +2899,8 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const parentReportAction = ReportActionsUtils.getParentReportAction(moneyRequestReport); const isRequestIOU = isIOUReport(moneyRequestReport); - const isRequestHoldCreator = isActionCreator(reportAction) && isRequestIOU; + const isHoldActionCreator = isHoldCreator(transaction, reportAction.childReportID ?? '-1'); + const isTrackExpenseMoneyReport = isTrackExpenseReport(moneyRequestReport); const isActionOwner = typeof parentReportAction?.actorAccountID === 'number' && @@ -2911,14 +2912,14 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction); const isClosed = isClosedReport(moneyRequestReport); + const isActionAndHoldOwner = isActionOwner && isHoldActionCreator; const canModifyStatus = !isTrackExpenseMoneyReport && (isAdmin || isActionOwner || isApprover); - const canModifyUnholdStatus = !isTrackExpenseMoneyReport && (isAdmin || isApprover || isHoldCreator(transaction, moneyRequestReport?.reportID)); const isDeletedParentAction = isEmptyObject(parentReportAction) || ReportActionsUtils.isDeletedAction(parentReportAction); const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction && !isClosed; const canHoldRequest = canHoldOrUnholdRequest && !isOnHold && (isRequestIOU || canModifyStatus) && !isScanning && !!transaction?.reimbursable; const canUnholdRequest = - !!(canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && (isRequestHoldCreator || (!isRequestIOU && canModifyUnholdStatus))) && + !!(canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && (isRequestIOU ? isHoldActionCreator : (canModifyStatus || isActionAndHoldOwner))) && !!transaction?.reimbursable; return {canHoldRequest, canUnholdRequest}; From 07c607d939e9972eeb8ce8db75478813a7153c9c Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 9 Aug 2024 12:04:28 +0200 Subject: [PATCH 15/17] fix prettier --- src/libs/ReportUtils.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 3e2e7bdf705b..aeb6f0402cf5 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2919,8 +2919,12 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction && !isClosed; const canHoldRequest = canHoldOrUnholdRequest && !isOnHold && (isRequestIOU || canModifyStatus) && !isScanning && !!transaction?.reimbursable; const canUnholdRequest = - !!(canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && (isRequestIOU ? isHoldActionCreator : (canModifyStatus || isActionAndHoldOwner))) && - !!transaction?.reimbursable; + !!( + canHoldOrUnholdRequest && + isOnHold && + !TransactionUtils.isDuplicate(transaction.transactionID, true) && + (isRequestIOU ? isHoldActionCreator : canModifyStatus || isActionAndHoldOwner) + ) && !!transaction?.reimbursable; return {canHoldRequest, canUnholdRequest}; } From eee69cb30d30f9860e7410bedf6030fc1e75769a Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 9 Aug 2024 13:34:52 +0200 Subject: [PATCH 16/17] correct logic for non-IOU unhold author conditional --- src/libs/ReportUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index fd1429d9982d..b703360b9d87 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2971,8 +2971,8 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction); const isClosed = isClosedReport(moneyRequestReport); - const isActionAndHoldOwner = isActionOwner && isHoldActionCreator; const canModifyStatus = !isTrackExpenseMoneyReport && (isAdmin || isActionOwner || isApprover); + const canModifyUnholdStatus = !isTrackExpenseMoneyReport && (isAdmin || (isActionOwner && isHoldActionCreator) || isApprover); const isDeletedParentAction = isEmptyObject(parentReportAction) || ReportActionsUtils.isDeletedAction(parentReportAction); const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction && !isClosed; @@ -2982,7 +2982,7 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && - (isRequestIOU ? isHoldActionCreator : canModifyStatus || isActionAndHoldOwner) + (isRequestIOU ? isHoldActionCreator : canModifyUnholdStatus) ) && !!transaction?.reimbursable; return {canHoldRequest, canUnholdRequest}; From 03e5b2503aac4998b727d539d31ec305068d6612 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 9 Aug 2024 13:35:40 +0200 Subject: [PATCH 17/17] fix prettier and formatting --- src/libs/ReportUtils.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index b703360b9d87..2e6d8afc7aab 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2978,12 +2978,8 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) const canHoldOrUnholdRequest = !isRequestSettled && !isApproved && !isDeletedParentAction && !isClosed; const canHoldRequest = canHoldOrUnholdRequest && !isOnHold && (isRequestIOU || canModifyStatus) && !isScanning && !!transaction?.reimbursable; const canUnholdRequest = - !!( - canHoldOrUnholdRequest && - isOnHold && - !TransactionUtils.isDuplicate(transaction.transactionID, true) && - (isRequestIOU ? isHoldActionCreator : canModifyUnholdStatus) - ) && !!transaction?.reimbursable; + !!(canHoldOrUnholdRequest && isOnHold && !TransactionUtils.isDuplicate(transaction.transactionID, true) && (isRequestIOU ? isHoldActionCreator : canModifyUnholdStatus)) && + !!transaction?.reimbursable; return {canHoldRequest, canUnholdRequest}; }