From 58833a1c59977079b34c594f6f178962c5d0b661 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Sun, 11 Aug 2024 17:42:22 +0300 Subject: [PATCH 001/808] rm padding from nested list --- docs/_sass/_main.scss | 8 ++++++++ .../Add-Expensify-Card-to-Apple-or-Google-Pay.md | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index 82446fe08b3a..2b8627921958 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -374,6 +374,14 @@ button { } } + ol { + li { + ul { + padding-bottom: 0; + } + } + } + table { margin-bottom: 20px; border-radius: 8px; diff --git a/docs/articles/new-expensify/expensify-card/Add-Expensify-Card-to-Apple-or-Google-Pay.md b/docs/articles/new-expensify/expensify-card/Add-Expensify-Card-to-Apple-or-Google-Pay.md index 844a688e0011..3c147e33517b 100644 --- a/docs/articles/new-expensify/expensify-card/Add-Expensify-Card-to-Apple-or-Google-Pay.md +++ b/docs/articles/new-expensify/expensify-card/Add-Expensify-Card-to-Apple-or-Google-Pay.md @@ -9,7 +9,7 @@ You can use your Expensify Card for contactless in-person payments by adding it {% include selector.html values="mobile" %} {% include option.html value="mobile" %} -**Apple Pay** +### Apple Pay 1. Open the Apple Pay app. 2. Tap the + button. @@ -17,7 +17,7 @@ You can use your Expensify Card for contactless in-person payments by adding it 4. Tap **Continue**. 5. Follow the steps provided to add your virtual card. -**Google Pay** +### Google Pay 1. Open the Google Pay app. 2. Tap **Add to Wallet**. From 6e03be685267d8b52b4b9974f0d48733bcf7371a Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Sun, 11 Aug 2024 18:04:23 +0300 Subject: [PATCH 002/808] add 4px padding to li --- docs/_sass/_main.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index 2b8627921958..2d87df80a13d 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -374,6 +374,10 @@ button { } } + li { + padding-bottom: 4px; + } + ol { li { ul { From 2f112533d31ad43e30c053cbf913cbcf44cd42f6 Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:01:05 +0530 Subject: [PATCH 003/808] Fix crash when disconnecting from Netsuite --- src/libs/OptionsListUtils.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index b9be3ffac761..082f6a423be1 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1353,7 +1353,14 @@ function getTagListSections( * Verifies that there is at least one enabled tag */ function hasEnabledTags(policyTagList: Array) { - const policyTagValueList = policyTagList.map(({tags}) => Object.values(tags)).flat(); + if (!policyTagList) { + return false; + } + + const policyTagValueList = policyTagList + .filter(tag => tag && tag.tags) + .map(({tags}) => Object.values(tags)) + .flat(); return hasEnabledOptions(policyTagValueList); } From 913a3d95b71cbb341946f38f04e1fc2d0cef715e Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 21 Aug 2024 22:13:58 +0530 Subject: [PATCH 004/808] demo skip dupe tax step. Signed-off-by: krishna2323 --- .../MoneyRequestPreviewContent.tsx | 25 ++++++++++++------- .../TransactionDuplicate/ReviewTaxCode.tsx | 9 ++++--- .../step/IOURequestStepConfirmation.tsx | 2 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 8597654576fc..02a3764bf419 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -31,6 +31,8 @@ import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as OptionsListUtils from '@libs/OptionsListUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; +import {getPolicy} from '@libs/PolicyUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -279,15 +281,20 @@ function MoneyRequestPreviewContent({ const navigateToReviewFields = () => { const comparisonResult = TransactionUtils.compareDuplicateTransactionFields(reviewingTransactionID); Transaction.setReviewDuplicatesKey({...comparisonResult.keep, duplicates, transactionID: transaction?.transactionID ?? ''}); - if ('merchant' in comparisonResult.change) { - Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(route.params?.threadReportID)); - } else if ('category' in comparisonResult.change) { - Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_CATEGORY_PAGE.getRoute(route.params?.threadReportID)); - } else if ('tag' in comparisonResult.change) { - Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAG_PAGE.getRoute(route.params?.threadReportID)); - } else if ('description' in comparisonResult.change) { - Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE.getRoute(route.params?.threadReportID)); - } else if ('taxCode' in comparisonResult.change) { + + const report2 = ReportUtils.getReport(transaction?.reportID ?? ''); + const policy = PolicyUtils.getPolicy(report2?.policyID); + const hasValidTaxes = comparisonResult.change.taxCode?.filter((taxID) => PolicyUtils.getTaxByID(policy, taxID ?? '')?.name).length; + // if ('merchant' in comparisonResult.change) { + // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(route.params?.threadReportID)); + // } else if ('category' in comparisonResult.change) { + // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_CATEGORY_PAGE.getRoute(route.params?.threadReportID)); + // } else if ('tag' in comparisonResult.change) { + // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAG_PAGE.getRoute(route.params?.threadReportID)); + // } else if ('description' in comparisonResult.change) { + // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE.getRoute(route.params?.threadReportID)); + // } + if ('taxCode' in comparisonResult.change && hasValidTaxes) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAX_CODE_PAGE.getRoute(route.params?.threadReportID)); } else if ('billable' in comparisonResult.change) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_BILLABLE_PAGE.getRoute(route.params?.threadReportID)); diff --git a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx index aa598bff8fcd..acb45b2c8a63 100644 --- a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx +++ b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx @@ -20,13 +20,13 @@ import ReviewFields from './ReviewFields'; function ReviewTaxRate() { const route = useRoute>(); const {translate} = useLocalize(); - const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const transaction = TransactionUtils.getTransaction(reviewDuplicates?.transactionID ?? ''); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`); const policy = PolicyUtils.getPolicy(report?.policyID ?? ''); - const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(reviewDuplicates?.transactionID ?? ''); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'taxCode', route.params.threadReportID ?? ''); - const transaction = TransactionUtils.getTransaction(transactionID); const options = useMemo( () => compareResult.change.taxCode?.map((taxID) => @@ -39,6 +39,7 @@ function ReviewTaxRate() { ), [compareResult.change.taxCode, policy, transaction, translate], ); + const getTaxAmount = useCallback( (taxID: string) => { const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, taxID); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index b33ce6f56600..5090c1dfb2d6 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -1,7 +1,7 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx, withOnyx} from 'react-native-onyx'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; From 0429b7f0e996e11f6649f218908d38add53c8e1f Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 28 Aug 2024 09:02:26 +0530 Subject: [PATCH 005/808] minor update. Signed-off-by: krishna2323 --- .../MoneyRequestPreview/MoneyRequestPreviewContent.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index d901e3eb7c3a..9f2f52d7ac35 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -294,6 +294,10 @@ function MoneyRequestPreviewContent({ // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE.getRoute(route.params?.threadReportID)); // } if ('taxCode' in comparisonResult.change && hasValidTaxes) { + if (!hasValidTaxes) { + Transaction.setReviewDuplicatesKey({taxCode: transaction?.taxCode}); + return; + } Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAX_CODE_PAGE.getRoute(route.params?.threadReportID)); } else if ('billable' in comparisonResult.change) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_BILLABLE_PAGE.getRoute(route.params?.threadReportID)); From 890eba70df851f1613896c3df84e137538dead09 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 9 Sep 2024 10:46:29 +0700 Subject: [PATCH 006/808] Feature: add loading indicator when ReconnectApp is running --- src/pages/home/ReportScreen.tsx | 3 +++ .../sidebar/SidebarScreen/BaseSidebarScreen.tsx | 4 ++++ src/styles/index.ts | 13 +++++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 4eaf3633af38..be4cf15787a5 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -13,6 +13,7 @@ import DragAndDropProvider from '@components/DragAndDrop/Provider'; import MoneyReportHeader from '@components/MoneyReportHeader'; import MoneyRequestHeader from '@components/MoneyRequestHeader'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import ProgressBar from '@components/ProgressBar'; import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView'; import ScreenWrapper from '@components/ScreenWrapper'; import TaskHeaderActionButton from '@components/TaskHeaderActionButton'; @@ -128,6 +129,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP); const [workspaceTooltip] = useOnyx(ONYXKEYS.NVP_WORKSPACE_TOOLTIP); const wasLoadingApp = usePrevious(isLoadingApp); + const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA, {initialValue: true}); const finishedLoadingApp = wasLoadingApp && !isLoadingApp; const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(parentReportAction); const prevIsDeletedParentAction = usePrevious(isDeletedParentAction); @@ -756,6 +758,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro needsOffscreenAlphaCompositing > {headerView} + {shouldUseNarrowLayout && } {ReportUtils.isTaskReport(report) && shouldUseNarrowLayout && ReportUtils.isOpenTaskReport(report, parentReportAction) && ( diff --git a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.tsx b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.tsx index edc8dfb3cb3a..4626429fb53c 100644 --- a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.tsx +++ b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.tsx @@ -1,6 +1,7 @@ import React, {useEffect} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import ProgressBar from '@components/ProgressBar'; import ScreenWrapper from '@components/ScreenWrapper'; import useActiveWorkspaceFromNavigationState from '@hooks/useActiveWorkspaceFromNavigationState'; import useLocalize from '@hooks/useLocalize'; @@ -29,6 +30,8 @@ function BaseSidebarScreen() { const {translate} = useLocalize(); const [activeWorkspace] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activeWorkspaceID ?? -1}`); + const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA, {initialValue: true}); + useEffect(() => { Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); Timing.start(CONST.TIMING.SIDEBAR_LOADED); @@ -57,6 +60,7 @@ function BaseSidebarScreen() { breadcrumbLabel={translate('common.inbox')} activeWorkspaceID={activeWorkspaceID} /> + top: 80, left: 12, }, + progressBarWrapper: { + height: 2, + width: '100%', + backgroundColor: '#1A3D32', + borderRadius: 5, + overflow: 'hidden', + }, + progressBar: { + height: '100%', + backgroundColor: '#03D47C', + borderRadius: 5, + width: '100%', + }, } satisfies Styles); type ThemeStyles = ReturnType; From 7a77276bd2414483144892228d98584faac03b9d Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 9 Sep 2024 10:55:23 +0700 Subject: [PATCH 007/808] fix ts check --- src/components/ProgressBar.tsx | 78 ++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/components/ProgressBar.tsx diff --git a/src/components/ProgressBar.tsx b/src/components/ProgressBar.tsx new file mode 100644 index 000000000000..d37d34887c03 --- /dev/null +++ b/src/components/ProgressBar.tsx @@ -0,0 +1,78 @@ +import React, {useEffect} from 'react'; +import Animated, {cancelAnimation, Easing, runOnJS, useAnimatedStyle, useSharedValue, withDelay, withRepeat, withSequence, withTiming} from 'react-native-reanimated'; +import useThemeStyles from '@hooks/useThemeStyles'; + +function ProgressBar({shouldShow}: {shouldShow: boolean}) { + const left = useSharedValue(0); + const width = useSharedValue(0); + const opacity = useSharedValue(0); + const isVisible = useSharedValue(false); + const styles = useThemeStyles(); + + useEffect(() => { + if (shouldShow) { + // eslint-disable-next-line react-compiler/react-compiler + isVisible.value = true; + left.value = 0; + width.value = 0; + opacity.value = withTiming(1, {duration: 300}); + left.value = withDelay( + 300, // 0.3s delay + withRepeat( + withSequence( + withTiming(0, {duration: 0}), + withTiming(0, {duration: 750, easing: Easing.bezier(0.65, 0, 0.35, 1)}), + withTiming(100, {duration: 750, easing: Easing.bezier(0.65, 0, 0.35, 1)}), + ), + -1, + false, + ), + ); + + width.value = withDelay( + 300, // 0.3s delay + withRepeat( + withSequence( + withTiming(0, {duration: 0}), + withTiming(100, {duration: 750, easing: Easing.bezier(0.65, 0, 0.35, 1)}), + withTiming(0, {duration: 750, easing: Easing.bezier(0.65, 0, 0.35, 1)}), + ), + -1, + false, + ), + ); + } else if (isVisible.value) { + opacity.value = withTiming(0, {duration: 300}, () => { + runOnJS(() => { + isVisible.value = false; + cancelAnimation(left); + cancelAnimation(width); + }); + }); + } + // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps + }, [shouldShow]); + + const animatedIndicatorStyle = useAnimatedStyle(() => { + return { + left: `${left.value}%`, + width: `${width.value}%`, + }; + }); + + const animatedContainerStyle = useAnimatedStyle(() => { + return { + opacity: opacity.value, + }; + }); + + return isVisible.value ? ( + + + + ) : null; +} + +ProgressBar.displayName = 'ProgressBar'; + +export default ProgressBar; From 0265bc6133f6e93382e98105646ba484831fd173 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 9 Sep 2024 16:53:46 +0700 Subject: [PATCH 008/808] fix style of progress bar --- src/styles/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index 8a742934739c..825f17701740 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -5202,13 +5202,13 @@ const styles = (theme: ThemeColors) => progressBarWrapper: { height: 2, width: '100%', - backgroundColor: '#1A3D32', + backgroundColor: theme.buttonDefaultBG, borderRadius: 5, overflow: 'hidden', }, progressBar: { height: '100%', - backgroundColor: '#03D47C', + backgroundColor: theme.success, borderRadius: 5, width: '100%', }, From af9b5b8a2f9406d1bf39b01727b3efeb65036bfe Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 9 Sep 2024 17:26:43 +0700 Subject: [PATCH 009/808] fix style progress bar --- src/styles/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index 825f17701740..b086d4cfd9b3 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -5202,7 +5202,7 @@ const styles = (theme: ThemeColors) => progressBarWrapper: { height: 2, width: '100%', - backgroundColor: theme.buttonDefaultBG, + backgroundColor: theme.border, borderRadius: 5, overflow: 'hidden', }, From c177829d889eb4a1998d524d17c4b453ff82d5bf Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 10 Sep 2024 22:05:34 +0700 Subject: [PATCH 010/808] add new const and fix style progress bar --- src/CONST.ts | 3 +++ src/components/ProgressBar.tsx | 17 +++++++++-------- src/styles/index.ts | 1 - 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index d0695b1e285f..a6578118e7c8 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -180,6 +180,9 @@ const CONST = { ANIMATED_HIGHLIGHT_END_DURATION: 2000, ANIMATED_TRANSITION: 300, ANIMATED_TRANSITION_FROM_VALUE: 100, + ANIMATED_PROGRESS_BAR_DELAY: 300, + ANIMATED_PROGRESS_BAR_OPACITY_DURATION: 300, + ANIMATED_PROGRESS_BAR_DURATION: 750, ANIMATION_IN_TIMING: 100, ANIMATION_DIRECTION: { IN: 'in', diff --git a/src/components/ProgressBar.tsx b/src/components/ProgressBar.tsx index d37d34887c03..63d3d1142d30 100644 --- a/src/components/ProgressBar.tsx +++ b/src/components/ProgressBar.tsx @@ -1,6 +1,7 @@ import React, {useEffect} from 'react'; import Animated, {cancelAnimation, Easing, runOnJS, useAnimatedStyle, useSharedValue, withDelay, withRepeat, withSequence, withTiming} from 'react-native-reanimated'; import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; function ProgressBar({shouldShow}: {shouldShow: boolean}) { const left = useSharedValue(0); @@ -15,14 +16,14 @@ function ProgressBar({shouldShow}: {shouldShow: boolean}) { isVisible.value = true; left.value = 0; width.value = 0; - opacity.value = withTiming(1, {duration: 300}); + opacity.value = withTiming(1, {duration: CONST.ANIMATED_PROGRESS_BAR_OPACITY_DURATION}); left.value = withDelay( - 300, // 0.3s delay + CONST.ANIMATED_PROGRESS_BAR_DELAY, withRepeat( withSequence( withTiming(0, {duration: 0}), - withTiming(0, {duration: 750, easing: Easing.bezier(0.65, 0, 0.35, 1)}), - withTiming(100, {duration: 750, easing: Easing.bezier(0.65, 0, 0.35, 1)}), + withTiming(0, {duration: CONST.ANIMATED_PROGRESS_BAR_DURATION, easing: Easing.bezier(0.65, 0, 0.35, 1)}), + withTiming(100, {duration: CONST.ANIMATED_PROGRESS_BAR_DURATION, easing: Easing.bezier(0.65, 0, 0.35, 1)}), ), -1, false, @@ -30,19 +31,19 @@ function ProgressBar({shouldShow}: {shouldShow: boolean}) { ); width.value = withDelay( - 300, // 0.3s delay + CONST.ANIMATED_PROGRESS_BAR_DELAY, withRepeat( withSequence( withTiming(0, {duration: 0}), - withTiming(100, {duration: 750, easing: Easing.bezier(0.65, 0, 0.35, 1)}), - withTiming(0, {duration: 750, easing: Easing.bezier(0.65, 0, 0.35, 1)}), + withTiming(100, {duration: CONST.ANIMATED_PROGRESS_BAR_DURATION, easing: Easing.bezier(0.65, 0, 0.35, 1)}), + withTiming(0, {duration: CONST.ANIMATED_PROGRESS_BAR_DURATION, easing: Easing.bezier(0.65, 0, 0.35, 1)}), ), -1, false, ), ); } else if (isVisible.value) { - opacity.value = withTiming(0, {duration: 300}, () => { + opacity.value = withTiming(0, {duration: CONST.ANIMATED_PROGRESS_BAR_OPACITY_DURATION}, () => { runOnJS(() => { isVisible.value = false; cancelAnimation(left); diff --git a/src/styles/index.ts b/src/styles/index.ts index b086d4cfd9b3..9221f480ab8e 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -5209,7 +5209,6 @@ const styles = (theme: ThemeColors) => progressBar: { height: '100%', backgroundColor: theme.success, - borderRadius: 5, width: '100%', }, } satisfies Styles); From 90508101c480f9b346da03d06c291394d28532b4 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Wed, 11 Sep 2024 11:38:15 +0530 Subject: [PATCH 011/808] revert changes in ReviewTaxRate page. Signed-off-by: krishna2323 --- .../MoneyRequestPreviewContent.tsx | 28 ++++++++++--------- .../TransactionDuplicate/ReviewTaxCode.tsx | 9 +++--- .../step/IOURequestStepConfirmation.tsx | 2 +- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index ecd5b4e73548..89a1c8dc412b 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -291,20 +291,22 @@ function MoneyRequestPreviewContent({ const report2 = ReportUtils.getReport(transaction?.reportID ?? ''); const policy = PolicyUtils.getPolicy(report2?.policyID); const hasValidTaxes = comparisonResult.change.taxCode?.filter((taxID) => PolicyUtils.getTaxByID(policy, taxID ?? '')?.name).length; - // if ('merchant' in comparisonResult.change) { - // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(route.params?.threadReportID)); - // } else if ('category' in comparisonResult.change) { - // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_CATEGORY_PAGE.getRoute(route.params?.threadReportID)); - // } else if ('tag' in comparisonResult.change) { - // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAG_PAGE.getRoute(route.params?.threadReportID)); - // } else if ('description' in comparisonResult.change) { - // Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE.getRoute(route.params?.threadReportID)); - // } + + if (!hasValidTaxes) { + Transaction.setReviewDuplicatesKey({taxCode: transaction?.taxCode}); + return; + } + + if ('merchant' in comparisonResult.change) { + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(route.params?.threadReportID)); + } else if ('category' in comparisonResult.change) { + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_CATEGORY_PAGE.getRoute(route.params?.threadReportID)); + } else if ('tag' in comparisonResult.change) { + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAG_PAGE.getRoute(route.params?.threadReportID)); + } else if ('description' in comparisonResult.change) { + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE.getRoute(route.params?.threadReportID)); + } if ('taxCode' in comparisonResult.change && hasValidTaxes) { - if (!hasValidTaxes) { - Transaction.setReviewDuplicatesKey({taxCode: transaction?.taxCode}); - return; - } Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAX_CODE_PAGE.getRoute(route.params?.threadReportID)); } else if ('billable' in comparisonResult.change) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_BILLABLE_PAGE.getRoute(route.params?.threadReportID)); diff --git a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx index acb45b2c8a63..aa598bff8fcd 100644 --- a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx +++ b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx @@ -20,13 +20,13 @@ import ReviewFields from './ReviewFields'; function ReviewTaxRate() { const route = useRoute>(); const {translate} = useLocalize(); - const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const transaction = TransactionUtils.getTransaction(reviewDuplicates?.transactionID ?? ''); - const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`); const policy = PolicyUtils.getPolicy(report?.policyID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(reviewDuplicates?.transactionID ?? ''); + const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'taxCode', route.params.threadReportID ?? ''); + const transaction = TransactionUtils.getTransaction(transactionID); const options = useMemo( () => compareResult.change.taxCode?.map((taxID) => @@ -39,7 +39,6 @@ function ReviewTaxRate() { ), [compareResult.change.taxCode, policy, transaction, translate], ); - const getTaxAmount = useCallback( (taxID: string) => { const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, taxID); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 3f8f17d57d0f..6c1457abef62 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -1,7 +1,7 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {useOnyx, withOnyx} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; From 511c9ad23a8410402c17caedc085d6c8e67c756b Mon Sep 17 00:00:00 2001 From: dominictb Date: Mon, 16 Sep 2024 02:26:27 +0700 Subject: [PATCH 012/808] fix: app goes to workspace initial page when back from not found page --- .../CustomFullScreenRouter.tsx | 21 ++++++++++++++++--- src/libs/Navigation/Navigation.ts | 14 +++++++++++++ src/libs/PolicyUtils.ts | 5 +++++ .../workspace/AccessOrNotFoundWrapper.tsx | 10 ++++++++- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx index 27e976d9be0c..3980be047d97 100644 --- a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx @@ -1,6 +1,10 @@ import type {ParamListBase, PartialState, RouterConfigOptions, StackNavigationState} from '@react-navigation/native'; import {StackRouter} from '@react-navigation/native'; +import {useOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import getIsNarrowLayout from '@libs/getIsNarrowLayout'; +import * as PolicyUtils from '@libs/PolicyUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; import SCREENS from '@src/SCREENS'; import type {FullScreenNavigatorRouterOptions} from './types'; @@ -8,12 +12,22 @@ type StackState = StackNavigationState | PartialState state.routes.some((route) => route.name === screenName); -function adaptStateIfNecessary(state: StackState) { +function adaptStateIfNecessary(state: StackState, isLoadingReportData: OnyxEntry) { const isNarrowLayout = getIsNarrowLayout(); const workspaceCentralPane = state.routes.at(-1); + const policyID = + workspaceCentralPane?.params && 'policyID' in workspaceCentralPane.params && typeof workspaceCentralPane.params.policyID === 'string' + ? workspaceCentralPane.params.policyID + : undefined; // There should always be WORKSPACE.INITIAL screen in the state to make sure go back works properly if we deeplinkg to a subpage of settings. if (!isAtLeastOneInState(state, SCREENS.WORKSPACE.INITIAL)) { + const policy = PolicyUtils.getPolicy(policyID ?? ''); + const isPolicyAccessible = PolicyUtils.isPolicyAccessible(policy); + if (isLoadingReportData && !isPolicyAccessible) { + return; + } + // @ts-expect-error Updating read only property // noinspection JSConstantReassignment state.stale = true; // eslint-disable-line @@ -51,12 +65,13 @@ function adaptStateIfNecessary(state: StackState) { function CustomFullScreenRouter(options: FullScreenNavigatorRouterOptions) { const stackRouter = StackRouter(options); + const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA, {initialValue: true}); return { ...stackRouter, getInitialState({routeNames, routeParamList, routeGetIdList}: RouterConfigOptions) { const initialState = stackRouter.getInitialState({routeNames, routeParamList, routeGetIdList}); - adaptStateIfNecessary(initialState); + adaptStateIfNecessary(initialState, isLoadingReportData); // If we needed to modify the state we need to rehydrate it to get keys for new routes. if (initialState.stale) { @@ -66,7 +81,7 @@ function CustomFullScreenRouter(options: FullScreenNavigatorRouterOptions) { return initialState; }, getRehydratedState(partialState: StackState, {routeNames, routeParamList, routeGetIdList}: RouterConfigOptions): StackNavigationState { - adaptStateIfNecessary(partialState); + adaptStateIfNecessary(partialState, isLoadingReportData); const state = stackRouter.getRehydratedState(partialState, {routeNames, routeParamList, routeGetIdList}); return state; }, diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index 4c61b953f572..67abfb53a9c3 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -12,6 +12,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {HybridAppRoute, Route} from '@src/ROUTES'; import ROUTES, {HYBRID_APP_ROUTES} from '@src/ROUTES'; import {PROTECTED_SCREENS} from '@src/SCREENS'; +import type {Screen} from '@src/SCREENS'; import type {Report} from '@src/types/onyx'; import originalCloseRHPFlow from './closeRHPFlow'; import originalDismissModal from './dismissModal'; @@ -410,6 +411,18 @@ function getTopMostCentralPaneRouteFromRootState() { return getTopmostCentralPaneRoute(navigationRef.getRootState() as State); } +function removeScreenFromNavigationState(screen: Screen) { + navigationRef.dispatch((state) => { + const routes = state.routes?.filter((item) => item.name !== screen); + + return CommonActions.reset({ + ...state, + routes, + index: routes.length < state.routes.length ? state.index - 1 : state.index, + }); + }); +} + export default { setShouldPopAllStateOnUP, navigate, @@ -433,6 +446,7 @@ export default { closeRHPFlow, setNavigationActionToMicrotaskQueue, getTopMostCentralPaneRouteFromRootState, + removeScreenFromNavigationState, }; export {navigationRef}; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index b98188567178..28f9989a3e51 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -996,6 +996,10 @@ function getWorkflowApprovalsUnavailable(policy: OnyxEntry) { return policy?.approvalMode === CONST.POLICY.APPROVAL_MODE.OPTIONAL || !!policy?.errorFields?.approvalMode; } +function isPolicyAccessible(policy: OnyxEntry) { + return !isEmptyObject(policy) && (Object.keys(policy).length !== 1 || isEmptyObject(policy.errors)) && policy?.id; +} + export { canEditTaxRate, extractPolicyIDFromPath, @@ -1105,6 +1109,7 @@ export { getTagNamesFromTagsLists, getDomainNameForPolicy, getWorkflowApprovalsUnavailable, + isPolicyAccessible, }; export type {MemberEmailsToAccountIDs}; diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx index 1a6f59830506..aa859f744f34 100644 --- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx +++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx @@ -16,6 +16,7 @@ import type {IOUType} from '@src/CONST'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {PolicyFeatureName} from '@src/types/onyx/Policy'; import callOrReturn from '@src/types/utils/callOrReturn'; @@ -132,7 +133,7 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps return acc && accessFunction(policy, login, report, allPolicies ?? null, iouType); }, true); - const isPolicyNotAccessible = isEmptyObject(policy) || (Object.keys(policy).length === 1 && !isEmptyObject(policy.errors)) || !policy?.id; + const isPolicyNotAccessible = !PolicyUtils.isPolicyAccessible(policy); const shouldShowNotFoundPage = (!isMoneyRequest && !isFromGlobalCreate && isPolicyNotAccessible) || !isPageAccessible || !isPolicyFeatureEnabled || shouldBeBlocked; // We only update the feature state if it isn't pending. @@ -145,6 +146,13 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps setIsPolicyFeatureEnabled(isFeatureEnabled); }, [pendingField, isOffline, isFeatureEnabled]); + useEffect(() => { + if (!isPolicyNotAccessible) { + return; + } + Navigation.removeScreenFromNavigationState(SCREENS.WORKSPACE.INITIAL); + }, [isPolicyNotAccessible]); + if (shouldShowFullScreenLoadingIndicator) { return ; } From 1df33b40e247ee4f175d88a26ce1185172148b55 Mon Sep 17 00:00:00 2001 From: dominictb Date: Mon, 16 Sep 2024 02:44:26 +0700 Subject: [PATCH 013/808] modify add route condition --- .../createCustomFullScreenNavigator/CustomFullScreenRouter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx index 3980be047d97..ee6c2179c4b4 100644 --- a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx @@ -24,7 +24,7 @@ function adaptStateIfNecessary(state: StackState, isLoadingReportData: OnyxEntry if (!isAtLeastOneInState(state, SCREENS.WORKSPACE.INITIAL)) { const policy = PolicyUtils.getPolicy(policyID ?? ''); const isPolicyAccessible = PolicyUtils.isPolicyAccessible(policy); - if (isLoadingReportData && !isPolicyAccessible) { + if (!isLoadingReportData && !isPolicyAccessible) { return; } From b2b979b31d4008e3b1580621c4f4542b8eef56ea Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 16 Sep 2024 02:54:28 +0530 Subject: [PATCH 014/808] revert changes. Signed-off-by: krishna2323 --- .../MoneyRequestPreviewContent.tsx | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index bf3c48e9e5b7..51f9c1c521a4 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -288,15 +288,6 @@ function MoneyRequestPreviewContent({ const comparisonResult = TransactionUtils.compareDuplicateTransactionFields(reviewingTransactionID); Transaction.setReviewDuplicatesKey({...comparisonResult.keep, duplicates, transactionID: transaction?.transactionID ?? ''}); - const report2 = ReportUtils.getReport(transaction?.reportID ?? ''); - const policy = PolicyUtils.getPolicy(report2?.policyID); - const hasValidTaxes = comparisonResult.change.taxCode?.filter((taxID) => PolicyUtils.getTaxByID(policy, taxID ?? '')?.name).length; - - if (!hasValidTaxes) { - Transaction.setReviewDuplicatesKey({taxCode: transaction?.taxCode}); - return; - } - if ('merchant' in comparisonResult.change) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(route.params?.threadReportID)); } else if ('category' in comparisonResult.change) { @@ -306,7 +297,7 @@ function MoneyRequestPreviewContent({ } else if ('description' in comparisonResult.change) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE.getRoute(route.params?.threadReportID)); } - if ('taxCode' in comparisonResult.change && hasValidTaxes) { + if ('taxCode' in comparisonResult.change) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_TAX_CODE_PAGE.getRoute(route.params?.threadReportID)); } else if ('billable' in comparisonResult.change) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_BILLABLE_PAGE.getRoute(route.params?.threadReportID)); From 61ce0021e927f584d9aa4a8b1ed1afa11aa24d05 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 16 Sep 2024 03:27:01 +0530 Subject: [PATCH 015/808] remove tax code from changes if policy doesn't include that. Signed-off-by: krishna2323 --- .../MoneyRequestPreviewContent.tsx | 6 ++---- src/libs/TransactionUtils/index.ts | 11 +++++++++++ src/pages/TransactionDuplicate/ReviewBillable.tsx | 5 ++++- src/pages/TransactionDuplicate/ReviewCategory.tsx | 5 ++++- src/pages/TransactionDuplicate/ReviewDescription.tsx | 5 ++++- src/pages/TransactionDuplicate/ReviewMerchant.tsx | 5 ++++- src/pages/TransactionDuplicate/ReviewReimbursable.tsx | 5 ++++- src/pages/TransactionDuplicate/ReviewTag.tsx | 5 ++++- src/pages/TransactionDuplicate/ReviewTaxCode.tsx | 3 ++- src/types/onyx/ReviewDuplicates.ts | 3 +++ 10 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 51f9c1c521a4..8e1cfb4a29e8 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -31,8 +31,6 @@ import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as OptionsListUtils from '@libs/OptionsListUtils'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import {getPolicy} from '@libs/PolicyUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -285,8 +283,8 @@ function MoneyRequestPreviewContent({ ); const navigateToReviewFields = () => { - const comparisonResult = TransactionUtils.compareDuplicateTransactionFields(reviewingTransactionID); - Transaction.setReviewDuplicatesKey({...comparisonResult.keep, duplicates, transactionID: transaction?.transactionID ?? ''}); + const comparisonResult = TransactionUtils.compareDuplicateTransactionFields(reviewingTransactionID, transaction?.reportID ?? ''); + Transaction.setReviewDuplicatesKey({...comparisonResult.keep, duplicates, transactionID: transaction?.transactionID ?? '', reportID: transaction?.reportID}); if ('merchant' in comparisonResult.change) { Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(route.params?.threadReportID)); diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 63c2f9aa9862..a734995a60ea 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -1020,6 +1020,17 @@ function compareDuplicateTransactionFields(transactionID: string): {keep: Partia } else { processChanges(fieldName, transactions, keys); } + } else if (fieldName === 'taxCode') { + const report = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; + const policy = PolicyUtils.getPolicy(report?.policyID); + const differentValues = getDifferentValues(transactions, keys); + const hasValidTaxes = differentValues?.filter((taxID) => PolicyUtils.getTaxByID(policy, (taxID as string) ?? '')?.name).length; + + if (areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) || !hasValidTaxes) { + keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; + } else { + processChanges(fieldName, transactions, keys); + } } else if (areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|'))) { keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } else { diff --git a/src/pages/TransactionDuplicate/ReviewBillable.tsx b/src/pages/TransactionDuplicate/ReviewBillable.tsx index 4cb2b130aea1..cd9fa8e1ae92 100644 --- a/src/pages/TransactionDuplicate/ReviewBillable.tsx +++ b/src/pages/TransactionDuplicate/ReviewBillable.tsx @@ -1,6 +1,7 @@ import type {RouteProp} from '@react-navigation/native'; import {useRoute} from '@react-navigation/native'; import React, {useMemo} from 'react'; +import {useOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -8,6 +9,7 @@ import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation' import {setReviewDuplicatesKey} from '@libs/actions/Transaction'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as TransactionUtils from '@libs/TransactionUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {FieldItemType} from './ReviewFields'; import ReviewFields from './ReviewFields'; @@ -16,7 +18,8 @@ function ReviewBillable() { const route = useRoute>(); const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'billable', route.params.threadReportID ?? ''); const options = useMemo( diff --git a/src/pages/TransactionDuplicate/ReviewCategory.tsx b/src/pages/TransactionDuplicate/ReviewCategory.tsx index 12a5968e2c43..04dbae092318 100644 --- a/src/pages/TransactionDuplicate/ReviewCategory.tsx +++ b/src/pages/TransactionDuplicate/ReviewCategory.tsx @@ -1,6 +1,7 @@ import type {RouteProp} from '@react-navigation/native'; import {useRoute} from '@react-navigation/native'; import React, {useMemo} from 'react'; +import {useOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -8,6 +9,7 @@ import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation' import {setReviewDuplicatesKey} from '@libs/actions/Transaction'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as TransactionUtils from '@libs/TransactionUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {FieldItemType} from './ReviewFields'; import ReviewFields from './ReviewFields'; @@ -16,7 +18,8 @@ function ReviewCategory() { const route = useRoute>(); const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'category', route.params.threadReportID ?? ''); const options = useMemo( diff --git a/src/pages/TransactionDuplicate/ReviewDescription.tsx b/src/pages/TransactionDuplicate/ReviewDescription.tsx index e6229afe48ac..fee570273e05 100644 --- a/src/pages/TransactionDuplicate/ReviewDescription.tsx +++ b/src/pages/TransactionDuplicate/ReviewDescription.tsx @@ -1,6 +1,7 @@ import type {RouteProp} from '@react-navigation/native'; import {useRoute} from '@react-navigation/native'; import React, {useMemo} from 'react'; +import {useOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -8,6 +9,7 @@ import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation' import {setReviewDuplicatesKey} from '@libs/actions/Transaction'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as TransactionUtils from '@libs/TransactionUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {FieldItemType} from './ReviewFields'; import ReviewFields from './ReviewFields'; @@ -16,7 +18,8 @@ function ReviewDescription() { const route = useRoute>(); const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'description', route.params.threadReportID ?? ''); const options = useMemo( diff --git a/src/pages/TransactionDuplicate/ReviewMerchant.tsx b/src/pages/TransactionDuplicate/ReviewMerchant.tsx index 80ae43a0d338..5a94161a72d5 100644 --- a/src/pages/TransactionDuplicate/ReviewMerchant.tsx +++ b/src/pages/TransactionDuplicate/ReviewMerchant.tsx @@ -1,6 +1,7 @@ import type {RouteProp} from '@react-navigation/native'; import {useRoute} from '@react-navigation/native'; import React, {useMemo} from 'react'; +import {useOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -8,6 +9,7 @@ import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation' import {setReviewDuplicatesKey} from '@libs/actions/Transaction'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as TransactionUtils from '@libs/TransactionUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {FieldItemType} from './ReviewFields'; import ReviewFields from './ReviewFields'; @@ -16,7 +18,8 @@ function ReviewMerchant() { const route = useRoute>(); const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'merchant', route.params.threadReportID ?? ''); const options = useMemo( diff --git a/src/pages/TransactionDuplicate/ReviewReimbursable.tsx b/src/pages/TransactionDuplicate/ReviewReimbursable.tsx index fbf7e43a2013..43e3a063e106 100644 --- a/src/pages/TransactionDuplicate/ReviewReimbursable.tsx +++ b/src/pages/TransactionDuplicate/ReviewReimbursable.tsx @@ -1,6 +1,7 @@ import type {RouteProp} from '@react-navigation/native'; import {useRoute} from '@react-navigation/native'; import React, {useMemo} from 'react'; +import {useOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -8,6 +9,7 @@ import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation' import {setReviewDuplicatesKey} from '@libs/actions/Transaction'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as TransactionUtils from '@libs/TransactionUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {FieldItemType} from './ReviewFields'; import ReviewFields from './ReviewFields'; @@ -16,7 +18,8 @@ function ReviewReimbursable() { const route = useRoute>(); const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'reimbursable', route.params.threadReportID ?? ''); const options = useMemo( diff --git a/src/pages/TransactionDuplicate/ReviewTag.tsx b/src/pages/TransactionDuplicate/ReviewTag.tsx index abab4d3e03f3..46c32b5f12ad 100644 --- a/src/pages/TransactionDuplicate/ReviewTag.tsx +++ b/src/pages/TransactionDuplicate/ReviewTag.tsx @@ -1,6 +1,7 @@ import type {RouteProp} from '@react-navigation/native'; import {useRoute} from '@react-navigation/native'; import React, {useMemo} from 'react'; +import {useOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -8,6 +9,7 @@ import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation' import {setReviewDuplicatesKey} from '@libs/actions/Transaction'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; import * as TransactionUtils from '@libs/TransactionUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {FieldItemType} from './ReviewFields'; import ReviewFields from './ReviewFields'; @@ -17,7 +19,8 @@ function ReviewTag() { const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'tag', route.params.threadReportID ?? ''); const options = useMemo( diff --git a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx index aa598bff8fcd..e52368f35005 100644 --- a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx +++ b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx @@ -23,7 +23,8 @@ function ReviewTaxRate() { const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`); const policy = PolicyUtils.getPolicy(report?.policyID ?? ''); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, navigateToNextScreen} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'taxCode', route.params.threadReportID ?? ''); const transaction = TransactionUtils.getTransaction(transactionID); diff --git a/src/types/onyx/ReviewDuplicates.ts b/src/types/onyx/ReviewDuplicates.ts index 0682ed0a7f7c..6c5ccbd93481 100644 --- a/src/types/onyx/ReviewDuplicates.ts +++ b/src/types/onyx/ReviewDuplicates.ts @@ -8,6 +8,9 @@ type ReviewDuplicates = { /** ID of transaction we want to keep */ transactionID: string; + /** ID of the transaction report we want to keep */ + reportID: string; + /** Merchant which user want to keep */ merchant: string; From 5fff73f2a953260d6e6719ea78d92ead9e4bfd98 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 16 Sep 2024 03:30:54 +0530 Subject: [PATCH 016/808] minor update. Signed-off-by: krishna2323 --- src/libs/TransactionUtils/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index a734995a60ea..1d5fe405ee70 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -943,7 +943,7 @@ function removeSettledAndApprovedTransactions(transactionIDs: string[]) { * 6. It returns the 'keep' and 'change' objects. */ -function compareDuplicateTransactionFields(transactionID: string): {keep: Partial; change: FieldsToChange} { +function compareDuplicateTransactionFields(transactionID: string, reportID: string): {keep: Partial; change: FieldsToChange} { const transactionViolations = allTransactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`]; const duplicates = transactionViolations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? []; const transactions = removeSettledAndApprovedTransactions([transactionID, ...duplicates]).map((item) => getTransaction(item)); From 9801ae89d3f0bf9ff300a2a4ed976b6ee9e2edad Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Tue, 17 Sep 2024 02:40:32 +0530 Subject: [PATCH 017/808] only add taxCode in changes if availble in policy. Signed-off-by: krishna2323 --- src/libs/TransactionUtils/index.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 1d5fe405ee70..9fb78eea1555 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -1024,12 +1024,10 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri const report = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; const policy = PolicyUtils.getPolicy(report?.policyID); const differentValues = getDifferentValues(transactions, keys); - const hasValidTaxes = differentValues?.filter((taxID) => PolicyUtils.getTaxByID(policy, (taxID as string) ?? '')?.name).length; + const validTaxes = differentValues?.filter((taxID) => PolicyUtils.getTaxByID(policy, (taxID as string) ?? '')?.name); - if (areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) || !hasValidTaxes) { - keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; - } else { - processChanges(fieldName, transactions, keys); + if (!areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) && validTaxes.length > 1) { + change[fieldName] = validTaxes; } } else if (areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|'))) { keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; From e43dcd15903ed4d3da9d7ecfb806aace4e0b81b6 Mon Sep 17 00:00:00 2001 From: dominictb Date: Tue, 24 Sep 2024 15:19:25 +0700 Subject: [PATCH 018/808] fix: add comment --- .../createCustomFullScreenNavigator/CustomFullScreenRouter.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx index ee6c2179c4b4..0994a25efea5 100644 --- a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx @@ -21,6 +21,7 @@ function adaptStateIfNecessary(state: StackState, isLoadingReportData: OnyxEntry : undefined; // There should always be WORKSPACE.INITIAL screen in the state to make sure go back works properly if we deeplinkg to a subpage of settings. + // The only exception is when the workspace is invalid or inaccessible. if (!isAtLeastOneInState(state, SCREENS.WORKSPACE.INITIAL)) { const policy = PolicyUtils.getPolicy(policyID ?? ''); const isPolicyAccessible = PolicyUtils.isPolicyAccessible(policy); From 32117b20050e7bce79e80d93ff9cb0cf0a87d153 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 30 Sep 2024 16:02:17 +0700 Subject: [PATCH 019/808] fix style progress bar --- src/components/ProgressBar.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ProgressBar.tsx b/src/components/ProgressBar.tsx index 63d3d1142d30..885fe337c002 100644 --- a/src/components/ProgressBar.tsx +++ b/src/components/ProgressBar.tsx @@ -67,11 +67,11 @@ function ProgressBar({shouldShow}: {shouldShow: boolean}) { }; }); - return isVisible.value ? ( + return ( - + {isVisible.value ? : null} - ) : null; + ); } ProgressBar.displayName = 'ProgressBar'; From 643c5c47ab2d21208af360d62d1691c7a1f29e0e Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Wed, 2 Oct 2024 15:17:04 +0100 Subject: [PATCH 020/808] Allow all even accountIDs to use "Create Expense" --- src/libs/AccountUtils.ts | 5 +---- src/libs/Permissions.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libs/AccountUtils.ts b/src/libs/AccountUtils.ts index b5b58bfbf70c..2d44e4d5ec8f 100644 --- a/src/libs/AccountUtils.ts +++ b/src/libs/AccountUtils.ts @@ -5,9 +5,6 @@ import type {Account} from '@src/types/onyx'; const isValidateCodeFormSubmitting = (account: OnyxEntry) => !!account?.isLoading && account.loadingForm === (account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); -/** Whether the accound ID is an odd number, useful for A/B testing. */ -const isAccountIDOddNumber = (accountID: number) => accountID % 2 === 1; - function isDelegateOnlySubmitter(account: OnyxEntry): boolean { const delegateEmail = account?.delegatedAccess?.delegate; const delegateRole = account?.delegatedAccess?.delegates?.find((delegate) => delegate.email === delegateEmail)?.role; @@ -15,4 +12,4 @@ function isDelegateOnlySubmitter(account: OnyxEntry): boolean { return delegateRole === CONST.DELEGATE_ROLE.SUBMITTER; } -export default {isValidateCodeFormSubmitting, isAccountIDOddNumber, isDelegateOnlySubmitter}; +export default {isValidateCodeFormSubmitting, isDelegateOnlySubmitter}; diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 7f7e89ad3585..e64d1f8b8a80 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -3,6 +3,9 @@ import CONST from '@src/CONST'; import type {IOUType} from '@src/CONST'; import type Beta from '@src/types/onyx/Beta'; import * as Environment from './Environment/Environment'; +import * as SessionUtils from './SessionUtils'; + +const isAccountIDEven = (accountID: number) => accountID % 2 === 0; function canUseAllBetas(betas: OnyxEntry): boolean { return !!betas?.includes(CONST.BETAS.ALL); @@ -45,9 +48,10 @@ function canUseWorkspaceRules(betas: OnyxEntry): boolean { return !!betas?.includes(CONST.BETAS.WORKSPACE_RULES) || canUseAllBetas(betas); } -function canUseCombinedTrackSubmit(betas: OnyxEntry): boolean { +function canUseCombinedTrackSubmit(): boolean { // We don't need to show this to all betas since this will be used for developing a feature for A/B testing. - return !!betas?.includes(CONST.BETAS.COMBINED_TRACK_SUBMIT); + const session = SessionUtils.getSession(); + return isAccountIDEven(session?.accountID ?? -1); } /** From 3791a3238c128e1dfa1605a810a573bb510646ae Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Wed, 2 Oct 2024 15:26:47 +0100 Subject: [PATCH 021/808] fix function call --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 687ef177609e..e5b749750520 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6961,7 +6961,7 @@ function canCreateRequest(report: OnyxEntry, policy: OnyxEntry, } const requestOptions = getMoneyRequestOptions(report, policy, participantAccountIDs); - if (Permissions.canUseCombinedTrackSubmit(allBetas ?? [])) { + if (Permissions.canUseCombinedTrackSubmit()) { requestOptions.push(CONST.IOU.TYPE.CREATE); } From b2b14cdc1033a168022dedca43baaa6b07518258 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Sun, 6 Oct 2024 15:37:21 +0530 Subject: [PATCH 022/808] feat: skip category review when category isn't present in policy. Signed-off-by: krishna2323 --- src/libs/TransactionUtils/index.ts | 13 ++++++++++++- src/libs/actions/Policy/Category.ts | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 71f103999c91..401e29976f71 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -3,6 +3,7 @@ import lodashIsEqual from 'lodash/isEqual'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import {getPolicyCategories} from '@libs/actions/Policy/Category'; import type {TransactionMergeParams} from '@libs/API/parameters'; import {getCurrencyDecimals} from '@libs/CurrencyUtils'; import DateUtils from '@libs/DateUtils'; @@ -1007,6 +1008,7 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri const keys = fieldsToCompare[fieldName]; const firstTransaction = transactions.at(0); const isFirstTransactionCommentEmptyObject = typeof firstTransaction?.comment === 'object' && firstTransaction?.comment?.comment === ''; + const report = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; if (fieldName === 'description') { const allCommentsAreEqual = areAllCommentsEqual(transactions, firstTransaction); @@ -1023,7 +1025,6 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri processChanges(fieldName, transactions, keys); } } else if (fieldName === 'taxCode') { - const report = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; const policy = PolicyUtils.getPolicy(report?.policyID); const differentValues = getDifferentValues(transactions, keys); const validTaxes = differentValues?.filter((taxID) => PolicyUtils.getTaxByID(policy, (taxID as string) ?? '')?.name); @@ -1031,6 +1032,16 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri if (!areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) && validTaxes.length > 1) { change[fieldName] = validTaxes; } + } else if (fieldName === 'category') { + const differentValues = getDifferentValues(transactions, keys); + const policyCategories = getPolicyCategories(report?.policyID ?? '-1'); + const availableCategories = Object.values(policyCategories) + .filter((category) => differentValues.includes(category.name)) + .map((e) => e.name); + + if (!areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) && availableCategories.length > 1) { + change[fieldName] = [...availableCategories, ...(differentValues.includes('') ? [''] : [])]; + } } else if (areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|'))) { keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } else { diff --git a/src/libs/actions/Policy/Category.ts b/src/libs/actions/Policy/Category.ts index e237ed80e293..2d4299cc224f 100644 --- a/src/libs/actions/Policy/Category.ts +++ b/src/libs/actions/Policy/Category.ts @@ -1331,6 +1331,10 @@ function setPolicyCategoryTax(policyID: string, categoryName: string, taxID: str API.write(WRITE_COMMANDS.SET_POLICY_CATEGORY_TAX, parameters, onyxData); } +function getPolicyCategories(policyID: string) { + return allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`] ?? {}; +} + export { openPolicyCategoriesPage, buildOptimisticPolicyRecentlyUsedCategories, @@ -1354,4 +1358,5 @@ export { setPolicyCategoryTax, importPolicyCategories, downloadCategoriesCSV, + getPolicyCategories, }; From 57bd4005b5c9982cb5e982ef4755da3b60002dda Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Sun, 6 Oct 2024 16:07:14 +0530 Subject: [PATCH 023/808] minor fix. Signed-off-by: krishna2323 --- src/pages/TransactionDuplicate/Confirmation.tsx | 2 +- src/pages/TransactionDuplicate/ReviewBillable.tsx | 2 +- src/pages/TransactionDuplicate/ReviewCategory.tsx | 2 +- src/pages/TransactionDuplicate/ReviewDescription.tsx | 2 +- src/pages/TransactionDuplicate/ReviewMerchant.tsx | 2 +- src/pages/TransactionDuplicate/ReviewReimbursable.tsx | 2 +- src/pages/TransactionDuplicate/ReviewTag.tsx | 2 +- src/pages/TransactionDuplicate/ReviewTaxCode.tsx | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pages/TransactionDuplicate/Confirmation.tsx b/src/pages/TransactionDuplicate/Confirmation.tsx index 15217e215ad4..a8d358184d77 100644 --- a/src/pages/TransactionDuplicate/Confirmation.tsx +++ b/src/pages/TransactionDuplicate/Confirmation.tsx @@ -38,7 +38,7 @@ function Confirmation() { const [reviewDuplicates, reviewDuplicatesResult] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); const transaction = useMemo(() => TransactionUtils.buildNewTransactionAfterReviewingDuplicates(reviewDuplicates), [reviewDuplicates]); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const {goBack} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'confirmation', route.params.threadReportID, route.params.backTo); const [report, reportResult] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`); const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transaction?.reportID}`); diff --git a/src/pages/TransactionDuplicate/ReviewBillable.tsx b/src/pages/TransactionDuplicate/ReviewBillable.tsx index 9b9900741c2c..166c61209a42 100644 --- a/src/pages/TransactionDuplicate/ReviewBillable.tsx +++ b/src/pages/TransactionDuplicate/ReviewBillable.tsx @@ -19,7 +19,7 @@ function ReviewBillable() { const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( Object.keys(compareResult.change ?? {}), diff --git a/src/pages/TransactionDuplicate/ReviewCategory.tsx b/src/pages/TransactionDuplicate/ReviewCategory.tsx index 5ded413d9f3f..b28cb6863137 100644 --- a/src/pages/TransactionDuplicate/ReviewCategory.tsx +++ b/src/pages/TransactionDuplicate/ReviewCategory.tsx @@ -19,7 +19,7 @@ function ReviewCategory() { const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( Object.keys(compareResult.change ?? {}), diff --git a/src/pages/TransactionDuplicate/ReviewDescription.tsx b/src/pages/TransactionDuplicate/ReviewDescription.tsx index e8ef70f9a70a..d3c379517cf1 100644 --- a/src/pages/TransactionDuplicate/ReviewDescription.tsx +++ b/src/pages/TransactionDuplicate/ReviewDescription.tsx @@ -19,7 +19,7 @@ function ReviewDescription() { const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( Object.keys(compareResult.change ?? {}), diff --git a/src/pages/TransactionDuplicate/ReviewMerchant.tsx b/src/pages/TransactionDuplicate/ReviewMerchant.tsx index 586857f7946f..d49a67d7d911 100644 --- a/src/pages/TransactionDuplicate/ReviewMerchant.tsx +++ b/src/pages/TransactionDuplicate/ReviewMerchant.tsx @@ -19,7 +19,7 @@ function ReviewMerchant() { const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( Object.keys(compareResult.change ?? {}), diff --git a/src/pages/TransactionDuplicate/ReviewReimbursable.tsx b/src/pages/TransactionDuplicate/ReviewReimbursable.tsx index dbddce9d208f..361b92c2af5a 100644 --- a/src/pages/TransactionDuplicate/ReviewReimbursable.tsx +++ b/src/pages/TransactionDuplicate/ReviewReimbursable.tsx @@ -19,7 +19,7 @@ function ReviewReimbursable() { const {translate} = useLocalize(); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( Object.keys(compareResult.change ?? {}), diff --git a/src/pages/TransactionDuplicate/ReviewTag.tsx b/src/pages/TransactionDuplicate/ReviewTag.tsx index db1e02db4809..16138865cfd0 100644 --- a/src/pages/TransactionDuplicate/ReviewTag.tsx +++ b/src/pages/TransactionDuplicate/ReviewTag.tsx @@ -21,7 +21,7 @@ function ReviewTag() { const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( Object.keys(compareResult.change ?? {}), diff --git a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx index ea75dc87c192..90e8c26656c9 100644 --- a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx +++ b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx @@ -24,7 +24,7 @@ function ReviewTaxRate() { const policy = PolicyUtils.getPolicy(report?.policyID ?? ''); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? ''); + const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( Object.keys(compareResult.change ?? {}), From 2124c249c02483ddda1aa3fa46a54a084f93b804 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Sun, 6 Oct 2024 16:09:18 +0530 Subject: [PATCH 024/808] minor update. Signed-off-by: krishna2323 --- src/libs/TransactionUtils/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 401e29976f71..3070eaa092a7 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -1039,7 +1039,10 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri .filter((category) => differentValues.includes(category.name)) .map((e) => e.name); - if (!areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) && availableCategories.length > 1) { + if ( + !areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) && + (availableCategories.length > 1 || (availableCategories.length === 1 && differentValues.includes(''))) + ) { change[fieldName] = [...availableCategories, ...(differentValues.includes('') ? [''] : [])]; } } else if (areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|'))) { From 1709905f776da09c567cc76349763a429de55406 Mon Sep 17 00:00:00 2001 From: Shahidullah Muffakir Date: Tue, 8 Oct 2024 22:42:35 +0530 Subject: [PATCH 025/808] migrate from withOnyx HOC to the useOnyx hook. --- src/components/MapView/MapView.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/MapView/MapView.tsx b/src/components/MapView/MapView.tsx index cbe604661c05..a72788fcc62f 100644 --- a/src/components/MapView/MapView.tsx +++ b/src/components/MapView/MapView.tsx @@ -3,7 +3,7 @@ import type {MapState} from '@rnmapbox/maps'; import Mapbox, {MarkerView, setAccessToken} from '@rnmapbox/maps'; import {forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import * as Expensicons from '@components/Icon/Expensicons'; import useTheme from '@hooks/useTheme'; @@ -21,11 +21,12 @@ import Direction from './Direction'; import type {MapViewHandle} from './MapViewTypes'; import PendingMapView from './PendingMapView'; import responder from './responder'; -import type {ComponentProps, MapViewOnyxProps} from './types'; +import type {ComponentProps} from './types'; import utils from './utils'; const MapView = forwardRef( - ({accessToken, style, mapPadding, userLocation, styleURL, pitchEnabled, initialState, waypoints, directionCoordinates, onMapReady, interactive = true}, ref) => { + ({accessToken, style, mapPadding, styleURL, pitchEnabled, initialState, waypoints, directionCoordinates, onMapReady, interactive = true}, ref) => { + const [userLocation] = useOnyx(ONYXKEYS.USER_LOCATION); const navigation = useNavigation(); const {isOffline} = useNetwork(); const {translate} = useLocalize(); @@ -298,8 +299,4 @@ const MapView = forwardRef( }, ); -export default withOnyx({ - userLocation: { - key: ONYXKEYS.USER_LOCATION, - }, -})(memo(MapView)); +export default memo(MapView); From 4bef7003eb8a3655663e3a63f428462db50efd1e Mon Sep 17 00:00:00 2001 From: Shahidullah Muffakir Date: Tue, 8 Oct 2024 23:02:04 +0530 Subject: [PATCH 026/808] remove userLocation from Props types and migrate from withOnyx HOC to useOnyx hook --- src/components/MapView/MapViewImpl.website.tsx | 13 +++++-------- src/components/MapView/types.ts | 8 ++------ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/components/MapView/MapViewImpl.website.tsx b/src/components/MapView/MapViewImpl.website.tsx index 7df277671043..5958b2939396 100644 --- a/src/components/MapView/MapViewImpl.website.tsx +++ b/src/components/MapView/MapViewImpl.website.tsx @@ -9,7 +9,7 @@ import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, import type {MapRef, ViewState} from 'react-map-gl'; import Map, {Marker} from 'react-map-gl'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import * as Expensicons from '@components/Icon/Expensicons'; import usePrevious from '@hooks/usePrevious'; @@ -29,7 +29,7 @@ import './mapbox.css'; import type {MapViewHandle} from './MapViewTypes'; import PendingMapView from './PendingMapView'; import responder from './responder'; -import type {ComponentProps, MapViewOnyxProps} from './types'; +import type {ComponentProps} from './types'; import utils from './utils'; const MapViewImpl = forwardRef( @@ -40,13 +40,14 @@ const MapViewImpl = forwardRef( waypoints, mapPadding, accessToken, - userLocation, directionCoordinates, initialState = {location: CONST.MAPBOX.DEFAULT_COORDINATE, zoom: CONST.MAPBOX.DEFAULT_ZOOM}, interactive = true, }, ref, ) => { + const [userLocation] = useOnyx(ONYXKEYS.USER_LOCATION); + const {isOffline} = useNetwork(); const {translate} = useLocalize(); @@ -295,8 +296,4 @@ const MapViewImpl = forwardRef( }, ); -export default withOnyx({ - userLocation: { - key: ONYXKEYS.USER_LOCATION, - }, -})(MapViewImpl); +export default MapViewImpl; diff --git a/src/components/MapView/types.ts b/src/components/MapView/types.ts index a0494a9ac499..77b1b9eb82c2 100644 --- a/src/components/MapView/types.ts +++ b/src/components/MapView/types.ts @@ -2,10 +2,6 @@ import type {OnyxEntry} from 'react-native-onyx'; import type * as OnyxTypes from '@src/types/onyx'; import type {MapViewProps} from './MapViewTypes'; -type MapViewOnyxProps = { - userLocation: OnyxEntry; -}; +type ComponentProps = MapViewProps; -type ComponentProps = MapViewProps & MapViewOnyxProps; - -export type {MapViewOnyxProps, ComponentProps}; +export type {ComponentProps}; From e7f3b6e14bf2044b274d44dfb24125f7ff2d0ca5 Mon Sep 17 00:00:00 2001 From: Shahidullah Muffakir Date: Tue, 8 Oct 2024 23:19:45 +0530 Subject: [PATCH 027/808] Address TypeScript errors --- src/components/MapView/MapView.website.tsx | 5 ++--- src/components/MapView/MapViewImpl.website.tsx | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/MapView/MapView.website.tsx b/src/components/MapView/MapView.website.tsx index 3a28943b575a..52cdaee902a3 100644 --- a/src/components/MapView/MapView.website.tsx +++ b/src/components/MapView/MapView.website.tsx @@ -4,11 +4,10 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import usePrevious from '@hooks/usePrevious'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MapViewHandle} from './MapViewTypes'; +import type {MapViewHandle, MapViewProps} from './MapViewTypes'; import PendingMapView from './PendingMapView'; -import type {ComponentProps} from './types'; -const MapView = forwardRef((props, ref) => { +const MapView = forwardRef((props, ref) => { const {isOffline} = useNetwork(); const {translate} = useLocalize(); const styles = useThemeStyles(); diff --git a/src/components/MapView/MapViewImpl.website.tsx b/src/components/MapView/MapViewImpl.website.tsx index 5958b2939396..5f68b041602e 100644 --- a/src/components/MapView/MapViewImpl.website.tsx +++ b/src/components/MapView/MapViewImpl.website.tsx @@ -26,13 +26,12 @@ import getCurrentPosition from '@src/libs/getCurrentPosition'; import ONYXKEYS from '@src/ONYXKEYS'; import Direction from './Direction'; import './mapbox.css'; -import type {MapViewHandle} from './MapViewTypes'; +import type {MapViewHandle, MapViewProps} from './MapViewTypes'; import PendingMapView from './PendingMapView'; import responder from './responder'; -import type {ComponentProps} from './types'; import utils from './utils'; -const MapViewImpl = forwardRef( +const MapViewImpl = forwardRef( ( { style, From 3cbc0df8fb4018812d46e92fd52c81b33f86a4ab Mon Sep 17 00:00:00 2001 From: Shahidullah Muffakir Date: Tue, 8 Oct 2024 23:25:09 +0530 Subject: [PATCH 028/808] deleted extra types file from Mapview --- src/components/MapView/MapView.tsx | 5 ++--- src/components/MapView/types.ts | 7 ------- 2 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 src/components/MapView/types.ts diff --git a/src/components/MapView/MapView.tsx b/src/components/MapView/MapView.tsx index a72788fcc62f..a611c3d62727 100644 --- a/src/components/MapView/MapView.tsx +++ b/src/components/MapView/MapView.tsx @@ -18,13 +18,12 @@ import useLocalize from '@src/hooks/useLocalize'; import useNetwork from '@src/hooks/useNetwork'; import ONYXKEYS from '@src/ONYXKEYS'; import Direction from './Direction'; -import type {MapViewHandle} from './MapViewTypes'; +import type {MapViewHandle, MapViewProps} from './MapViewTypes'; import PendingMapView from './PendingMapView'; import responder from './responder'; -import type {ComponentProps} from './types'; import utils from './utils'; -const MapView = forwardRef( +const MapView = forwardRef( ({accessToken, style, mapPadding, styleURL, pitchEnabled, initialState, waypoints, directionCoordinates, onMapReady, interactive = true}, ref) => { const [userLocation] = useOnyx(ONYXKEYS.USER_LOCATION); const navigation = useNavigation(); diff --git a/src/components/MapView/types.ts b/src/components/MapView/types.ts deleted file mode 100644 index 77b1b9eb82c2..000000000000 --- a/src/components/MapView/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type {OnyxEntry} from 'react-native-onyx'; -import type * as OnyxTypes from '@src/types/onyx'; -import type {MapViewProps} from './MapViewTypes'; - -type ComponentProps = MapViewProps; - -export type {ComponentProps}; From 801c3678937740e61db937a5cc32ae33d236fb79 Mon Sep 17 00:00:00 2001 From: Shahidullah Muffakir Date: Tue, 8 Oct 2024 23:39:53 +0530 Subject: [PATCH 029/808] Remove unused @ts-expect-error directive from MapView --- src/components/MapView/MapView.website.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/MapView/MapView.website.tsx b/src/components/MapView/MapView.website.tsx index 52cdaee902a3..b89bfa19e98e 100644 --- a/src/components/MapView/MapView.website.tsx +++ b/src/components/MapView/MapView.website.tsx @@ -50,7 +50,6 @@ const MapView = forwardRef((props, ref) => { } > Date: Thu, 10 Oct 2024 00:38:39 +0530 Subject: [PATCH 030/808] minor fix. Signed-off-by: krishna2323 --- src/libs/actions/Policy/Category.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/libs/actions/Policy/Category.ts b/src/libs/actions/Policy/Category.ts index a49a5e5c733f..78b0f2dec9e2 100644 --- a/src/libs/actions/Policy/Category.ts +++ b/src/libs/actions/Policy/Category.ts @@ -1346,10 +1346,6 @@ function setPolicyCategoryTax(policyID: string, categoryName: string, taxID: str API.write(WRITE_COMMANDS.SET_POLICY_CATEGORY_TAX, parameters, onyxData); } -function getPolicyCategories(policyID: string) { - return allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`] ?? {}; -} - export { getPolicyCategories, openPolicyCategoriesPage, @@ -1374,5 +1370,4 @@ export { setPolicyCategoryTax, importPolicyCategories, downloadCategoriesCSV, - getPolicyCategories, }; From d8cecc998c28b73e41c027f6b395cf9b41065663 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Thu, 10 Oct 2024 01:05:06 +0530 Subject: [PATCH 031/808] fix category dupe step skip. Signed-off-by: krishna2323 --- src/libs/TransactionUtils/index.ts | 6 +++--- src/libs/actions/Policy/Category.ts | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 3070eaa092a7..cd2c6544b199 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -3,7 +3,7 @@ import lodashIsEqual from 'lodash/isEqual'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; -import {getPolicyCategories} from '@libs/actions/Policy/Category'; +import {getPolicyCategoriesData} from '@libs/actions/Policy/Category'; import type {TransactionMergeParams} from '@libs/API/parameters'; import {getCurrencyDecimals} from '@libs/CurrencyUtils'; import DateUtils from '@libs/DateUtils'; @@ -1034,9 +1034,9 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri } } else if (fieldName === 'category') { const differentValues = getDifferentValues(transactions, keys); - const policyCategories = getPolicyCategories(report?.policyID ?? '-1'); + const policyCategories = getPolicyCategoriesData(report?.policyID ?? '-1'); const availableCategories = Object.values(policyCategories) - .filter((category) => differentValues.includes(category.name)) + .filter((category) => differentValues.includes(category.name) && firstTransaction?.category !== category.name) .map((e) => e.name); if ( diff --git a/src/libs/actions/Policy/Category.ts b/src/libs/actions/Policy/Category.ts index 78b0f2dec9e2..41771ac5aa0e 100644 --- a/src/libs/actions/Policy/Category.ts +++ b/src/libs/actions/Policy/Category.ts @@ -1346,6 +1346,10 @@ function setPolicyCategoryTax(policyID: string, categoryName: string, taxID: str API.write(WRITE_COMMANDS.SET_POLICY_CATEGORY_TAX, parameters, onyxData); } +function getPolicyCategoriesData(policyID: string) { + return allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`] ?? {}; +} + export { getPolicyCategories, openPolicyCategoriesPage, @@ -1370,4 +1374,5 @@ export { setPolicyCategoryTax, importPolicyCategories, downloadCategoriesCSV, + getPolicyCategoriesData, }; From 09e9fb1144ed14b41f14d77a766e055ff21bc8cb Mon Sep 17 00:00:00 2001 From: dominictb Date: Fri, 11 Oct 2024 14:56:11 +0700 Subject: [PATCH 032/808] do not use hook to get isLoadingReportData --- .../CustomFullScreenRouter.tsx | 12 ++++-------- src/libs/PolicyUtils.ts | 9 ++++++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx index e6c190d4002b..e09de8fce287 100644 --- a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx @@ -1,10 +1,7 @@ import type {ParamListBase, PartialState, RouterConfigOptions, StackNavigationState} from '@react-navigation/native'; import {StackRouter} from '@react-navigation/native'; -import {useOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx'; import getIsNarrowLayout from '@libs/getIsNarrowLayout'; import * as PolicyUtils from '@libs/PolicyUtils'; -import ONYXKEYS from '@src/ONYXKEYS'; import SCREENS from '@src/SCREENS'; import type {FullScreenNavigatorRouterOptions} from './types'; @@ -12,7 +9,7 @@ type StackState = StackNavigationState | PartialState state.routes.some((route) => route.name === screenName); -function adaptStateIfNecessary(state: StackState, isLoadingReportData: OnyxEntry) { +function adaptStateIfNecessary(state: StackState) { const isNarrowLayout = getIsNarrowLayout(); const workspaceCentralPane = state.routes.at(-1); const policyID = @@ -25,7 +22,7 @@ function adaptStateIfNecessary(state: StackState, isLoadingReportData: OnyxEntry if (!isAtLeastOneInState(state, SCREENS.WORKSPACE.INITIAL)) { const policy = PolicyUtils.getPolicy(policyID ?? ''); const isPolicyAccessible = PolicyUtils.isPolicyAccessible(policy); - if (!isLoadingReportData && !isPolicyAccessible) { + if (!isPolicyAccessible) { return; } @@ -66,13 +63,12 @@ function adaptStateIfNecessary(state: StackState, isLoadingReportData: OnyxEntry function CustomFullScreenRouter(options: FullScreenNavigatorRouterOptions) { const stackRouter = StackRouter(options); - const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA, {initialValue: true}); return { ...stackRouter, getInitialState({routeNames, routeParamList, routeGetIdList}: RouterConfigOptions) { const initialState = stackRouter.getInitialState({routeNames, routeParamList, routeGetIdList}); - adaptStateIfNecessary(initialState, isLoadingReportData); + adaptStateIfNecessary(initialState); // If we needed to modify the state we need to rehydrate it to get keys for new routes. if (initialState.stale) { @@ -82,7 +78,7 @@ function CustomFullScreenRouter(options: FullScreenNavigatorRouterOptions) { return initialState; }, getRehydratedState(partialState: StackState, {routeNames, routeParamList, routeGetIdList}: RouterConfigOptions): StackNavigationState { - adaptStateIfNecessary(partialState, isLoadingReportData); + adaptStateIfNecessary(partialState); const state = stackRouter.getRehydratedState(partialState, {routeNames, routeParamList, routeGetIdList}); return state; }, diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 24287e5b265e..b8ccf21616b4 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -55,6 +55,13 @@ Onyx.connect({ callback: (value) => (allPolicies = value), }); +let isLoadingReportData = true; +Onyx.connect({ + key: ONYXKEYS.IS_LOADING_REPORT_DATA, + initWithStoredValues: false, + callback: (value) => (isLoadingReportData = value ?? false), +}); + /** * Filter out the active policies, which will exclude policies with pending deletion * These are policies that we can use to create reports with in NewDot. @@ -1041,7 +1048,7 @@ function getWorkflowApprovalsUnavailable(policy: OnyxEntry) { } function isPolicyAccessible(policy: OnyxEntry) { - return !isEmptyObject(policy) && (Object.keys(policy).length !== 1 || isEmptyObject(policy.errors)) && policy?.id; + return !isLoadingReportData && !isEmptyObject(policy) && (Object.keys(policy).length !== 1 || isEmptyObject(policy.errors)) && policy?.id; } export { From 6d07d46ae17c867d108cab7cdcd77649d76cb8d9 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 14 Oct 2024 03:41:22 +0530 Subject: [PATCH 033/808] feat: skip tags review if no valid tags are available. Signed-off-by: krishna2323 --- src/libs/TransactionUtils/index.ts | 35 +++++++++++++++++++++++++----- src/libs/actions/Policy/Tag.ts | 5 +++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index a627a7e61fd9..0e308af2692e 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -4,6 +4,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import {getPolicyCategoriesData} from '@libs/actions/Policy/Category'; +import {getPolicyTagsData} from '@libs/actions/Policy/Tag'; import type {TransactionMergeParams} from '@libs/API/parameters'; import {getCurrencyDecimals} from '@libs/CurrencyUtils'; import DateUtils from '@libs/DateUtils'; @@ -1014,6 +1015,8 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri const isFirstTransactionCommentEmptyObject = typeof firstTransaction?.comment === 'object' && firstTransaction?.comment?.comment === ''; const report = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; + const areAllFieldsEqualForKey = areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')); + if (fieldName === 'description') { const allCommentsAreEqual = areAllCommentsEqual(transactions, firstTransaction); const allCommentsAreEmpty = isFirstTransactionCommentEmptyObject && transactions.every((item) => getDescription(item) === ''); @@ -1033,8 +1036,10 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri const differentValues = getDifferentValues(transactions, keys); const validTaxes = differentValues?.filter((taxID) => PolicyUtils.getTaxByID(policy, (taxID as string) ?? '')?.name); - if (!areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) && validTaxes.length > 1) { + if (!areAllFieldsEqualForKey && validTaxes.length > 1) { change[fieldName] = validTaxes; + } else { + keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } } else if (fieldName === 'category') { const differentValues = getDifferentValues(transactions, keys); @@ -1043,13 +1048,31 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri .filter((category) => differentValues.includes(category.name) && firstTransaction?.category !== category.name) .map((e) => e.name); - if ( - !areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')) && - (availableCategories.length > 1 || (availableCategories.length === 1 && differentValues.includes(''))) - ) { + if (!areAllFieldsEqualForKey && (availableCategories.length > 1 || (availableCategories.length === 1 && differentValues.includes('')))) { change[fieldName] = [...availableCategories, ...(differentValues.includes('') ? [''] : [])]; + } else { + keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; + } + } else if (fieldName === 'tag') { + const policyTags = getPolicyTagsData(report?.policyID ?? '-1'); + const isMultiLevelTags = PolicyUtils.isMultiLevelTags(policyTags); + if (isMultiLevelTags) { + if (areAllFieldsEqualForKey) { + keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; + } else { + processChanges(fieldName, transactions, keys); + } + } else { + const differentValues = getDifferentValues(transactions, keys); + const policyTagsObj = Object.values(Object.values(policyTags).at(0)?.tags ?? {}); + const availableTags = policyTagsObj.filter((tag) => differentValues.includes(tag.name) && firstTransaction?.tag !== tag.name).map((e) => e.name); + if (!areAllFieldsEqualForKey && (availableTags.length > 1 || (availableTags.length === 1 && differentValues.includes('')))) { + change[fieldName] = [...availableTags, ...(differentValues.includes('') ? [''] : [])]; + } else { + keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; + } } - } else if (areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|'))) { + } else if (areAllFieldsEqualForKey) { keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } else { processChanges(fieldName, transactions, keys); diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index 7708921f57b5..772e748ad4f2 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -1040,6 +1040,10 @@ function downloadTagsCSV(policyID: string, onDownloadFailed: () => void) { fileDownload(ApiUtils.getCommandURL({command: WRITE_COMMANDS.EXPORT_TAGS_CSV}), fileName, '', false, formData, CONST.NETWORK.METHOD.POST, onDownloadFailed); } +function getPolicyTagsData(policyID: string) { + return allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {}; +} + export { buildOptimisticPolicyRecentlyUsedTags, setPolicyRequiresTag, @@ -1058,6 +1062,7 @@ export { setPolicyTagApprover, importPolicyTags, downloadTagsCSV, + getPolicyTagsData, }; export type {NewCustomUnit}; From bd352700e4209128f32a17a382ec81af53367425 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 14 Oct 2024 16:36:45 +0700 Subject: [PATCH 034/808] build optimistic change field action --- src/libs/ReportUtils.ts | 58 +++++++++++++++++++++++++++++++++++++- src/libs/actions/Report.ts | 27 ++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 2623fab86a05..a53c3d32d4a1 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -53,7 +53,7 @@ import type {OriginalMessageChangeLog, PaymentMethodType} from '@src/types/onyx/ import type {Status} from '@src/types/onyx/PersonalDetails'; import type {ConnectionName} from '@src/types/onyx/Policy'; import type {NotificationPreference, Participants, PendingChatMember, Participant as ReportParticipant} from '@src/types/onyx/Report'; -import type {Message, ReportActions} from '@src/types/onyx/ReportAction'; +import type {Message, OldDotReportAction, ReportActions} from '@src/types/onyx/ReportAction'; import type {Comment, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; @@ -258,6 +258,11 @@ type OptimisticCancelPaymentReportAction = Pick< 'actionName' | 'actorAccountID' | 'message' | 'originalMessage' | 'person' | 'reportActionID' | 'shouldShow' | 'created' | 'pendingAction' >; +type OptimisticChangeFieldAction = Pick< + OldDotReportAction & ReportAction, + 'actionName' | 'actorAccountID' | 'originalMessage' | 'person' | 'reportActionID' | 'created' | 'pendingAction' | 'message' +>; + type OptimisticEditedTaskReportAction = Pick< ReportAction, 'reportActionID' | 'actionName' | 'pendingAction' | 'actorAccountID' | 'automatic' | 'avatar' | 'created' | 'shouldShow' | 'message' | 'person' | 'delegateAccountID' @@ -2539,6 +2544,56 @@ function getReimbursementDeQueuedActionMessage( return Localize.translateLocal('iou.canceledRequest', {submitterDisplayName, amount: formattedAmount}); } +/** + * Builds an optimistic REIMBURSEMENT_DEQUEUED report action with a randomly generated reportActionID. + * + */ +function buildOptimisticChangeFieldAction(reportField: PolicyReportField, previousReportField: PolicyReportField): OptimisticChangeFieldAction { + return { + actionName: CONST.REPORT.ACTIONS.TYPE.CHANGE_FIELD, + actorAccountID: currentUserAccountID, + message: [ + { + type: 'TEXT', + style: 'strong', + text: 'You', + }, + { + type: 'TEXT', + style: 'normal', + text: ` modified field '${reportField.name}'.`, + }, + { + type: 'TEXT', + style: 'normal', + text: ` New value is '${reportField.value}'`, + }, + { + type: 'TEXT', + style: 'normal', + text: ` (previously '${previousReportField.value}').`, + }, + ], + originalMessage: { + fieldName: reportField.name, + newType: reportField.type, + newValue: reportField.value, + oldType: previousReportField.type, + oldValue: previousReportField.value, + }, + person: [ + { + style: 'strong', + text: getCurrentUserDisplayNameOrEmail(), + type: 'TEXT', + }, + ], + reportActionID: NumberUtils.rand64(), + created: DateUtils.getDBTime(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }; +} + /** * Builds an optimistic REIMBURSEMENT_DEQUEUED report action with a randomly generated reportActionID. * @@ -8470,6 +8525,7 @@ export { hasMissingInvoiceBankAccount, reasonForReportToBeInOptionList, getReasonAndReportActionThatRequiresAttention, + buildOptimisticChangeFieldAction, }; export type { diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 13b14d380758..57d5d7e8e287 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1909,6 +1909,8 @@ function updateReportField(reportID: string, reportField: PolicyReportField, pre const fieldViolation = ReportUtils.getFieldViolation(reportViolations, reportField); const recentlyUsedValues = allRecentlyUsedReportFields?.[fieldKey] ?? []; + const optimisticChangeFieldAction = ReportUtils.buildOptimisticChangeFieldAction(reportField, previousReportField); + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -1922,6 +1924,13 @@ function updateReportField(reportID: string, reportField: PolicyReportField, pre }, }, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticChangeFieldAction.reportActionID]: optimisticChangeFieldAction, + }, + }, ]; if (fieldViolation) { @@ -1962,6 +1971,15 @@ function updateReportField(reportID: string, reportField: PolicyReportField, pre }, }, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticChangeFieldAction.reportActionID]: { + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('report.genericUpdateReportFieldFailureMessage'), + }, + }, + }, ]; if (reportField.type === 'dropdown') { @@ -1987,6 +2005,15 @@ function updateReportField(reportID: string, reportField: PolicyReportField, pre }, }, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticChangeFieldAction.reportActionID]: { + pendingAction: null, + }, + }, + }, ]; const parameters = { From aa64f7e326e644586087632e2ee4b757640e6801 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Mon, 14 Oct 2024 18:53:43 +0530 Subject: [PATCH 035/808] minor fix. Signed-off-by: krishna2323 --- src/libs/TransactionUtils/index.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 0e308af2692e..0a3c18ec7a89 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -1038,8 +1038,6 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri if (!areAllFieldsEqualForKey && validTaxes.length > 1) { change[fieldName] = validTaxes; - } else { - keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } } else if (fieldName === 'category') { const differentValues = getDifferentValues(transactions, keys); @@ -1050,8 +1048,6 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri if (!areAllFieldsEqualForKey && (availableCategories.length > 1 || (availableCategories.length === 1 && differentValues.includes('')))) { change[fieldName] = [...availableCategories, ...(differentValues.includes('') ? [''] : [])]; - } else { - keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } } else if (fieldName === 'tag') { const policyTags = getPolicyTagsData(report?.policyID ?? '-1'); @@ -1068,8 +1064,6 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri const availableTags = policyTagsObj.filter((tag) => differentValues.includes(tag.name) && firstTransaction?.tag !== tag.name).map((e) => e.name); if (!areAllFieldsEqualForKey && (availableTags.length > 1 || (availableTags.length === 1 && differentValues.includes('')))) { change[fieldName] = [...availableTags, ...(differentValues.includes('') ? [''] : [])]; - } else { - keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } } } else if (areAllFieldsEqualForKey) { From 3fb2bea0fc36361b555dfbe410c4dc26f8f9c8a9 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 14 Oct 2024 21:42:23 +0700 Subject: [PATCH 036/808] add parameter --- src/libs/actions/Report.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 57d5d7e8e287..f69c3fce4fb5 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2019,6 +2019,7 @@ function updateReportField(reportID: string, reportField: PolicyReportField, pre const parameters = { reportID, reportFields: JSON.stringify({[fieldKey]: reportField}), + reportFieldsActionIDs: JSON.stringify({[fieldKey]: optimisticChangeFieldAction.reportActionID}), }; API.write(WRITE_COMMANDS.SET_REPORT_FIELD, parameters, {optimisticData, failureData, successData}); From 249e28ce40206d8e91f8528c6cd834003815568c Mon Sep 17 00:00:00 2001 From: thelullabyy Date: Tue, 15 Oct 2024 11:38:24 +0700 Subject: [PATCH 037/808] fix: unify distance rates display --- src/CONST.ts | 1 + src/libs/CurrencyUtils.ts | 3 ++- src/libs/PolicyUtils.ts | 5 ++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 996354e3d60c..277348d97ce7 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5541,6 +5541,7 @@ const CONST = { MAX_TAX_RATE_INTEGER_PLACES: 4, MAX_TAX_RATE_DECIMAL_PLACES: 4, + MIN_TAX_RATE_DECIMAL_PLACES: 2, DOWNLOADS_PATH: '/Downloads', DOWNLOADS_TIMEOUT: 5000, diff --git a/src/libs/CurrencyUtils.ts b/src/libs/CurrencyUtils.ts index f9ac681cb468..b701a32a7c98 100644 --- a/src/libs/CurrencyUtils.ts +++ b/src/libs/CurrencyUtils.ts @@ -164,7 +164,8 @@ function convertAmountToDisplayString(amount = 0, currency: string = CONST.CURRE return NumberFormatUtils.format(BaseLocaleListener.getPreferredLocale(), convertedAmount, { style: 'currency', currency, - minimumFractionDigits: CONST.MAX_TAX_RATE_DECIMAL_PLACES, + minimumFractionDigits: CONST.MIN_TAX_RATE_DECIMAL_PLACES, + maximumFractionDigits: CONST.MAX_TAX_RATE_DECIMAL_PLACES, }); } diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 6a1a61afa05d..95e1ffd85ce1 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -120,7 +120,7 @@ function getNumericValue(value: number | string, toLocaleDigit: (arg: string) => if (Number.isNaN(numValue)) { return NaN; } - return numValue.toFixed(CONST.CUSTOM_UNITS.RATE_DECIMALS); + return numValue.toFixed(CONST.MAX_TAX_RATE_DECIMAL_PLACES); } /** @@ -147,8 +147,7 @@ function getRateDisplayValue(value: number, toLocaleDigit: (arg: string) => stri if (withDecimals) { const decimalPart = numValue.toString().split('.').at(1); if (decimalPart) { - const fixedDecimalPoints = decimalPart.length > 2 && !decimalPart.endsWith('0') ? 3 : 2; - return Number(numValue).toFixed(fixedDecimalPoints).toString().replace('.', toLocaleDigit('.')); + return Number(numValue).toFixed(CONST.MAX_TAX_RATE_DECIMAL_PLACES).toString().replace('.', toLocaleDigit('.')); } } From ece998d26fe90da12b61ffe3a869189a635eb79b Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 15 Oct 2024 15:27:55 +0200 Subject: [PATCH 038/808] android support, ios wip --- src/libs/actions/Delegate.ts | 7 +++++++ src/libs/actions/Session/index.ts | 22 +++++++++++++++------- src/types/modules/react-native.d.ts | 1 + 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index 06d7093df385..b75801779f5b 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -1,3 +1,4 @@ +import {NativeModules} from 'react-native'; import Onyx from 'react-native-onyx'; import type {OnyxUpdate} from 'react-native-onyx'; import * as API from '@libs/API'; @@ -6,6 +7,7 @@ import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import Log from '@libs/Log'; import * as NetworkStore from '@libs/Network/NetworkStore'; +import {getCurrentUserEmail} from '@libs/Network/NetworkStore'; import * as SequentialQueue from '@libs/Network/SequentialQueue'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -97,6 +99,8 @@ function connect(email: string) { NetworkStore.setAuthToken(response?.restrictedToken ?? null); confirmReadyToOpenApp(); openApp(); + + NativeModules.HybridAppModule.switchAccounts(email); }); }) .catch((error) => { @@ -160,6 +164,8 @@ function disconnect() { NetworkStore.setAuthToken(response?.authToken ?? null); confirmReadyToOpenApp(); openApp(); + + NativeModules.HybridAppModule.switchAccounts(getCurrentUserEmail() ?? ''); }); }) .catch((error) => { @@ -573,4 +579,5 @@ export { clearDelegateRolePendingAction, updateDelegateRole, removeDelegate, + KEYS_TO_PRESERVE_DELEGATE_ACCESS, }; diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index 4d6ba6cfa774..4d621c15d39f 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -40,6 +40,7 @@ import Timers from '@libs/Timers'; import {hideContextMenu} from '@pages/home/report/ContextMenu/ReportActionContextMenu'; import {KEYS_TO_PRESERVE, openApp} from '@userActions/App'; import * as App from '@userActions/App'; +import {KEYS_TO_PRESERVE_DELEGATE_ACCESS} from '@userActions/Delegate'; import * as Device from '@userActions/Device'; import * as PriorityMode from '@userActions/PriorityMode'; import redirectToSignIn from '@userActions/SignInRedirect'; @@ -482,19 +483,26 @@ function signUpUser() { function signInAfterTransitionFromOldDot(transitionURL: string) { const [route, queryParams] = transitionURL.split('?'); - const {email, authToken, encryptedAuthToken, accountID, autoGeneratedLogin, autoGeneratedPassword, clearOnyxOnStart, completedHybridAppOnboarding} = Object.fromEntries( - queryParams.split('&').map((param) => { - const [key, value] = param.split('='); - return [key, value]; - }), - ); + const {email, authToken, encryptedAuthToken, accountID, autoGeneratedLogin, autoGeneratedPassword, clearOnyxOnStart, completedHybridAppOnboarding, shouldRemoveDelegatedAccess} = + Object.fromEntries( + queryParams.split('&').map((param) => { + const [key, value] = param.split('='); + return [key, value]; + }), + ); const setSessionDataAndOpenApp = () => { Onyx.multiSet({ [ONYXKEYS.SESSION]: {email, authToken, encryptedAuthToken: decodeURIComponent(encryptedAuthToken), accountID: Number(accountID)}, [ONYXKEYS.CREDENTIALS]: {autoGeneratedLogin, autoGeneratedPassword}, [ONYXKEYS.NVP_TRYNEWDOT]: {classicRedirect: {completedHybridAppOnboarding: completedHybridAppOnboarding === 'true'}}, - }).then(App.openApp); + }).then(() => { + if (shouldRemoveDelegatedAccess) { + Onyx.clear(KEYS_TO_PRESERVE_DELEGATE_ACCESS).then(App.openApp); + } else { + App.openApp(); + } + }); }; if (clearOnyxOnStart === 'true') { diff --git a/src/types/modules/react-native.d.ts b/src/types/modules/react-native.d.ts index 40c5b72ce1e4..1e4a942deb04 100644 --- a/src/types/modules/react-native.d.ts +++ b/src/types/modules/react-native.d.ts @@ -8,6 +8,7 @@ import type StartupTimer from '@libs/StartupTimer/types'; type HybridAppModule = { closeReactNativeApp: (shouldSignOut: boolean, shouldSetNVP: boolean) => void; completeOnboarding: (status: boolean) => void; + switchAccounts: (newDotCurrentAccount: string) => void; exitApp: () => void; }; From 54f0842cbee9356f20ecb15e6909f116f66cdbed Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Tue, 15 Oct 2024 16:24:25 -0400 Subject: [PATCH 039/808] check for new authTokens --- src/libs/actions/OnyxUpdateManager/index.ts | 33 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/OnyxUpdateManager/index.ts b/src/libs/actions/OnyxUpdateManager/index.ts index db00a55aa25b..085e05b0a449 100644 --- a/src/libs/actions/OnyxUpdateManager/index.ts +++ b/src/libs/actions/OnyxUpdateManager/index.ts @@ -1,11 +1,13 @@ -import type {OnyxEntry} from 'react-native-onyx'; +import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import * as ActiveClientManager from '@libs/ActiveClientManager'; import Log from '@libs/Log'; +import * as NetworkStore from '@libs/Network/NetworkStore'; import * as SequentialQueue from '@libs/Network/SequentialQueue'; import * as App from '@userActions/App'; +import updateSessionAuthTokens from '@userActions/Session/updateSessionAuthTokens'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {OnyxUpdatesFromServer} from '@src/types/onyx'; +import type {OnyxUpdatesFromServer, Session} from '@src/types/onyx'; import {isValidOnyxUpdateFromServer} from '@src/types/onyx/OnyxUpdatesFromServer'; import * as OnyxUpdateManagerUtils from './utils'; import * as DeferredOnyxUpdates from './utils/DeferredOnyxUpdates'; @@ -90,6 +92,10 @@ function handleOnyxUpdateGap(onyxUpdatesFromServer: OnyxEntry): void { + // Consolidate all of the given Onyx updates + const onyxUpdates: OnyxUpdate[] = []; + onyxUpdatesFromServer?.updates?.forEach((updateEvent) => onyxUpdates.push(...updateEvent.data)); + onyxUpdates.push(...(onyxUpdatesFromServer?.response?.onyxData ?? [])); + + // Find any session updates + const sessionUpdates = onyxUpdates?.filter((onyxUpdate) => onyxUpdate.key === ONYXKEYS.SESSION); + + // If any of the updates changes the authToken, let's update it now + sessionUpdates?.forEach((sessionUpdate) => { + const session = (sessionUpdate.value ?? {}) as Session; + const newAuthToken = session.authToken ?? ''; + if (!newAuthToken) { + return; + } + + Log.info('[OnyxUpdateManager] Found an authToken update while handling an Onyx update gap. Updating the authToken.'); + updateSessionAuthTokens(newAuthToken); + NetworkStore.setAuthToken(newAuthToken); + }); +} + export default () => { console.debug('[OnyxUpdateManager] Listening for updates from the server'); Onyx.connect({ From b4093f2c3a6908cc0e37ead4bb215ca680d860ef Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Tue, 15 Oct 2024 17:31:50 -0400 Subject: [PATCH 040/808] navigate to the enable payments page after validating --- src/components/SettlementButton/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index f371545ab7b0..ff522a494b1c 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -190,7 +190,7 @@ function SettlementButton({ if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA) { if (!isUserValidated) { - Navigation.navigate(ROUTES.SETTINGS_WALLET_VERIFY_ACCOUNT.getRoute()); + Navigation.navigate(ROUTES.SETTINGS_WALLET_VERIFY_ACCOUNT.getRoute(ROUTES.SETTINGS_ENABLE_PAYMENTS)); return; } triggerKYCFlow(event, iouPaymentType); From 92a86acf372ce0bdd141cf43b687f951ca100d62 Mon Sep 17 00:00:00 2001 From: war-in Date: Wed, 16 Oct 2024 13:00:15 +0200 Subject: [PATCH 041/808] fix typo --- src/libs/actions/Delegate.ts | 4 ++-- src/types/modules/react-native.d.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts index b75801779f5b..af1dd7600b04 100644 --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -100,7 +100,7 @@ function connect(email: string) { confirmReadyToOpenApp(); openApp(); - NativeModules.HybridAppModule.switchAccounts(email); + NativeModules.HybridAppModule.switchAccount(email); }); }) .catch((error) => { @@ -165,7 +165,7 @@ function disconnect() { confirmReadyToOpenApp(); openApp(); - NativeModules.HybridAppModule.switchAccounts(getCurrentUserEmail() ?? ''); + NativeModules.HybridAppModule.switchAccount(getCurrentUserEmail() ?? ''); }); }) .catch((error) => { diff --git a/src/types/modules/react-native.d.ts b/src/types/modules/react-native.d.ts index 1e4a942deb04..a08e17c28f4a 100644 --- a/src/types/modules/react-native.d.ts +++ b/src/types/modules/react-native.d.ts @@ -8,7 +8,7 @@ import type StartupTimer from '@libs/StartupTimer/types'; type HybridAppModule = { closeReactNativeApp: (shouldSignOut: boolean, shouldSetNVP: boolean) => void; completeOnboarding: (status: boolean) => void; - switchAccounts: (newDotCurrentAccount: string) => void; + switchAccount: (newDotCurrentAccount: string) => void; exitApp: () => void; }; From 58663255a5c7d8eaf92eb41dd27b93998426bda7 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 16 Oct 2024 23:49:06 +0500 Subject: [PATCH 042/808] hide expensify from new chat page --- src/libs/OptionsListUtils.ts | 2 +- src/pages/NewChatPage.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index fbf2f3b94c7c..1ede98338f87 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1994,7 +1994,7 @@ function getOptions( allPersonalDetailsOptions = lodashOrderBy(allPersonalDetailsOptions, [(personalDetail) => personalDetail.text?.toLowerCase()], 'asc'); } - const optionsToExclude: Option[] = []; + const optionsToExclude: Option[] = [{login: CONST.EMAIL.NOTIFICATIONS}]; // If we're including selected options from the search results, we only want to exclude them if the search input is empty // This is because on certain pages, we show the selected options at the top when the search input is empty diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index c406f7f3058c..494e099933fe 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -229,7 +229,7 @@ function NewChatPage({isGroupChat}: NewChatPageProps) { const itemRightSideComponent = useCallback( (item: ListItem & OptionsListUtils.Option, isFocused?: boolean) => { - if (!!item.isSelfDM || (item.accountID && CONST.NON_ADDABLE_ACCOUNT_IDS.includes(item.accountID))) { + if (!!item.isSelfDM || (item.login && excludedGroupEmails.includes(item.login))) { return null; } /** From 039f0d6982b91199c18400bf4bafccfa3a0a6390 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 17 Oct 2024 00:12:55 +0500 Subject: [PATCH 043/808] fix type error --- src/pages/NewChatPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 494e099933fe..bd3e30a48cf4 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -38,7 +38,7 @@ type NewChatPageProps = { isGroupChat?: boolean; }; -const excludedGroupEmails = CONST.EXPENSIFY_EMAILS.filter((value) => value !== CONST.EMAIL.CONCIERGE); +const excludedGroupEmails: Array = CONST.EXPENSIFY_EMAILS.filter((value) => value !== CONST.EMAIL.CONCIERGE); function useOptions({isGroupChat}: NewChatPageProps) { const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); From 0fd9a41a1e274fbf11b4d7c0b8aef6f9ade3d4aa Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 17 Oct 2024 00:28:04 +0500 Subject: [PATCH 044/808] fix lint error --- src/pages/NewChatPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index bd3e30a48cf4..5b44659babab 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -38,7 +38,7 @@ type NewChatPageProps = { isGroupChat?: boolean; }; -const excludedGroupEmails: Array = CONST.EXPENSIFY_EMAILS.filter((value) => value !== CONST.EMAIL.CONCIERGE); +const excludedGroupEmails: string[] = CONST.EXPENSIFY_EMAILS.filter((value) => value !== CONST.EMAIL.CONCIERGE); function useOptions({isGroupChat}: NewChatPageProps) { const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); From 45d852fd4d6a968b82b3e8ef0b87dc87f2136263 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Thu, 17 Oct 2024 20:01:02 +0530 Subject: [PATCH 045/808] clear review duplicates data when starting a new flow. Signed-off-by: krishna2323 --- .../MoneyRequestPreview/MoneyRequestPreviewContent.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 92444062ced9..5021a3e65c56 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -289,6 +289,7 @@ function MoneyRequestPreviewContent({ const navigateToReviewFields = () => { const backTo = route.params.backTo; + Transaction.abandonReviewDuplicateTransactions(); const comparisonResult = TransactionUtils.compareDuplicateTransactionFields(reviewingTransactionID, transaction?.reportID ?? ''); Transaction.setReviewDuplicatesKey({...comparisonResult.keep, duplicates, transactionID: transaction?.transactionID ?? '', reportID: transaction?.reportID}); From d31cc9cc4446bddcd08c080faf1d6e03c51b3dce Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Fri, 18 Oct 2024 00:49:32 +0530 Subject: [PATCH 046/808] fix: update navigation for qab --- .../FloatingActionButtonAndPopover.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx index a49b474b185e..700c2d5ad021 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx @@ -248,37 +248,37 @@ function FloatingActionButtonAndPopover( switch (quickAction?.action) { case CONST.QUICK_ACTIONS.REQUEST_MANUAL: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true), true); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, undefined, true), true); return; case CONST.QUICK_ACTIONS.REQUEST_SCAN: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true), true); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, undefined, true), true); return; case CONST.QUICK_ACTIONS.REQUEST_DISTANCE: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, true), true); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, undefined, true), true); return; case CONST.QUICK_ACTIONS.SPLIT_MANUAL: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true), true); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, undefined, true), true); return; case CONST.QUICK_ACTIONS.SPLIT_SCAN: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true), true); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, undefined, true), true); return; case CONST.QUICK_ACTIONS.SPLIT_DISTANCE: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, false), true); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, undefined, false), true); return; case CONST.QUICK_ACTIONS.SEND_MONEY: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.PAY, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true), false); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.PAY, quickActionReportID, undefined, true), false); return; case CONST.QUICK_ACTIONS.ASSIGN_TASK: selectOption(() => Task.startOutCreateTaskQuickAction(isValidReport ? quickActionReportID : '', quickAction.targetAccountID ?? -1), false); break; case CONST.QUICK_ACTIONS.TRACK_MANUAL: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true), false); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, undefined, true), false); break; case CONST.QUICK_ACTIONS.TRACK_SCAN: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true), false); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, undefined, true), false); break; case CONST.QUICK_ACTIONS.TRACK_DISTANCE: - selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, true), false); + selectOption(() => IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, undefined, true), false); break; default: } From 4374ed18dd160a238f88a943c3e4b81625492430 Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Thu, 17 Oct 2024 16:41:23 -0400 Subject: [PATCH 047/808] use validateLogin --- src/pages/settings/Wallet/VerifyAccountPage.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pages/settings/Wallet/VerifyAccountPage.tsx b/src/pages/settings/Wallet/VerifyAccountPage.tsx index e375f03ba58c..484ebbb4225e 100644 --- a/src/pages/settings/Wallet/VerifyAccountPage.tsx +++ b/src/pages/settings/Wallet/VerifyAccountPage.tsx @@ -32,6 +32,7 @@ function VerifyAccountPage({route}: VerifyAccountPageProps) { const styles = useThemeStyles(); const validateLoginError = ErrorUtils.getEarliestErrorField(loginData, 'validateLogin'); const [isUserValidated] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.validated}); + const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID ?? 0}); const [validateCodeAction] = useOnyx(ONYXKEYS.VALIDATE_ACTION_CODE); @@ -43,10 +44,10 @@ function VerifyAccountPage({route}: VerifyAccountPageProps) { }, []); const handleSubmitForm = useCallback( - (submitCode: string) => { - User.validateSecondaryLogin(loginList, contactMethod ?? '', submitCode); + (validateCode: string) => { + User.validateLogin(accountID ?? 0, validateCode); }, - [loginList, contactMethod], + [accountID], ); const clearError = useCallback(() => { From 81b4a2f7feaa8c5c4464af7b4ae6750b49502e8f Mon Sep 17 00:00:00 2001 From: Andrew Rosiclair Date: Thu, 17 Oct 2024 17:47:29 -0400 Subject: [PATCH 048/808] check both user and account validated state --- src/pages/settings/Wallet/VerifyAccountPage.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Wallet/VerifyAccountPage.tsx b/src/pages/settings/Wallet/VerifyAccountPage.tsx index 484ebbb4225e..ff0fa1ba3cb2 100644 --- a/src/pages/settings/Wallet/VerifyAccountPage.tsx +++ b/src/pages/settings/Wallet/VerifyAccountPage.tsx @@ -22,6 +22,7 @@ type VerifyAccountPageProps = StackScreenProps !!user?.validated}); const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID ?? 0}); - const [validateCodeAction] = useOnyx(ONYXKEYS.VALIDATE_ACTION_CODE); + // We store validated state in two places so this is a bit of a workaround to check both + const isUserValidated = user?.validated ?? false; + const isAccountValidated = account?.validated ?? false; + const isValidated = isUserValidated || isAccountValidated; + const navigateBackTo = route?.params?.backTo ?? ROUTES.SETTINGS_WALLET; useEffect(() => { @@ -55,11 +59,11 @@ function VerifyAccountPage({route}: VerifyAccountPageProps) { }, [contactMethod]); useEffect(() => { - if (!isUserValidated) { + if (!isValidated) { return; } Navigation.navigate(navigateBackTo); - }, [isUserValidated, navigateBackTo]); + }, [isValidated, navigateBackTo]); return ( Date: Fri, 18 Oct 2024 15:56:14 +1300 Subject: [PATCH 049/808] Upgrade react-native-web to v0.19.13 --- package-lock.json | 7 ++-- package.json | 2 +- ...eact-native-web+0.19.13+001+initial.patch} | 40 +++++++++---------- ...ative-web+0.19.13+002+fixLastSpacer.patch} | 6 +-- ...eb+0.19.13+003+image-header-support.patch} | 12 +++--- ...web+0.19.13+004+fixPointerEventDown.patch} | 0 ...ive-web+0.19.13+005+osr-improvement.patch} | 20 +++++----- ...13+006+remove-focus-trap-from-modal.patch} | 4 +- ...3+007+fix-scrollable-overflown-text.patch} | 8 ++-- 9 files changed, 50 insertions(+), 49 deletions(-) rename patches/{react-native-web+0.19.12+001+initial.patch => react-native-web+0.19.13+001+initial.patch} (95%) rename patches/{react-native-web+0.19.12+002+fixLastSpacer.patch => react-native-web+0.19.13+002+fixLastSpacer.patch} (94%) rename patches/{react-native-web+0.19.12+003+image-header-support.patch => react-native-web+0.19.13+003+image-header-support.patch} (95%) rename patches/{react-native-web+0.19.12+004+fixPointerEventDown.patch => react-native-web+0.19.13+004+fixPointerEventDown.patch} (100%) rename patches/{react-native-web+0.19.12+005+osr-improvement.patch => react-native-web+0.19.13+005+osr-improvement.patch} (94%) rename patches/{react-native-web+0.19.12+006+remove focus trap from modal.patch => react-native-web+0.19.13+006+remove-focus-trap-from-modal.patch} (88%) rename patches/{react-native-web+0.19.12+007+fix-scrollable-overflown-text.patch => react-native-web+0.19.13+007+fix-scrollable-overflown-text.patch} (84%) diff --git a/package-lock.json b/package-lock.json index 78b95d5ea122..150f2731e3de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -115,7 +115,7 @@ "react-native-url-polyfill": "^2.0.0", "react-native-view-shot": "3.8.0", "react-native-vision-camera": "4.0.0-beta.13", - "react-native-web": "^0.19.12", + "react-native-web": "0.19.13", "react-native-web-sound": "^0.1.3", "react-native-webview": "13.8.6", "react-plaid-link": "3.3.2", @@ -35730,8 +35730,9 @@ } }, "node_modules/react-native-web": { - "version": "0.19.12", - "license": "MIT", + "version": "0.19.13", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.13.tgz", + "integrity": "sha512-etv3bN8rJglrRCp/uL4p7l8QvUNUC++QwDbdZ8CB7BvZiMvsxfFIRM1j04vxNldG3uo2puRd6OSWR3ibtmc29A==", "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", diff --git a/package.json b/package.json index b1f9b1aba231..b92b68b26b44 100644 --- a/package.json +++ b/package.json @@ -170,7 +170,7 @@ "react-native-url-polyfill": "^2.0.0", "react-native-view-shot": "3.8.0", "react-native-vision-camera": "4.0.0-beta.13", - "react-native-web": "^0.19.12", + "react-native-web": "0.19.13", "react-native-web-sound": "^0.1.3", "react-native-webview": "13.8.6", "react-plaid-link": "3.3.2", diff --git a/patches/react-native-web+0.19.12+001+initial.patch b/patches/react-native-web+0.19.13+001+initial.patch similarity index 95% rename from patches/react-native-web+0.19.12+001+initial.patch rename to patches/react-native-web+0.19.13+001+initial.patch index c77cfc7829ed..75efdf4da117 100644 --- a/patches/react-native-web+0.19.12+001+initial.patch +++ b/patches/react-native-web+0.19.13+001+initial.patch @@ -1,8 +1,8 @@ diff --git a/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js b/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js -index e137def..c3e5054 100644 +index 1f52b73..53b1a83 100644 --- a/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js +++ b/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js -@@ -285,7 +285,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -287,7 +287,7 @@ class VirtualizedList extends StateSafePureComponent { // REACT-NATIVE-WEB patch to preserve during future RN merges: Support inverted wheel scroller. constructor(_props) { @@ -11,7 +11,7 @@ index e137def..c3e5054 100644 super(_props); this._getScrollMetrics = () => { return this._scrollMetrics; -@@ -520,6 +520,11 @@ class VirtualizedList extends StateSafePureComponent { +@@ -522,6 +522,11 @@ class VirtualizedList extends StateSafePureComponent { visibleLength, zoomScale }; @@ -23,7 +23,7 @@ index e137def..c3e5054 100644 this._updateViewableItems(this.props, this.state.cellsAroundViewport); if (!this.props) { return; -@@ -569,7 +574,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -571,7 +576,7 @@ class VirtualizedList extends StateSafePureComponent { this._updateCellsToRender = () => { this._updateViewableItems(this.props, this.state.cellsAroundViewport); this.setState((state, props) => { @@ -32,7 +32,7 @@ index e137def..c3e5054 100644 var renderMask = VirtualizedList._createRenderMask(props, cellsAroundViewport, this._getNonViewportRenderRegions(props)); if (cellsAroundViewport.first === state.cellsAroundViewport.first && cellsAroundViewport.last === state.cellsAroundViewport.last && renderMask.equals(state.renderMask)) { return null; -@@ -589,7 +594,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -591,7 +596,7 @@ class VirtualizedList extends StateSafePureComponent { return { index, item, @@ -41,7 +41,7 @@ index e137def..c3e5054 100644 isViewable }; }; -@@ -621,12 +626,10 @@ class VirtualizedList extends StateSafePureComponent { +@@ -623,12 +628,10 @@ class VirtualizedList extends StateSafePureComponent { }; this._getFrameMetrics = (index, props) => { var data = props.data, @@ -55,7 +55,7 @@ index e137def..c3e5054 100644 if (!frame || frame.index !== index) { if (getItemLayout) { /* $FlowFixMe[prop-missing] (>=0.63.0 site=react_native_fb) This comment -@@ -650,7 +653,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -652,7 +655,7 @@ class VirtualizedList extends StateSafePureComponent { // The last cell we rendered may be at a new index. Bail if we don't know // where it is. @@ -64,7 +64,7 @@ index e137def..c3e5054 100644 return []; } var first = focusedCellIndex; -@@ -690,9 +693,15 @@ class VirtualizedList extends StateSafePureComponent { +@@ -692,9 +695,15 @@ class VirtualizedList extends StateSafePureComponent { } } var initialRenderRegion = VirtualizedList._initialRenderRegion(_props); @@ -81,7 +81,7 @@ index e137def..c3e5054 100644 }; // REACT-NATIVE-WEB patch to preserve during future RN merges: Support inverted wheel scroller. -@@ -748,6 +757,26 @@ class VirtualizedList extends StateSafePureComponent { +@@ -750,6 +759,26 @@ class VirtualizedList extends StateSafePureComponent { } } } @@ -108,7 +108,7 @@ index e137def..c3e5054 100644 static _createRenderMask(props, cellsAroundViewport, additionalRegions) { var itemCount = props.getItemCount(props.data); invariant(cellsAroundViewport.first >= 0 && cellsAroundViewport.last >= cellsAroundViewport.first - 1 && cellsAroundViewport.last < itemCount, "Invalid cells around viewport \"[" + cellsAroundViewport.first + ", " + cellsAroundViewport.last + "]\" was passed to VirtualizedList._createRenderMask"); -@@ -796,7 +825,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -798,7 +827,7 @@ class VirtualizedList extends StateSafePureComponent { } } } @@ -117,7 +117,7 @@ index e137def..c3e5054 100644 var data = props.data, getItemCount = props.getItemCount; var onEndReachedThreshold = onEndReachedThresholdOrDefault(props.onEndReachedThreshold); -@@ -819,17 +848,9 @@ class VirtualizedList extends StateSafePureComponent { +@@ -821,17 +850,9 @@ class VirtualizedList extends StateSafePureComponent { last: Math.min(cellsAroundViewport.last + renderAhead, getItemCount(data) - 1) }; } else { @@ -138,7 +138,7 @@ index e137def..c3e5054 100644 return cellsAroundViewport.last >= getItemCount(data) ? VirtualizedList._constrainToItemCount(cellsAroundViewport, props) : cellsAroundViewport; } newCellsAroundViewport = computeWindowedRenderLimits(props, maxToRenderPerBatchOrDefault(props.maxToRenderPerBatch), windowSizeOrDefault(props.windowSize), cellsAroundViewport, this.__getFrameMetricsApprox, this._scrollMetrics); -@@ -902,16 +923,36 @@ class VirtualizedList extends StateSafePureComponent { +@@ -904,16 +925,36 @@ class VirtualizedList extends StateSafePureComponent { } } static getDerivedStateFromProps(newProps, prevState) { @@ -177,7 +177,7 @@ index e137def..c3e5054 100644 }; } _pushCells(cells, stickyHeaderIndices, stickyIndicesFromProps, first, last, inversionStyle) { -@@ -934,7 +975,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -936,7 +977,7 @@ class VirtualizedList extends StateSafePureComponent { last = Math.min(end, last); var _loop = function _loop() { var item = getItem(data, ii); @@ -186,7 +186,7 @@ index e137def..c3e5054 100644 _this._indicesToKeys.set(ii, key); if (stickyIndicesFromProps.has(ii + stickyOffset)) { stickyHeaderIndices.push(cells.length); -@@ -969,20 +1010,23 @@ class VirtualizedList extends StateSafePureComponent { +@@ -971,20 +1012,23 @@ class VirtualizedList extends StateSafePureComponent { } static _constrainToItemCount(cells, props) { var itemCount = props.getItemCount(props.data); @@ -216,8 +216,8 @@ index e137def..c3e5054 100644 if (props.keyExtractor != null) { return props.keyExtractor(item, index); } -@@ -1022,7 +1066,12 @@ class VirtualizedList extends StateSafePureComponent { - cells.push( /*#__PURE__*/React.createElement(VirtualizedListCellContextProvider, { +@@ -1024,7 +1068,12 @@ class VirtualizedList extends StateSafePureComponent { + cells.push(/*#__PURE__*/React.createElement(VirtualizedListCellContextProvider, { cellKey: this._getCellKey() + '-header', key: "$header" - }, /*#__PURE__*/React.createElement(View, { @@ -230,7 +230,7 @@ index e137def..c3e5054 100644 onLayout: this._onLayoutHeader, style: [inversionStyle, this.props.ListHeaderComponentStyle] }, -@@ -1124,7 +1173,11 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1126,7 +1175,11 @@ class VirtualizedList extends StateSafePureComponent { // TODO: Android support invertStickyHeaders: this.props.invertStickyHeaders !== undefined ? this.props.invertStickyHeaders : this.props.inverted, stickyHeaderIndices, @@ -243,7 +243,7 @@ index e137def..c3e5054 100644 }); this._hasMore = this.state.cellsAroundViewport.last < itemCount - 1; var innerRet = /*#__PURE__*/React.createElement(VirtualizedListContextProvider, { -@@ -1317,8 +1370,12 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1319,8 +1372,12 @@ class VirtualizedList extends StateSafePureComponent { onStartReached = _this$props8.onStartReached, onStartReachedThreshold = _this$props8.onStartReachedThreshold, onEndReached = _this$props8.onEndReached, @@ -258,7 +258,7 @@ index e137def..c3e5054 100644 var _this$_scrollMetrics2 = this._scrollMetrics, contentLength = _this$_scrollMetrics2.contentLength, visibleLength = _this$_scrollMetrics2.visibleLength, -@@ -1358,16 +1415,10 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1360,16 +1417,10 @@ class VirtualizedList extends StateSafePureComponent { // and call onStartReached only once for a given content length, // and only if onEndReached is not being executed else if (onStartReached != null && this.state.cellsAroundViewport.first === 0 && isWithinStartThreshold && this._scrollMetrics.contentLength !== this._sentStartForContentLength) { @@ -279,7 +279,7 @@ index e137def..c3e5054 100644 } // If the user scrolls away from the start or end and back again, -@@ -1433,6 +1484,11 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1435,6 +1486,11 @@ class VirtualizedList extends StateSafePureComponent { */ _updateViewableItems(props, cellsAroundViewport) { diff --git a/patches/react-native-web+0.19.12+002+fixLastSpacer.patch b/patches/react-native-web+0.19.13+002+fixLastSpacer.patch similarity index 94% rename from patches/react-native-web+0.19.12+002+fixLastSpacer.patch rename to patches/react-native-web+0.19.13+002+fixLastSpacer.patch index 581298613492..c400dcfc8cca 100644 --- a/patches/react-native-web+0.19.12+002+fixLastSpacer.patch +++ b/patches/react-native-web+0.19.13+002+fixLastSpacer.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/react-native-web/dist/modules/AccessibilityUtil/propsToAccessibilityComponent.js b/node_modules/react-native-web/dist/modules/AccessibilityUtil/propsToAccessibilityComponent.js -index 9c9a533..7794181 100644 +index 7d1d587..de51afe 100644 --- a/node_modules/react-native-web/dist/modules/AccessibilityUtil/propsToAccessibilityComponent.js +++ b/node_modules/react-native-web/dist/modules/AccessibilityUtil/propsToAccessibilityComponent.js @@ -27,7 +27,8 @@ var roleComponents = { @@ -13,7 +13,7 @@ index 9c9a533..7794181 100644 var emptyObject = {}; var propsToAccessibilityComponent = function propsToAccessibilityComponent(props) { diff --git a/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js b/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js -index 7f6c880..b05da08 100644 +index 53b1a83..5689220 100644 --- a/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js +++ b/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js @@ -78,14 +78,6 @@ function scrollEventThrottleOrDefault(scrollEventThrottle) { @@ -31,7 +31,7 @@ index 7f6c880..b05da08 100644 /** * Base implementation for the more convenient [``](https://reactnative.dev/docs/flatlist) -@@ -1107,7 +1099,8 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1109,7 +1101,8 @@ class VirtualizedList extends StateSafePureComponent { _keylessItemComponentName = ''; var spacerKey = this._getSpacerKey(!horizontal); var renderRegions = this.state.renderMask.enumerateRegions(); diff --git a/patches/react-native-web+0.19.12+003+image-header-support.patch b/patches/react-native-web+0.19.13+003+image-header-support.patch similarity index 95% rename from patches/react-native-web+0.19.12+003+image-header-support.patch rename to patches/react-native-web+0.19.13+003+image-header-support.patch index d0a490a4ed70..15e83ce31f8a 100644 --- a/patches/react-native-web+0.19.12+003+image-header-support.patch +++ b/patches/react-native-web+0.19.13+003+image-header-support.patch @@ -1,8 +1,8 @@ diff --git a/node_modules/react-native-web/dist/exports/Image/index.js b/node_modules/react-native-web/dist/exports/Image/index.js -index 9649d27..66ef95c 100644 +index 348831d..ca40ee8 100644 --- a/node_modules/react-native-web/dist/exports/Image/index.js +++ b/node_modules/react-native-web/dist/exports/Image/index.js -@@ -135,7 +135,22 @@ function resolveAssetUri(source) { +@@ -137,7 +137,22 @@ function resolveAssetUri(source) { } return uri; } @@ -13,7 +13,7 @@ index 9649d27..66ef95c 100644 + if (onError) { + onError({ + nativeEvent: { -+ error: "Failed to load resource " + uri + " (404)" ++ error: "Failed to load resource " + uri + } + }); + } @@ -26,14 +26,14 @@ index 9649d27..66ef95c 100644 var _ariaLabel = props['aria-label'], accessibilityLabel = props.accessibilityLabel, blurRadius = props.blurRadius, -@@ -238,16 +253,10 @@ var Image = /*#__PURE__*/React.forwardRef((props, ref) => { +@@ -240,16 +255,10 @@ var Image = /*#__PURE__*/React.forwardRef((props, ref) => { } }, function error() { updateState(ERRORED); - if (onError) { - onError({ - nativeEvent: { -- error: "Failed to load resource " + uri + " (404)" +- error: "Failed to load resource " + uri - } - }); - } @@ -47,7 +47,7 @@ index 9649d27..66ef95c 100644 }); } function abortPendingRequest() { -@@ -279,10 +288,79 @@ var Image = /*#__PURE__*/React.forwardRef((props, ref) => { +@@ -281,10 +290,79 @@ var Image = /*#__PURE__*/React.forwardRef((props, ref) => { suppressHydrationWarning: true }), hiddenImage, createTintColorSVG(tintColor, filterRef.current)); }); diff --git a/patches/react-native-web+0.19.12+004+fixPointerEventDown.patch b/patches/react-native-web+0.19.13+004+fixPointerEventDown.patch similarity index 100% rename from patches/react-native-web+0.19.12+004+fixPointerEventDown.patch rename to patches/react-native-web+0.19.13+004+fixPointerEventDown.patch diff --git a/patches/react-native-web+0.19.12+005+osr-improvement.patch b/patches/react-native-web+0.19.13+005+osr-improvement.patch similarity index 94% rename from patches/react-native-web+0.19.12+005+osr-improvement.patch rename to patches/react-native-web+0.19.13+005+osr-improvement.patch index b1afa699e7a2..d0a952172768 100644 --- a/patches/react-native-web+0.19.12+005+osr-improvement.patch +++ b/patches/react-native-web+0.19.13+005+osr-improvement.patch @@ -1,8 +1,8 @@ diff --git a/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js b/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js -index bede95b..2aef4c6 100644 +index 5689220..df40877 100644 --- a/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js +++ b/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js -@@ -332,7 +332,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -334,7 +334,7 @@ class VirtualizedList extends StateSafePureComponent { zoomScale: 1 }; this._scrollRef = null; @@ -11,7 +11,7 @@ index bede95b..2aef4c6 100644 this._sentEndForContentLength = 0; this._totalCellLength = 0; this._totalCellsMeasured = 0; -@@ -684,16 +684,18 @@ class VirtualizedList extends StateSafePureComponent { +@@ -686,16 +686,18 @@ class VirtualizedList extends StateSafePureComponent { }); } } @@ -32,7 +32,7 @@ index bede95b..2aef4c6 100644 }; // REACT-NATIVE-WEB patch to preserve during future RN merges: Support inverted wheel scroller. -@@ -919,13 +921,13 @@ class VirtualizedList extends StateSafePureComponent { +@@ -921,13 +923,13 @@ class VirtualizedList extends StateSafePureComponent { // first and last could be stale (e.g. if a new, shorter items props is passed in), so we make // sure we're rendering a reasonable range here. var itemCount = newProps.getItemCount(newProps.data); @@ -48,7 +48,7 @@ index bede95b..2aef4c6 100644 if (newProps.maintainVisibleContentPosition != null && prevFirstVisibleItemKey != null && newFirstVisibleItemKey != null) { if (newFirstVisibleItemKey !== prevFirstVisibleItemKey) { // Fast path if items were added at the start of the list. -@@ -944,7 +946,8 @@ class VirtualizedList extends StateSafePureComponent { +@@ -946,7 +948,8 @@ class VirtualizedList extends StateSafePureComponent { cellsAroundViewport: constrainedCells, renderMask: VirtualizedList._createRenderMask(newProps, constrainedCells), firstVisibleItemKey: newFirstVisibleItemKey, @@ -58,7 +58,7 @@ index bede95b..2aef4c6 100644 }; } _pushCells(cells, stickyHeaderIndices, stickyIndicesFromProps, first, last, inversionStyle) { -@@ -1220,7 +1223,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1222,7 +1225,7 @@ class VirtualizedList extends StateSafePureComponent { return ret; } } @@ -67,7 +67,7 @@ index bede95b..2aef4c6 100644 var _this$props7 = this.props, data = _this$props7.data, extraData = _this$props7.extraData; -@@ -1244,6 +1247,11 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1246,6 +1249,11 @@ class VirtualizedList extends StateSafePureComponent { if (hiPriInProgress) { this._hiPriInProgress = false; } @@ -79,7 +79,7 @@ index bede95b..2aef4c6 100644 } // Used for preventing scrollToIndex from being called multiple times for initialScrollIndex -@@ -1407,8 +1415,8 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1409,8 +1417,8 @@ class VirtualizedList extends StateSafePureComponent { // Next check if the user just scrolled within the start threshold // and call onStartReached only once for a given content length, // and only if onEndReached is not being executed @@ -90,7 +90,7 @@ index bede95b..2aef4c6 100644 onStartReached({ distanceFromStart }); -@@ -1417,7 +1425,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1419,7 +1427,7 @@ class VirtualizedList extends StateSafePureComponent { // If the user scrolls away from the start or end and back again, // cause onStartReached or onEndReached to be triggered again else { @@ -100,7 +100,7 @@ index bede95b..2aef4c6 100644 } } diff --git a/node_modules/react-native-web/src/vendor/react-native/VirtualizedList/index.js b/node_modules/react-native-web/src/vendor/react-native/VirtualizedList/index.js -index 459f017..d20115c 100644 +index 459f017..fb2d269 100644 --- a/node_modules/react-native-web/src/vendor/react-native/VirtualizedList/index.js +++ b/node_modules/react-native-web/src/vendor/react-native/VirtualizedList/index.js @@ -79,6 +79,7 @@ type State = { diff --git a/patches/react-native-web+0.19.12+006+remove focus trap from modal.patch b/patches/react-native-web+0.19.13+006+remove-focus-trap-from-modal.patch similarity index 88% rename from patches/react-native-web+0.19.12+006+remove focus trap from modal.patch rename to patches/react-native-web+0.19.13+006+remove-focus-trap-from-modal.patch index 14dbc88b0b1c..eac73db57e35 100644 --- a/patches/react-native-web+0.19.12+006+remove focus trap from modal.patch +++ b/patches/react-native-web+0.19.13+006+remove-focus-trap-from-modal.patch @@ -1,8 +1,8 @@ diff --git a/node_modules/react-native-web/dist/exports/Modal/index.js b/node_modules/react-native-web/dist/exports/Modal/index.js -index d5df021..e2c46cf 100644 +index a9a7c36..522ef93 100644 --- a/node_modules/react-native-web/dist/exports/Modal/index.js +++ b/node_modules/react-native-web/dist/exports/Modal/index.js -@@ -86,13 +86,11 @@ var Modal = /*#__PURE__*/React.forwardRef((props, forwardedRef) => { +@@ -88,13 +88,11 @@ var Modal = /*#__PURE__*/React.forwardRef((props, forwardedRef) => { onDismiss: onDismissCallback, onShow: onShowCallback, visible: visible diff --git a/patches/react-native-web+0.19.12+007+fix-scrollable-overflown-text.patch b/patches/react-native-web+0.19.13+007+fix-scrollable-overflown-text.patch similarity index 84% rename from patches/react-native-web+0.19.12+007+fix-scrollable-overflown-text.patch rename to patches/react-native-web+0.19.13+007+fix-scrollable-overflown-text.patch index 11b85afcf86c..304a57ad0657 100644 --- a/patches/react-native-web+0.19.12+007+fix-scrollable-overflown-text.patch +++ b/patches/react-native-web+0.19.13+007+fix-scrollable-overflown-text.patch @@ -1,8 +1,8 @@ diff --git a/node_modules/react-native-web/dist/exports/Text/index.js b/node_modules/react-native-web/dist/exports/Text/index.js -index 8c5f79b..4a47f80 100644 +index 4130386..1076f55 100644 --- a/node_modules/react-native-web/dist/exports/Text/index.js +++ b/node_modules/react-native-web/dist/exports/Text/index.js -@@ -166,7 +166,7 @@ var styles = StyleSheet.create({ +@@ -176,7 +176,7 @@ var styles = StyleSheet.create({ textMultiLine: { display: '-webkit-box', maxWidth: '100%', @@ -12,10 +12,10 @@ index 8c5f79b..4a47f80 100644 WebkitBoxOrient: 'vertical' }, diff --git a/node_modules/react-native-web/src/exports/Text/index.js b/node_modules/react-native-web/src/exports/Text/index.js -index 071ae10..e43042c 100644 +index f79e82c..f27ccec 100644 --- a/node_modules/react-native-web/src/exports/Text/index.js +++ b/node_modules/react-native-web/src/exports/Text/index.js -@@ -219,7 +219,7 @@ const styles = StyleSheet.create({ +@@ -223,7 +223,7 @@ const styles = StyleSheet.create({ textMultiLine: { display: '-webkit-box', maxWidth: '100%', From 1d3dee84a0e4a16646cd83cd8c5968d5ad9c92d9 Mon Sep 17 00:00:00 2001 From: krishna2323 Date: Fri, 18 Oct 2024 18:16:58 +0530 Subject: [PATCH 050/808] category/tag review shows when feature is disabled. Signed-off-by: krishna2323 --- src/libs/TransactionUtils/index.ts | 15 ++++++++++----- src/pages/TransactionDuplicate/ReviewTaxCode.tsx | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 0a3c18ec7a89..919ce85c5c1d 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -1014,9 +1014,9 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri const firstTransaction = transactions.at(0); const isFirstTransactionCommentEmptyObject = typeof firstTransaction?.comment === 'object' && firstTransaction?.comment?.comment === ''; const report = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; + const policy = PolicyUtils.getPolicy(report?.policyID); const areAllFieldsEqualForKey = areAllFieldsEqual(transactions, (item) => keys.map((key) => item?.[key]).join('|')); - if (fieldName === 'description') { const allCommentsAreEqual = areAllCommentsEqual(transactions, firstTransaction); const allCommentsAreEmpty = isFirstTransactionCommentEmptyObject && transactions.every((item) => getDescription(item) === ''); @@ -1032,12 +1032,13 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri processChanges(fieldName, transactions, keys); } } else if (fieldName === 'taxCode') { - const policy = PolicyUtils.getPolicy(report?.policyID); const differentValues = getDifferentValues(transactions, keys); const validTaxes = differentValues?.filter((taxID) => PolicyUtils.getTaxByID(policy, (taxID as string) ?? '')?.name); if (!areAllFieldsEqualForKey && validTaxes.length > 1) { change[fieldName] = validTaxes; + } else { + keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } } else if (fieldName === 'category') { const differentValues = getDifferentValues(transactions, keys); @@ -1046,14 +1047,16 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri .filter((category) => differentValues.includes(category.name) && firstTransaction?.category !== category.name) .map((e) => e.name); - if (!areAllFieldsEqualForKey && (availableCategories.length > 1 || (availableCategories.length === 1 && differentValues.includes('')))) { + if (!areAllFieldsEqualForKey && policy?.areCategoriesEnabled && (availableCategories.length > 1 || (availableCategories.length === 1 && differentValues.includes('')))) { change[fieldName] = [...availableCategories, ...(differentValues.includes('') ? [''] : [])]; + } else { + keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } } else if (fieldName === 'tag') { const policyTags = getPolicyTagsData(report?.policyID ?? '-1'); const isMultiLevelTags = PolicyUtils.isMultiLevelTags(policyTags); if (isMultiLevelTags) { - if (areAllFieldsEqualForKey) { + if (areAllFieldsEqualForKey || !policy?.areTagsEnabled) { keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } else { processChanges(fieldName, transactions, keys); @@ -1062,8 +1065,10 @@ function compareDuplicateTransactionFields(transactionID: string, reportID: stri const differentValues = getDifferentValues(transactions, keys); const policyTagsObj = Object.values(Object.values(policyTags).at(0)?.tags ?? {}); const availableTags = policyTagsObj.filter((tag) => differentValues.includes(tag.name) && firstTransaction?.tag !== tag.name).map((e) => e.name); - if (!areAllFieldsEqualForKey && (availableTags.length > 1 || (availableTags.length === 1 && differentValues.includes('')))) { + if (!areAllFieldsEqualForKey && policy?.areTagsEnabled && (availableTags.length > 1 || (availableTags.length === 1 && differentValues.includes('')))) { change[fieldName] = [...availableTags, ...(differentValues.includes('') ? [''] : [])]; + } else { + keep[fieldName] = firstTransaction?.[keys[0]] ?? firstTransaction?.[keys[1]]; } } } else if (areAllFieldsEqualForKey) { diff --git a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx index 90e8c26656c9..857a93429f00 100644 --- a/src/pages/TransactionDuplicate/ReviewTaxCode.tsx +++ b/src/pages/TransactionDuplicate/ReviewTaxCode.tsx @@ -20,10 +20,10 @@ import ReviewFields from './ReviewFields'; function ReviewTaxRate() { const route = useRoute>(); const {translate} = useLocalize(); - const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reviewDuplicates?.reportID ?? route.params.threadReportID}`); const policy = PolicyUtils.getPolicy(report?.policyID ?? ''); const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( From 363fb75a0c7a097b369046526aacf65c8170abe2 Mon Sep 17 00:00:00 2001 From: QichenZhu <57348009+QichenZhu@users.noreply.github.com> Date: Sat, 19 Oct 2024 04:38:08 +1300 Subject: [PATCH 051/808] Prevent the active cell from being virtualized --- .../SelectionList/BaseSelectionList.tsx | 2 ++ src/components/SelectionList/index.tsx | 19 ++++++++++++++++--- src/components/SelectionList/types.ts | 9 ++++++++- .../settings/Profile/TimezoneSelectPage.tsx | 1 + 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 06bf8eb6434a..50b90bf3f180 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -105,6 +105,7 @@ function BaseSelectionList( shouldIgnoreFocus = false, scrollEventThrottle, contentContainerStyle, + CellRendererComponent, }: BaseSelectionListProps, ref: ForwardedRef, ) { @@ -758,6 +759,7 @@ function BaseSelectionList( onEndReachedThreshold={onEndReachedThreshold} scrollEventThrottle={scrollEventThrottle} contentContainerStyle={contentContainerStyle} + CellRendererComponent={CellRendererComponent} /> {children} diff --git a/src/components/SelectionList/index.tsx b/src/components/SelectionList/index.tsx index fc788a7e2b4b..8d2f009c0599 100644 --- a/src/components/SelectionList/index.tsx +++ b/src/components/SelectionList/index.tsx @@ -1,12 +1,23 @@ import React, {forwardRef, useEffect, useState} from 'react'; -import type {ForwardedRef} from 'react'; -import {Keyboard} from 'react-native'; +import type {FocusEventHandler, ForwardedRef} from 'react'; +import {Keyboard, View} from 'react-native'; +import type {CellRendererProps} from 'react-native'; import * as Browser from '@libs/Browser'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import BaseSelectionList from './BaseSelectionList'; import type {BaseSelectionListProps, ListItem, SelectionListHandle} from './types'; -function SelectionList({onScroll, ...props}: BaseSelectionListProps, ref: ForwardedRef) { +function FocusAwareCellRenderer({onFocusCapture, ...rest}: CellRendererProps) { + return ( + + ); +} + +function SelectionList({onScroll, shouldPreventActiveCellVirtualization, ...props}: BaseSelectionListProps, ref: ForwardedRef) { const [isScreenTouched, setIsScreenTouched] = useState(false); const touchStart = () => setIsScreenTouched(true); @@ -46,6 +57,8 @@ function SelectionList({onScroll, ...props}: BaseSelecti // Ignore the focus if it's caused by a touch event on mobile chrome. // For example, a long press will trigger a focus event on mobile chrome. shouldIgnoreFocus={Browser.isMobileChrome() && isScreenTouched} + // Customize the cell renderer so the VirtualizedList can receive focus events and avoid virtualizing the active cell. + CellRendererComponent={shouldPreventActiveCellVirtualization ? FocusAwareCellRenderer : undefined} /> ); } diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index d90f329dbf4c..58e4f55fe0ce 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -1,5 +1,6 @@ -import type {MutableRefObject, ReactElement, ReactNode} from 'react'; +import type {ComponentType, MutableRefObject, ReactElement, ReactNode} from 'react'; import type { + CellRendererProps, GestureResponderEvent, InputModeOptions, LayoutChangeEvent, @@ -584,6 +585,12 @@ type BaseSelectionListProps = Partial & { /** Additional styles to apply to scrollable content */ contentContainerStyle?: StyleProp; + + /** Custom cell wrapper */ + CellRendererComponent?: ComponentType>; + + /** Whether to prevent the active cell from being virtualized and losing focus in browsers */ + shouldPreventActiveCellVirtualization?: boolean; } & TRightHandSideComponent; type SelectionListHandle = { diff --git a/src/pages/settings/Profile/TimezoneSelectPage.tsx b/src/pages/settings/Profile/TimezoneSelectPage.tsx index 326db5481d37..cee713065de7 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.tsx +++ b/src/pages/settings/Profile/TimezoneSelectPage.tsx @@ -78,6 +78,7 @@ function TimezoneSelectPage({currentUserPersonalDetails}: TimezoneSelectPageProp showScrollIndicator shouldShowTooltips={false} ListItem={RadioListItem} + shouldPreventActiveCellVirtualization /> ); From 92510d03885d6b9df307dca2ed7c8da0e120ab59 Mon Sep 17 00:00:00 2001 From: QichenZhu <57348009+QichenZhu@users.noreply.github.com> Date: Sat, 19 Oct 2024 05:21:28 +1300 Subject: [PATCH 052/808] Refactor FocuseAwareCellRendererComponent --- .../SelectionList/BaseSelectionList.tsx | 5 +++-- .../index.native.tsx | 3 +++ .../FocusAwareCellRendererComponent/index.tsx | 20 +++++++++++++++++++ src/components/SelectionList/index.tsx | 19 +++--------------- src/components/SelectionList/types.ts | 3 --- 5 files changed, 29 insertions(+), 21 deletions(-) create mode 100644 src/components/SelectionList/FocusAwareCellRendererComponent/index.native.tsx create mode 100644 src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 50b90bf3f180..82ea3b80a284 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -30,6 +30,7 @@ import CONST from '@src/CONST'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import arraysEqual from '@src/utils/arraysEqual'; import type {BaseSelectionListProps, ButtonOrCheckBoxRoles, FlattenedSectionsReturn, ListItem, SectionListDataType, SectionWithIndexOffset, SelectionListHandle} from './types'; +import FocusAwareCellRendererComponent from './FocusAwareCellRendererComponent'; const getDefaultItemHeight = () => variables.optionRowHeight; @@ -105,7 +106,7 @@ function BaseSelectionList( shouldIgnoreFocus = false, scrollEventThrottle, contentContainerStyle, - CellRendererComponent, + shouldPreventActiveCellVirtualization = false, }: BaseSelectionListProps, ref: ForwardedRef, ) { @@ -759,7 +760,7 @@ function BaseSelectionList( onEndReachedThreshold={onEndReachedThreshold} scrollEventThrottle={scrollEventThrottle} contentContainerStyle={contentContainerStyle} - CellRendererComponent={CellRendererComponent} + CellRendererComponent={shouldPreventActiveCellVirtualization ? FocusAwareCellRendererComponent : undefined} /> {children} diff --git a/src/components/SelectionList/FocusAwareCellRendererComponent/index.native.tsx b/src/components/SelectionList/FocusAwareCellRendererComponent/index.native.tsx new file mode 100644 index 000000000000..94833b707acd --- /dev/null +++ b/src/components/SelectionList/FocusAwareCellRendererComponent/index.native.tsx @@ -0,0 +1,3 @@ +const FocusAwareCellRendererComponent = undefined; + +export default FocusAwareCellRendererComponent; diff --git a/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx b/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx new file mode 100644 index 000000000000..573b83c50a09 --- /dev/null +++ b/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import {View} from 'react-native'; +import type {CellRendererProps} from 'react-native'; +import type {FocusEventHandler} from 'react'; +import type {ListItem} from '../types'; + +function FocusAwareCellRendererComponent({onFocusCapture, ...rest}: CellRendererProps) { + return ( + + ); +} + +FocusAwareCellRendererComponent.displayName = 'FocusAwareCellRendererComponent'; + +export default FocusAwareCellRendererComponent; diff --git a/src/components/SelectionList/index.tsx b/src/components/SelectionList/index.tsx index 8d2f009c0599..fc788a7e2b4b 100644 --- a/src/components/SelectionList/index.tsx +++ b/src/components/SelectionList/index.tsx @@ -1,23 +1,12 @@ import React, {forwardRef, useEffect, useState} from 'react'; -import type {FocusEventHandler, ForwardedRef} from 'react'; -import {Keyboard, View} from 'react-native'; -import type {CellRendererProps} from 'react-native'; +import type {ForwardedRef} from 'react'; +import {Keyboard} from 'react-native'; import * as Browser from '@libs/Browser'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import BaseSelectionList from './BaseSelectionList'; import type {BaseSelectionListProps, ListItem, SelectionListHandle} from './types'; -function FocusAwareCellRenderer({onFocusCapture, ...rest}: CellRendererProps) { - return ( - - ); -} - -function SelectionList({onScroll, shouldPreventActiveCellVirtualization, ...props}: BaseSelectionListProps, ref: ForwardedRef) { +function SelectionList({onScroll, ...props}: BaseSelectionListProps, ref: ForwardedRef) { const [isScreenTouched, setIsScreenTouched] = useState(false); const touchStart = () => setIsScreenTouched(true); @@ -57,8 +46,6 @@ function SelectionList({onScroll, shouldPreventActiveCel // Ignore the focus if it's caused by a touch event on mobile chrome. // For example, a long press will trigger a focus event on mobile chrome. shouldIgnoreFocus={Browser.isMobileChrome() && isScreenTouched} - // Customize the cell renderer so the VirtualizedList can receive focus events and avoid virtualizing the active cell. - CellRendererComponent={shouldPreventActiveCellVirtualization ? FocusAwareCellRenderer : undefined} /> ); } diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 58e4f55fe0ce..4133c6ce3823 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -586,9 +586,6 @@ type BaseSelectionListProps = Partial & { /** Additional styles to apply to scrollable content */ contentContainerStyle?: StyleProp; - /** Custom cell wrapper */ - CellRendererComponent?: ComponentType>; - /** Whether to prevent the active cell from being virtualized and losing focus in browsers */ shouldPreventActiveCellVirtualization?: boolean; } & TRightHandSideComponent; From fcb6ad09ad5ba58d3f30c3e7ce50f2ca0a880911 Mon Sep 17 00:00:00 2001 From: QichenZhu <57348009+QichenZhu@users.noreply.github.com> Date: Sat, 19 Oct 2024 05:26:48 +1300 Subject: [PATCH 053/808] Update imports --- src/components/SelectionList/BaseSelectionList.tsx | 2 +- .../SelectionList/FocusAwareCellRendererComponent/index.tsx | 4 ++-- src/components/SelectionList/types.ts | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 82ea3b80a284..fa7f31da7626 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -29,8 +29,8 @@ import variables from '@styles/variables'; import CONST from '@src/CONST'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import arraysEqual from '@src/utils/arraysEqual'; -import type {BaseSelectionListProps, ButtonOrCheckBoxRoles, FlattenedSectionsReturn, ListItem, SectionListDataType, SectionWithIndexOffset, SelectionListHandle} from './types'; import FocusAwareCellRendererComponent from './FocusAwareCellRendererComponent'; +import type {BaseSelectionListProps, ButtonOrCheckBoxRoles, FlattenedSectionsReturn, ListItem, SectionListDataType, SectionWithIndexOffset, SelectionListHandle} from './types'; const getDefaultItemHeight = () => variables.optionRowHeight; diff --git a/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx b/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx index 573b83c50a09..35e5a57d60a0 100644 --- a/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx +++ b/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx @@ -1,8 +1,8 @@ import React from 'react'; import {View} from 'react-native'; -import type {CellRendererProps} from 'react-native'; import type {FocusEventHandler} from 'react'; -import type {ListItem} from '../types'; +import type {CellRendererProps} from 'react-native'; +import type {ListItem} from '@components/SelectionList/types'; function FocusAwareCellRendererComponent({onFocusCapture, ...rest}: CellRendererProps) { return ( diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 4133c6ce3823..2782f1cfa2cd 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -1,6 +1,5 @@ -import type {ComponentType, MutableRefObject, ReactElement, ReactNode} from 'react'; +import type {MutableRefObject, ReactElement, ReactNode} from 'react'; import type { - CellRendererProps, GestureResponderEvent, InputModeOptions, LayoutChangeEvent, From 120f7abb13ae3919e17a5d58241867f29faf1c78 Mon Sep 17 00:00:00 2001 From: QichenZhu <57348009+QichenZhu@users.noreply.github.com> Date: Sat, 19 Oct 2024 05:31:31 +1300 Subject: [PATCH 054/808] Update imports --- .../SelectionList/FocusAwareCellRendererComponent/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx b/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx index 35e5a57d60a0..1df71d0fcea9 100644 --- a/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx +++ b/src/components/SelectionList/FocusAwareCellRendererComponent/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import {View} from 'react-native'; import type {FocusEventHandler} from 'react'; +import {View} from 'react-native'; import type {CellRendererProps} from 'react-native'; import type {ListItem} from '@components/SelectionList/types'; From 166363deccf92f3f4bad280e59b67d63df33595c Mon Sep 17 00:00:00 2001 From: QichenZhu <57348009+QichenZhu@users.noreply.github.com> Date: Sun, 20 Oct 2024 03:42:13 +1300 Subject: [PATCH 055/808] Improve SelectionList item rendering performance --- src/CONST.ts | 1 + .../SelectionList/BaseSelectionList.tsx | 138 +++++++++--------- .../BaseSelectionListItemRenderer.tsx | 89 +++++++++++ src/components/SelectionList/index.tsx | 29 ++++ src/components/SelectionList/types.ts | 3 + 5 files changed, 191 insertions(+), 69 deletions(-) create mode 100644 src/components/SelectionList/BaseSelectionListItemRenderer.tsx diff --git a/src/CONST.ts b/src/CONST.ts index 84003710938a..be64e5108ef7 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1135,6 +1135,7 @@ const CONST = { SEARCH_BUILD_TREE: 'search_build_tree', SEARCH_FILTER_OPTIONS: 'search_filter_options', USE_DEBOUNCED_STATE_DELAY: 300, + LIST_SCROLLING_DEBOUNCE_TIME: 200, }, PRIORITY_MODE: { GSD: 'gsd', diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 262959d7f218..dca738248b39 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -1,4 +1,5 @@ import {useFocusEffect, useIsFocused} from '@react-navigation/native'; +import lodashDebounce from 'lodash/debounce'; import isEmpty from 'lodash/isEmpty'; import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; @@ -24,11 +25,11 @@ import useSingleExecution from '@hooks/useSingleExecution'; import useThemeStyles from '@hooks/useThemeStyles'; import getSectionsWithIndexOffset from '@libs/getSectionsWithIndexOffset'; import Log from '@libs/Log'; -import * as SearchUtils from '@libs/SearchUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import arraysEqual from '@src/utils/arraysEqual'; +import BaseSelectionListItemRenderer from './BaseSelectionListItemRenderer'; import FocusAwareCellRendererComponent from './FocusAwareCellRendererComponent'; import type {BaseSelectionListProps, ButtonOrCheckBoxRoles, FlattenedSectionsReturn, ListItem, SectionListDataType, SectionWithIndexOffset, SelectionListHandle} from './types'; @@ -106,6 +107,7 @@ function BaseSelectionList( shouldIgnoreFocus = false, scrollEventThrottle, contentContainerStyle, + shouldDebounceScrolling = false, shouldPreventActiveCellVirtualization = false, }: BaseSelectionListProps, ref: ForwardedRef, @@ -275,6 +277,8 @@ function BaseSelectionList( // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps }, [flattenedSections.disabledArrowKeyOptionsIndexes]); + const debouncedScrollToIndex = useMemo(() => lodashDebounce(scrollToIndex, CONST.TIMING.LIST_SCROLLING_DEBOUNCE_TIME, {leading: true, trailing: true}), [scrollToIndex]); + // If `initiallyFocusedOptionKey` is not passed, we fall back to `-1`, to avoid showing the highlight on the first member const [focusedIndex, setFocusedIndex] = useArrowKeyFocusManager({ initialFocusedIndex: flattenedSections.allOptions.findIndex((option) => option.keyForList === initiallyFocusedOptionKey), @@ -282,7 +286,7 @@ function BaseSelectionList( disabledIndexes: disabledArrowKeyIndexes, isActive: isFocused, onFocusedIndexChange: (index: number) => { - scrollToIndex(index, true); + (shouldDebounceScrolling ? debouncedScrollToIndex : scrollToIndex)(index, true); }, isFocused, }); @@ -297,36 +301,50 @@ function BaseSelectionList( * @param item - the list item * @param indexToFocus - the list item index to focus */ - const selectRow = (item: TItem, indexToFocus?: number) => { - // In single-selection lists we don't care about updating the focused index, because the list is closed after selecting an item - if (canSelectMultiple) { - if (sections.length > 1) { - // If the list has only 1 section (e.g. Workspace Members list), we do nothing. - // If the list has multiple sections (e.g. Workspace Invite list), and `shouldUnfocusRow` is false, - // we focus the first one after all the selected (selected items are always at the top). - const selectedOptionsCount = item.isSelected ? flattenedSections.selectedOptions.length - 1 : flattenedSections.selectedOptions.length + 1; - - if (!item.isSelected) { - // If we're selecting an item, scroll to it's position at the top, so we can see it - scrollToIndex(Math.max(selectedOptionsCount - 1, 0), true); + const selectRow = useCallback( + (item: TItem, indexToFocus?: number) => { + // In single-selection lists we don't care about updating the focused index, because the list is closed after selecting an item + if (canSelectMultiple) { + if (sections.length > 1) { + // If the list has only 1 section (e.g. Workspace Members list), we do nothing. + // If the list has multiple sections (e.g. Workspace Invite list), and `shouldUnfocusRow` is false, + // we focus the first one after all the selected (selected items are always at the top). + const selectedOptionsCount = item.isSelected ? flattenedSections.selectedOptions.length - 1 : flattenedSections.selectedOptions.length + 1; + + if (!item.isSelected) { + // If we're selecting an item, scroll to it's position at the top, so we can see it + scrollToIndex(Math.max(selectedOptionsCount - 1, 0), true); + } } - } - if (shouldShowTextInput) { - clearInputAfterSelect(); + if (shouldShowTextInput) { + clearInputAfterSelect(); + } } - } - if (shouldUpdateFocusedIndex && typeof indexToFocus === 'number') { - setFocusedIndex(indexToFocus); - } + if (shouldUpdateFocusedIndex && typeof indexToFocus === 'number') { + setFocusedIndex(indexToFocus); + } - onSelectRow(item); + onSelectRow(item); - if (shouldShowTextInput && shouldPreventDefaultFocusOnSelectRow && innerTextInputRef.current) { - innerTextInputRef.current.focus(); - } - }; + if (shouldShowTextInput && shouldPreventDefaultFocusOnSelectRow && innerTextInputRef.current) { + innerTextInputRef.current.focus(); + } + }, + [ + canSelectMultiple, + sections.length, + flattenedSections.selectedOptions.length, + scrollToIndex, + shouldShowTextInput, + clearInputAfterSelect, + shouldUpdateFocusedIndex, + setFocusedIndex, + onSelectRow, + shouldPreventDefaultFocusOnSelectRow, + ], + ); const selectAllRow = () => { onSelectAll?.(); @@ -438,50 +456,32 @@ function BaseSelectionList( // We only create tooltips for the first 10 users or so since some reports have hundreds of users, causing performance to degrade. const showTooltip = shouldShowTooltips && normalizedIndex < 10; - const handleOnCheckboxPress = () => { - if (SearchUtils.isReportListItemType(item)) { - return onCheckboxPress; - } - return onCheckboxPress ? () => onCheckboxPress(item) : undefined; - }; - return ( - <> - { - if (shouldSingleExecuteRowSelect) { - singleExecution(() => selectRow(item, index))(); - } else { - selectRow(item, index); - } - }} - onCheckboxPress={handleOnCheckboxPress()} - onDismissError={() => onDismissError?.(item)} - shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} - // We're already handling the Enter key press in the useKeyboardShortcut hook, so we don't want the list item to submit the form - shouldPreventEnterKeySubmit - rightHandSideComponent={rightHandSideComponent} - keyForList={item.keyForList ?? ''} - isMultilineSupported={isRowMultilineSupported} - isAlternateTextMultilineSupported={isAlternateTextMultilineSupported} - alternateTextNumberOfLines={alternateTextNumberOfLines} - onFocus={() => { - if (shouldIgnoreFocus || isDisabled) { - return; - } - setFocusedIndex(normalizedIndex); - }} - shouldSyncFocus={!isTextInputFocusedRef.current} - wrapperStyle={listItemWrapperStyle} - /> - {item.footerContent && item.footerContent} - + ); }; diff --git a/src/components/SelectionList/BaseSelectionListItemRenderer.tsx b/src/components/SelectionList/BaseSelectionListItemRenderer.tsx new file mode 100644 index 000000000000..4697ac87eef0 --- /dev/null +++ b/src/components/SelectionList/BaseSelectionListItemRenderer.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import type useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; +import type useSingleExecution from '@hooks/useSingleExecution'; +import * as SearchUtils from '@libs/SearchUtils'; +import type {BaseListItemProps, BaseSelectionListProps, ListItem} from './types'; + +function BaseSelectionListItemRenderer({ + ListItem, + item, + index, + isFocused, + isDisabled, + showTooltip, + canSelectMultiple, + onLongPressRow, + shouldSingleExecuteRowSelect, + selectRow, + onCheckboxPress, + onDismissError, + shouldPreventDefaultFocusOnSelectRow, + rightHandSideComponent, + isMultilineSupported, + isAlternateTextMultilineSupported, + alternateTextNumberOfLines, + shouldIgnoreFocus, + setFocusedIndex, + normalizedIndex, + shouldSyncFocus, + wrapperStyle, + singleExecution, +}: Omit, 'onSelectRow'> & + Pick, 'ListItem' | 'shouldIgnoreFocus' | 'shouldSingleExecuteRowSelect'> & { + index: number; + selectRow: (item: TItem, indexToFocus?: number) => void; + setFocusedIndex: ReturnType[1]; + normalizedIndex: number; + singleExecution: ReturnType['singleExecution']; + }) { + const handleOnCheckboxPress = () => { + if (SearchUtils.isReportListItemType(item)) { + return onCheckboxPress; + } + return onCheckboxPress ? () => onCheckboxPress(item) : undefined; + }; + + return ( + <> + { + if (shouldSingleExecuteRowSelect) { + singleExecution(() => selectRow(item, index))(); + } else { + selectRow(item, index); + } + }} + onCheckboxPress={handleOnCheckboxPress()} + onDismissError={() => onDismissError?.(item)} + shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} + // We're already handling the Enter key press in the useKeyboardShortcut hook, so we don't want the list item to submit the form + shouldPreventEnterKeySubmit + rightHandSideComponent={rightHandSideComponent} + keyForList={item.keyForList ?? ''} + isMultilineSupported={isMultilineSupported} + isAlternateTextMultilineSupported={isAlternateTextMultilineSupported} + alternateTextNumberOfLines={alternateTextNumberOfLines} + onFocus={() => { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + if (shouldIgnoreFocus || isDisabled) { + return; + } + setFocusedIndex(normalizedIndex); + }} + shouldSyncFocus={shouldSyncFocus} + wrapperStyle={wrapperStyle} + /> + {item.footerContent && item.footerContent} + + ); +} + +BaseSelectionListItemRenderer.displayName = 'BaseSelectionListItemRenderer'; + +export default BaseSelectionListItemRenderer; diff --git a/src/components/SelectionList/index.tsx b/src/components/SelectionList/index.tsx index fc788a7e2b4b..ecb63fc31e74 100644 --- a/src/components/SelectionList/index.tsx +++ b/src/components/SelectionList/index.tsx @@ -3,6 +3,7 @@ import type {ForwardedRef} from 'react'; import {Keyboard} from 'react-native'; import * as Browser from '@libs/Browser'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import CONST from '@src/CONST'; import BaseSelectionList from './BaseSelectionList'; import type {BaseSelectionListProps, ListItem, SelectionListHandle} from './types'; @@ -28,6 +29,33 @@ function SelectionList({onScroll, ...props}: BaseSelecti }; }, []); + const [shouldDebounceScrolling, setShouldDebounceScrolling] = useState(false); + + const checkShouldDebounceScrolling = (event: KeyboardEvent) => { + if (!event) { + return; + } + + // Moving through items using the keyboard triggers scrolling by the browser, so we debounce programmatic scrolling to prevent jittering. + if ( + event.key === CONST.KEYBOARD_SHORTCUTS.ARROW_DOWN.shortcutKey || + event.key === CONST.KEYBOARD_SHORTCUTS.ARROW_UP.shortcutKey || + event.key === CONST.KEYBOARD_SHORTCUTS.TAB.shortcutKey + ) { + setShouldDebounceScrolling(event.type === 'keydown'); + } + }; + + useEffect(() => { + document.addEventListener('keydown', checkShouldDebounceScrolling, {passive: true}); + document.addEventListener('keyup', checkShouldDebounceScrolling, {passive: true}); + + return () => { + document.removeEventListener('keydown', checkShouldDebounceScrolling); + document.removeEventListener('keyup', checkShouldDebounceScrolling); + }; + }, []); + // In SearchPageBottomTab we use useAnimatedScrollHandler from reanimated(for performance reasons) and it returns object instead of function. In that case we cannot change it to a function call, that's why we have to choose between onScroll and defaultOnScroll. const defaultOnScroll = () => { // Only dismiss the keyboard whenever the user scrolls the screen @@ -46,6 +74,7 @@ function SelectionList({onScroll, ...props}: BaseSelecti // Ignore the focus if it's caused by a touch event on mobile chrome. // For example, a long press will trigger a focus event on mobile chrome. shouldIgnoreFocus={Browser.isMobileChrome() && isScreenTouched} + shouldDebounceScrolling={shouldDebounceScrolling} /> ); } diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 2782f1cfa2cd..039f9ecb2316 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -585,6 +585,9 @@ type BaseSelectionListProps = Partial & { /** Additional styles to apply to scrollable content */ contentContainerStyle?: StyleProp; + /** Whether to debounce scrolling on focused index change */ + shouldDebounceScrolling?: boolean; + /** Whether to prevent the active cell from being virtualized and losing focus in browsers */ shouldPreventActiveCellVirtualization?: boolean; } & TRightHandSideComponent; From 01079a5fd7ca561c2a463807bedf6ca12c7bb5df Mon Sep 17 00:00:00 2001 From: QichenZhu <57348009+QichenZhu@users.noreply.github.com> Date: Sun, 20 Oct 2024 04:41:54 +1300 Subject: [PATCH 056/808] Define prop types --- .../BaseSelectionListItemRenderer.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionListItemRenderer.tsx b/src/components/SelectionList/BaseSelectionListItemRenderer.tsx index 4697ac87eef0..3a740b4aee94 100644 --- a/src/components/SelectionList/BaseSelectionListItemRenderer.tsx +++ b/src/components/SelectionList/BaseSelectionListItemRenderer.tsx @@ -4,6 +4,15 @@ import type useSingleExecution from '@hooks/useSingleExecution'; import * as SearchUtils from '@libs/SearchUtils'; import type {BaseListItemProps, BaseSelectionListProps, ListItem} from './types'; +type BaseSelectionListItemRendererProps = Omit, 'onSelectRow'> & + Pick, 'ListItem' | 'shouldIgnoreFocus' | 'shouldSingleExecuteRowSelect'> & { + index: number; + selectRow: (item: TItem, indexToFocus?: number) => void; + setFocusedIndex: ReturnType[1]; + normalizedIndex: number; + singleExecution: ReturnType['singleExecution']; + }; + function BaseSelectionListItemRenderer({ ListItem, item, @@ -28,14 +37,7 @@ function BaseSelectionListItemRenderer({ shouldSyncFocus, wrapperStyle, singleExecution, -}: Omit, 'onSelectRow'> & - Pick, 'ListItem' | 'shouldIgnoreFocus' | 'shouldSingleExecuteRowSelect'> & { - index: number; - selectRow: (item: TItem, indexToFocus?: number) => void; - setFocusedIndex: ReturnType[1]; - normalizedIndex: number; - singleExecution: ReturnType['singleExecution']; - }) { +}: BaseSelectionListItemRendererProps) { const handleOnCheckboxPress = () => { if (SearchUtils.isReportListItemType(item)) { return onCheckboxPress; From 2df4f36884c231c7fc610d79d627074ce4c8114f Mon Sep 17 00:00:00 2001 From: Youssef Lourayad Date: Mon, 21 Oct 2024 03:05:57 +0100 Subject: [PATCH 057/808] Sort command alphabetically --- src/libs/API/types.ts | 1679 ++++++++++++++++++++--------------------- 1 file changed, 834 insertions(+), 845 deletions(-) diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 929e709559b7..aec784e076ea 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -9,1021 +9,1010 @@ import type UpdateBeneficialOwnersForBankAccountParams from './parameters/Update type ApiRequestType = ValueOf; const WRITE_COMMANDS = { - SET_WORKSPACE_AUTO_REPORTING_FREQUENCY: 'SetWorkspaceAutoReportingFrequency', - SET_WORKSPACE_AUTO_REPORTING_MONTHLY_OFFSET: 'SetWorkspaceAutoReportingOffset', - SET_WORKSPACE_APPROVAL_MODE: 'SetWorkspaceApprovalMode', - SET_WORKSPACE_PAYER: 'SetWorkspacePayer', - SET_WORKSPACE_REIMBURSEMENT: 'SetWorkspaceReimbursement', - SET_POLICY_DEFAULT_REPORT_TITLE: 'SetPolicyDefaultReportTitle', - SET_POLICY_PREVENT_MEMBER_CREATED_TITLE: 'SetPolicyPreventMemberCreatedTitle', - SET_POLICY_PREVENT_SELF_APPROVAL: 'SetPolicyPreventSelfApproval', - SET_POLICY_AUTOMATIC_APPROVAL_LIMIT: 'SetPolicyAutomaticApprovalLimit', - SET_POLICY_AUTOMATIC_APPROVAL_RATE: 'SetPolicyAutomaticApprovalRate', - SET_POLICY_AUTO_REIMBURSEMENT_LIMIT: 'SetPolicyAutoReimbursementLimit', - ENABLE_POLICY_AUTO_REIMBURSEMENT_LIMIT: 'EnablePolicyAutoReimbursementLimit', - ENABLE_POLICY_AUTO_APPROVAL_OPTIONS: 'EnablePolicyAutoApprovalOptions', - ENABLE_POLICY_DEFAULT_REPORT_TITLE: 'EnablePolicyDefaultReportTitle', - SET_WORKSPACE_DEFAULT_SPEND_CATEGORY: 'SetPolicyDefaultSpendCategory', - DISMISS_REFERRAL_BANNER: 'DismissReferralBanner', - UPDATE_PREFERRED_LOCALE: 'UpdatePreferredLocale', - OPEN_APP: 'OpenApp', - RECONNECT_APP: 'ReconnectApp', - HANDLE_RESTRICTED_EVENT: 'HandleRestrictedEvent', - OPEN_REPORT: 'OpenReport', - DELETE_PAYMENT_BANK_ACCOUNT: 'DeletePaymentBankAccount', - UPDATE_PERSONAL_INFORMATION_FOR_BANK_ACCOUNT: 'UpdatePersonalInformationForBankAccount', - VALIDATE_BANK_ACCOUNT_WITH_TRANSACTIONS: 'ValidateBankAccountWithTransactions', - UPDATE_COMPANY_INFORMATION_FOR_BANK_ACCOUNT: 'UpdateCompanyInformationForBankAccount', - UPDATE_BENEFICIAL_OWNERS_FOR_BANK_ACCOUNT: 'UpdateBeneficialOwnersForBankAccount', - CONNECT_BANK_ACCOUNT_MANUALLY: 'ConnectBankAccountManually', - VERIFY_IDENTITY_FOR_BANK_ACCOUNT: 'VerifyIdentityForBankAccount', - BANK_ACCOUNT_HANDLE_PLAID_ERROR: 'BankAccount_HandlePlaidError', - REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD: 'ReportVirtualExpensifyCardFraud', - REQUEST_REPLACEMENT_EXPENSIFY_CARD: 'RequestReplacementExpensifyCard', + ACCEPT_ACH_CONTRACT_FOR_BANK_ACCOUNT: 'AcceptACHContractForBankAccount', + ACCEPT_JOIN_REQUEST: 'AcceptJoinRequest', + ACCEPT_SPOTNANA_TERMS: 'AcceptSpotnanaTerms', + ACCEPT_WALLET_TERMS: 'AcceptWalletTerms', ACTIVATE_PHYSICAL_EXPENSIFY_CARD: 'ActivatePhysicalExpensifyCard', - UPDATE_EXPENSIFY_CARD_LIMIT: 'UpdateExpensifyCardLimit', - UPDATE_EXPENSIFY_CARD_TITLE: 'UpdateExpensifyCardTitle', - UPDATE_EXPENSIFY_CARD_LIMIT_TYPE: 'UpdateExpensifyCardLimitType', - CARD_DEACTIVATE: 'Card_Deactivate', - CHRONOS_REMOVE_OOO_EVENT: 'Chronos_RemoveOOOEvent', - MAKE_DEFAULT_PAYMENT_METHOD: 'MakeDefaultPaymentMethod', + ADD_ATTACHMENT: 'AddAttachment', + ADD_BILLING_CARD_AND_REQUEST_WORKSPACE_OWNER_CHANGE: 'AddBillingCardAndRequestPolicyOwnerChange', + ADD_COMMENT: 'AddComment', + ADD_DELEGATE: 'AddDelegate', + ADD_EMOJI_REACTION: 'AddEmojiReaction', + ADD_MEMBERS_TO_WORKSPACE: 'AddMembersToWorkspace', + ADD_NEW_CONTACT_METHOD: 'AddNewContactMethod', ADD_PAYMENT_CARD: 'AddPaymentCard', ADD_PAYMENT_CARD_GBP: 'AddPaymentCardGBP', - VERIFY_SETUP_INTENT: 'User_VerifySetupIntent', - VERIFY_SETUP_INTENT_AND_REQUEST_POLICY_OWNER_CHANGE: 'VerifySetupIntentAndRequestPolicyOwnerChange', - TRANSFER_WALLET_BALANCE: 'TransferWalletBalance', - DELETE_PAYMENT_CARD: 'DeletePaymentCard', - UPDATE_PRONOUNS: 'UpdatePronouns', - UPDATE_DISPLAY_NAME: 'UpdateDisplayName', - UPDATE_LEGAL_NAME: 'UpdateLegalName', - UPDATE_DATE_OF_BIRTH: 'UpdateDateOfBirth', - UPDATE_HOME_ADDRESS: 'UpdateHomeAddress', - UPDATE_POLICY_ADDRESS: 'SetPolicyAddress', - UPDATE_AUTOMATIC_TIMEZONE: 'UpdateAutomaticTimezone', - UPDATE_SELECTED_TIMEZONE: 'UpdateSelectedTimezone', - UPDATE_USER_AVATAR: 'UpdateUserAvatar', - UPDATE_GROUP_CHAT_AVATAR: 'UpdateGroupChatAvatar', - DELETE_USER_AVATAR: 'DeleteUserAvatar', - REFER_TEACHERS_UNITE_VOLUNTEER: 'ReferTeachersUniteVolunteer', + ADD_PERSONAL_BANK_ACCOUNT: 'AddPersonalBankAccount', ADD_SCHOOL_PRINCIPAL: 'AddSchoolPrincipal', - CLOSE_ACCOUNT: 'CloseAccount', - REQUEST_CONTACT_METHOD_VALIDATE_CODE: 'RequestContactMethodValidateCode', - UPDATE_NEWSLETTER_SUBSCRIPTION: 'UpdateNewsletterSubscription', - DELETE_CONTACT_METHOD: 'DeleteContactMethod', - ADD_NEW_CONTACT_METHOD: 'AddNewContactMethod', - VALIDATE_LOGIN: 'ValidateLogin', - VALIDATE_SECONDARY_LOGIN: 'ValidateSecondaryLogin', - UPDATE_PREFERRED_EMOJI_SKIN_TONE: 'UpdatePreferredEmojiSkinTone', - UPDATE_CHAT_PRIORITY_MODE: 'UpdateChatPriorityMode', - SET_CONTACT_METHOD_AS_DEFAULT: 'SetContactMethodAsDefault', - UPDATE_THEME: 'UpdateTheme', - UPDATE_STATUS: 'UpdateStatus', - CLEAR_STATUS: 'ClearStatus', - UPDATE_PERSONAL_DETAILS_FOR_WALLET: 'UpdatePersonalDetailsForWallet', - VERIFY_IDENTITY: 'VerifyIdentity', - ACCEPT_WALLET_TERMS: 'AcceptWalletTerms', - ANSWER_QUESTIONS_FOR_WALLET: 'AnswerQuestionsForWallet', - REQUEST_PHYSICAL_EXPENSIFY_CARD: 'RequestPhysicalExpensifyCard', - LOG_OUT: 'LogOut', - REQUEST_ACCOUNT_VALIDATION_LINK: 'RequestAccountValidationLink', - REQUEST_NEW_VALIDATE_CODE: 'RequestNewValidateCode', - SIGN_IN_WITH_APPLE: 'SignInWithApple', - SIGN_IN_WITH_GOOGLE: 'SignInWithGoogle', - SIGN_IN_USER: 'SigninUser', - SIGN_IN_USER_WITH_LINK: 'SigninUserWithLink', - SEARCH: 'Search', - REQUEST_UNLINK_VALIDATION_LINK: 'RequestUnlinkValidationLink', - UNLINK_LOGIN: 'UnlinkLogin', - ENABLE_TWO_FACTOR_AUTH: 'EnableTwoFactorAuth', - DISABLE_TWO_FACTOR_AUTH: 'DisableTwoFactorAuth', - ADD_COMMENT: 'AddComment', - ADD_ATTACHMENT: 'AddAttachment', ADD_TEXT_AND_ATTACHMENT: 'AddTextAndAttachment', - CONNECT_BANK_ACCOUNT_WITH_PLAID: 'ConnectBankAccountWithPlaid', - ADD_PERSONAL_BANK_ACCOUNT: 'AddPersonalBankAccount', - RESTART_BANK_ACCOUNT_SETUP: 'RestartBankAccountSetup', - RESEND_VALIDATE_CODE: 'ResendValidateCode', - OPT_IN_TO_PUSH_NOTIFICATIONS: 'OptInToPushNotifications', - OPT_OUT_OF_PUSH_NOTIFICATIONS: 'OptOutOfPushNotifications', - READ_NEWEST_ACTION: 'ReadNewestAction', - MARK_AS_UNREAD: 'MarkAsUnread', - TOGGLE_PINNED_CHAT: 'TogglePinnedChat', - DELETE_COMMENT: 'DeleteComment', - UPDATE_COMMENT: 'UpdateComment', - UPDATE_REPORT_NOTIFICATION_PREFERENCE: 'UpdateReportNotificationPreference', - UPDATE_ROOM_VISIBILITY: 'UpdateRoomVisibility', - UPDATE_ROOM_DESCRIPTION: 'UpdateRoomDescription', - UPDATE_REPORT_WRITE_CAPABILITY: 'UpdateReportWriteCapability', ADD_WORKSPACE_ROOM: 'AddWorkspaceRoom', - UPDATE_POLICY_ROOM_NAME: 'UpdatePolicyRoomName', - ADD_EMOJI_REACTION: 'AddEmojiReaction', - REMOVE_EMOJI_REACTION: 'RemoveEmojiReaction', - LEAVE_ROOM: 'LeaveRoom', - LEAVE_GROUP_CHAT: 'LeaveGroupChat', - INVITE_TO_ROOM: 'InviteToRoom', - INVITE_TO_GROUP_CHAT: 'InviteToGroupChat', - UPDATE_GROUP_CHAT_NAME: 'UpdateGroupChatName', - UPDATE_GROUP_CHAT_MEMBER_ROLES: 'UpdateGroupChatMemberRoles', - REMOVE_FROM_ROOM: 'RemoveFromRoom', - REMOVE_FROM_GROUP_CHAT: 'RemoveFromGroupChat', - FLAG_COMMENT: 'FlagComment', - UPDATE_REPORT_PRIVATE_NOTE: 'UpdateReportPrivateNote', - RESOLVE_ACTIONABLE_MENTION_WHISPER: 'ResolveActionableMentionWhisper', - RESOLVE_ACTIONABLE_REPORT_MENTION_WHISPER: 'ResolveActionableReportMentionWhisper', - DELETE_WORKSPACE: 'DeleteWorkspace', - DELETE_MEMBERS_FROM_WORKSPACE: 'DeleteMembersFromWorkspace', - ADD_MEMBERS_TO_WORKSPACE: 'AddMembersToWorkspace', - UPDATE_WORKSPACE_AVATAR: 'UpdateWorkspaceAvatar', - DELETE_WORKSPACE_AVATAR: 'DeleteWorkspaceAvatar', - UPDATE_WORKSPACE_GENERAL_SETTINGS: 'UpdateWorkspaceGeneralSettings', - UPDATE_WORKSPACE_DESCRIPTION: 'UpdateWorkspaceDescription', - UPDATE_WORKSPACE_MEMBERS_ROLE: 'UpdateWorkspaceMembersRole', + ANSWER_QUESTIONS_FOR_WALLET: 'AnswerQuestionsForWallet', + APPROVE_MONEY_REQUEST: 'ApproveMoneyRequest', + ASSIGN_COMPANY_CARD: 'AssignCard', + BANK_ACCOUNT_HANDLE_PLAID_ERROR: 'BankAccount_HandlePlaidError', + CANCEL_BILLING_SUBSCRIPTION: 'CancelBillingSubscriptionNewDot', + CANCEL_PAYMENT: 'CancelPayment', + CANCEL_TASK: 'CancelTask', + CARD_DEACTIVATE: 'Card_Deactivate', + CATEGORIZE_TRACKED_EXPENSE: 'CategorizeTrackedExpense', + CHRONOS_REMOVE_OOO_EVENT: 'Chronos_RemoveOOOEvent', + CLEAR_OUTSTANDING_BALANCE: 'ClearOutstandingBalance', + CLEAR_STATUS: 'ClearStatus', + CLOSE_ACCOUNT: 'CloseAccount', + COMPLETE_GUIDED_SETUP: 'CompleteGuidedSetup', + COMPLETE_SPLIT_BILL: 'CompleteSplitBill', + COMPLETE_TASK: 'CompleteTask', + CONFIGURE_EXPENSIFY_CARDS_FOR_POLICY: 'ConfigureExpensifyCardsForPolicy', + CONNECT_BANK_ACCOUNT_MANUALLY: 'ConnectBankAccountManually', + CONNECT_BANK_ACCOUNT_WITH_PLAID: 'ConnectBankAccountWithPlaid', + CONNECT_POLICY_TO_NETSUITE: 'ConnectPolicyToNetSuite', + CONNECT_POLICY_TO_SAGE_INTACCT: 'ConnectPolicyToSageIntacct', + CONVERT_TRACKED_EXPENSE_TO_REQUEST: 'ConvertTrackedExpenseToRequest', + COPY_EXISTING_POLICY_CONNECTION: 'CopyExistingPolicyConnection', + CREATE_ADMIN_ISSUED_VIRTUAL_CARD: 'CreateAdminIssuedVirtualCard', + CREATE_DISTANCE_REQUEST: 'CreateDistanceRequest', + CREATE_EXPENSIFY_CARD: 'CreateExpensifyCard', + CREATE_POLICY_DISTANCE_RATE: 'CreatePolicyDistanceRate', + CREATE_POLICY_TAG: 'CreatePolicyTag', + CREATE_POLICY_TAX: 'CreatePolicyTax', + CREATE_TASK: 'CreateTask', CREATE_WORKSPACE: 'CreateWorkspace', - CREATE_WORKSPACE_FROM_IOU_PAYMENT: 'CreateWorkspaceFromIOUPayment', - SET_WORKSPACE_CATEGORIES_ENABLED: 'SetWorkspaceCategoriesEnabled', - SET_POLICY_TAGS_ENABLED: 'SetPolicyTagsEnabled', + CREATE_WORKSPACE_APPROVAL: 'CreateWorkspaceApproval', CREATE_WORKSPACE_CATEGORIES: 'CreateWorkspaceCategories', - IMPORT_CATEGORIES_SPREADSHEET: 'ImportCategoriesSpreadsheet', - IMPORT_MEMBERS_SPREADSHEET: 'ImportMembersSpreadsheet', - IMPORT_TAGS_SPREADSHEET: 'ImportTagsSpreadsheet', - EXPORT_CATEGORIES_CSV: 'ExportCategoriesCSV', - EXPORT_MEMBERS_CSV: 'ExportMembersCSV', - EXPORT_TAGS_CSV: 'ExportTagsCSV', - EXPORT_REPORT_TO_CSV: 'ExportReportToCSV', - RENAME_WORKSPACE_CATEGORY: 'RenameWorkspaceCategory', - CREATE_POLICY_TAG: 'CreatePolicyTag', - RENAME_POLICY_TAG: 'RenamePolicyTag', - SET_WORKSPACE_REQUIRES_CATEGORY: 'SetWorkspaceRequiresCategory', - UPDATE_POLICY_CATEGORY_PAYROLL_CODE: 'UpdatePolicyCategoryPayrollCode', - UPDATE_POLICY_CATEGORY_GL_CODE: 'UpdatePolicyCategoryGLCode', - DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories', + CREATE_WORKSPACE_FROM_IOU_PAYMENT: 'CreateWorkspaceFromIOUPayment', + CREATE_WORKSPACE_REPORT_FIELD: 'CreatePolicyReportField', + CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'CreatePolicyReportFieldOption', + DECLINE_JOIN_REQUEST: 'DeclineJoinRequest', + DELETE_COMMENT: 'DeleteComment', + DELETE_COMPANY_CARD_FEED: 'RemoveFeed', + DELETE_CONTACT_METHOD: 'DeleteContactMethod', + DELETE_MEMBERS_FROM_WORKSPACE: 'DeleteMembersFromWorkspace', + DELETE_MONEY_REQUEST: 'DeleteMoneyRequest', + DELETE_MONEY_REQUEST_ON_SEARCH: 'DeleteMoneyRequestOnSearch', + DELETE_PAYMENT_BANK_ACCOUNT: 'DeletePaymentBankAccount', + DELETE_PAYMENT_CARD: 'DeletePaymentCard', + DELETE_POLICY_DISTANCE_RATES: 'DeletePolicyDistanceRates', DELETE_POLICY_REPORT_FIELD: 'DeletePolicyReportField', - SET_POLICY_TAGS_REQUIRED: 'SetPolicyTagsRequired', - SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag', - RENAME_POLICY_TAG_LIST: 'RenamePolicyTaglist', DELETE_POLICY_TAGS: 'DeletePolicyTags', - UPDATE_POLICY_TAG_GL_CODE: 'UpdatePolicyTagGLCode', - CREATE_TASK: 'CreateTask', - CANCEL_TASK: 'CancelTask', - EDIT_TASK_ASSIGNEE: 'EditTaskAssignee', - EDIT_TASK: 'EditTask', - REOPEN_TASK: 'ReopenTask', - COMPLETE_TASK: 'CompleteTask', - COMPLETE_GUIDED_SETUP: 'CompleteGuidedSetup', - SET_NAME_VALUE_PAIR: 'SetNameValuePair', - SET_REPORT_FIELD: 'Report_SetFields', + DELETE_POLICY_TAXES: 'DeletePolicyTaxes', DELETE_REPORT_FIELD: 'RemoveReportField', - SET_REPORT_NAME: 'RenameReport', - COMPLETE_SPLIT_BILL: 'CompleteSplitBill', - UPDATE_MONEY_REQUEST_DATE: 'UpdateMoneyRequestDate', - UPDATE_MONEY_REQUEST_BILLABLE: 'UpdateMoneyRequestBillable', - UPDATE_MONEY_REQUEST_MERCHANT: 'UpdateMoneyRequestMerchant', - UPDATE_MONEY_REQUEST_TAG: 'UpdateMoneyRequestTag', - UPDATE_MONEY_REQUEST_TAX_AMOUNT: 'UpdateMoneyRequestTaxAmount', - UPDATE_MONEY_REQUEST_TAX_RATE: 'UpdateMoneyRequestTaxRate', - UPDATE_MONEY_REQUEST_DISTANCE: 'UpdateMoneyRequestDistance', - UPDATE_MONEY_REQUEST_DISTANCE_RATE: 'UpdateMoneyRequestDistanceRate', - UPDATE_MONEY_REQUEST_CATEGORY: 'UpdateMoneyRequestCategory', - UPDATE_MONEY_REQUEST_DESCRIPTION: 'UpdateMoneyRequestDescription', - UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY: 'UpdateMoneyRequestAmountAndCurrency', - HOLD_MONEY_REQUEST: 'HoldRequest', - UPDATE_BILLING_CARD_CURRENCY: 'UpdateBillingCardCurrency', - UNHOLD_MONEY_REQUEST: 'UnHoldRequest', - UPDATE_DISTANCE_REQUEST: 'UpdateDistanceRequest', - REQUEST_MONEY: 'RequestMoney', - SPLIT_BILL: 'SplitBill', - SPLIT_BILL_AND_OPEN_REPORT: 'SplitBillAndOpenReport', - DELETE_MONEY_REQUEST: 'DeleteMoneyRequest', - CREATE_DISTANCE_REQUEST: 'CreateDistanceRequest', - START_SPLIT_BILL: 'StartSplitBill', - SEND_MONEY_ELSEWHERE: 'SendMoneyElsewhere', - SEND_MONEY_WITH_WALLET: 'SendMoneyWithWallet', - APPROVE_MONEY_REQUEST: 'ApproveMoneyRequest', - UNAPPROVE_EXPENSE_REPORT: 'UnapproveExpenseReport', - EDIT_MONEY_REQUEST: 'EditMoneyRequest', - REPLACE_RECEIPT: 'ReplaceReceipt', - SUBMIT_REPORT: 'SubmitReport', + DELETE_SAVED_SEARCH: 'DeleteSavedSearch', + DELETE_USER_AVATAR: 'DeleteUserAvatar', + DELETE_WORKSPACE: 'DeleteWorkspace', + DELETE_WORKSPACE_AVATAR: 'DeleteWorkspaceAvatar', + DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories', DETACH_RECEIPT: 'DetachReceipt', - PAY_MONEY_REQUEST_WITH_WALLET: 'PayMoneyRequestWithWallet', - PAY_MONEY_REQUEST: 'PayMoneyRequest', - CANCEL_PAYMENT: 'CancelPayment', - ACCEPT_ACH_CONTRACT_FOR_BANK_ACCOUNT: 'AcceptACHContractForBankAccount', - SWITCH_TO_OLD_DOT: 'SwitchToOldDot', - TRACK_EXPENSE: 'TrackExpense', + DISABLE_POLICY_BILLABLE_MODE: 'DisablePolicyBillableExpenses', + DISABLE_TWO_FACTOR_AUTH: 'DisableTwoFactorAuth', + DISMISS_REFERRAL_BANNER: 'DismissReferralBanner', + DISMISS_TRACK_EXPENSE_ACTIONABLE_WHISPER: 'DismissActionableWhisper', + DISMISS_VIOLATION: 'DismissViolation', + EDIT_MONEY_REQUEST: 'EditMoneyRequest', + EDIT_TASK: 'EditTask', + EDIT_TASK_ASSIGNEE: 'EditTaskAssignee', + ENABLE_DISTANCE_REQUEST_TAX: 'EnableDistanceRequestTax', + ENABLE_POLICY_AUTO_APPROVAL_OPTIONS: 'EnablePolicyAutoApprovalOptions', + ENABLE_POLICY_AUTO_REIMBURSEMENT_LIMIT: 'EnablePolicyAutoReimbursementLimit', ENABLE_POLICY_CATEGORIES: 'EnablePolicyCategories', + ENABLE_POLICY_COMPANY_CARDS: 'EnablePolicyCompanyCards', ENABLE_POLICY_CONNECTIONS: 'EnablePolicyConnections', + ENABLE_POLICY_DEFAULT_REPORT_TITLE: 'EnablePolicyDefaultReportTitle', ENABLE_POLICY_DISTANCE_RATES: 'EnablePolicyDistanceRates', + ENABLE_POLICY_EXPENSIFY_CARDS: 'EnablePolicyExpensifyCards', + ENABLE_POLICY_INVOICING: 'EnablePolicyInvoicing', + ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields', ENABLE_POLICY_TAGS: 'EnablePolicyTags', ENABLE_POLICY_TAXES: 'EnablePolicyTaxes', ENABLE_POLICY_WORKFLOWS: 'EnablePolicyWorkflows', - ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields', - ENABLE_POLICY_EXPENSIFY_CARDS: 'EnablePolicyExpensifyCards', - ENABLE_POLICY_COMPANY_CARDS: 'EnablePolicyCompanyCards', - ENABLE_POLICY_INVOICING: 'EnablePolicyInvoicing', - SET_POLICY_RULES_ENABLED: 'SetPolicyRulesEnabled', - SET_POLICY_EXPENSE_MAX_AMOUNT_NO_RECEIPT: 'SetPolicyExpenseMaxAmountNoReceipt', - SET_POLICY_EXPENSE_MAX_AMOUNT: 'SetPolicyExpenseMaxAmount', - SET_POLICY_EXPENSE_MAX_AGE: ' SetPolicyExpenseMaxAge', - SET_POLICY_BILLABLE_MODE: ' SetPolicyBillableMode', - DISABLE_POLICY_BILLABLE_MODE: 'DisablePolicyBillableExpenses', - SET_WORKSPACE_ERECEIPTS_ENABLED: 'SetWorkspaceEReceiptsEnabled', - SET_POLICY_CATEGORY_DESCRIPTION_REQUIRED: 'SetPolicyCategoryDescriptionRequired', - SET_WORKSPACE_CATEGORY_DESCRIPTION_HINT: 'SetWorkspaceCategoryDescriptionHint', - SET_POLICY_CATEGORY_RECEIPTS_REQUIRED: 'SetPolicyCategoryReceiptsRequired', - REMOVE_POLICY_CATEGORY_RECEIPTS_REQUIRED: 'RemoveWorkspaceCategoryReceiptsRequired', - SET_POLICY_CATEGORY_MAX_AMOUNT: 'SetPolicyCategoryMaxAmount', - SET_POLICY_CATEGORY_APPROVER: 'SetPolicyCategoryApprover', - SET_POLICY_CATEGORY_TAX: 'SetPolicyCategoryTax', - SET_POLICY_TAXES_CURRENCY_DEFAULT: 'SetPolicyCurrencyDefaultTax', - SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT: 'SetPolicyForeignCurrencyDefaultTax', - SET_POLICY_CUSTOM_TAX_NAME: 'SetPolicyCustomTaxName', + ENABLE_TWO_FACTOR_AUTH: 'EnableTwoFactorAuth', + ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'EnablePolicyReportFieldOption', + EXPORT_CATEGORIES_CSV: 'ExportCategoriesCSV', + EXPORT_MEMBERS_CSV: 'ExportMembersCSV', + EXPORT_REPORT_TO_CSV: 'ExportReportToCSV', + EXPORT_SEARCH_ITEMS_TO_CSV: 'ExportSearchToCSV', + EXPORT_TAGS_CSV: 'ExportTagsCSV', + FLAG_COMMENT: 'FlagComment', + HANDLE_RESTRICTED_EVENT: 'HandleRestrictedEvent', + HOLD_MONEY_REQUEST: 'HoldRequest', + HOLD_MONEY_REQUEST_ON_SEARCH: 'HoldMoneyRequestOnSearch', + IMPORT_CATEGORIES_SPREADSHEET: 'ImportCategoriesSpreadsheet', + IMPORT_MEMBERS_SPREADSHEET: 'ImportMembersSpreadsheet', + IMPORT_TAGS_SPREADSHEET: 'ImportTagsSpreadsheet', + INVITE_TO_GROUP_CHAT: 'InviteToGroupChat', + INVITE_TO_ROOM: 'InviteToRoom', JOIN_POLICY_VIA_INVITE_LINK: 'JoinWorkspaceViaInviteLink', - ACCEPT_JOIN_REQUEST: 'AcceptJoinRequest', - DECLINE_JOIN_REQUEST: 'DeclineJoinRequest', - CREATE_POLICY_TAX: 'CreatePolicyTax', - UPDATE_POLICY_CONNECTION_CONFIG: 'UpdatePolicyConnectionConfiguration', - UPDATE_QUICKBOOKS_ONLINE_ENABLE_NEW_CATEGORIES: 'UpdateQuickbooksOnlineEnableNewCategories', - UPDATE_QUICKBOOKS_ONLINE_AUTO_CREATE_VENDOR: 'UpdateQuickbooksOnlineAutoCreateVendor', - UPDATE_QUICKBOOKS_ONLINE_REIMBURSABLE_EXPENSES_ACCOUNT: 'UpdateQuickbooksOnlineReimbursableExpensesAccount', - UPDATE_QUICKBOOKS_ONLINE_RECEIVABLE_ACCOUNT: 'UpdateQuickbooksOnlineReceivableAccount', - UPDATE_QUICKBOOKS_ONLINE_EXPORT_DATE: 'UpdateQuickbooksOnlineExportDate', - UPDATE_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_EXPENSES_ACCOUNT: 'UpdateQuickbooksOnlineNonReimbursableExpensesAccount', - UPDATE_QUICKBOOKS_ONLINE_COLLECTION_ACCOUNT_ID: 'UpdateQuickbooksOnlineCollectionAccountID', - UPDATE_QUICKBOOKS_ONLINE_SYNC_TAX: 'UpdateQuickbooksOnlineSyncTax', - UPDATE_QUICKBOOKS_ONLINE_SYNC_LOCATIONS: 'UpdateQuickbooksOnlineSyncLocations', - UPDATE_QUICKBOOKS_ONLINE_SYNC_CUSTOMERS: 'UpdateQuickbooksOnlineSyncCustomers', - UPDATE_QUICKBOOKS_ONLINE_SYNC_CLASSES: 'UpdateQuickbooksOnlineSyncClasses', - UPDATE_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_BILL_DEFAULT_VENDOR: 'UpdateQuickbooksOnlineNonReimbursableBillDefaultVendor', - UPDATE_QUICKBOOKS_ONLINE_AUTO_SYNC: 'UpdateQuickbooksOnlineAutoSync', - UPDATE_QUICKBOOKS_ONLINE_SYNC_PEOPLE: 'UpdateQuickbooksOnlineSyncPeople', - UPDATE_QUICKBOOKS_ONLINE_REIMBURSEMENT_ACCOUNT_ID: 'UpdateQuickbooksOnlineReimbursementAccountID', - UPDATE_QUICKBOOKS_ONLINE_EXPORT: 'UpdateQuickbooksOnlineExport', - UPDATE_QUICKBOOKS_DESKTOP_EXPORT_DATE: 'UpdateQuickbooksDesktopExportDate', - UPDATE_MANY_POLICY_CONNECTION_CONFIGS: 'UpdateManyPolicyConnectionConfigurations', - UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateQuickbooksDesktopNonReimbursableExpensesExportDestination', - UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPENSES_ACCOUNT: 'UpdateQuickbooksDesktopNonReimbursableExpensesAccount', - UPDATE_QUICKBOOKS_DESKTOP_AUTO_CREATE_VENDOR: 'UpdateQuickbooksDesktopAutoCreateVendor', - UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_BILL_DEFAULT_VENDOR: 'UpdateQuickbooksDesktopNonReimbursableBillDefaultVendor', - UPDATE_QUICKBOOKS_DESKTOP_AUTO_SYNC: 'UpdateQuickbooksDesktopAutoSync', - UPDATE_QUICKBOOKS_DESKTOP_EXPORT: 'UpdateQuickbooksDesktopExport', - UPDATE_QUICKBOOKS_DESKTOP_REIMBURSABLE_EXPENSES_ACCOUNT: 'UpdateQuickbooksDesktopReimbursableExpensesAccount', - UPDATE_QUICKBOOKS_DESKTOP_MARK_CHECKS_TO_BE_PRINTED: 'UpdateQuickbooksDesktopMarkChecksToBePrinted', - UPDATE_QUICKBOOKS_DESKTOP_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateQuickbooksDesktopReimbursableExpensesExportDestination', - UPDATE_QUICKBOOKS_DESKTOP_ENABLE_NEW_CATEGORIES: 'UpdateQuickbooksDesktopEnableNewCategories', - UPDATE_QUICKBOOKS_DESKTOP_SYNC_CLASSES: 'UpdateQuickbooksDesktopSyncClasses', - UPDATE_QUICKBOOKS_DESKTOP_SYNC_CUSTOMERS: 'UpdateQuickbooksDesktopSyncCustomers', - UPDATE_QUICKBOOKS_DESKTOP_SYNC_ITEMS: 'UpdateQuickbooksDesktopSyncItems', + LEAVE_GROUP_CHAT: 'LeaveGroupChat', + LEAVE_POLICY: 'LeavePolicy', + LEAVE_ROOM: 'LeaveRoom', + LOG_OUT: 'LogOut', + MAKE_DEFAULT_PAYMENT_METHOD: 'MakeDefaultPaymentMethod', + MARK_AS_CASH: 'MarkAsCash', + MARK_AS_EXPORTED: 'MarkAsExported', + MARK_AS_UNREAD: 'MarkAsUnread', + OPEN_APP: 'OpenApp', + OPEN_REPORT: 'OpenReport', + OPT_IN_TO_PUSH_NOTIFICATIONS: 'OptInToPushNotifications', + OPT_OUT_OF_PUSH_NOTIFICATIONS: 'OptOutOfPushNotifications', + PAY_INVOICE: 'PayInvoice', + PAY_MONEY_REQUEST: 'PayMoneyRequest', + PAY_MONEY_REQUEST_WITH_WALLET: 'PayMoneyRequestWithWallet', + READ_NEWEST_ACTION: 'ReadNewestAction', + RECONNECT_APP: 'ReconnectApp', + REFER_TEACHERS_UNITE_VOLUNTEER: 'ReferTeachersUniteVolunteer', + REMOVE_DELEGATE: 'RemoveDelegate', + REMOVE_EMOJI_REACTION: 'RemoveEmojiReaction', + REMOVE_FROM_GROUP_CHAT: 'RemoveFromGroupChat', + REMOVE_FROM_ROOM: 'RemoveFromRoom', + REMOVE_POLICY_CATEGORY_RECEIPTS_REQUIRED: 'RemoveWorkspaceCategoryReceiptsRequired', REMOVE_POLICY_CONNECTION: 'RemovePolicyConnection', - SET_POLICY_TAXES_ENABLED: 'SetPolicyTaxesEnabled', - DELETE_POLICY_TAXES: 'DeletePolicyTaxes', - UPDATE_POLICY_TAX_VALUE: 'UpdatePolicyTaxValue', + REMOVE_WORKSPACE_APPROVAL: 'RemoveWorkspaceApproval', + REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'RemovePolicyReportFieldOption', + RENAME_POLICY_TAG: 'RenamePolicyTag', + RENAME_POLICY_TAG_LIST: 'RenamePolicyTaglist', RENAME_POLICY_TAX: 'RenamePolicyTax', - UPDATE_POLICY_TAX_CODE: 'UpdatePolicyTaxCode', - CREATE_POLICY_DISTANCE_RATE: 'CreatePolicyDistanceRate', + RENAME_WORKSPACE_CATEGORY: 'RenameWorkspaceCategory', + REOPEN_TASK: 'ReopenTask', + REPLACE_RECEIPT: 'ReplaceReceipt', + REPORT_EXPORT: 'Report_Export', + REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD: 'ReportVirtualExpensifyCardFraud', + REQUEST_ACCOUNT_VALIDATION_LINK: 'RequestAccountValidationLink', + REQUEST_CONTACT_METHOD_VALIDATE_CODE: 'RequestContactMethodValidateCode', + REQUEST_EXPENSIFY_CARD_LIMIT_INCREASE: 'RequestExpensifyCardLimitIncrease', + REQUEST_FEED_SETUP: 'RequestFeedSetup', + REQUEST_MONEY: 'RequestMoney', + REQUEST_NEW_VALIDATE_CODE: 'RequestNewValidateCode', + REQUEST_PHYSICAL_EXPENSIFY_CARD: 'RequestPhysicalExpensifyCard', + REQUEST_REFUND: 'User_RefundPurchase', + REQUEST_REPLACEMENT_EXPENSIFY_CARD: 'RequestReplacementExpensifyCard', + REQUEST_TAX_EXEMPTION: 'RequestTaxExemption', + REQUEST_UNLINK_VALIDATION_LINK: 'RequestUnlinkValidationLink', REQUEST_WORKSPACE_OWNER_CHANGE: 'RequestWorkspaceOwnerChange', - ADD_BILLING_CARD_AND_REQUEST_WORKSPACE_OWNER_CHANGE: 'AddBillingCardAndRequestPolicyOwnerChange', - SET_POLICY_DISTANCE_RATES_UNIT: 'SetPolicyDistanceRatesUnit', + RESEND_VALIDATE_CODE: 'ResendValidateCode', + RESOLVE_ACTIONABLE_MENTION_WHISPER: 'ResolveActionableMentionWhisper', + RESOLVE_ACTIONABLE_REPORT_MENTION_WHISPER: 'ResolveActionableReportMentionWhisper', + RESOLVE_DUPLICATES: 'ResolveDuplicates', + RESTART_BANK_ACCOUNT_SETUP: 'RestartBankAccountSetup', + SAVE_SEARCH: 'SaveSearch', + SEARCH: 'Search', + SEND_INVOICE: 'SendInvoice', + SEND_MONEY_ELSEWHERE: 'SendMoneyElsewhere', + SEND_MONEY_WITH_WALLET: 'SendMoneyWithWallet', + SET_CARD_EXPORT_ACCOUNT: 'SetCardExportAccount', + SET_COMPANY_CARD_FEED_NAME: 'SetFeedName', + SET_COMPANY_CARD_TRANSACTION_LIABILITY: 'SetFeedTransactionLiability', + SET_CONTACT_METHOD_AS_DEFAULT: 'SetContactMethodAsDefault', + SET_INVOICING_TRANSFER_BANK_ACCOUNT: 'SetInvoicingTransferBankAccount', + SET_MISSING_PERSONAL_DETAILS_AND_SHIP_EXPENSIFY_CARD: 'SetMissingPersonalDetailsAndShipExpensifyCard', + SET_NAME_VALUE_PAIR: 'SetNameValuePair', + SET_POLICY_AUTOMATIC_APPROVAL_LIMIT: 'SetPolicyAutomaticApprovalLimit', + SET_POLICY_AUTOMATIC_APPROVAL_RATE: 'SetPolicyAutomaticApprovalRate', + SET_POLICY_AUTO_REIMBURSEMENT_LIMIT: 'SetPolicyAutoReimbursementLimit', + SET_POLICY_BILLABLE_MODE: ' SetPolicyBillableMode', + SET_POLICY_CATEGORY_APPROVER: 'SetPolicyCategoryApprover', + SET_POLICY_CATEGORY_DESCRIPTION_REQUIRED: 'SetPolicyCategoryDescriptionRequired', + SET_POLICY_CATEGORY_MAX_AMOUNT: 'SetPolicyCategoryMaxAmount', + SET_POLICY_CATEGORY_RECEIPTS_REQUIRED: 'SetPolicyCategoryReceiptsRequired', + SET_POLICY_CATEGORY_TAX: 'SetPolicyCategoryTax', + SET_POLICY_CUSTOM_TAX_NAME: 'SetPolicyCustomTaxName', + SET_POLICY_DEFAULT_REPORT_TITLE: 'SetPolicyDefaultReportTitle', SET_POLICY_DISTANCE_RATES_DEFAULT_CATEGORY: 'SetPolicyDistanceRatesDefaultCategory', - ENABLE_DISTANCE_REQUEST_TAX: 'EnableDistanceRequestTax', - UPDATE_POLICY_DISTANCE_RATE_VALUE: 'UpdatePolicyDistanceRateValue', - UPDATE_POLICY_DISTANCE_TAX_RATE_VALUE: 'UpdateDistanceTaxRate', - UPDATE_DISTANCE_TAX_CLAIMABLE_VALUE: 'UpdateDistanceTaxClaimableValue', SET_POLICY_DISTANCE_RATES_ENABLED: 'SetPolicyDistanceRatesEnabled', - DELETE_POLICY_DISTANCE_RATES: 'DeletePolicyDistanceRates', - DISMISS_TRACK_EXPENSE_ACTIONABLE_WHISPER: 'DismissActionableWhisper', - CONVERT_TRACKED_EXPENSE_TO_REQUEST: 'ConvertTrackedExpenseToRequest', - CATEGORIZE_TRACKED_EXPENSE: 'CategorizeTrackedExpense', + SET_POLICY_DISTANCE_RATES_UNIT: 'SetPolicyDistanceRatesUnit', + SET_POLICY_EXPENSE_MAX_AGE: ' SetPolicyExpenseMaxAge', + SET_POLICY_EXPENSE_MAX_AMOUNT: 'SetPolicyExpenseMaxAmount', + SET_POLICY_EXPENSE_MAX_AMOUNT_NO_RECEIPT: 'SetPolicyExpenseMaxAmountNoReceipt', + SET_POLICY_PREVENT_MEMBER_CREATED_TITLE: 'SetPolicyPreventMemberCreatedTitle', + SET_POLICY_PREVENT_SELF_APPROVAL: 'SetPolicyPreventSelfApproval', + SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag', + SET_POLICY_RULES_ENABLED: 'SetPolicyRulesEnabled', + SET_POLICY_TAGS_ENABLED: 'SetPolicyTagsEnabled', + SET_POLICY_TAGS_REQUIRED: 'SetPolicyTagsRequired', + SET_POLICY_TAG_APPROVER: 'SetPolicyTagApprover', + SET_POLICY_TAXES_CURRENCY_DEFAULT: 'SetPolicyCurrencyDefaultTax', + SET_POLICY_TAXES_ENABLED: 'SetPolicyTaxesEnabled', + SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT: 'SetPolicyForeignCurrencyDefaultTax', + SET_REPORT_FIELD: 'Report_SetFields', + SET_REPORT_NAME: 'RenameReport', + SET_WORKSPACE_APPROVAL_MODE: 'SetWorkspaceApprovalMode', + SET_WORKSPACE_AUTO_REPORTING_FREQUENCY: 'SetWorkspaceAutoReportingFrequency', + SET_WORKSPACE_AUTO_REPORTING_MONTHLY_OFFSET: 'SetWorkspaceAutoReportingOffset', + SET_WORKSPACE_CATEGORIES_ENABLED: 'SetWorkspaceCategoriesEnabled', + SET_WORKSPACE_CATEGORY_DESCRIPTION_HINT: 'SetWorkspaceCategoryDescriptionHint', + SET_WORKSPACE_DEFAULT_SPEND_CATEGORY: 'SetPolicyDefaultSpendCategory', + SET_WORKSPACE_ERECEIPTS_ENABLED: 'SetWorkspaceEReceiptsEnabled', + SET_WORKSPACE_PAYER: 'SetWorkspacePayer', + SET_WORKSPACE_REIMBURSEMENT: 'SetWorkspaceReimbursement', + SET_WORKSPACE_REQUIRES_CATEGORY: 'SetWorkspaceRequiresCategory', SHARE_TRACKED_EXPENSE: 'ShareTrackedExpense', - LEAVE_POLICY: 'LeavePolicy', - DISMISS_VIOLATION: 'DismissViolation', - ACCEPT_SPOTNANA_TERMS: 'AcceptSpotnanaTerms', - SEND_INVOICE: 'SendInvoice', - PAY_INVOICE: 'PayInvoice', - MARK_AS_CASH: 'MarkAsCash', - TRANSACTION_MERGE: 'Transaction_Merge', - RESOLVE_DUPLICATES: 'ResolveDuplicates', - UPDATE_SUBSCRIPTION_TYPE: 'UpdateSubscriptionType', + SIGN_IN_USER: 'SigninUser', + SIGN_IN_USER_WITH_LINK: 'SigninUserWithLink', + SIGN_IN_WITH_APPLE: 'SignInWithApple', + SIGN_IN_WITH_GOOGLE: 'SignInWithGoogle', SIGN_UP_USER: 'SignUpUser', - UPDATE_SUBSCRIPTION_AUTO_RENEW: 'UpdateSubscriptionAutoRenew', - UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY: 'UpdateSubscriptionAddNewUsersAutomatically', - UPDATE_SUBSCRIPTION_SIZE: 'UpdateSubscriptionSize', - REPORT_EXPORT: 'Report_Export', - MARK_AS_EXPORTED: 'MarkAsExported', - UPGRADE_TO_CORPORATE: 'UpgradeToCorporate', - DELETE_MONEY_REQUEST_ON_SEARCH: 'DeleteMoneyRequestOnSearch', - HOLD_MONEY_REQUEST_ON_SEARCH: 'HoldMoneyRequestOnSearch', + SPLIT_BILL: 'SplitBill', + SPLIT_BILL_AND_OPEN_REPORT: 'SplitBillAndOpenReport', + START_SPLIT_BILL: 'StartSplitBill', + SUBMIT_REPORT: 'SubmitReport', + SWITCH_TO_OLD_DOT: 'SwitchToOldDot', + TOGGLE_CARD_CONTINUOUS_RECONCILIATION: 'ToggleCardContinuousReconciliation', + TOGGLE_PINNED_CHAT: 'TogglePinnedChat', + TRACK_EXPENSE: 'TrackExpense', + TRANSACTION_MERGE: 'Transaction_Merge', + TRANSFER_WALLET_BALANCE: 'TransferWalletBalance', + UNAPPROVE_EXPENSE_REPORT: 'UnapproveExpenseReport', + UNASSIGN_COMPANY_CARD: 'UnassignCard', + UNHOLD_MONEY_REQUEST: 'UnHoldRequest', UNHOLD_MONEY_REQUEST_ON_SEARCH: 'UnholdMoneyRequestOnSearch', - REQUEST_REFUND: 'User_RefundPurchase', - UPDATE_NETSUITE_SUBSIDIARY: 'UpdateNetSuiteSubsidiary', - CREATE_WORKSPACE_REPORT_FIELD: 'CreatePolicyReportField', - UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE: 'SetPolicyReportFieldDefault', - ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'EnablePolicyReportFieldOption', - CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'CreatePolicyReportFieldOption', - REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'RemovePolicyReportFieldOption', - UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION: 'UpdateNetSuiteSyncTaxConfiguration', - UPDATE_NETSUITE_CROSS_SUBSIDIARY_CUSTOMER_CONFIGURATION: 'UpdateNetSuiteCrossSubsidiaryCustomerConfiguration', - UPDATE_NETSUITE_DEPARTMENTS_MAPPING: 'UpdateNetSuiteDepartmentsMapping', + UNLINK_LOGIN: 'UnlinkLogin', + UPDATE_AUTOMATIC_TIMEZONE: 'UpdateAutomaticTimezone', + UPDATE_BENEFICIAL_OWNERS_FOR_BANK_ACCOUNT: 'UpdateBeneficialOwnersForBankAccount', + UPDATE_BILLING_CARD_CURRENCY: 'UpdateBillingCardCurrency', + UPDATE_CARD_SETTLEMENT_ACCOUNT: 'UpdateCardSettlementAccount', + UPDATE_CARD_SETTLEMENT_FREQUENCY: 'UpdateCardSettlementFrequency', + UPDATE_CHAT_PRIORITY_MODE: 'UpdateChatPriorityMode', + UPDATE_COMMENT: 'UpdateComment', + UPDATE_COMPANY_CARD: 'SyncCard', + UPDATE_COMPANY_CARD_NAME: 'SetCardName', + UPDATE_COMPANY_INFORMATION_FOR_BANK_ACCOUNT: 'UpdateCompanyInformationForBankAccount', + UPDATE_DATE_OF_BIRTH: 'UpdateDateOfBirth', + UPDATE_DELEGATE_ROLE: 'UpdateDelegateRole', + UPDATE_DISPLAY_NAME: 'UpdateDisplayName', + UPDATE_DISTANCE_REQUEST: 'UpdateDistanceRequest', + UPDATE_DISTANCE_TAX_CLAIMABLE_VALUE: 'UpdateDistanceTaxClaimableValue', + UPDATE_EXPENSIFY_CARD_LIMIT: 'UpdateExpensifyCardLimit', + UPDATE_EXPENSIFY_CARD_LIMIT_TYPE: 'UpdateExpensifyCardLimitType', + UPDATE_EXPENSIFY_CARD_TITLE: 'UpdateExpensifyCardTitle', + UPDATE_GROUP_CHAT_AVATAR: 'UpdateGroupChatAvatar', + UPDATE_GROUP_CHAT_MEMBER_ROLES: 'UpdateGroupChatMemberRoles', + UPDATE_GROUP_CHAT_NAME: 'UpdateGroupChatName', + UPDATE_HOME_ADDRESS: 'UpdateHomeAddress', + UPDATE_LEGAL_NAME: 'UpdateLegalName', + UPDATE_MANY_POLICY_CONNECTION_CONFIGS: 'UpdateManyPolicyConnectionConfigurations', + UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY: 'UpdateMoneyRequestAmountAndCurrency', + UPDATE_MONEY_REQUEST_BILLABLE: 'UpdateMoneyRequestBillable', + UPDATE_MONEY_REQUEST_CATEGORY: 'UpdateMoneyRequestCategory', + UPDATE_MONEY_REQUEST_DATE: 'UpdateMoneyRequestDate', + UPDATE_MONEY_REQUEST_DESCRIPTION: 'UpdateMoneyRequestDescription', + UPDATE_MONEY_REQUEST_DISTANCE: 'UpdateMoneyRequestDistance', + UPDATE_MONEY_REQUEST_DISTANCE_RATE: 'UpdateMoneyRequestDistanceRate', + UPDATE_MONEY_REQUEST_MERCHANT: 'UpdateMoneyRequestMerchant', + UPDATE_MONEY_REQUEST_TAG: 'UpdateMoneyRequestTag', + UPDATE_MONEY_REQUEST_TAX_AMOUNT: 'UpdateMoneyRequestTaxAmount', + UPDATE_MONEY_REQUEST_TAX_RATE: 'UpdateMoneyRequestTaxRate', + UPDATE_NETSUITE_ALLOW_FOREIGN_CURRENCY: 'UpdateNetSuiteAllowForeignCurrency', + UPDATE_NETSUITE_APPROVAL_ACCOUNT: 'UpdateNetSuiteApprovalAccount', + UPDATE_NETSUITE_AUTO_CREATE_ENTITIES: 'UpdateNetSuiteAutoCreateEntities', + UPDATE_NETSUITE_AUTO_SYNC: 'UpdateNetSuiteAutoSync', UPDATE_NETSUITE_CLASSES_MAPPING: 'UpdateNetSuiteClassesMapping', - UPDATE_NETSUITE_LOCATIONS_MAPPING: 'UpdateNetSuiteLocationsMapping', - UPDATE_NETSUITE_CUSTOMERS_MAPPING: 'UpdateNetSuiteCustomersMapping', - UPDATE_NETSUITE_JOBS_MAPPING: 'UpdateNetSuiteJobsMapping', + UPDATE_NETSUITE_COLLECTION_ACCOUNT: 'UpdateNetSuiteCollectionAccount', + UPDATE_NETSUITE_CROSS_SUBSIDIARY_CUSTOMER_CONFIGURATION: 'UpdateNetSuiteCrossSubsidiaryCustomerConfiguration', UPDATE_NETSUITE_CUSTOMERS_JOBS_MAPPING: 'UpdateNetSuiteCustomersJobsMapping', + UPDATE_NETSUITE_CUSTOMERS_MAPPING: 'UpdateNetSuiteCustomersMapping', + UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_ENABLED: 'UpdateNetSuiteCustomFormIDOptionsEnabled', + UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_NON_REIMBURSABLE: 'UpdateNetSuiteCustomFormIDOptionsNonReimbursable', + UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_REIMBURSABLE: 'UpdateNetSuiteCustomFormIDOptionsReimbursable', + UPDATE_NETSUITE_CUSTOM_LISTS: 'UpdateNetSuiteCustomLists', + UPDATE_NETSUITE_CUSTOM_SEGMENTS: 'UpdateNetSuiteCustomSegments', + UPDATE_NETSUITE_DEFAULT_VENDOR: 'UpdateNetSuiteDefaultVendor', + UPDATE_NETSUITE_DEPARTMENTS_MAPPING: 'UpdateNetSuiteDepartmentsMapping', + UPDATE_NETSUITE_ENABLE_NEW_CATEGORIES: 'UpdateNetSuiteEnableNewCategories', UPDATE_NETSUITE_EXPORTER: 'UpdateNetSuiteExporter', UPDATE_NETSUITE_EXPORT_DATE: 'UpdateNetSuiteExportDate', - UPDATE_NETSUITE_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateNetSuiteReimbursableExpensesExportDestination', + UPDATE_NETSUITE_EXPORT_REPORTS_TO: 'UpdateNetSuiteExportReportsTo', + UPDATE_NETSUITE_EXPORT_TO_NEXT_OPEN_PERIOD: 'UpdateNetSuiteExportToNextOpenPeriod', + UPDATE_NETSUITE_INVOICE_ITEM: 'UpdateNetSuiteInvoiceItem', + UPDATE_NETSUITE_INVOICE_ITEM_PREFERENCE: 'UpdateNetSuiteInvoiceItemPreference', + UPDATE_NETSUITE_JOBS_MAPPING: 'UpdateNetSuiteJobsMapping', + UPDATE_NETSUITE_JOURNALS_TO: 'UpdateNetSuiteExportJournalsTo', + UPDATE_NETSUITE_JOURNAL_POSTING_PREFERENCE: 'UpdateNetSuiteJournalPostingPreference', + UPDATE_NETSUITE_LOCATIONS_MAPPING: 'UpdateNetSuiteLocationsMapping', UPDATE_NETSUITE_NONREIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateNetSuiteNonreimbursableExpensesExportDestination', - UPDATE_NETSUITE_DEFAULT_VENDOR: 'UpdateNetSuiteDefaultVendor', - UPDATE_NETSUITE_REIMBURSABLE_PAYABLE_ACCOUNT: 'UpdateNetSuiteReimbursablePayableAccount', UPDATE_NETSUITE_PAYABLE_ACCT: 'UpdateNetSuitePayableAcct', - UPDATE_NETSUITE_JOURNAL_POSTING_PREFERENCE: 'UpdateNetSuiteJournalPostingPreference', - UPDATE_NETSUITE_RECEIVABLE_ACCOUNT: 'UpdateNetSuiteReceivableAccount', - UPDATE_NETSUITE_INVOICE_ITEM_PREFERENCE: 'UpdateNetSuiteInvoiceItemPreference', - UPDATE_NETSUITE_INVOICE_ITEM: 'UpdateNetSuiteInvoiceItem', UPDATE_NETSUITE_PROVINCIAL_TAX_POSTING_ACCOUNT: 'UpdateNetSuiteProvincialTaxPostingAccount', - UPDATE_NETSUITE_TAX_POSTING_ACCOUNT: 'UpdateNetSuiteTaxPostingAccount', - UPDATE_NETSUITE_ALLOW_FOREIGN_CURRENCY: 'UpdateNetSuiteAllowForeignCurrency', - UPDATE_NETSUITE_EXPORT_TO_NEXT_OPEN_PERIOD: 'UpdateNetSuiteExportToNextOpenPeriod', - UPDATE_NETSUITE_CUSTOM_SEGMENTS: 'UpdateNetSuiteCustomSegments', - UPDATE_NETSUITE_CUSTOM_LISTS: 'UpdateNetSuiteCustomLists', - UPDATE_NETSUITE_AUTO_SYNC: 'UpdateNetSuiteAutoSync', - UPDATE_NETSUITE_SYNC_REIMBURSED_REPORTS: 'UpdateNetSuiteSyncReimbursedReports', - UPDATE_NETSUITE_SYNC_PEOPLE: 'UpdateNetSuiteSyncPeople', - UPDATE_NETSUITE_AUTO_CREATE_ENTITIES: 'UpdateNetSuiteAutoCreateEntities', - UPDATE_NETSUITE_ENABLE_NEW_CATEGORIES: 'UpdateNetSuiteEnableNewCategories', - UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_ENABLED: 'UpdateNetSuiteCustomFormIDOptionsEnabled', + UPDATE_NETSUITE_RECEIVABLE_ACCOUNT: 'UpdateNetSuiteReceivableAccount', + UPDATE_NETSUITE_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateNetSuiteReimbursableExpensesExportDestination', + UPDATE_NETSUITE_REIMBURSABLE_PAYABLE_ACCOUNT: 'UpdateNetSuiteReimbursablePayableAccount', UPDATE_NETSUITE_REIMBURSEMENT_ACCOUNT_ID: 'UpdateNetSuiteReimbursementAccountID', - UPDATE_NETSUITE_COLLECTION_ACCOUNT: 'UpdateNetSuiteCollectionAccount', - UPDATE_NETSUITE_EXPORT_REPORTS_TO: 'UpdateNetSuiteExportReportsTo', + UPDATE_NETSUITE_SUBSIDIARY: 'UpdateNetSuiteSubsidiary', + UPDATE_NETSUITE_SYNC_PEOPLE: 'UpdateNetSuiteSyncPeople', + UPDATE_NETSUITE_SYNC_REIMBURSED_REPORTS: 'UpdateNetSuiteSyncReimbursedReports', + UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION: 'UpdateNetSuiteSyncTaxConfiguration', + UPDATE_NETSUITE_TAX_POSTING_ACCOUNT: 'UpdateNetSuiteTaxPostingAccount', UPDATE_NETSUITE_VENDOR_BILLS_TO: 'UpdateNetSuiteExportVendorBillsTo', - UPDATE_NETSUITE_JOURNALS_TO: 'UpdateNetSuiteExportJournalsTo', - UPDATE_NETSUITE_APPROVAL_ACCOUNT: 'UpdateNetSuiteApprovalAccount', - UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_REIMBURSABLE: 'UpdateNetSuiteCustomFormIDOptionsReimbursable', - UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_NON_REIMBURSABLE: 'UpdateNetSuiteCustomFormIDOptionsNonReimbursable', - REQUEST_EXPENSIFY_CARD_LIMIT_INCREASE: 'RequestExpensifyCardLimitIncrease', - CONNECT_POLICY_TO_SAGE_INTACCT: 'ConnectPolicyToSageIntacct', - COPY_EXISTING_POLICY_CONNECTION: 'CopyExistingPolicyConnection', - UPDATE_SAGE_INTACCT_AUTO_SYNC: 'UpdateSageIntacctAutoSync', - UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES: 'UpdateSageIntacctImportEmployees', + UPDATE_NEWSLETTER_SUBSCRIPTION: 'UpdateNewsletterSubscription', + UPDATE_PERSONAL_DETAILS_FOR_WALLET: 'UpdatePersonalDetailsForWallet', + UPDATE_PERSONAL_INFORMATION_FOR_BANK_ACCOUNT: 'UpdatePersonalInformationForBankAccount', + UPDATE_POLICY_ADDRESS: 'SetPolicyAddress', + UPDATE_POLICY_CATEGORY_GL_CODE: 'UpdatePolicyCategoryGLCode', + UPDATE_POLICY_CATEGORY_PAYROLL_CODE: 'UpdatePolicyCategoryPayrollCode', + UPDATE_POLICY_CONNECTION_CONFIG: 'UpdatePolicyConnectionConfiguration', + UPDATE_POLICY_DISTANCE_RATE_VALUE: 'UpdatePolicyDistanceRateValue', + UPDATE_POLICY_DISTANCE_TAX_RATE_VALUE: 'UpdateDistanceTaxRate', + UPDATE_POLICY_ROOM_NAME: 'UpdatePolicyRoomName', + UPDATE_POLICY_TAG_GL_CODE: 'UpdatePolicyTagGLCode', + UPDATE_POLICY_TAX_CODE: 'UpdatePolicyTaxCode', + UPDATE_POLICY_TAX_VALUE: 'UpdatePolicyTaxValue', + UPDATE_PREFERRED_EMOJI_SKIN_TONE: 'UpdatePreferredEmojiSkinTone', + UPDATE_PREFERRED_LOCALE: 'UpdatePreferredLocale', + UPDATE_PRONOUNS: 'UpdatePronouns', + UPDATE_QUICKBOOKS_DESKTOP_AUTO_CREATE_VENDOR: 'UpdateQuickbooksDesktopAutoCreateVendor', + UPDATE_QUICKBOOKS_DESKTOP_AUTO_SYNC: 'UpdateQuickbooksDesktopAutoSync', + UPDATE_QUICKBOOKS_DESKTOP_ENABLE_NEW_CATEGORIES: 'UpdateQuickbooksDesktopEnableNewCategories', + UPDATE_QUICKBOOKS_DESKTOP_EXPORT: 'UpdateQuickbooksDesktopExport', + UPDATE_QUICKBOOKS_DESKTOP_EXPORT_DATE: 'UpdateQuickbooksDesktopExportDate', + UPDATE_QUICKBOOKS_DESKTOP_MARK_CHECKS_TO_BE_PRINTED: 'UpdateQuickbooksDesktopMarkChecksToBePrinted', + UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_BILL_DEFAULT_VENDOR: 'UpdateQuickbooksDesktopNonReimbursableBillDefaultVendor', + UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPENSES_ACCOUNT: 'UpdateQuickbooksDesktopNonReimbursableExpensesAccount', + UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateQuickbooksDesktopNonReimbursableExpensesExportDestination', + UPDATE_QUICKBOOKS_DESKTOP_REIMBURSABLE_EXPENSES_ACCOUNT: 'UpdateQuickbooksDesktopReimbursableExpensesAccount', + UPDATE_QUICKBOOKS_DESKTOP_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateQuickbooksDesktopReimbursableExpensesExportDestination', + UPDATE_QUICKBOOKS_DESKTOP_SYNC_CLASSES: 'UpdateQuickbooksDesktopSyncClasses', + UPDATE_QUICKBOOKS_DESKTOP_SYNC_CUSTOMERS: 'UpdateQuickbooksDesktopSyncCustomers', + UPDATE_QUICKBOOKS_DESKTOP_SYNC_ITEMS: 'UpdateQuickbooksDesktopSyncItems', + UPDATE_QUICKBOOKS_ONLINE_AUTO_CREATE_VENDOR: 'UpdateQuickbooksOnlineAutoCreateVendor', + UPDATE_QUICKBOOKS_ONLINE_AUTO_SYNC: 'UpdateQuickbooksOnlineAutoSync', + UPDATE_QUICKBOOKS_ONLINE_COLLECTION_ACCOUNT_ID: 'UpdateQuickbooksOnlineCollectionAccountID', + UPDATE_QUICKBOOKS_ONLINE_ENABLE_NEW_CATEGORIES: 'UpdateQuickbooksOnlineEnableNewCategories', + UPDATE_QUICKBOOKS_ONLINE_EXPORT: 'UpdateQuickbooksOnlineExport', + UPDATE_QUICKBOOKS_ONLINE_EXPORT_DATE: 'UpdateQuickbooksOnlineExportDate', + UPDATE_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_BILL_DEFAULT_VENDOR: 'UpdateQuickbooksOnlineNonReimbursableBillDefaultVendor', + UPDATE_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_EXPENSES_ACCOUNT: 'UpdateQuickbooksOnlineNonReimbursableExpensesAccount', + UPDATE_QUICKBOOKS_ONLINE_RECEIVABLE_ACCOUNT: 'UpdateQuickbooksOnlineReceivableAccount', + UPDATE_QUICKBOOKS_ONLINE_REIMBURSABLE_EXPENSES_ACCOUNT: 'UpdateQuickbooksOnlineReimbursableExpensesAccount', + UPDATE_QUICKBOOKS_ONLINE_REIMBURSEMENT_ACCOUNT_ID: 'UpdateQuickbooksOnlineReimbursementAccountID', + UPDATE_QUICKBOOKS_ONLINE_SYNC_CLASSES: 'UpdateQuickbooksOnlineSyncClasses', + UPDATE_QUICKBOOKS_ONLINE_SYNC_CUSTOMERS: 'UpdateQuickbooksOnlineSyncCustomers', + UPDATE_QUICKBOOKS_ONLINE_SYNC_LOCATIONS: 'UpdateQuickbooksOnlineSyncLocations', + UPDATE_QUICKBOOKS_ONLINE_SYNC_PEOPLE: 'UpdateQuickbooksOnlineSyncPeople', + UPDATE_QUICKBOOKS_ONLINE_SYNC_TAX: 'UpdateQuickbooksOnlineSyncTax', + UPDATE_REPORT_NOTIFICATION_PREFERENCE: 'UpdateReportNotificationPreference', + UPDATE_REPORT_PRIVATE_NOTE: 'UpdateReportPrivateNote', + UPDATE_REPORT_WRITE_CAPABILITY: 'UpdateReportWriteCapability', + UPDATE_ROOM_DESCRIPTION: 'UpdateRoomDescription', + UPDATE_ROOM_VISIBILITY: 'UpdateRoomVisibility', UPDATE_SAGE_INTACCT_APPROVAL_MODE: 'UpdateSageIntacctApprovalMode', - UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS: 'UpdateSageIntacctSyncReimbursedReports', - UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID: 'UpdateSageIntacctSyncReimbursementAccountID', - CONNECT_POLICY_TO_NETSUITE: 'ConnectPolicyToNetSuite', - CLEAR_OUTSTANDING_BALANCE: 'ClearOutstandingBalance', - CANCEL_BILLING_SUBSCRIPTION: 'CancelBillingSubscriptionNewDot', - UPDATE_SAGE_INTACCT_ENTITY: 'UpdateSageIntacctEntity', + UPDATE_SAGE_INTACCT_AUTO_SYNC: 'UpdateSageIntacctAutoSync', UPDATE_SAGE_INTACCT_BILLABLE: 'UpdateSageIntacctBillable', - UPDATE_SAGE_INTACCT_DEPARTMENT_MAPPING: 'UpdateSageIntacctDepartmentsMapping', UPDATE_SAGE_INTACCT_CLASSES_MAPPING: 'UpdateSageIntacctClassesMapping', - UPDATE_SAGE_INTACCT_LOCATIONS_MAPPING: 'UpdateSageIntacctLocationsMapping', UPDATE_SAGE_INTACCT_CUSTOMERS_MAPPING: 'UpdateSageIntacctCustomersMapping', - UPDATE_SAGE_INTACCT_PROJECTS_MAPPING: 'UpdateSageIntacctProjectsMapping', - UPDATE_SAGE_INTACCT_SYNC_TAX_CONFIGURATION: 'UpdateSageIntacctSyncTaxConfiguration', - UPDATE_SAGE_INTACCT_USER_DIMENSION: 'UpdateSageIntacctUserDimension', + UPDATE_SAGE_INTACCT_DEPARTMENT_MAPPING: 'UpdateSageIntacctDepartmentsMapping', + UPDATE_SAGE_INTACCT_ENTITY: 'UpdateSageIntacctEntity', UPDATE_SAGE_INTACCT_EXPORTER: 'UpdateSageIntacctExporter', UPDATE_SAGE_INTACCT_EXPORT_DATE: 'UpdateSageIntacctExportDate', - UPDATE_SAGE_INTACCT_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateSageIntacctReimbursableExpensesExportDestination', - UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateSageIntacctNonreimbursableExpensesExportDestination', - UPDATE_SAGE_INTACCT_REIMBURSABLE_EXPENSES_REPORT_EXPORT_DEFAULT_VENDOR: 'UpdateSageIntacctReimbursableExpensesReportExportDefaultVendor', + UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES: 'UpdateSageIntacctImportEmployees', + UPDATE_SAGE_INTACCT_LOCATIONS_MAPPING: 'UpdateSageIntacctLocationsMapping', UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_CREDIT_CARD_CHARGE_EXPORT_DEFAULT_VENDOR: 'UpdateSageIntacctNonreimbursableExpensesCreditCardChargeExportDefaultVendor', UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_ACCOUNT: 'UpdateSageIntacctNonreimbursableExpensesExportAccount', + UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateSageIntacctNonreimbursableExpensesExportDestination', UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_VENDOR: 'UpdateSageIntacctNonreimbursableExpensesExportVendor', - REQUEST_TAX_EXEMPTION: 'RequestTaxExemption', - EXPORT_SEARCH_ITEMS_TO_CSV: 'ExportSearchToCSV', - CREATE_WORKSPACE_APPROVAL: 'CreateWorkspaceApproval', + UPDATE_SAGE_INTACCT_PROJECTS_MAPPING: 'UpdateSageIntacctProjectsMapping', + UPDATE_SAGE_INTACCT_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'UpdateSageIntacctReimbursableExpensesExportDestination', + UPDATE_SAGE_INTACCT_REIMBURSABLE_EXPENSES_REPORT_EXPORT_DEFAULT_VENDOR: 'UpdateSageIntacctReimbursableExpensesReportExportDefaultVendor', + UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS: 'UpdateSageIntacctSyncReimbursedReports', + UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID: 'UpdateSageIntacctSyncReimbursementAccountID', + UPDATE_SAGE_INTACCT_SYNC_TAX_CONFIGURATION: 'UpdateSageIntacctSyncTaxConfiguration', + UPDATE_SAGE_INTACCT_USER_DIMENSION: 'UpdateSageIntacctUserDimension', + UPDATE_SELECTED_TIMEZONE: 'UpdateSelectedTimezone', + UPDATE_STATUS: 'UpdateStatus', + UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY: 'UpdateSubscriptionAddNewUsersAutomatically', + UPDATE_SUBSCRIPTION_AUTO_RENEW: 'UpdateSubscriptionAutoRenew', + UPDATE_SUBSCRIPTION_SIZE: 'UpdateSubscriptionSize', + UPDATE_SUBSCRIPTION_TYPE: 'UpdateSubscriptionType', + UPDATE_THEME: 'UpdateTheme', + UPDATE_USER_AVATAR: 'UpdateUserAvatar', UPDATE_WORKSPACE_APPROVAL: 'UpdateWorkspaceApproval', - REMOVE_WORKSPACE_APPROVAL: 'RemoveWorkspaceApproval', - CONFIGURE_EXPENSIFY_CARDS_FOR_POLICY: 'ConfigureExpensifyCardsForPolicy', - CREATE_EXPENSIFY_CARD: 'CreateExpensifyCard', - CREATE_ADMIN_ISSUED_VIRTUAL_CARD: 'CreateAdminIssuedVirtualCard', - ADD_DELEGATE: 'AddDelegate', - REMOVE_DELEGATE: 'RemoveDelegate', - UPDATE_DELEGATE_ROLE: 'UpdateDelegateRole', - TOGGLE_CARD_CONTINUOUS_RECONCILIATION: 'ToggleCardContinuousReconciliation', - SET_POLICY_TAG_APPROVER: 'SetPolicyTagApprover', - SAVE_SEARCH: 'SaveSearch', - DELETE_SAVED_SEARCH: 'DeleteSavedSearch', - UPDATE_CARD_SETTLEMENT_FREQUENCY: 'UpdateCardSettlementFrequency', - UPDATE_CARD_SETTLEMENT_ACCOUNT: 'UpdateCardSettlementAccount', - UPDATE_XERO_IMPORT_TRACKING_CATEGORIES: 'UpdateXeroImportTrackingCategories', - UPDATE_XERO_IMPORT_TAX_RATES: 'UpdateXeroImportTaxRates', - UPDATE_XERO_TENANT_ID: 'UpdateXeroTenantID', - UPDATE_XERO_MAPPING: 'UpdateXeroMappings', - UPDATE_XERO_IMPORT_CUSTOMERS: 'UpdateXeroImportCustomers', - UPDATE_XERO_ENABLE_NEW_CATEGORIES: 'UpdateXeroEnableNewCategories', + UPDATE_WORKSPACE_AVATAR: 'UpdateWorkspaceAvatar', + UPDATE_WORKSPACE_DESCRIPTION: 'UpdateWorkspaceDescription', + UPDATE_WORKSPACE_GENERAL_SETTINGS: 'UpdateWorkspaceGeneralSettings', + UPDATE_WORKSPACE_MEMBERS_ROLE: 'UpdateWorkspaceMembersRole', + UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE: 'SetPolicyReportFieldDefault', UPDATE_XERO_AUTO_SYNC: 'UpdateXeroAutoSync', - UPDATE_XERO_EXPORT_BILL_STATUS: 'UpdateXeroExportBillStatus', + UPDATE_XERO_ENABLE_NEW_CATEGORIES: 'UpdateXeroEnableNewCategories', UPDATE_XERO_EXPORT_BILL_DATE: 'UpdateXeroExportBillDate', + UPDATE_XERO_EXPORT_BILL_STATUS: 'UpdateXeroExportBillStatus', UPDATE_XERO_EXPORT_EXPORTER: 'UpdateXeroExportExporter', UPDATE_XERO_EXPORT_NON_REIMBURSABLE_ACCOUNT: 'UpdateXeroExportNonReimbursableAccount', + UPDATE_XERO_IMPORT_CUSTOMERS: 'UpdateXeroImportCustomers', + UPDATE_XERO_IMPORT_TAX_RATES: 'UpdateXeroImportTaxRates', + UPDATE_XERO_IMPORT_TRACKING_CATEGORIES: 'UpdateXeroImportTrackingCategories', + UPDATE_XERO_MAPPING: 'UpdateXeroMappings', UPDATE_XERO_SYNC_INVOICE_COLLECTIONS_ACCOUNT_ID: 'UpdateXeroSyncInvoiceCollectionsAccountID', - UPDATE_XERO_SYNC_SYNC_REIMBURSED_REPORTS: 'UpdateXeroSyncSyncReimbursedReports', UPDATE_XERO_SYNC_REIMBURSEMENT_ACCOUNT_ID: 'UpdateXeroSyncReimbursementAccountID', - REQUEST_FEED_SETUP: 'RequestFeedSetup', - SET_COMPANY_CARD_FEED_NAME: 'SetFeedName', - DELETE_COMPANY_CARD_FEED: 'RemoveFeed', - SET_COMPANY_CARD_TRANSACTION_LIABILITY: 'SetFeedTransactionLiability', - ASSIGN_COMPANY_CARD: 'AssignCard', - UNASSIGN_COMPANY_CARD: 'UnassignCard', - UPDATE_COMPANY_CARD: 'SyncCard', - UPDATE_COMPANY_CARD_NAME: 'SetCardName', - SET_CARD_EXPORT_ACCOUNT: 'SetCardExportAccount', - SET_MISSING_PERSONAL_DETAILS_AND_SHIP_EXPENSIFY_CARD: 'SetMissingPersonalDetailsAndShipExpensifyCard', - SET_INVOICING_TRANSFER_BANK_ACCOUNT: 'SetInvoicingTransferBankAccount', + UPDATE_XERO_SYNC_SYNC_REIMBURSED_REPORTS: 'UpdateXeroSyncSyncReimbursedReports', + UPDATE_XERO_TENANT_ID: 'UpdateXeroTenantID', + UPGRADE_TO_CORPORATE: 'UpgradeToCorporate', + VALIDATE_BANK_ACCOUNT_WITH_TRANSACTIONS: 'ValidateBankAccountWithTransactions', + VALIDATE_LOGIN: 'ValidateLogin', + VALIDATE_SECONDARY_LOGIN: 'ValidateSecondaryLogin', + VERIFY_IDENTITY: 'VerifyIdentity', + VERIFY_IDENTITY_FOR_BANK_ACCOUNT: 'VerifyIdentityForBankAccount', + VERIFY_SETUP_INTENT: 'User_VerifySetupIntent', + VERIFY_SETUP_INTENT_AND_REQUEST_POLICY_OWNER_CHANGE: 'VerifySetupIntentAndRequestPolicyOwnerChange', } as const; type WriteCommand = ValueOf; type WriteCommandParameters = { - [WRITE_COMMANDS.DISMISS_REFERRAL_BANNER]: Parameters.DismissReferralBannerParams; - [WRITE_COMMANDS.UPDATE_PREFERRED_LOCALE]: Parameters.UpdatePreferredLocaleParams; - [WRITE_COMMANDS.RECONNECT_APP]: Parameters.ReconnectAppParams; - [WRITE_COMMANDS.OPEN_APP]: Parameters.OpenAppParams; - [WRITE_COMMANDS.HANDLE_RESTRICTED_EVENT]: Parameters.HandleRestrictedEventParams; - [WRITE_COMMANDS.OPEN_REPORT]: Parameters.OpenReportParams; - [WRITE_COMMANDS.DELETE_PAYMENT_BANK_ACCOUNT]: Parameters.DeletePaymentBankAccountParams; - [WRITE_COMMANDS.UPDATE_PERSONAL_INFORMATION_FOR_BANK_ACCOUNT]: Parameters.UpdatePersonalInformationForBankAccountParams; - [WRITE_COMMANDS.VALIDATE_BANK_ACCOUNT_WITH_TRANSACTIONS]: Parameters.ValidateBankAccountWithTransactionsParams; - [WRITE_COMMANDS.UPDATE_COMPANY_INFORMATION_FOR_BANK_ACCOUNT]: Parameters.UpdateCompanyInformationForBankAccountParams; - [WRITE_COMMANDS.UPDATE_BENEFICIAL_OWNERS_FOR_BANK_ACCOUNT]: UpdateBeneficialOwnersForBankAccountParams; - [WRITE_COMMANDS.CONNECT_BANK_ACCOUNT_MANUALLY]: Parameters.ConnectBankAccountParams; - [WRITE_COMMANDS.VERIFY_IDENTITY_FOR_BANK_ACCOUNT]: Parameters.VerifyIdentityForBankAccountParams; - [WRITE_COMMANDS.BANK_ACCOUNT_HANDLE_PLAID_ERROR]: Parameters.BankAccountHandlePlaidErrorParams; - [WRITE_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD]: Parameters.ReportVirtualExpensifyCardFraudParams; - [WRITE_COMMANDS.REQUEST_REPLACEMENT_EXPENSIFY_CARD]: Parameters.RequestReplacementExpensifyCardParams; + [WRITE_COMMANDS.ACCEPT_ACH_CONTRACT_FOR_BANK_ACCOUNT]: Parameters.AcceptACHContractForBankAccount; + [WRITE_COMMANDS.ACCEPT_JOIN_REQUEST]: Parameters.AcceptJoinRequestParams; + [WRITE_COMMANDS.ACCEPT_SPOTNANA_TERMS]: null; + [WRITE_COMMANDS.ACCEPT_WALLET_TERMS]: Parameters.AcceptWalletTermsParams; [WRITE_COMMANDS.ACTIVATE_PHYSICAL_EXPENSIFY_CARD]: Parameters.ActivatePhysicalExpensifyCardParams; - [WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_LIMIT]: Parameters.UpdateExpensifyCardLimitParams; - [WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_TITLE]: Parameters.UpdateExpensifyCardTitleParams; - [WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_LIMIT_TYPE]: Parameters.UpdateExpensifyCardLimitTypeParams; - [WRITE_COMMANDS.CARD_DEACTIVATE]: Parameters.CardDeactivateParams; - [WRITE_COMMANDS.MAKE_DEFAULT_PAYMENT_METHOD]: Parameters.MakeDefaultPaymentMethodParams; + [WRITE_COMMANDS.ADD_ATTACHMENT]: Parameters.AddCommentOrAttachementParams; + [WRITE_COMMANDS.ADD_BILLING_CARD_AND_REQUEST_WORKSPACE_OWNER_CHANGE]: Parameters.AddBillingCardAndRequestWorkspaceOwnerChangeParams; + [WRITE_COMMANDS.ADD_COMMENT]: Parameters.AddCommentOrAttachementParams; + [WRITE_COMMANDS.ADD_DELEGATE]: Parameters.AddDelegateParams; + [WRITE_COMMANDS.ADD_EMOJI_REACTION]: Parameters.AddEmojiReactionParams; + [WRITE_COMMANDS.ADD_MEMBERS_TO_WORKSPACE]: Parameters.AddMembersToWorkspaceParams; + [WRITE_COMMANDS.ADD_NEW_CONTACT_METHOD]: Parameters.AddNewContactMethodParams; [WRITE_COMMANDS.ADD_PAYMENT_CARD]: Parameters.AddPaymentCardParams; [WRITE_COMMANDS.ADD_PAYMENT_CARD_GBP]: Parameters.AddPaymentCardParams; - [WRITE_COMMANDS.VERIFY_SETUP_INTENT]: Parameters.VerifySetupIntentParams; - [WRITE_COMMANDS.VERIFY_SETUP_INTENT_AND_REQUEST_POLICY_OWNER_CHANGE]: Parameters.VerifySetupIntentAndRequestPolicyOwnerChangeParams; - [WRITE_COMMANDS.DELETE_PAYMENT_CARD]: Parameters.DeletePaymentCardParams; - [WRITE_COMMANDS.UPDATE_PRONOUNS]: Parameters.UpdatePronounsParams; - [WRITE_COMMANDS.UPDATE_DISPLAY_NAME]: Parameters.UpdateDisplayNameParams; - [WRITE_COMMANDS.UPDATE_LEGAL_NAME]: Parameters.UpdateLegalNameParams; - [WRITE_COMMANDS.UPDATE_DATE_OF_BIRTH]: Parameters.UpdateDateOfBirthParams; - [WRITE_COMMANDS.UPDATE_POLICY_ADDRESS]: Parameters.UpdatePolicyAddressParams; - [WRITE_COMMANDS.UPDATE_HOME_ADDRESS]: Parameters.UpdateHomeAddressParams; - [WRITE_COMMANDS.UPDATE_AUTOMATIC_TIMEZONE]: Parameters.UpdateAutomaticTimezoneParams; - [WRITE_COMMANDS.UPDATE_SELECTED_TIMEZONE]: Parameters.UpdateSelectedTimezoneParams; - [WRITE_COMMANDS.UPDATE_USER_AVATAR]: Parameters.UpdateUserAvatarParams; - [WRITE_COMMANDS.DELETE_USER_AVATAR]: null; - [WRITE_COMMANDS.REFER_TEACHERS_UNITE_VOLUNTEER]: Parameters.ReferTeachersUniteVolunteerParams; + [WRITE_COMMANDS.ADD_PERSONAL_BANK_ACCOUNT]: Parameters.AddPersonalBankAccountParams; [WRITE_COMMANDS.ADD_SCHOOL_PRINCIPAL]: Parameters.AddSchoolPrincipalParams; - [WRITE_COMMANDS.CLOSE_ACCOUNT]: Parameters.CloseAccountParams; - [WRITE_COMMANDS.REQUEST_CONTACT_METHOD_VALIDATE_CODE]: Parameters.RequestContactMethodValidateCodeParams; - [WRITE_COMMANDS.UPDATE_NEWSLETTER_SUBSCRIPTION]: Parameters.UpdateNewsletterSubscriptionParams; - [WRITE_COMMANDS.DELETE_CONTACT_METHOD]: Parameters.DeleteContactMethodParams; - [WRITE_COMMANDS.ADD_NEW_CONTACT_METHOD]: Parameters.AddNewContactMethodParams; - [WRITE_COMMANDS.VALIDATE_LOGIN]: Parameters.ValidateLoginParams; - [WRITE_COMMANDS.VALIDATE_SECONDARY_LOGIN]: Parameters.ValidateSecondaryLoginParams; - [WRITE_COMMANDS.UPDATE_PREFERRED_EMOJI_SKIN_TONE]: Parameters.UpdatePreferredEmojiSkinToneParams; - [WRITE_COMMANDS.UPDATE_CHAT_PRIORITY_MODE]: Parameters.UpdateChatPriorityModeParams; - [WRITE_COMMANDS.SET_CONTACT_METHOD_AS_DEFAULT]: Parameters.SetContactMethodAsDefaultParams; - [WRITE_COMMANDS.UPDATE_THEME]: Parameters.UpdateThemeParams; - [WRITE_COMMANDS.UPDATE_STATUS]: Parameters.UpdateStatusParams; - [WRITE_COMMANDS.CLEAR_STATUS]: null; - [WRITE_COMMANDS.UPDATE_PERSONAL_DETAILS_FOR_WALLET]: Parameters.UpdatePersonalDetailsForWalletParams; - [WRITE_COMMANDS.REQUEST_FEED_SETUP]: Parameters.RequestFeedSetupParams; - [WRITE_COMMANDS.SET_COMPANY_CARD_FEED_NAME]: Parameters.SetCompanyCardFeedName; - [WRITE_COMMANDS.DELETE_COMPANY_CARD_FEED]: Parameters.DeleteCompanyCardFeed; - [WRITE_COMMANDS.ASSIGN_COMPANY_CARD]: Parameters.AssignCompanyCardParams; - [WRITE_COMMANDS.UNASSIGN_COMPANY_CARD]: Parameters.UnassignCompanyCard; - [WRITE_COMMANDS.UPDATE_COMPANY_CARD]: Parameters.UpdateCompanyCard; - [WRITE_COMMANDS.UPDATE_COMPANY_CARD_NAME]: Parameters.UpdateCompanyCardNameParams; - [WRITE_COMMANDS.SET_CARD_EXPORT_ACCOUNT]: Parameters.SetCompanyCardExportAccountParams; - [WRITE_COMMANDS.SET_COMPANY_CARD_TRANSACTION_LIABILITY]: Parameters.SetCompanyCardTransactionLiability; - [WRITE_COMMANDS.VERIFY_IDENTITY]: Parameters.VerifyIdentityParams; - [WRITE_COMMANDS.ACCEPT_WALLET_TERMS]: Parameters.AcceptWalletTermsParams; - [WRITE_COMMANDS.ANSWER_QUESTIONS_FOR_WALLET]: Parameters.AnswerQuestionsForWalletParams; - [WRITE_COMMANDS.REQUEST_PHYSICAL_EXPENSIFY_CARD]: Parameters.RequestPhysicalExpensifyCardParams; - [WRITE_COMMANDS.LOG_OUT]: Parameters.LogOutParams; - [WRITE_COMMANDS.REQUEST_ACCOUNT_VALIDATION_LINK]: Parameters.RequestAccountValidationLinkParams; - [WRITE_COMMANDS.REQUEST_NEW_VALIDATE_CODE]: Parameters.RequestNewValidateCodeParams; - [WRITE_COMMANDS.SIGN_IN_WITH_APPLE]: Parameters.BeginAppleSignInParams; - [WRITE_COMMANDS.SIGN_IN_WITH_GOOGLE]: Parameters.BeginGoogleSignInParams; - [WRITE_COMMANDS.SIGN_IN_USER]: SignInUserParams; - [WRITE_COMMANDS.SIGN_IN_USER_WITH_LINK]: Parameters.SignInUserWithLinkParams; - [WRITE_COMMANDS.REQUEST_UNLINK_VALIDATION_LINK]: Parameters.RequestUnlinkValidationLinkParams; - [WRITE_COMMANDS.UNLINK_LOGIN]: Parameters.UnlinkLoginParams; - [WRITE_COMMANDS.ENABLE_TWO_FACTOR_AUTH]: null; - [WRITE_COMMANDS.DISABLE_TWO_FACTOR_AUTH]: Parameters.DisableTwoFactorAuthParams; - [WRITE_COMMANDS.ADD_COMMENT]: Parameters.AddCommentOrAttachementParams; - [WRITE_COMMANDS.ADD_ATTACHMENT]: Parameters.AddCommentOrAttachementParams; [WRITE_COMMANDS.ADD_TEXT_AND_ATTACHMENT]: Parameters.AddCommentOrAttachementParams; - [WRITE_COMMANDS.CONNECT_BANK_ACCOUNT_WITH_PLAID]: Parameters.ConnectBankAccountParams; - [WRITE_COMMANDS.ADD_PERSONAL_BANK_ACCOUNT]: Parameters.AddPersonalBankAccountParams; - [WRITE_COMMANDS.RESTART_BANK_ACCOUNT_SETUP]: Parameters.RestartBankAccountSetupParams; - [WRITE_COMMANDS.OPT_IN_TO_PUSH_NOTIFICATIONS]: Parameters.OptInOutToPushNotificationsParams; - [WRITE_COMMANDS.RESEND_VALIDATE_CODE]: null; - [WRITE_COMMANDS.OPT_OUT_OF_PUSH_NOTIFICATIONS]: Parameters.OptInOutToPushNotificationsParams; - [WRITE_COMMANDS.READ_NEWEST_ACTION]: Parameters.ReadNewestActionParams; - [WRITE_COMMANDS.MARK_AS_UNREAD]: Parameters.MarkAsUnreadParams; - [WRITE_COMMANDS.TOGGLE_PINNED_CHAT]: Parameters.TogglePinnedChatParams; - [WRITE_COMMANDS.DELETE_COMMENT]: Parameters.DeleteCommentParams; - [WRITE_COMMANDS.UPDATE_COMMENT]: Parameters.UpdateCommentParams; - [WRITE_COMMANDS.UPDATE_REPORT_NOTIFICATION_PREFERENCE]: Parameters.UpdateReportNotificationPreferenceParams; - [WRITE_COMMANDS.UPDATE_ROOM_VISIBILITY]: Parameters.UpdateRoomVisibilityParams; - [WRITE_COMMANDS.UPDATE_ROOM_DESCRIPTION]: Parameters.UpdateRoomDescriptionParams; - [WRITE_COMMANDS.UPDATE_REPORT_WRITE_CAPABILITY]: Parameters.UpdateReportWriteCapabilityParams; [WRITE_COMMANDS.ADD_WORKSPACE_ROOM]: Parameters.AddWorkspaceRoomParams; - [WRITE_COMMANDS.UPDATE_POLICY_ROOM_NAME]: Parameters.UpdatePolicyRoomNameParams; - [WRITE_COMMANDS.ADD_EMOJI_REACTION]: Parameters.AddEmojiReactionParams; - [WRITE_COMMANDS.REMOVE_EMOJI_REACTION]: Parameters.RemoveEmojiReactionParams; - [WRITE_COMMANDS.LEAVE_ROOM]: Parameters.LeaveRoomParams; - [WRITE_COMMANDS.INVITE_TO_ROOM]: Parameters.InviteToRoomParams; - [WRITE_COMMANDS.INVITE_TO_GROUP_CHAT]: Parameters.InviteToGroupChatParams; - [WRITE_COMMANDS.UPDATE_GROUP_CHAT_AVATAR]: Parameters.UpdateGroupChatAvatarParams; - [WRITE_COMMANDS.LEAVE_GROUP_CHAT]: Parameters.LeaveGroupChatParams; - [WRITE_COMMANDS.REMOVE_FROM_GROUP_CHAT]: Parameters.RemoveFromGroupChatParams; - [WRITE_COMMANDS.UPDATE_GROUP_CHAT_MEMBER_ROLES]: Parameters.UpdateGroupChatMemberRolesParams; - [WRITE_COMMANDS.UPDATE_GROUP_CHAT_NAME]: Parameters.UpdateGroupChatNameParams; - [WRITE_COMMANDS.REMOVE_FROM_ROOM]: Parameters.RemoveFromRoomParams; - [WRITE_COMMANDS.FLAG_COMMENT]: Parameters.FlagCommentParams; - [WRITE_COMMANDS.UPDATE_REPORT_PRIVATE_NOTE]: Parameters.UpdateReportPrivateNoteParams; - [WRITE_COMMANDS.RESOLVE_ACTIONABLE_MENTION_WHISPER]: Parameters.ResolveActionableMentionWhisperParams; - [WRITE_COMMANDS.RESOLVE_ACTIONABLE_REPORT_MENTION_WHISPER]: Parameters.ResolveActionableReportMentionWhisperParams; + [WRITE_COMMANDS.ANSWER_QUESTIONS_FOR_WALLET]: Parameters.AnswerQuestionsForWalletParams; + [WRITE_COMMANDS.APPROVE_MONEY_REQUEST]: Parameters.ApproveMoneyRequestParams; + [WRITE_COMMANDS.ASSIGN_COMPANY_CARD]: Parameters.AssignCompanyCardParams; + [WRITE_COMMANDS.BANK_ACCOUNT_HANDLE_PLAID_ERROR]: Parameters.BankAccountHandlePlaidErrorParams; + [WRITE_COMMANDS.CANCEL_BILLING_SUBSCRIPTION]: Parameters.CancelBillingSubscriptionParams; + [WRITE_COMMANDS.CANCEL_PAYMENT]: Parameters.CancelPaymentParams; + [WRITE_COMMANDS.CANCEL_TASK]: Parameters.CancelTaskParams; + [WRITE_COMMANDS.CARD_DEACTIVATE]: Parameters.CardDeactivateParams; + [WRITE_COMMANDS.CATEGORIZE_TRACKED_EXPENSE]: Parameters.CategorizeTrackedExpenseParams; [WRITE_COMMANDS.CHRONOS_REMOVE_OOO_EVENT]: Parameters.ChronosRemoveOOOEventParams; - [WRITE_COMMANDS.TRANSFER_WALLET_BALANCE]: Parameters.TransferWalletBalanceParams; - [WRITE_COMMANDS.DELETE_WORKSPACE]: Parameters.DeleteWorkspaceParams; - [WRITE_COMMANDS.DELETE_MEMBERS_FROM_WORKSPACE]: Parameters.DeleteMembersFromWorkspaceParams; - [WRITE_COMMANDS.ADD_MEMBERS_TO_WORKSPACE]: Parameters.AddMembersToWorkspaceParams; - [WRITE_COMMANDS.UPDATE_WORKSPACE_AVATAR]: Parameters.UpdateWorkspaceAvatarParams; - [WRITE_COMMANDS.DELETE_WORKSPACE_AVATAR]: Parameters.DeleteWorkspaceAvatarParams; - [WRITE_COMMANDS.UPDATE_WORKSPACE_GENERAL_SETTINGS]: Parameters.UpdateWorkspaceGeneralSettingsParams; - [WRITE_COMMANDS.UPDATE_WORKSPACE_DESCRIPTION]: Parameters.UpdateWorkspaceDescriptionParams; - [WRITE_COMMANDS.UPDATE_WORKSPACE_MEMBERS_ROLE]: Parameters.UpdateWorkspaceMembersRoleParams; - [WRITE_COMMANDS.CREATE_WORKSPACE]: Parameters.CreateWorkspaceParams; - [WRITE_COMMANDS.CREATE_WORKSPACE_FROM_IOU_PAYMENT]: Parameters.CreateWorkspaceFromIOUPaymentParams; - [WRITE_COMMANDS.SET_WORKSPACE_CATEGORIES_ENABLED]: Parameters.SetWorkspaceCategoriesEnabledParams; - [WRITE_COMMANDS.CREATE_WORKSPACE_CATEGORIES]: Parameters.CreateWorkspaceCategoriesParams; - [WRITE_COMMANDS.IMPORT_CATEGORIES_SPREADSHEET]: Parameters.ImportCategoriesSpreadsheetParams; - [WRITE_COMMANDS.IMPORT_MEMBERS_SPREADSHEET]: Parameters.ImportMembersSpreadsheetParams; - [WRITE_COMMANDS.IMPORT_TAGS_SPREADSHEET]: Parameters.ImportTagsSpreadsheetParams; - [WRITE_COMMANDS.EXPORT_CATEGORIES_CSV]: Parameters.ExportCategoriesSpreadsheetParams; - [WRITE_COMMANDS.EXPORT_MEMBERS_CSV]: Parameters.ExportMembersSpreadsheetParams; - [WRITE_COMMANDS.EXPORT_TAGS_CSV]: Parameters.ExportTagsSpreadsheetParams; - [WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY]: Parameters.RenameWorkspaceCategoriesParams; - [WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams; - [WRITE_COMMANDS.DELETE_WORKSPACE_CATEGORIES]: Parameters.DeleteWorkspaceCategoriesParams; - [WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_PAYROLL_CODE]: Parameters.UpdatePolicyCategoryPayrollCodeParams; - [WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_GL_CODE]: Parameters.UpdatePolicyCategoryGLCodeParams; - [WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD]: Parameters.DeletePolicyReportField; - [WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag; - [WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED]: Parameters.SetPolicyTagsRequired; - [WRITE_COMMANDS.RENAME_POLICY_TAG_LIST]: Parameters.RenamePolicyTaglistParams; + [WRITE_COMMANDS.CLEAR_OUTSTANDING_BALANCE]: null; + [WRITE_COMMANDS.CLEAR_STATUS]: null; + [WRITE_COMMANDS.CLOSE_ACCOUNT]: Parameters.CloseAccountParams; + [WRITE_COMMANDS.COMPLETE_GUIDED_SETUP]: Parameters.CompleteGuidedSetupParams; + [WRITE_COMMANDS.COMPLETE_SPLIT_BILL]: Parameters.CompleteSplitBillParams; + [WRITE_COMMANDS.COMPLETE_TASK]: Parameters.CompleteTaskParams; + [WRITE_COMMANDS.CONFIGURE_EXPENSIFY_CARDS_FOR_POLICY]: Parameters.ConfigureExpensifyCardsForPolicyParams; + [WRITE_COMMANDS.CONNECT_BANK_ACCOUNT_MANUALLY]: Parameters.ConnectBankAccountParams; + [WRITE_COMMANDS.CONNECT_BANK_ACCOUNT_WITH_PLAID]: Parameters.ConnectBankAccountParams; + [WRITE_COMMANDS.CONNECT_POLICY_TO_NETSUITE]: Parameters.ConnectPolicyToNetSuiteParams; + [WRITE_COMMANDS.CONNECT_POLICY_TO_SAGE_INTACCT]: Parameters.ConnectPolicyToSageIntacctParams; + [WRITE_COMMANDS.CONVERT_TRACKED_EXPENSE_TO_REQUEST]: Parameters.ConvertTrackedExpenseToRequestParams; + [WRITE_COMMANDS.COPY_EXISTING_POLICY_CONNECTION]: Parameters.CopyExistingPolicyConnectionParams; + [WRITE_COMMANDS.CREATE_ADMIN_ISSUED_VIRTUAL_CARD]: Omit; + [WRITE_COMMANDS.CREATE_DISTANCE_REQUEST]: Parameters.CreateDistanceRequestParams; + [WRITE_COMMANDS.CREATE_EXPENSIFY_CARD]: Omit; + [WRITE_COMMANDS.CREATE_POLICY_DISTANCE_RATE]: Parameters.CreatePolicyDistanceRateParams; [WRITE_COMMANDS.CREATE_POLICY_TAG]: Parameters.CreatePolicyTagsParams; - [WRITE_COMMANDS.RENAME_POLICY_TAG]: Parameters.RenamePolicyTagsParams; - [WRITE_COMMANDS.UPDATE_POLICY_TAG_GL_CODE]: Parameters.UpdatePolicyTagGLCodeParams; - [WRITE_COMMANDS.SET_POLICY_TAGS_ENABLED]: Parameters.SetPolicyTagsEnabled; - [WRITE_COMMANDS.DELETE_POLICY_TAGS]: Parameters.DeletePolicyTagsParams; + [WRITE_COMMANDS.CREATE_POLICY_TAX]: Parameters.CreatePolicyTaxParams; [WRITE_COMMANDS.CREATE_TASK]: Parameters.CreateTaskParams; - [WRITE_COMMANDS.CANCEL_TASK]: Parameters.CancelTaskParams; - [WRITE_COMMANDS.EDIT_TASK_ASSIGNEE]: Parameters.EditTaskAssigneeParams; - [WRITE_COMMANDS.EDIT_TASK]: Parameters.EditTaskParams; - [WRITE_COMMANDS.REOPEN_TASK]: Parameters.ReopenTaskParams; - [WRITE_COMMANDS.COMPLETE_TASK]: Parameters.CompleteTaskParams; - [WRITE_COMMANDS.COMPLETE_GUIDED_SETUP]: Parameters.CompleteGuidedSetupParams; - [WRITE_COMMANDS.SET_NAME_VALUE_PAIR]: Parameters.SetNameValuePairParams; - [WRITE_COMMANDS.SET_REPORT_FIELD]: Parameters.SetReportFieldParams; - [WRITE_COMMANDS.SET_REPORT_NAME]: Parameters.SetReportNameParams; - [WRITE_COMMANDS.DELETE_REPORT_FIELD]: Parameters.DeleteReportFieldParams; - [WRITE_COMMANDS.COMPLETE_SPLIT_BILL]: Parameters.CompleteSplitBillParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DATE]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_MERCHANT]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_BILLABLE]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAG]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_AMOUNT]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_RATE]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE_RATE]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_CATEGORY]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.HOLD_MONEY_REQUEST]: Parameters.HoldMoneyRequestParams; - [WRITE_COMMANDS.UNHOLD_MONEY_REQUEST]: Parameters.UnHoldMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_DISTANCE_REQUEST]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.REQUEST_MONEY]: Parameters.RequestMoneyParams; - [WRITE_COMMANDS.SPLIT_BILL]: Parameters.SplitBillParams; - [WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT]: Parameters.SplitBillParams; + [WRITE_COMMANDS.CREATE_WORKSPACE]: Parameters.CreateWorkspaceParams; + [WRITE_COMMANDS.CREATE_WORKSPACE_APPROVAL]: Parameters.CreateWorkspaceApprovalParams; + [WRITE_COMMANDS.CREATE_WORKSPACE_CATEGORIES]: Parameters.CreateWorkspaceCategoriesParams; + [WRITE_COMMANDS.CREATE_WORKSPACE_FROM_IOU_PAYMENT]: Parameters.CreateWorkspaceFromIOUPaymentParams; + [WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD]: Parameters.CreateWorkspaceReportFieldParams; + [WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.CreateWorkspaceReportFieldListValueParams; + [WRITE_COMMANDS.DECLINE_JOIN_REQUEST]: Parameters.DeclineJoinRequestParams; + [WRITE_COMMANDS.DELETE_COMMENT]: Parameters.DeleteCommentParams; + [WRITE_COMMANDS.DELETE_COMPANY_CARD_FEED]: Parameters.DeleteCompanyCardFeed; + [WRITE_COMMANDS.DELETE_CONTACT_METHOD]: Parameters.DeleteContactMethodParams; + [WRITE_COMMANDS.DELETE_MEMBERS_FROM_WORKSPACE]: Parameters.DeleteMembersFromWorkspaceParams; [WRITE_COMMANDS.DELETE_MONEY_REQUEST]: Parameters.DeleteMoneyRequestParams; - [WRITE_COMMANDS.CREATE_DISTANCE_REQUEST]: Parameters.CreateDistanceRequestParams; - [WRITE_COMMANDS.START_SPLIT_BILL]: Parameters.StartSplitBillParams; - [WRITE_COMMANDS.SEND_MONEY_ELSEWHERE]: Parameters.SendMoneyParams; - [WRITE_COMMANDS.SEND_MONEY_WITH_WALLET]: Parameters.SendMoneyParams; - [WRITE_COMMANDS.APPROVE_MONEY_REQUEST]: Parameters.ApproveMoneyRequestParams; - [WRITE_COMMANDS.UNAPPROVE_EXPENSE_REPORT]: Parameters.UnapproveExpenseReportParams; - [WRITE_COMMANDS.EDIT_MONEY_REQUEST]: Parameters.EditMoneyRequestParams; - [WRITE_COMMANDS.REPLACE_RECEIPT]: Parameters.ReplaceReceiptParams; - [WRITE_COMMANDS.SUBMIT_REPORT]: Parameters.SubmitReportParams; + [WRITE_COMMANDS.DELETE_MONEY_REQUEST_ON_SEARCH]: Parameters.DeleteMoneyRequestOnSearchParams; + [WRITE_COMMANDS.DELETE_PAYMENT_BANK_ACCOUNT]: Parameters.DeletePaymentBankAccountParams; + [WRITE_COMMANDS.DELETE_PAYMENT_CARD]: Parameters.DeletePaymentCardParams; + [WRITE_COMMANDS.DELETE_POLICY_DISTANCE_RATES]: Parameters.DeletePolicyDistanceRatesParams; + [WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD]: Parameters.DeletePolicyReportField; + [WRITE_COMMANDS.DELETE_POLICY_TAGS]: Parameters.DeletePolicyTagsParams; + [WRITE_COMMANDS.DELETE_POLICY_TAXES]: Parameters.DeletePolicyTaxesParams; + [WRITE_COMMANDS.DELETE_REPORT_FIELD]: Parameters.DeleteReportFieldParams; + [WRITE_COMMANDS.DELETE_SAVED_SEARCH]: Parameters.DeleteSavedSearchParams; + [WRITE_COMMANDS.DELETE_USER_AVATAR]: null; + [WRITE_COMMANDS.DELETE_WORKSPACE]: Parameters.DeleteWorkspaceParams; + [WRITE_COMMANDS.DELETE_WORKSPACE_AVATAR]: Parameters.DeleteWorkspaceAvatarParams; + [WRITE_COMMANDS.DELETE_WORKSPACE_CATEGORIES]: Parameters.DeleteWorkspaceCategoriesParams; [WRITE_COMMANDS.DETACH_RECEIPT]: Parameters.DetachReceiptParams; - [WRITE_COMMANDS.PAY_MONEY_REQUEST_WITH_WALLET]: Parameters.PayMoneyRequestParams; - [WRITE_COMMANDS.PAY_MONEY_REQUEST]: Parameters.PayMoneyRequestParams; - [WRITE_COMMANDS.CANCEL_PAYMENT]: Parameters.CancelPaymentParams; - [WRITE_COMMANDS.ACCEPT_ACH_CONTRACT_FOR_BANK_ACCOUNT]: Parameters.AcceptACHContractForBankAccount; - [WRITE_COMMANDS.UPDATE_WORKSPACE_DESCRIPTION]: Parameters.UpdateWorkspaceDescriptionParams; - [WRITE_COMMANDS.SET_WORKSPACE_AUTO_REPORTING_FREQUENCY]: Parameters.SetWorkspaceAutoReportingFrequencyParams; - [WRITE_COMMANDS.SET_WORKSPACE_AUTO_REPORTING_MONTHLY_OFFSET]: Parameters.SetWorkspaceAutoReportingMonthlyOffsetParams; - [WRITE_COMMANDS.SET_WORKSPACE_APPROVAL_MODE]: Parameters.SetWorkspaceApprovalModeParams; - [WRITE_COMMANDS.SET_WORKSPACE_PAYER]: Parameters.SetWorkspacePayerParams; - [WRITE_COMMANDS.SET_WORKSPACE_REIMBURSEMENT]: Parameters.SetWorkspaceReimbursementParams; - [WRITE_COMMANDS.SET_POLICY_DEFAULT_REPORT_TITLE]: Parameters.SetPolicyDefaultReportTitleParams; - [WRITE_COMMANDS.SET_POLICY_PREVENT_MEMBER_CREATED_TITLE]: Parameters.SetPolicyPreventMemberCreatedTitleParams; - [WRITE_COMMANDS.SET_POLICY_PREVENT_SELF_APPROVAL]: Parameters.SetPolicyPreventSelfApprovalParams; - [WRITE_COMMANDS.SET_POLICY_AUTOMATIC_APPROVAL_LIMIT]: Parameters.SetPolicyAutomaticApprovalLimitParams; - [WRITE_COMMANDS.SET_POLICY_AUTOMATIC_APPROVAL_RATE]: Parameters.SetPolicyAutomaticApprovalRateParams; - [WRITE_COMMANDS.SET_POLICY_AUTO_REIMBURSEMENT_LIMIT]: Parameters.SetPolicyAutoReimbursementLimitParams; - [WRITE_COMMANDS.ENABLE_POLICY_AUTO_REIMBURSEMENT_LIMIT]: Parameters.EnablePolicyAutoReimbursementLimitParams; + [WRITE_COMMANDS.DISABLE_POLICY_BILLABLE_MODE]: Parameters.DisablePolicyBillableModeParams; + [WRITE_COMMANDS.DISABLE_TWO_FACTOR_AUTH]: Parameters.DisableTwoFactorAuthParams; + [WRITE_COMMANDS.DISMISS_REFERRAL_BANNER]: Parameters.DismissReferralBannerParams; + [WRITE_COMMANDS.DISMISS_TRACK_EXPENSE_ACTIONABLE_WHISPER]: Parameters.DismissTrackExpenseActionableWhisperParams; + [WRITE_COMMANDS.DISMISS_VIOLATION]: Parameters.DismissViolationParams; + [WRITE_COMMANDS.EDIT_MONEY_REQUEST]: Parameters.EditMoneyRequestParams; + [WRITE_COMMANDS.EDIT_TASK]: Parameters.EditTaskParams; + [WRITE_COMMANDS.EDIT_TASK_ASSIGNEE]: Parameters.EditTaskAssigneeParams; + [WRITE_COMMANDS.ENABLE_DISTANCE_REQUEST_TAX]: Parameters.SetPolicyDistanceRatesDefaultCategoryParams; [WRITE_COMMANDS.ENABLE_POLICY_AUTO_APPROVAL_OPTIONS]: Parameters.EnablePolicyAutoApprovalOptionsParams; - [WRITE_COMMANDS.ENABLE_POLICY_DEFAULT_REPORT_TITLE]: Parameters.EnablePolicyDefaultReportTitleParams; - [WRITE_COMMANDS.SET_WORKSPACE_DEFAULT_SPEND_CATEGORY]: Parameters.SetWorkspaceDefaultSpendCategoryParams; - [WRITE_COMMANDS.SWITCH_TO_OLD_DOT]: Parameters.SwitchToOldDotParams; - [WRITE_COMMANDS.TRACK_EXPENSE]: Parameters.TrackExpenseParams; + [WRITE_COMMANDS.ENABLE_POLICY_AUTO_REIMBURSEMENT_LIMIT]: Parameters.EnablePolicyAutoReimbursementLimitParams; [WRITE_COMMANDS.ENABLE_POLICY_CATEGORIES]: Parameters.EnablePolicyCategoriesParams; + [WRITE_COMMANDS.ENABLE_POLICY_COMPANY_CARDS]: Parameters.EnablePolicyCompanyCardsParams; [WRITE_COMMANDS.ENABLE_POLICY_CONNECTIONS]: Parameters.EnablePolicyConnectionsParams; + [WRITE_COMMANDS.ENABLE_POLICY_DEFAULT_REPORT_TITLE]: Parameters.EnablePolicyDefaultReportTitleParams; [WRITE_COMMANDS.ENABLE_POLICY_DISTANCE_RATES]: Parameters.EnablePolicyDistanceRatesParams; + [WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS]: Parameters.EnablePolicyExpensifyCardsParams; + [WRITE_COMMANDS.ENABLE_POLICY_INVOICING]: Parameters.EnablePolicyInvoicingParams; + [WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS]: Parameters.EnablePolicyReportFieldsParams; [WRITE_COMMANDS.ENABLE_POLICY_TAGS]: Parameters.EnablePolicyTagsParams; [WRITE_COMMANDS.ENABLE_POLICY_TAXES]: Parameters.EnablePolicyTaxesParams; [WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS]: Parameters.EnablePolicyWorkflowsParams; - [WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS]: Parameters.EnablePolicyReportFieldsParams; - [WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS]: Parameters.EnablePolicyExpensifyCardsParams; - [WRITE_COMMANDS.ENABLE_POLICY_COMPANY_CARDS]: Parameters.EnablePolicyCompanyCardsParams; - [WRITE_COMMANDS.ENABLE_POLICY_INVOICING]: Parameters.EnablePolicyInvoicingParams; - [WRITE_COMMANDS.SET_POLICY_RULES_ENABLED]: Parameters.SetPolicyRulesEnabledParams; - [WRITE_COMMANDS.SET_POLICY_CATEGORY_DESCRIPTION_REQUIRED]: Parameters.SetPolicyCategoryDescriptionRequiredParams; - [WRITE_COMMANDS.SET_WORKSPACE_CATEGORY_DESCRIPTION_HINT]: Parameters.SetWorkspaceCategoryDescriptionHintParams; - [WRITE_COMMANDS.SET_POLICY_CATEGORY_RECEIPTS_REQUIRED]: Parameters.SetPolicyCategoryReceiptsRequiredParams; - [WRITE_COMMANDS.REMOVE_POLICY_CATEGORY_RECEIPTS_REQUIRED]: Parameters.RemovePolicyCategoryReceiptsRequiredParams; - [WRITE_COMMANDS.SET_POLICY_CATEGORY_MAX_AMOUNT]: Parameters.SetPolicyCategoryMaxAmountParams; - [WRITE_COMMANDS.SET_POLICY_CATEGORY_APPROVER]: Parameters.SetPolicyCategoryApproverParams; - [WRITE_COMMANDS.SEARCH]: Parameters.SearchParams; - [WRITE_COMMANDS.SET_POLICY_CATEGORY_TAX]: Parameters.SetPolicyCategoryTaxParams; + [WRITE_COMMANDS.ENABLE_TWO_FACTOR_AUTH]: null; + [WRITE_COMMANDS.ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.EnableWorkspaceReportFieldListValueParams; + [WRITE_COMMANDS.EXPORT_CATEGORIES_CSV]: Parameters.ExportCategoriesSpreadsheetParams; + [WRITE_COMMANDS.EXPORT_MEMBERS_CSV]: Parameters.ExportMembersSpreadsheetParams; + [WRITE_COMMANDS.EXPORT_REPORT_TO_CSV]: Parameters.ExportReportCSVParams; + [WRITE_COMMANDS.EXPORT_SEARCH_ITEMS_TO_CSV]: Parameters.ExportSearchItemsToCSVParams; + [WRITE_COMMANDS.EXPORT_TAGS_CSV]: Parameters.ExportTagsSpreadsheetParams; + [WRITE_COMMANDS.FLAG_COMMENT]: Parameters.FlagCommentParams; + [WRITE_COMMANDS.HANDLE_RESTRICTED_EVENT]: Parameters.HandleRestrictedEventParams; + [WRITE_COMMANDS.HOLD_MONEY_REQUEST]: Parameters.HoldMoneyRequestParams; + [WRITE_COMMANDS.HOLD_MONEY_REQUEST_ON_SEARCH]: Parameters.HoldMoneyRequestOnSearchParams; + [WRITE_COMMANDS.IMPORT_CATEGORIES_SPREADSHEET]: Parameters.ImportCategoriesSpreadsheetParams; + [WRITE_COMMANDS.IMPORT_MEMBERS_SPREADSHEET]: Parameters.ImportMembersSpreadsheetParams; + [WRITE_COMMANDS.IMPORT_TAGS_SPREADSHEET]: Parameters.ImportTagsSpreadsheetParams; + [WRITE_COMMANDS.INVITE_TO_GROUP_CHAT]: Parameters.InviteToGroupChatParams; + [WRITE_COMMANDS.INVITE_TO_ROOM]: Parameters.InviteToRoomParams; [WRITE_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams; - [WRITE_COMMANDS.ACCEPT_JOIN_REQUEST]: Parameters.AcceptJoinRequestParams; - [WRITE_COMMANDS.DECLINE_JOIN_REQUEST]: Parameters.DeclineJoinRequestParams; - [WRITE_COMMANDS.SET_POLICY_TAXES_CURRENCY_DEFAULT]: Parameters.SetPolicyCurrencyDefaultParams; - [WRITE_COMMANDS.SET_POLICY_CUSTOM_TAX_NAME]: Parameters.SetPolicyCustomTaxNameParams; - [WRITE_COMMANDS.SET_POLICY_TAG_APPROVER]: Parameters.SetPolicyTagApproverParams; - [WRITE_COMMANDS.SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT]: Parameters.SetPolicyForeignCurrencyDefaultParams; - [WRITE_COMMANDS.CREATE_POLICY_TAX]: Parameters.CreatePolicyTaxParams; - [WRITE_COMMANDS.SET_POLICY_TAXES_ENABLED]: Parameters.SetPolicyTaxesEnabledParams; - [WRITE_COMMANDS.DELETE_POLICY_TAXES]: Parameters.DeletePolicyTaxesParams; - [WRITE_COMMANDS.UPDATE_POLICY_TAX_VALUE]: Parameters.UpdatePolicyTaxValueParams; - [WRITE_COMMANDS.CREATE_POLICY_DISTANCE_RATE]: Parameters.CreatePolicyDistanceRateParams; - [WRITE_COMMANDS.REQUEST_WORKSPACE_OWNER_CHANGE]: Parameters.RequestWorkspaceOwnerChangeParams; - [WRITE_COMMANDS.ADD_BILLING_CARD_AND_REQUEST_WORKSPACE_OWNER_CHANGE]: Parameters.AddBillingCardAndRequestWorkspaceOwnerChangeParams; + [WRITE_COMMANDS.LEAVE_GROUP_CHAT]: Parameters.LeaveGroupChatParams; + [WRITE_COMMANDS.LEAVE_POLICY]: Parameters.LeavePolicyParams; + [WRITE_COMMANDS.LEAVE_ROOM]: Parameters.LeaveRoomParams; + [WRITE_COMMANDS.LOG_OUT]: Parameters.LogOutParams; + [WRITE_COMMANDS.MAKE_DEFAULT_PAYMENT_METHOD]: Parameters.MakeDefaultPaymentMethodParams; + [WRITE_COMMANDS.MARK_AS_CASH]: Parameters.MarkAsCashParams; + [WRITE_COMMANDS.MARK_AS_EXPORTED]: Parameters.MarkAsExportedParams; + [WRITE_COMMANDS.MARK_AS_UNREAD]: Parameters.MarkAsUnreadParams; + [WRITE_COMMANDS.OPEN_APP]: Parameters.OpenAppParams; + [WRITE_COMMANDS.OPEN_REPORT]: Parameters.OpenReportParams; + [WRITE_COMMANDS.OPT_IN_TO_PUSH_NOTIFICATIONS]: Parameters.OptInOutToPushNotificationsParams; + [WRITE_COMMANDS.OPT_OUT_OF_PUSH_NOTIFICATIONS]: Parameters.OptInOutToPushNotificationsParams; + [WRITE_COMMANDS.PAY_INVOICE]: Parameters.PayInvoiceParams; + [WRITE_COMMANDS.PAY_MONEY_REQUEST]: Parameters.PayMoneyRequestParams; + [WRITE_COMMANDS.PAY_MONEY_REQUEST_WITH_WALLET]: Parameters.PayMoneyRequestParams; + [WRITE_COMMANDS.READ_NEWEST_ACTION]: Parameters.ReadNewestActionParams; + [WRITE_COMMANDS.RECONNECT_APP]: Parameters.ReconnectAppParams; + [WRITE_COMMANDS.REFER_TEACHERS_UNITE_VOLUNTEER]: Parameters.ReferTeachersUniteVolunteerParams; + [WRITE_COMMANDS.REMOVE_DELEGATE]: Parameters.RemoveDelegateParams; + [WRITE_COMMANDS.REMOVE_EMOJI_REACTION]: Parameters.RemoveEmojiReactionParams; + [WRITE_COMMANDS.REMOVE_FROM_GROUP_CHAT]: Parameters.RemoveFromGroupChatParams; + [WRITE_COMMANDS.REMOVE_FROM_ROOM]: Parameters.RemoveFromRoomParams; + [WRITE_COMMANDS.REMOVE_POLICY_CATEGORY_RECEIPTS_REQUIRED]: Parameters.RemovePolicyCategoryReceiptsRequiredParams; + [WRITE_COMMANDS.REMOVE_POLICY_CONNECTION]: Parameters.RemovePolicyConnectionParams; + [WRITE_COMMANDS.REMOVE_WORKSPACE_APPROVAL]: Parameters.RemoveWorkspaceApprovalParams; + [WRITE_COMMANDS.REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.RemoveWorkspaceReportFieldListValueParams; + [WRITE_COMMANDS.RENAME_POLICY_TAG]: Parameters.RenamePolicyTagsParams; + [WRITE_COMMANDS.RENAME_POLICY_TAG_LIST]: Parameters.RenamePolicyTaglistParams; [WRITE_COMMANDS.RENAME_POLICY_TAX]: Parameters.RenamePolicyTaxParams; - [WRITE_COMMANDS.UPDATE_POLICY_TAX_CODE]: Parameters.UpdatePolicyTaxCodeParams; - [WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_UNIT]: Parameters.SetPolicyDistanceRatesUnitParams; - [WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_DEFAULT_CATEGORY]: Parameters.SetPolicyDistanceRatesDefaultCategoryParams; - [WRITE_COMMANDS.ENABLE_DISTANCE_REQUEST_TAX]: Parameters.SetPolicyDistanceRatesDefaultCategoryParams; + [WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY]: Parameters.RenameWorkspaceCategoriesParams; + [WRITE_COMMANDS.REOPEN_TASK]: Parameters.ReopenTaskParams; + [WRITE_COMMANDS.REPLACE_RECEIPT]: Parameters.ReplaceReceiptParams; [WRITE_COMMANDS.REPORT_EXPORT]: Parameters.ReportExportParams; - [WRITE_COMMANDS.MARK_AS_EXPORTED]: Parameters.MarkAsExportedParams; + [WRITE_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD]: Parameters.ReportVirtualExpensifyCardFraudParams; + [WRITE_COMMANDS.REQUEST_ACCOUNT_VALIDATION_LINK]: Parameters.RequestAccountValidationLinkParams; + [WRITE_COMMANDS.REQUEST_CONTACT_METHOD_VALIDATE_CODE]: Parameters.RequestContactMethodValidateCodeParams; [WRITE_COMMANDS.REQUEST_EXPENSIFY_CARD_LIMIT_INCREASE]: Parameters.RequestExpensifyCardLimitIncreaseParams; - [WRITE_COMMANDS.CLEAR_OUTSTANDING_BALANCE]: null; - [WRITE_COMMANDS.CANCEL_BILLING_SUBSCRIPTION]: Parameters.CancelBillingSubscriptionParams; - [WRITE_COMMANDS.SET_POLICY_RULES_ENABLED]: Parameters.SetPolicyRulesEnabledParams; - [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AMOUNT_NO_RECEIPT]: Parameters.SetPolicyExpenseMaxAmountNoReceipt; - [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AMOUNT]: Parameters.SetPolicyExpenseMaxAmount; - [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AGE]: Parameters.SetPolicyExpenseMaxAge; + [WRITE_COMMANDS.REQUEST_FEED_SETUP]: Parameters.RequestFeedSetupParams; + [WRITE_COMMANDS.REQUEST_MONEY]: Parameters.RequestMoneyParams; + [WRITE_COMMANDS.REQUEST_NEW_VALIDATE_CODE]: Parameters.RequestNewValidateCodeParams; + [WRITE_COMMANDS.REQUEST_PHYSICAL_EXPENSIFY_CARD]: Parameters.RequestPhysicalExpensifyCardParams; + [WRITE_COMMANDS.REQUEST_REFUND]: null; + [WRITE_COMMANDS.REQUEST_REPLACEMENT_EXPENSIFY_CARD]: Parameters.RequestReplacementExpensifyCardParams; + [WRITE_COMMANDS.REQUEST_TAX_EXEMPTION]: null; + [WRITE_COMMANDS.REQUEST_UNLINK_VALIDATION_LINK]: Parameters.RequestUnlinkValidationLinkParams; + [WRITE_COMMANDS.REQUEST_WORKSPACE_OWNER_CHANGE]: Parameters.RequestWorkspaceOwnerChangeParams; + [WRITE_COMMANDS.RESEND_VALIDATE_CODE]: null; + [WRITE_COMMANDS.RESOLVE_ACTIONABLE_MENTION_WHISPER]: Parameters.ResolveActionableMentionWhisperParams; + [WRITE_COMMANDS.RESOLVE_ACTIONABLE_REPORT_MENTION_WHISPER]: Parameters.ResolveActionableReportMentionWhisperParams; + [WRITE_COMMANDS.RESOLVE_DUPLICATES]: Parameters.ResolveDuplicatesParams; + [WRITE_COMMANDS.RESTART_BANK_ACCOUNT_SETUP]: Parameters.RestartBankAccountSetupParams; + [WRITE_COMMANDS.SAVE_SEARCH]: Parameters.SaveSearchParams; + [WRITE_COMMANDS.SEARCH]: Parameters.SearchParams; + [WRITE_COMMANDS.SEND_INVOICE]: Parameters.SendInvoiceParams; + [WRITE_COMMANDS.SEND_MONEY_ELSEWHERE]: Parameters.SendMoneyParams; + [WRITE_COMMANDS.SEND_MONEY_WITH_WALLET]: Parameters.SendMoneyParams; + [WRITE_COMMANDS.SET_CARD_EXPORT_ACCOUNT]: Parameters.SetCompanyCardExportAccountParams; + [WRITE_COMMANDS.SET_COMPANY_CARD_FEED_NAME]: Parameters.SetCompanyCardFeedName; + [WRITE_COMMANDS.SET_COMPANY_CARD_TRANSACTION_LIABILITY]: Parameters.SetCompanyCardTransactionLiability; + [WRITE_COMMANDS.SET_CONTACT_METHOD_AS_DEFAULT]: Parameters.SetContactMethodAsDefaultParams; + [WRITE_COMMANDS.SET_INVOICING_TRANSFER_BANK_ACCOUNT]: Parameters.SetInvoicingTransferBankAccountParams; + [WRITE_COMMANDS.SET_MISSING_PERSONAL_DETAILS_AND_SHIP_EXPENSIFY_CARD]: Parameters.SetMissingPersonalDetailsAndShipExpensifyCardParams; + [WRITE_COMMANDS.SET_NAME_VALUE_PAIR]: Parameters.SetNameValuePairParams; + [WRITE_COMMANDS.SET_POLICY_AUTOMATIC_APPROVAL_LIMIT]: Parameters.SetPolicyAutomaticApprovalLimitParams; + [WRITE_COMMANDS.SET_POLICY_AUTOMATIC_APPROVAL_RATE]: Parameters.SetPolicyAutomaticApprovalRateParams; + [WRITE_COMMANDS.SET_POLICY_AUTO_REIMBURSEMENT_LIMIT]: Parameters.SetPolicyAutoReimbursementLimitParams; [WRITE_COMMANDS.SET_POLICY_BILLABLE_MODE]: Parameters.SetPolicyBillableModeParams; - [WRITE_COMMANDS.DISABLE_POLICY_BILLABLE_MODE]: Parameters.DisablePolicyBillableModeParams; - [WRITE_COMMANDS.SET_WORKSPACE_ERECEIPTS_ENABLED]: Parameters.SetWorkspaceEReceiptsEnabled; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_ENABLE_NEW_CATEGORIES]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_AUTO_CREATE_VENDOR]: Parameters.UpdateQuickbooksOnlineAutoCreateVendorParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_TAX]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_LOCATIONS]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_CUSTOMERS]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_CLASSES]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_REIMBURSABLE_EXPENSES_ACCOUNT]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_AUTO_SYNC]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_PEOPLE]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_EXPORT]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_RECEIVABLE_ACCOUNT]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_EXPORT_DATE]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_EXPENSES_ACCOUNT]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_COLLECTION_ACCOUNT_ID]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_EXPORT_DATE]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_MARK_CHECKS_TO_BE_PRINTED]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_AUTO_CREATE_VENDOR]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPENSES_ACCOUNT]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateQuickbooksDesktopCompanyCardExpenseAccountTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_AUTO_SYNC]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_REIMBURSABLE_EXPENSES_ACCOUNT]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateQuickbooksDesktopExpensesExportDestinationTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_ENABLE_NEW_CATEGORIES]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_SYNC_CLASSES]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_SYNC_CUSTOMERS]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_SYNC_ITEMS]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_EXPORT]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; - [WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG]: Parameters.UpdatePolicyConnectionConfigParams; - [WRITE_COMMANDS.UPDATE_MANY_POLICY_CONNECTION_CONFIGS]: Parameters.UpdateManyPolicyConnectionConfigurationsParams; - [WRITE_COMMANDS.REMOVE_POLICY_CONNECTION]: Parameters.RemovePolicyConnectionParams; - [WRITE_COMMANDS.UPDATE_POLICY_DISTANCE_RATE_VALUE]: Parameters.UpdatePolicyDistanceRateValueParams; - [WRITE_COMMANDS.UPDATE_POLICY_DISTANCE_TAX_RATE_VALUE]: Parameters.UpdatePolicyDistanceRateValueParams; - [WRITE_COMMANDS.UPDATE_DISTANCE_TAX_CLAIMABLE_VALUE]: Parameters.UpdatePolicyDistanceRateValueParams; + [WRITE_COMMANDS.SET_POLICY_CATEGORY_APPROVER]: Parameters.SetPolicyCategoryApproverParams; + [WRITE_COMMANDS.SET_POLICY_CATEGORY_DESCRIPTION_REQUIRED]: Parameters.SetPolicyCategoryDescriptionRequiredParams; + [WRITE_COMMANDS.SET_POLICY_CATEGORY_MAX_AMOUNT]: Parameters.SetPolicyCategoryMaxAmountParams; + [WRITE_COMMANDS.SET_POLICY_CATEGORY_RECEIPTS_REQUIRED]: Parameters.SetPolicyCategoryReceiptsRequiredParams; + [WRITE_COMMANDS.SET_POLICY_CATEGORY_TAX]: Parameters.SetPolicyCategoryTaxParams; + [WRITE_COMMANDS.SET_POLICY_CUSTOM_TAX_NAME]: Parameters.SetPolicyCustomTaxNameParams; + [WRITE_COMMANDS.SET_POLICY_DEFAULT_REPORT_TITLE]: Parameters.SetPolicyDefaultReportTitleParams; + [WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_DEFAULT_CATEGORY]: Parameters.SetPolicyDistanceRatesDefaultCategoryParams; [WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_ENABLED]: Parameters.SetPolicyDistanceRatesEnabledParams; - [WRITE_COMMANDS.DELETE_POLICY_DISTANCE_RATES]: Parameters.DeletePolicyDistanceRatesParams; - [WRITE_COMMANDS.DISMISS_TRACK_EXPENSE_ACTIONABLE_WHISPER]: Parameters.DismissTrackExpenseActionableWhisperParams; - [WRITE_COMMANDS.UPDATE_BILLING_CARD_CURRENCY]: Parameters.UpdateBillingCurrencyParams; - [WRITE_COMMANDS.CONVERT_TRACKED_EXPENSE_TO_REQUEST]: Parameters.ConvertTrackedExpenseToRequestParams; - [WRITE_COMMANDS.CATEGORIZE_TRACKED_EXPENSE]: Parameters.CategorizeTrackedExpenseParams; + [WRITE_COMMANDS.SET_POLICY_DISTANCE_RATES_UNIT]: Parameters.SetPolicyDistanceRatesUnitParams; + [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AGE]: Parameters.SetPolicyExpenseMaxAge; + [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AMOUNT]: Parameters.SetPolicyExpenseMaxAmount; + [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AMOUNT_NO_RECEIPT]: Parameters.SetPolicyExpenseMaxAmountNoReceipt; + [WRITE_COMMANDS.SET_POLICY_PREVENT_MEMBER_CREATED_TITLE]: Parameters.SetPolicyPreventMemberCreatedTitleParams; + [WRITE_COMMANDS.SET_POLICY_PREVENT_SELF_APPROVAL]: Parameters.SetPolicyPreventSelfApprovalParams; + [WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag; + [WRITE_COMMANDS.SET_POLICY_RULES_ENABLED]: Parameters.SetPolicyRulesEnabledParams; + [WRITE_COMMANDS.SET_POLICY_RULES_ENABLED]: Parameters.SetPolicyRulesEnabledParams; + [WRITE_COMMANDS.SET_POLICY_TAGS_ENABLED]: Parameters.SetPolicyTagsEnabled; + [WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED]: Parameters.SetPolicyTagsRequired; + [WRITE_COMMANDS.SET_POLICY_TAG_APPROVER]: Parameters.SetPolicyTagApproverParams; + [WRITE_COMMANDS.SET_POLICY_TAXES_CURRENCY_DEFAULT]: Parameters.SetPolicyCurrencyDefaultParams; + [WRITE_COMMANDS.SET_POLICY_TAXES_ENABLED]: Parameters.SetPolicyTaxesEnabledParams; + [WRITE_COMMANDS.SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT]: Parameters.SetPolicyForeignCurrencyDefaultParams; + [WRITE_COMMANDS.SET_REPORT_FIELD]: Parameters.SetReportFieldParams; + [WRITE_COMMANDS.SET_REPORT_NAME]: Parameters.SetReportNameParams; + [WRITE_COMMANDS.SET_WORKSPACE_APPROVAL_MODE]: Parameters.SetWorkspaceApprovalModeParams; + [WRITE_COMMANDS.SET_WORKSPACE_AUTO_REPORTING_FREQUENCY]: Parameters.SetWorkspaceAutoReportingFrequencyParams; + [WRITE_COMMANDS.SET_WORKSPACE_AUTO_REPORTING_MONTHLY_OFFSET]: Parameters.SetWorkspaceAutoReportingMonthlyOffsetParams; + [WRITE_COMMANDS.SET_WORKSPACE_CATEGORIES_ENABLED]: Parameters.SetWorkspaceCategoriesEnabledParams; + [WRITE_COMMANDS.SET_WORKSPACE_CATEGORY_DESCRIPTION_HINT]: Parameters.SetWorkspaceCategoryDescriptionHintParams; + [WRITE_COMMANDS.SET_WORKSPACE_DEFAULT_SPEND_CATEGORY]: Parameters.SetWorkspaceDefaultSpendCategoryParams; + [WRITE_COMMANDS.SET_WORKSPACE_ERECEIPTS_ENABLED]: Parameters.SetWorkspaceEReceiptsEnabled; + [WRITE_COMMANDS.SET_WORKSPACE_PAYER]: Parameters.SetWorkspacePayerParams; + [WRITE_COMMANDS.SET_WORKSPACE_REIMBURSEMENT]: Parameters.SetWorkspaceReimbursementParams; + [WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams; [WRITE_COMMANDS.SHARE_TRACKED_EXPENSE]: Parameters.ShareTrackedExpenseParams; - [WRITE_COMMANDS.LEAVE_POLICY]: Parameters.LeavePolicyParams; - [WRITE_COMMANDS.DISMISS_VIOLATION]: Parameters.DismissViolationParams; - [WRITE_COMMANDS.ACCEPT_SPOTNANA_TERMS]: null; - [WRITE_COMMANDS.SEND_INVOICE]: Parameters.SendInvoiceParams; - [WRITE_COMMANDS.PAY_INVOICE]: Parameters.PayInvoiceParams; - [WRITE_COMMANDS.MARK_AS_CASH]: Parameters.MarkAsCashParams; - [WRITE_COMMANDS.TRANSACTION_MERGE]: Parameters.TransactionMergeParams; - [WRITE_COMMANDS.RESOLVE_DUPLICATES]: Parameters.ResolveDuplicatesParams; - [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_TYPE]: Parameters.UpdateSubscriptionTypeParams; + [WRITE_COMMANDS.SIGN_IN_USER]: SignInUserParams; + [WRITE_COMMANDS.SIGN_IN_USER_WITH_LINK]: Parameters.SignInUserWithLinkParams; + [WRITE_COMMANDS.SIGN_IN_WITH_APPLE]: Parameters.BeginAppleSignInParams; + [WRITE_COMMANDS.SIGN_IN_WITH_GOOGLE]: Parameters.BeginGoogleSignInParams; [WRITE_COMMANDS.SIGN_UP_USER]: Parameters.SignUpUserParams; - [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_AUTO_RENEW]: Parameters.UpdateSubscriptionAutoRenewParams; - [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY]: Parameters.UpdateSubscriptionAddNewUsersAutomaticallyParams; - [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_SIZE]: Parameters.UpdateSubscriptionSizeParams; - [WRITE_COMMANDS.REQUEST_TAX_EXEMPTION]: null; - - [WRITE_COMMANDS.DELETE_MONEY_REQUEST_ON_SEARCH]: Parameters.DeleteMoneyRequestOnSearchParams; - [WRITE_COMMANDS.HOLD_MONEY_REQUEST_ON_SEARCH]: Parameters.HoldMoneyRequestOnSearchParams; + [WRITE_COMMANDS.SPLIT_BILL]: Parameters.SplitBillParams; + [WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT]: Parameters.SplitBillParams; + [WRITE_COMMANDS.START_SPLIT_BILL]: Parameters.StartSplitBillParams; + [WRITE_COMMANDS.SUBMIT_REPORT]: Parameters.SubmitReportParams; + [WRITE_COMMANDS.SWITCH_TO_OLD_DOT]: Parameters.SwitchToOldDotParams; + [WRITE_COMMANDS.TOGGLE_CARD_CONTINUOUS_RECONCILIATION]: Parameters.ToggleCardContinuousReconciliationParams; + [WRITE_COMMANDS.TOGGLE_PINNED_CHAT]: Parameters.TogglePinnedChatParams; + [WRITE_COMMANDS.TRACK_EXPENSE]: Parameters.TrackExpenseParams; + [WRITE_COMMANDS.TRANSACTION_MERGE]: Parameters.TransactionMergeParams; + [WRITE_COMMANDS.TRANSFER_WALLET_BALANCE]: Parameters.TransferWalletBalanceParams; + [WRITE_COMMANDS.UNAPPROVE_EXPENSE_REPORT]: Parameters.UnapproveExpenseReportParams; + [WRITE_COMMANDS.UNASSIGN_COMPANY_CARD]: Parameters.UnassignCompanyCard; + [WRITE_COMMANDS.UNHOLD_MONEY_REQUEST]: Parameters.UnHoldMoneyRequestParams; [WRITE_COMMANDS.UNHOLD_MONEY_REQUEST_ON_SEARCH]: Parameters.UnholdMoneyRequestOnSearchParams; - - [WRITE_COMMANDS.REQUEST_REFUND]: null; - [WRITE_COMMANDS.CONNECT_POLICY_TO_SAGE_INTACCT]: Parameters.ConnectPolicyToSageIntacctParams; - [WRITE_COMMANDS.COPY_EXISTING_POLICY_CONNECTION]: Parameters.CopyExistingPolicyConnectionParams; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_EXPORTER]: Parameters.UpdateSageIntacctGenericTypeParams<'email', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_EXPORT_DATE]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_REIMBURSABLE_EXPENSES_REPORT_EXPORT_DEFAULT_VENDOR]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_CREDIT_CARD_CHARGE_EXPORT_DEFAULT_VENDOR]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_ACCOUNT]: Parameters.UpdateSageIntacctGenericTypeParams<'creditCardAccountID', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_VENDOR]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_AUTO_SYNC]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_APPROVAL_MODE]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; - - [WRITE_COMMANDS.UPGRADE_TO_CORPORATE]: Parameters.UpgradeToCorporateParams; - - // Netsuite parameters - [WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY]: Parameters.UpdateNetSuiteSubsidiaryParams; - [WRITE_COMMANDS.CONNECT_POLICY_TO_NETSUITE]: Parameters.ConnectPolicyToNetSuiteParams; - - // Workspace report field parameters - [WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD]: Parameters.CreateWorkspaceReportFieldParams; - [WRITE_COMMANDS.UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE]: Parameters.UpdateWorkspaceReportFieldInitialValueParams; - [WRITE_COMMANDS.ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.EnableWorkspaceReportFieldListValueParams; - [WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.CreateWorkspaceReportFieldListValueParams; - [WRITE_COMMANDS.REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.RemoveWorkspaceReportFieldListValueParams; - - [WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_CROSS_SUBSIDIARY_CUSTOMER_CONFIGURATION]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_DEPARTMENTS_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; + [WRITE_COMMANDS.UNLINK_LOGIN]: Parameters.UnlinkLoginParams; + [WRITE_COMMANDS.UPDATE_AUTOMATIC_TIMEZONE]: Parameters.UpdateAutomaticTimezoneParams; + [WRITE_COMMANDS.UPDATE_BENEFICIAL_OWNERS_FOR_BANK_ACCOUNT]: UpdateBeneficialOwnersForBankAccountParams; + [WRITE_COMMANDS.UPDATE_BILLING_CARD_CURRENCY]: Parameters.UpdateBillingCurrencyParams; + [WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_ACCOUNT]: Parameters.UpdateCardSettlementAccountParams; + [WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY]: Parameters.UpdateCardSettlementFrequencyParams; + [WRITE_COMMANDS.UPDATE_CHAT_PRIORITY_MODE]: Parameters.UpdateChatPriorityModeParams; + [WRITE_COMMANDS.UPDATE_COMMENT]: Parameters.UpdateCommentParams; + [WRITE_COMMANDS.UPDATE_COMPANY_CARD]: Parameters.UpdateCompanyCard; + [WRITE_COMMANDS.UPDATE_COMPANY_CARD_NAME]: Parameters.UpdateCompanyCardNameParams; + [WRITE_COMMANDS.UPDATE_COMPANY_INFORMATION_FOR_BANK_ACCOUNT]: Parameters.UpdateCompanyInformationForBankAccountParams; + [WRITE_COMMANDS.UPDATE_DATE_OF_BIRTH]: Parameters.UpdateDateOfBirthParams; + [WRITE_COMMANDS.UPDATE_DELEGATE_ROLE]: Parameters.UpdateDelegateRoleParams; + [WRITE_COMMANDS.UPDATE_DISPLAY_NAME]: Parameters.UpdateDisplayNameParams; + [WRITE_COMMANDS.UPDATE_DISTANCE_REQUEST]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_DISTANCE_TAX_CLAIMABLE_VALUE]: Parameters.UpdatePolicyDistanceRateValueParams; + [WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_LIMIT]: Parameters.UpdateExpensifyCardLimitParams; + [WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_LIMIT_TYPE]: Parameters.UpdateExpensifyCardLimitTypeParams; + [WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_TITLE]: Parameters.UpdateExpensifyCardTitleParams; + [WRITE_COMMANDS.UPDATE_GROUP_CHAT_AVATAR]: Parameters.UpdateGroupChatAvatarParams; + [WRITE_COMMANDS.UPDATE_GROUP_CHAT_MEMBER_ROLES]: Parameters.UpdateGroupChatMemberRolesParams; + [WRITE_COMMANDS.UPDATE_GROUP_CHAT_NAME]: Parameters.UpdateGroupChatNameParams; + [WRITE_COMMANDS.UPDATE_HOME_ADDRESS]: Parameters.UpdateHomeAddressParams; + [WRITE_COMMANDS.UPDATE_LEGAL_NAME]: Parameters.UpdateLegalNameParams; + [WRITE_COMMANDS.UPDATE_MANY_POLICY_CONNECTION_CONFIGS]: Parameters.UpdateManyPolicyConnectionConfigurationsParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_BILLABLE]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_CATEGORY]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DATE]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE_RATE]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_MERCHANT]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAG]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_AMOUNT]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_RATE]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_NETSUITE_ALLOW_FOREIGN_CURRENCY]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_APPROVAL_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'value', string>; + [WRITE_COMMANDS.UPDATE_NETSUITE_AUTO_CREATE_ENTITIES]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_AUTO_SYNC]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; [WRITE_COMMANDS.UPDATE_NETSUITE_CLASSES_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_LOCATIONS_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOMERS_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_JOBS_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_COLLECTION_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; + [WRITE_COMMANDS.UPDATE_NETSUITE_CROSS_SUBSIDIARY_CUSTOMER_CONFIGURATION]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOMERS_JOBS_MAPPING]: Parameters.UpdateNetSuiteCustomersJobsParams; + [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOMERS_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_ENABLED]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_NON_REIMBURSABLE]: Parameters.UpdateNetSuiteCustomFormIDParams; + [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_REIMBURSABLE]: Parameters.UpdateNetSuiteCustomFormIDParams; + [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_LISTS]: Parameters.UpdateNetSuiteGenericTypeParams<'customLists', string>; // JSON string NetSuiteCustomList[] + [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_SEGMENTS]: Parameters.UpdateNetSuiteGenericTypeParams<'customSegments', string>; // JSON string NetSuiteCustomSegment[] + [WRITE_COMMANDS.UPDATE_NETSUITE_DEFAULT_VENDOR]: Parameters.UpdateNetSuiteGenericTypeParams<'vendorID', string>; + [WRITE_COMMANDS.UPDATE_NETSUITE_DEPARTMENTS_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_ENABLE_NEW_CATEGORIES]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; [WRITE_COMMANDS.UPDATE_NETSUITE_EXPORTER]: Parameters.UpdateNetSuiteGenericTypeParams<'email', string>; [WRITE_COMMANDS.UPDATE_NETSUITE_EXPORT_DATE]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_EXPORT_REPORTS_TO]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_EXPORT_TO_NEXT_OPEN_PERIOD]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_INVOICE_ITEM]: Parameters.UpdateNetSuiteGenericTypeParams<'itemID', string>; + [WRITE_COMMANDS.UPDATE_NETSUITE_INVOICE_ITEM_PREFERENCE]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_JOBS_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_JOURNALS_TO]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_JOURNAL_POSTING_PREFERENCE]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_LOCATIONS_MAPPING]: Parameters.UpdateNetSuiteGenericTypeParams<'mapping', ValueOf>; [WRITE_COMMANDS.UPDATE_NETSUITE_NONREIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_DEFAULT_VENDOR]: Parameters.UpdateNetSuiteGenericTypeParams<'vendorID', string>; - [WRITE_COMMANDS.UPDATE_NETSUITE_REIMBURSABLE_PAYABLE_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; [WRITE_COMMANDS.UPDATE_NETSUITE_PAYABLE_ACCT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; - [WRITE_COMMANDS.UPDATE_NETSUITE_JOURNAL_POSTING_PREFERENCE]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_RECEIVABLE_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; - [WRITE_COMMANDS.UPDATE_NETSUITE_INVOICE_ITEM_PREFERENCE]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_INVOICE_ITEM]: Parameters.UpdateNetSuiteGenericTypeParams<'itemID', string>; [WRITE_COMMANDS.UPDATE_NETSUITE_PROVINCIAL_TAX_POSTING_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; - [WRITE_COMMANDS.UPDATE_NETSUITE_TAX_POSTING_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; - [WRITE_COMMANDS.UPDATE_NETSUITE_ALLOW_FOREIGN_CURRENCY]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_EXPORT_TO_NEXT_OPEN_PERIOD]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_SEGMENTS]: Parameters.UpdateNetSuiteGenericTypeParams<'customSegments', string>; // JSON string NetSuiteCustomSegment[] - [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_LISTS]: Parameters.UpdateNetSuiteGenericTypeParams<'customLists', string>; // JSON string NetSuiteCustomList[] - [WRITE_COMMANDS.UPDATE_NETSUITE_AUTO_SYNC]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_PEOPLE]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_AUTO_CREATE_ENTITIES]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_ENABLE_NEW_CATEGORIES]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_ENABLED]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_RECEIVABLE_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; + [WRITE_COMMANDS.UPDATE_NETSUITE_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_REIMBURSABLE_PAYABLE_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; [WRITE_COMMANDS.UPDATE_NETSUITE_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; - [WRITE_COMMANDS.UPDATE_NETSUITE_COLLECTION_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; - [WRITE_COMMANDS.UPDATE_NETSUITE_EXPORT_REPORTS_TO]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY]: Parameters.UpdateNetSuiteSubsidiaryParams; + [WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_PEOPLE]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_TAX_POSTING_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; [WRITE_COMMANDS.UPDATE_NETSUITE_VENDOR_BILLS_TO]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_JOURNALS_TO]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; - [WRITE_COMMANDS.UPDATE_NETSUITE_APPROVAL_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'value', string>; - [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_REIMBURSABLE]: Parameters.UpdateNetSuiteCustomFormIDParams; - [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_NON_REIMBURSABLE]: Parameters.UpdateNetSuiteCustomFormIDParams; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_ENTITY]: Parameters.UpdateSageIntacctGenericTypeParams<'entity', string>; + [WRITE_COMMANDS.UPDATE_NEWSLETTER_SUBSCRIPTION]: Parameters.UpdateNewsletterSubscriptionParams; + [WRITE_COMMANDS.UPDATE_PERSONAL_DETAILS_FOR_WALLET]: Parameters.UpdatePersonalDetailsForWalletParams; + [WRITE_COMMANDS.UPDATE_PERSONAL_INFORMATION_FOR_BANK_ACCOUNT]: Parameters.UpdatePersonalInformationForBankAccountParams; + [WRITE_COMMANDS.UPDATE_POLICY_ADDRESS]: Parameters.UpdatePolicyAddressParams; + [WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_GL_CODE]: Parameters.UpdatePolicyCategoryGLCodeParams; + [WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_PAYROLL_CODE]: Parameters.UpdatePolicyCategoryPayrollCodeParams; + [WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG]: Parameters.UpdatePolicyConnectionConfigParams; + [WRITE_COMMANDS.UPDATE_POLICY_DISTANCE_RATE_VALUE]: Parameters.UpdatePolicyDistanceRateValueParams; + [WRITE_COMMANDS.UPDATE_POLICY_DISTANCE_TAX_RATE_VALUE]: Parameters.UpdatePolicyDistanceRateValueParams; + [WRITE_COMMANDS.UPDATE_POLICY_ROOM_NAME]: Parameters.UpdatePolicyRoomNameParams; + [WRITE_COMMANDS.UPDATE_POLICY_TAG_GL_CODE]: Parameters.UpdatePolicyTagGLCodeParams; + [WRITE_COMMANDS.UPDATE_POLICY_TAX_CODE]: Parameters.UpdatePolicyTaxCodeParams; + [WRITE_COMMANDS.UPDATE_POLICY_TAX_VALUE]: Parameters.UpdatePolicyTaxValueParams; + [WRITE_COMMANDS.UPDATE_PREFERRED_EMOJI_SKIN_TONE]: Parameters.UpdatePreferredEmojiSkinToneParams; + [WRITE_COMMANDS.UPDATE_PREFERRED_LOCALE]: Parameters.UpdatePreferredLocaleParams; + [WRITE_COMMANDS.UPDATE_PRONOUNS]: Parameters.UpdatePronounsParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_AUTO_CREATE_VENDOR]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_AUTO_SYNC]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_ENABLE_NEW_CATEGORIES]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_EXPORT]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_EXPORT_DATE]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_MARK_CHECKS_TO_BE_PRINTED]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPENSES_ACCOUNT]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateQuickbooksDesktopCompanyCardExpenseAccountTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_REIMBURSABLE_EXPENSES_ACCOUNT]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateQuickbooksDesktopExpensesExportDestinationTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_SYNC_CLASSES]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_SYNC_CUSTOMERS]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_SYNC_ITEMS]: Parameters.UpdateQuickbooksDesktopGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_AUTO_CREATE_VENDOR]: Parameters.UpdateQuickbooksOnlineAutoCreateVendorParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_AUTO_SYNC]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_COLLECTION_ACCOUNT_ID]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_ENABLE_NEW_CATEGORIES]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_EXPORT]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_EXPORT_DATE]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_EXPENSES_ACCOUNT]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_RECEIVABLE_ACCOUNT]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_REIMBURSABLE_EXPENSES_ACCOUNT]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_CLASSES]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_CUSTOMERS]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_LOCATIONS]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_PEOPLE]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_QUICKBOOKS_ONLINE_SYNC_TAX]: Parameters.UpdateQuickbooksOnlineGenericTypeParams; + [WRITE_COMMANDS.UPDATE_REPORT_NOTIFICATION_PREFERENCE]: Parameters.UpdateReportNotificationPreferenceParams; + [WRITE_COMMANDS.UPDATE_REPORT_PRIVATE_NOTE]: Parameters.UpdateReportPrivateNoteParams; + [WRITE_COMMANDS.UPDATE_REPORT_WRITE_CAPABILITY]: Parameters.UpdateReportWriteCapabilityParams; + [WRITE_COMMANDS.UPDATE_ROOM_DESCRIPTION]: Parameters.UpdateRoomDescriptionParams; + [WRITE_COMMANDS.UPDATE_ROOM_VISIBILITY]: Parameters.UpdateRoomVisibilityParams; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_APPROVAL_MODE]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_AUTO_SYNC]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_BILLABLE]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_DEPARTMENT_MAPPING]: Parameters.UpdateSageIntacctGenericTypeParams<'mapping', SageIntacctMappingValue>; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_CLASSES_MAPPING]: Parameters.UpdateSageIntacctGenericTypeParams<'mapping', SageIntacctMappingValue>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_CUSTOMERS_MAPPING]: Parameters.UpdateSageIntacctGenericTypeParams<'mapping', SageIntacctMappingValue>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_DEPARTMENT_MAPPING]: Parameters.UpdateSageIntacctGenericTypeParams<'mapping', SageIntacctMappingValue>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_ENTITY]: Parameters.UpdateSageIntacctGenericTypeParams<'entity', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_EXPORTER]: Parameters.UpdateSageIntacctGenericTypeParams<'email', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_EXPORT_DATE]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_LOCATIONS_MAPPING]: Parameters.UpdateSageIntacctGenericTypeParams<'mapping', SageIntacctMappingValue>; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_CUSTOMERS_MAPPING]: Parameters.UpdateSageIntacctGenericTypeParams<'mapping', SageIntacctMappingValue>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_CREDIT_CARD_CHARGE_EXPORT_DEFAULT_VENDOR]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_ACCOUNT]: Parameters.UpdateSageIntacctGenericTypeParams<'creditCardAccountID', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_VENDOR]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_PROJECTS_MAPPING]: Parameters.UpdateSageIntacctGenericTypeParams<'mapping', SageIntacctMappingValue>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_REIMBURSABLE_EXPENSES_REPORT_EXPORT_DEFAULT_VENDOR]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_TAX_CONFIGURATION]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_USER_DIMENSION]: Parameters.UpdateSageIntacctGenericTypeParams<'dimensions', string>; - [WRITE_COMMANDS.EXPORT_SEARCH_ITEMS_TO_CSV]: Parameters.ExportSearchItemsToCSVParams; - [WRITE_COMMANDS.EXPORT_REPORT_TO_CSV]: Parameters.ExportReportCSVParams; - [WRITE_COMMANDS.CREATE_WORKSPACE_APPROVAL]: Parameters.CreateWorkspaceApprovalParams; + [WRITE_COMMANDS.UPDATE_SELECTED_TIMEZONE]: Parameters.UpdateSelectedTimezoneParams; + [WRITE_COMMANDS.UPDATE_STATUS]: Parameters.UpdateStatusParams; + [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY]: Parameters.UpdateSubscriptionAddNewUsersAutomaticallyParams; + [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_AUTO_RENEW]: Parameters.UpdateSubscriptionAutoRenewParams; + [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_SIZE]: Parameters.UpdateSubscriptionSizeParams; + [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_TYPE]: Parameters.UpdateSubscriptionTypeParams; + [WRITE_COMMANDS.UPDATE_THEME]: Parameters.UpdateThemeParams; + [WRITE_COMMANDS.UPDATE_USER_AVATAR]: Parameters.UpdateUserAvatarParams; [WRITE_COMMANDS.UPDATE_WORKSPACE_APPROVAL]: Parameters.UpdateWorkspaceApprovalParams; - [WRITE_COMMANDS.REMOVE_WORKSPACE_APPROVAL]: Parameters.RemoveWorkspaceApprovalParams; - [WRITE_COMMANDS.CONFIGURE_EXPENSIFY_CARDS_FOR_POLICY]: Parameters.ConfigureExpensifyCardsForPolicyParams; - [WRITE_COMMANDS.CREATE_EXPENSIFY_CARD]: Omit; - [WRITE_COMMANDS.CREATE_ADMIN_ISSUED_VIRTUAL_CARD]: Omit; - [WRITE_COMMANDS.ADD_DELEGATE]: Parameters.AddDelegateParams; - [WRITE_COMMANDS.UPDATE_DELEGATE_ROLE]: Parameters.UpdateDelegateRoleParams; - [WRITE_COMMANDS.REMOVE_DELEGATE]: Parameters.RemoveDelegateParams; - [WRITE_COMMANDS.TOGGLE_CARD_CONTINUOUS_RECONCILIATION]: Parameters.ToggleCardContinuousReconciliationParams; - [WRITE_COMMANDS.SAVE_SEARCH]: Parameters.SaveSearchParams; - [WRITE_COMMANDS.DELETE_SAVED_SEARCH]: Parameters.DeleteSavedSearchParams; - [WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY]: Parameters.UpdateCardSettlementFrequencyParams; - [WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_ACCOUNT]: Parameters.UpdateCardSettlementAccountParams; - [WRITE_COMMANDS.SET_MISSING_PERSONAL_DETAILS_AND_SHIP_EXPENSIFY_CARD]: Parameters.SetMissingPersonalDetailsAndShipExpensifyCardParams; - - // Xero API - [WRITE_COMMANDS.UPDATE_XERO_TENANT_ID]: Parameters.UpdateXeroGenericTypeParams; - [WRITE_COMMANDS.UPDATE_XERO_IMPORT_TAX_RATES]: Parameters.UpdateXeroGenericTypeParams; - [WRITE_COMMANDS.UPDATE_XERO_MAPPING]: Parameters.UpdateXeroGenericTypeParams; - [WRITE_COMMANDS.UPDATE_XERO_IMPORT_TRACKING_CATEGORIES]: Parameters.UpdateXeroGenericTypeParams; - [WRITE_COMMANDS.UPDATE_XERO_IMPORT_CUSTOMERS]: Parameters.UpdateXeroGenericTypeParams; - [WRITE_COMMANDS.UPDATE_XERO_ENABLE_NEW_CATEGORIES]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPDATE_WORKSPACE_AVATAR]: Parameters.UpdateWorkspaceAvatarParams; + [WRITE_COMMANDS.UPDATE_WORKSPACE_DESCRIPTION]: Parameters.UpdateWorkspaceDescriptionParams; + [WRITE_COMMANDS.UPDATE_WORKSPACE_DESCRIPTION]: Parameters.UpdateWorkspaceDescriptionParams; + [WRITE_COMMANDS.UPDATE_WORKSPACE_GENERAL_SETTINGS]: Parameters.UpdateWorkspaceGeneralSettingsParams; + [WRITE_COMMANDS.UPDATE_WORKSPACE_MEMBERS_ROLE]: Parameters.UpdateWorkspaceMembersRoleParams; + [WRITE_COMMANDS.UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE]: Parameters.UpdateWorkspaceReportFieldInitialValueParams; [WRITE_COMMANDS.UPDATE_XERO_AUTO_SYNC]: Parameters.UpdateXeroGenericTypeParams; [WRITE_COMMANDS.UPDATE_XERO_AUTO_SYNC]: Parameters.UpdateXeroGenericTypeParams; - [WRITE_COMMANDS.UPDATE_XERO_EXPORT_BILL_STATUS]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPDATE_XERO_ENABLE_NEW_CATEGORIES]: Parameters.UpdateXeroGenericTypeParams; [WRITE_COMMANDS.UPDATE_XERO_EXPORT_BILL_DATE]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPDATE_XERO_EXPORT_BILL_STATUS]: Parameters.UpdateXeroGenericTypeParams; [WRITE_COMMANDS.UPDATE_XERO_EXPORT_EXPORTER]: Parameters.UpdateXeroGenericTypeParams; [WRITE_COMMANDS.UPDATE_XERO_EXPORT_NON_REIMBURSABLE_ACCOUNT]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPDATE_XERO_IMPORT_CUSTOMERS]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPDATE_XERO_IMPORT_TAX_RATES]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPDATE_XERO_IMPORT_TRACKING_CATEGORIES]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPDATE_XERO_MAPPING]: Parameters.UpdateXeroGenericTypeParams; [WRITE_COMMANDS.UPDATE_XERO_SYNC_INVOICE_COLLECTIONS_ACCOUNT_ID]: Parameters.UpdateXeroGenericTypeParams; - [WRITE_COMMANDS.UPDATE_XERO_SYNC_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateXeroGenericTypeParams; [WRITE_COMMANDS.UPDATE_XERO_SYNC_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateXeroGenericTypeParams; - - [WRITE_COMMANDS.SET_INVOICING_TRANSFER_BANK_ACCOUNT]: Parameters.SetInvoicingTransferBankAccountParams; + [WRITE_COMMANDS.UPDATE_XERO_SYNC_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPDATE_XERO_TENANT_ID]: Parameters.UpdateXeroGenericTypeParams; + [WRITE_COMMANDS.UPGRADE_TO_CORPORATE]: Parameters.UpgradeToCorporateParams; + [WRITE_COMMANDS.VALIDATE_BANK_ACCOUNT_WITH_TRANSACTIONS]: Parameters.ValidateBankAccountWithTransactionsParams; + [WRITE_COMMANDS.VALIDATE_LOGIN]: Parameters.ValidateLoginParams; + [WRITE_COMMANDS.VALIDATE_SECONDARY_LOGIN]: Parameters.ValidateSecondaryLoginParams; + [WRITE_COMMANDS.VERIFY_IDENTITY]: Parameters.VerifyIdentityParams; + [WRITE_COMMANDS.VERIFY_IDENTITY_FOR_BANK_ACCOUNT]: Parameters.VerifyIdentityForBankAccountParams; + [WRITE_COMMANDS.VERIFY_SETUP_INTENT]: Parameters.VerifySetupIntentParams; + [WRITE_COMMANDS.VERIFY_SETUP_INTENT_AND_REQUEST_POLICY_OWNER_CHANGE]: Parameters.VerifySetupIntentAndRequestPolicyOwnerChangeParams; }; const READ_COMMANDS = { + BEGIN_SIGNIN: 'BeginSignIn', CONNECT_POLICY_TO_QUICKBOOKS_ONLINE: 'ConnectPolicyToQuickbooksOnline', CONNECT_POLICY_TO_XERO: 'ConnectPolicyToXero', - SYNC_POLICY_TO_QUICKBOOKS_ONLINE: 'SyncPolicyToQuickbooksOnline', - SYNC_POLICY_TO_XERO: 'SyncPolicyToXero', - SYNC_POLICY_TO_NETSUITE: 'SyncPolicyToNetSuite', - SYNC_POLICY_TO_SAGE_INTACCT: 'SyncPolicyToSageIntacct', - SYNC_POLICY_TO_QUICKBOOKS_DESKTOP: 'SyncPolicyToQuickbooksDesktop', - OPEN_REIMBURSEMENT_ACCOUNT_PAGE: 'OpenReimbursementAccountPage', - OPEN_WORKSPACE_VIEW: 'OpenWorkspaceView', + EXPAND_URL_PREVIEW: 'ExpandURLPreview', GET_MAPBOX_ACCESS_TOKEN: 'GetMapboxAccessToken', - OPEN_PAYMENTS_PAGE: 'OpenPaymentsPage', - OPEN_PERSONAL_DETAILS: 'OpenPersonalDetailsPage', - OPEN_PUBLIC_PROFILE_PAGE: 'OpenPublicProfilePage', - OPEN_PLAID_BANK_LOGIN: 'OpenPlaidBankLogin', - OPEN_PLAID_BANK_ACCOUNT_SELECTOR: 'OpenPlaidBankAccountSelector', - GET_OLDER_ACTIONS: 'GetOlderActions', GET_NEWER_ACTIONS: 'GetNewerActions', - EXPAND_URL_PREVIEW: 'ExpandURLPreview', + GET_OLDER_ACTIONS: 'GetOlderActions', + GET_POLICY_CATEGORIES: 'GetPolicyCategories', GET_REPORT_PRIVATE_NOTE: 'GetReportPrivateNote', - OPEN_ROOM_MEMBERS_PAGE: 'OpenRoomMembersPage', - SEARCH_FOR_REPORTS: 'SearchForReports', - SEARCH_FOR_ROOMS_TO_MENTION: 'SearchForRoomsToMention', - SEND_PERFORMANCE_TIMING: 'SendPerformanceTiming', GET_ROUTE: 'GetRoute', GET_ROUTE_FOR_DRAFT: 'GetRouteForDraft', GET_STATEMENT_PDF: 'GetStatementPDF', - OPEN_ONFIDO_FLOW: 'OpenOnfidoFlow', - OPEN_INITIAL_SETTINGS_PAGE: 'OpenInitialSettingsPage', + OPEN_CARD_DETAILS_PAGE: 'OpenCardDetailsPage', + OPEN_DRAFT_DISTANCE_EXPENSE: 'OpenDraftDistanceExpense', + OPEN_DRAFT_WORKSPACE_REQUEST: 'OpenDraftWorkspaceRequest', OPEN_ENABLE_PAYMENTS_PAGE: 'OpenEnablePaymentsPage', - BEGIN_SIGNIN: 'BeginSignIn', - SIGN_IN_WITH_SHORT_LIVED_AUTH_TOKEN: 'SignInWithShortLivedAuthToken', - SIGN_IN_WITH_SUPPORT_AUTH_TOKEN: 'SignInWithSupportAuthToken', - GET_POLICY_CATEGORIES: 'GetPolicyCategories', - OPEN_WORKSPACE: 'OpenWorkspace', - OPEN_WORKSPACE_MEMBERS_PAGE: 'OpenWorkspaceMembersPage', + OPEN_INITIAL_SETTINGS_PAGE: 'OpenInitialSettingsPage', + OPEN_ONFIDO_FLOW: 'OpenOnfidoFlow', + OPEN_PAYMENTS_PAGE: 'OpenPaymentsPage', + OPEN_PERSONAL_DETAILS: 'OpenPersonalDetailsPage', + OPEN_PLAID_BANK_ACCOUNT_SELECTOR: 'OpenPlaidBankAccountSelector', + OPEN_PLAID_BANK_LOGIN: 'OpenPlaidBankLogin', + OPEN_POLICY_ACCOUNTING_PAGE: 'OpenPolicyAccountingPage', OPEN_POLICY_CATEGORIES_PAGE: 'OpenPolicyCategoriesPage', - OPEN_POLICY_TAGS_PAGE: 'OpenPolicyTagsPage', - OPEN_POLICY_TAXES_PAGE: 'OpenPolicyTaxesPage', - OPEN_POLICY_REPORT_FIELDS_PAGE: 'OpenPolicyReportFieldsPage', - OPEN_POLICY_EXPENSIFY_CARDS_PAGE: 'OpenPolicyExpensifyCardsPage', OPEN_POLICY_COMPANY_CARDS_FEED: 'OpenPolicyCompanyCardsFeed', OPEN_POLICY_COMPANY_CARDS_PAGE: 'OpenPolicyCompanyCardsPage', - OPEN_POLICY_EDIT_CARD_LIMIT_TYPE_PAGE: 'OpenPolicyEditCardLimitTypePage', - OPEN_WORKSPACE_INVITE_PAGE: 'OpenWorkspaceInvitePage', - OPEN_DRAFT_WORKSPACE_REQUEST: 'OpenDraftWorkspaceRequest', - OPEN_POLICY_WORKFLOWS_PAGE: 'OpenPolicyWorkflowsPage', OPEN_POLICY_DISTANCE_RATES_PAGE: 'OpenPolicyDistanceRatesPage', + OPEN_POLICY_EDIT_CARD_LIMIT_TYPE_PAGE: 'OpenPolicyEditCardLimitTypePage', + OPEN_POLICY_EXPENSIFY_CARDS_PAGE: 'OpenPolicyExpensifyCardsPage', + OPEN_POLICY_INITIAL_PAGE: 'OpenPolicyInitialPage', OPEN_POLICY_MORE_FEATURES_PAGE: 'OpenPolicyMoreFeaturesPage', - OPEN_POLICY_ACCOUNTING_PAGE: 'OpenPolicyAccountingPage', OPEN_POLICY_PROFILE_PAGE: 'OpenPolicyProfilePage', - OPEN_POLICY_INITIAL_PAGE: 'OpenPolicyInitialPage', + OPEN_POLICY_REPORT_FIELDS_PAGE: 'OpenPolicyReportFieldsPage', + OPEN_POLICY_TAGS_PAGE: 'OpenPolicyTagsPage', + OPEN_POLICY_TAXES_PAGE: 'OpenPolicyTaxesPage', + OPEN_POLICY_WORKFLOWS_PAGE: 'OpenPolicyWorkflowsPage', + OPEN_PUBLIC_PROFILE_PAGE: 'OpenPublicProfilePage', + OPEN_REIMBURSEMENT_ACCOUNT_PAGE: 'OpenReimbursementAccountPage', + OPEN_ROOM_MEMBERS_PAGE: 'OpenRoomMembersPage', OPEN_SUBSCRIPTION_PAGE: 'OpenSubscriptionPage', - OPEN_DRAFT_DISTANCE_EXPENSE: 'OpenDraftDistanceExpense', + OPEN_WORKSPACE: 'OpenWorkspace', + OPEN_WORKSPACE_INVITE_PAGE: 'OpenWorkspaceInvitePage', + OPEN_WORKSPACE_MEMBERS_PAGE: 'OpenWorkspaceMembersPage', + OPEN_WORKSPACE_VIEW: 'OpenWorkspaceView', + SEARCH_FOR_REPORTS: 'SearchForReports', + SEARCH_FOR_ROOMS_TO_MENTION: 'SearchForRoomsToMention', + SEND_PERFORMANCE_TIMING: 'SendPerformanceTiming', + SIGN_IN_WITH_SHORT_LIVED_AUTH_TOKEN: 'SignInWithShortLivedAuthToken', + SIGN_IN_WITH_SUPPORT_AUTH_TOKEN: 'SignInWithSupportAuthToken', START_ISSUE_NEW_CARD_FLOW: 'StartIssueNewCardFlow', - OPEN_CARD_DETAILS_PAGE: 'OpenCardDetailsPage', + SYNC_POLICY_TO_NETSUITE: 'SyncPolicyToNetSuite', + SYNC_POLICY_TO_QUICKBOOKS_DESKTOP: 'SyncPolicyToQuickbooksDesktop', + SYNC_POLICY_TO_QUICKBOOKS_ONLINE: 'SyncPolicyToQuickbooksOnline', + SYNC_POLICY_TO_SAGE_INTACCT: 'SyncPolicyToSageIntacct', + SYNC_POLICY_TO_XERO: 'SyncPolicyToXero', } as const; type ReadCommand = ValueOf; type ReadCommandParameters = { + [READ_COMMANDS.BEGIN_SIGNIN]: Parameters.BeginSignInParams; [READ_COMMANDS.CONNECT_POLICY_TO_QUICKBOOKS_ONLINE]: Parameters.ConnectPolicyToAccountingIntegrationParams; [READ_COMMANDS.CONNECT_POLICY_TO_XERO]: Parameters.ConnectPolicyToAccountingIntegrationParams; - [READ_COMMANDS.SYNC_POLICY_TO_QUICKBOOKS_ONLINE]: Parameters.SyncPolicyToQuickbooksOnlineParams; - [READ_COMMANDS.SYNC_POLICY_TO_XERO]: Parameters.SyncPolicyToXeroParams; - [READ_COMMANDS.SYNC_POLICY_TO_NETSUITE]: Parameters.SyncPolicyToNetSuiteParams; - [READ_COMMANDS.SYNC_POLICY_TO_SAGE_INTACCT]: Parameters.SyncPolicyToNetSuiteParams; - [READ_COMMANDS.SYNC_POLICY_TO_QUICKBOOKS_DESKTOP]: Parameters.SyncPolicyToQuickbooksDesktopParams; - [READ_COMMANDS.OPEN_REIMBURSEMENT_ACCOUNT_PAGE]: Parameters.OpenReimbursementAccountPageParams; - [READ_COMMANDS.OPEN_WORKSPACE_VIEW]: Parameters.OpenWorkspaceViewParams; + [READ_COMMANDS.EXPAND_URL_PREVIEW]: Parameters.ExpandURLPreviewParams; [READ_COMMANDS.GET_MAPBOX_ACCESS_TOKEN]: null; - [READ_COMMANDS.OPEN_PAYMENTS_PAGE]: null; - [READ_COMMANDS.OPEN_PERSONAL_DETAILS]: null; - [READ_COMMANDS.OPEN_PUBLIC_PROFILE_PAGE]: Parameters.OpenPublicProfilePageParams; - [READ_COMMANDS.OPEN_PLAID_BANK_LOGIN]: Parameters.OpenPlaidBankLoginParams; - [READ_COMMANDS.OPEN_PLAID_BANK_ACCOUNT_SELECTOR]: Parameters.OpenPlaidBankAccountSelectorParams; - [READ_COMMANDS.GET_OLDER_ACTIONS]: Parameters.GetOlderActionsParams; [READ_COMMANDS.GET_NEWER_ACTIONS]: Parameters.GetNewerActionsParams; - [READ_COMMANDS.EXPAND_URL_PREVIEW]: Parameters.ExpandURLPreviewParams; + [READ_COMMANDS.GET_OLDER_ACTIONS]: Parameters.GetOlderActionsParams; + [READ_COMMANDS.GET_POLICY_CATEGORIES]: Parameters.GetPolicyCategoriesParams; [READ_COMMANDS.GET_REPORT_PRIVATE_NOTE]: Parameters.GetReportPrivateNoteParams; - [READ_COMMANDS.OPEN_ROOM_MEMBERS_PAGE]: Parameters.OpenRoomMembersPageParams; - [READ_COMMANDS.SEARCH_FOR_REPORTS]: Parameters.SearchForReportsParams; - [READ_COMMANDS.SEARCH_FOR_ROOMS_TO_MENTION]: Parameters.SearchForRoomsToMentionParams; - [READ_COMMANDS.SEND_PERFORMANCE_TIMING]: Parameters.SendPerformanceTimingParams; [READ_COMMANDS.GET_ROUTE]: Parameters.GetRouteParams; [READ_COMMANDS.GET_ROUTE_FOR_DRAFT]: Parameters.GetRouteParams; [READ_COMMANDS.GET_STATEMENT_PDF]: Parameters.GetStatementPDFParams; - [READ_COMMANDS.OPEN_ONFIDO_FLOW]: null; - [READ_COMMANDS.OPEN_INITIAL_SETTINGS_PAGE]: null; - [READ_COMMANDS.OPEN_ENABLE_PAYMENTS_PAGE]: null; - [READ_COMMANDS.BEGIN_SIGNIN]: Parameters.BeginSignInParams; - [READ_COMMANDS.SIGN_IN_WITH_SHORT_LIVED_AUTH_TOKEN]: Parameters.SignInWithShortLivedAuthTokenParams; - [READ_COMMANDS.SIGN_IN_WITH_SUPPORT_AUTH_TOKEN]: Parameters.SignInWithSupportAuthTokenParams; - [READ_COMMANDS.GET_POLICY_CATEGORIES]: Parameters.GetPolicyCategoriesParams; - [READ_COMMANDS.OPEN_WORKSPACE]: Parameters.OpenWorkspaceParams; - [READ_COMMANDS.OPEN_WORKSPACE_MEMBERS_PAGE]: Parameters.OpenWorkspaceMembersPageParams; - [READ_COMMANDS.OPEN_POLICY_CATEGORIES_PAGE]: Parameters.OpenPolicyCategoriesPageParams; - [READ_COMMANDS.OPEN_POLICY_TAGS_PAGE]: Parameters.OpenPolicyTagsPageParams; - [READ_COMMANDS.OPEN_POLICY_TAXES_PAGE]: Parameters.OpenPolicyTaxesPageParams; - [READ_COMMANDS.OPEN_POLICY_REPORT_FIELDS_PAGE]: Parameters.OpenPolicyReportFieldsPageParams; - [READ_COMMANDS.OPEN_WORKSPACE_INVITE_PAGE]: Parameters.OpenWorkspaceInvitePageParams; + [READ_COMMANDS.OPEN_CARD_DETAILS_PAGE]: Parameters.OpenCardDetailsPageParams; + [READ_COMMANDS.OPEN_DRAFT_DISTANCE_EXPENSE]: null; [READ_COMMANDS.OPEN_DRAFT_WORKSPACE_REQUEST]: Parameters.OpenDraftWorkspaceRequestParams; - [READ_COMMANDS.OPEN_POLICY_WORKFLOWS_PAGE]: Parameters.OpenPolicyWorkflowsPageParams; - [READ_COMMANDS.OPEN_POLICY_DISTANCE_RATES_PAGE]: Parameters.OpenPolicyDistanceRatesPageParams; - [READ_COMMANDS.OPEN_POLICY_MORE_FEATURES_PAGE]: Parameters.OpenPolicyMoreFeaturesPageParams; + [READ_COMMANDS.OPEN_ENABLE_PAYMENTS_PAGE]: null; + [READ_COMMANDS.OPEN_INITIAL_SETTINGS_PAGE]: null; + [READ_COMMANDS.OPEN_ONFIDO_FLOW]: null; + [READ_COMMANDS.OPEN_PAYMENTS_PAGE]: null; + [READ_COMMANDS.OPEN_PERSONAL_DETAILS]: null; + [READ_COMMANDS.OPEN_PLAID_BANK_ACCOUNT_SELECTOR]: Parameters.OpenPlaidBankAccountSelectorParams; + [READ_COMMANDS.OPEN_PLAID_BANK_LOGIN]: Parameters.OpenPlaidBankLoginParams; [READ_COMMANDS.OPEN_POLICY_ACCOUNTING_PAGE]: Parameters.OpenPolicyAccountingPageParams; - [READ_COMMANDS.OPEN_POLICY_EXPENSIFY_CARDS_PAGE]: Parameters.OpenPolicyExpensifyCardsPageParams; - [READ_COMMANDS.OPEN_POLICY_COMPANY_CARDS_PAGE]: Parameters.OpenPolicyExpensifyCardsPageParams; + [READ_COMMANDS.OPEN_POLICY_CATEGORIES_PAGE]: Parameters.OpenPolicyCategoriesPageParams; [READ_COMMANDS.OPEN_POLICY_COMPANY_CARDS_FEED]: Parameters.OpenPolicyCompanyCardsFeedParams; + [READ_COMMANDS.OPEN_POLICY_COMPANY_CARDS_PAGE]: Parameters.OpenPolicyExpensifyCardsPageParams; + [READ_COMMANDS.OPEN_POLICY_DISTANCE_RATES_PAGE]: Parameters.OpenPolicyDistanceRatesPageParams; [READ_COMMANDS.OPEN_POLICY_EDIT_CARD_LIMIT_TYPE_PAGE]: Parameters.OpenPolicyEditCardLimitTypePageParams; - [READ_COMMANDS.OPEN_POLICY_PROFILE_PAGE]: Parameters.OpenPolicyProfilePageParams; + [READ_COMMANDS.OPEN_POLICY_EXPENSIFY_CARDS_PAGE]: Parameters.OpenPolicyExpensifyCardsPageParams; [READ_COMMANDS.OPEN_POLICY_INITIAL_PAGE]: Parameters.OpenPolicyInitialPageParams; + [READ_COMMANDS.OPEN_POLICY_MORE_FEATURES_PAGE]: Parameters.OpenPolicyMoreFeaturesPageParams; + [READ_COMMANDS.OPEN_POLICY_PROFILE_PAGE]: Parameters.OpenPolicyProfilePageParams; + [READ_COMMANDS.OPEN_POLICY_REPORT_FIELDS_PAGE]: Parameters.OpenPolicyReportFieldsPageParams; + [READ_COMMANDS.OPEN_POLICY_TAGS_PAGE]: Parameters.OpenPolicyTagsPageParams; + [READ_COMMANDS.OPEN_POLICY_TAXES_PAGE]: Parameters.OpenPolicyTaxesPageParams; + [READ_COMMANDS.OPEN_POLICY_WORKFLOWS_PAGE]: Parameters.OpenPolicyWorkflowsPageParams; + [READ_COMMANDS.OPEN_PUBLIC_PROFILE_PAGE]: Parameters.OpenPublicProfilePageParams; + [READ_COMMANDS.OPEN_REIMBURSEMENT_ACCOUNT_PAGE]: Parameters.OpenReimbursementAccountPageParams; + [READ_COMMANDS.OPEN_ROOM_MEMBERS_PAGE]: Parameters.OpenRoomMembersPageParams; [READ_COMMANDS.OPEN_SUBSCRIPTION_PAGE]: null; - [READ_COMMANDS.OPEN_DRAFT_DISTANCE_EXPENSE]: null; + [READ_COMMANDS.OPEN_WORKSPACE]: Parameters.OpenWorkspaceParams; + [READ_COMMANDS.OPEN_WORKSPACE_INVITE_PAGE]: Parameters.OpenWorkspaceInvitePageParams; + [READ_COMMANDS.OPEN_WORKSPACE_MEMBERS_PAGE]: Parameters.OpenWorkspaceMembersPageParams; + [READ_COMMANDS.OPEN_WORKSPACE_VIEW]: Parameters.OpenWorkspaceViewParams; + [READ_COMMANDS.SEARCH_FOR_REPORTS]: Parameters.SearchForReportsParams; + [READ_COMMANDS.SEARCH_FOR_ROOMS_TO_MENTION]: Parameters.SearchForRoomsToMentionParams; + [READ_COMMANDS.SEND_PERFORMANCE_TIMING]: Parameters.SendPerformanceTimingParams; + [READ_COMMANDS.SIGN_IN_WITH_SHORT_LIVED_AUTH_TOKEN]: Parameters.SignInWithShortLivedAuthTokenParams; + [READ_COMMANDS.SIGN_IN_WITH_SUPPORT_AUTH_TOKEN]: Parameters.SignInWithSupportAuthTokenParams; [READ_COMMANDS.START_ISSUE_NEW_CARD_FLOW]: Parameters.StartIssueNewCardFlowParams; - [READ_COMMANDS.OPEN_CARD_DETAILS_PAGE]: Parameters.OpenCardDetailsPageParams; + [READ_COMMANDS.SYNC_POLICY_TO_NETSUITE]: Parameters.SyncPolicyToNetSuiteParams; + [READ_COMMANDS.SYNC_POLICY_TO_QUICKBOOKS_DESKTOP]: Parameters.SyncPolicyToQuickbooksDesktopParams; + [READ_COMMANDS.SYNC_POLICY_TO_QUICKBOOKS_ONLINE]: Parameters.SyncPolicyToQuickbooksOnlineParams; + [READ_COMMANDS.SYNC_POLICY_TO_SAGE_INTACCT]: Parameters.SyncPolicyToNetSuiteParams; + [READ_COMMANDS.SYNC_POLICY_TO_XERO]: Parameters.SyncPolicyToXeroParams; }; const SIDE_EFFECT_REQUEST_COMMANDS = { ACCEPT_SPOTNANA_TERMS: 'AcceptSpotnanaTerms', + ADD_PAYMENT_CARD_GBP: 'AddPaymentCardGBP', AUTHENTICATE_PUSHER: 'AuthenticatePusher', + COMPLETE_HYBRID_APP_ONBOARDING: 'CompleteHybridAppOnboarding', + CONNECT_AS_DELEGATE: 'ConnectAsDelegate', + CONNECT_POLICY_TO_QUICKBOOKS_DESKTOP: 'ConnectPolicyToQuickbooksDesktop', + DISCONNECT_AS_DELEGATE: 'DisconnectAsDelegate', GENERATE_SPOTNANA_TOKEN: 'GenerateSpotnanaToken', GET_MISSING_ONYX_MESSAGES: 'GetMissingOnyxMessages', JOIN_POLICY_VIA_INVITE_LINK: 'JoinWorkspaceViaInviteLink', OPEN_OLD_DOT_LINK: 'OpenOldDotLink', OPEN_REPORT: 'OpenReport', RECONNECT_APP: 'ReconnectApp', - ADD_PAYMENT_CARD_GBP: 'AddPaymentCardGBP', REVEAL_EXPENSIFY_CARD_DETAILS: 'RevealExpensifyCardDetails', TWO_FACTOR_AUTH_VALIDATE: 'TwoFactorAuth_Validate', - CONNECT_AS_DELEGATE: 'ConnectAsDelegate', - DISCONNECT_AS_DELEGATE: 'DisconnectAsDelegate', - COMPLETE_HYBRID_APP_ONBOARDING: 'CompleteHybridAppOnboarding', - CONNECT_POLICY_TO_QUICKBOOKS_DESKTOP: 'ConnectPolicyToQuickbooksDesktop', } as const; type SideEffectRequestCommand = ValueOf; type SideEffectRequestCommandParameters = { + [SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS]: null; + [SIDE_EFFECT_REQUEST_COMMANDS.ADD_PAYMENT_CARD_GBP]: Parameters.AddPaymentCardParams; [SIDE_EFFECT_REQUEST_COMMANDS.AUTHENTICATE_PUSHER]: Parameters.AuthenticatePusherParams; - [SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT]: Parameters.OpenReportParams; - [SIDE_EFFECT_REQUEST_COMMANDS.OPEN_OLD_DOT_LINK]: Parameters.OpenOldDotLinkParams; - [SIDE_EFFECT_REQUEST_COMMANDS.REVEAL_EXPENSIFY_CARD_DETAILS]: Parameters.RevealExpensifyCardDetailsParams; + [SIDE_EFFECT_REQUEST_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING]: EmptyObject; + [SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE]: Parameters.ConnectAsDelegateParams; + [SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_POLICY_TO_QUICKBOOKS_DESKTOP]: Parameters.ConnectPolicyToQuickBooksDesktopParams; + [SIDE_EFFECT_REQUEST_COMMANDS.DISCONNECT_AS_DELEGATE]: EmptyObject; + [SIDE_EFFECT_REQUEST_COMMANDS.GENERATE_SPOTNANA_TOKEN]: Parameters.GenerateSpotnanaTokenParams; [SIDE_EFFECT_REQUEST_COMMANDS.GET_MISSING_ONYX_MESSAGES]: Parameters.GetMissingOnyxMessagesParams; [SIDE_EFFECT_REQUEST_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams; + [SIDE_EFFECT_REQUEST_COMMANDS.OPEN_OLD_DOT_LINK]: Parameters.OpenOldDotLinkParams; + [SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT]: Parameters.OpenReportParams; [SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP]: Parameters.ReconnectAppParams; - [SIDE_EFFECT_REQUEST_COMMANDS.GENERATE_SPOTNANA_TOKEN]: Parameters.GenerateSpotnanaTokenParams; - [SIDE_EFFECT_REQUEST_COMMANDS.ADD_PAYMENT_CARD_GBP]: Parameters.AddPaymentCardParams; - [SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS]: null; + [SIDE_EFFECT_REQUEST_COMMANDS.REVEAL_EXPENSIFY_CARD_DETAILS]: Parameters.RevealExpensifyCardDetailsParams; [SIDE_EFFECT_REQUEST_COMMANDS.TWO_FACTOR_AUTH_VALIDATE]: Parameters.ValidateTwoFactorAuthParams; - [SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE]: Parameters.ConnectAsDelegateParams; - [SIDE_EFFECT_REQUEST_COMMANDS.DISCONNECT_AS_DELEGATE]: EmptyObject; - [SIDE_EFFECT_REQUEST_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING]: EmptyObject; - [SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_POLICY_TO_QUICKBOOKS_DESKTOP]: Parameters.ConnectPolicyToQuickBooksDesktopParams; }; type ApiRequestCommandParameters = WriteCommandParameters & ReadCommandParameters & SideEffectRequestCommandParameters; From e0af6006af02e7ce545f192dbf956e01664db26a Mon Sep 17 00:00:00 2001 From: Youssef Lourayad Date: Mon, 21 Oct 2024 03:09:57 +0100 Subject: [PATCH 058/808] Move commands to side effect commands list --- src/libs/API/types.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index aec784e076ea..185dd44f0ab0 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -155,7 +155,6 @@ const WRITE_COMMANDS = { REOPEN_TASK: 'ReopenTask', REPLACE_RECEIPT: 'ReplaceReceipt', REPORT_EXPORT: 'Report_Export', - REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD: 'ReportVirtualExpensifyCardFraud', REQUEST_ACCOUNT_VALIDATION_LINK: 'RequestAccountValidationLink', REQUEST_CONTACT_METHOD_VALIDATE_CODE: 'RequestContactMethodValidateCode', REQUEST_EXPENSIFY_CARD_LIMIT_INCREASE: 'RequestExpensifyCardLimitIncrease', @@ -164,7 +163,6 @@ const WRITE_COMMANDS = { REQUEST_NEW_VALIDATE_CODE: 'RequestNewValidateCode', REQUEST_PHYSICAL_EXPENSIFY_CARD: 'RequestPhysicalExpensifyCard', REQUEST_REFUND: 'User_RefundPurchase', - REQUEST_REPLACEMENT_EXPENSIFY_CARD: 'RequestReplacementExpensifyCard', REQUEST_TAX_EXEMPTION: 'RequestTaxExemption', REQUEST_UNLINK_VALIDATION_LINK: 'RequestUnlinkValidationLink', REQUEST_WORKSPACE_OWNER_CHANGE: 'RequestWorkspaceOwnerChange', @@ -580,7 +578,6 @@ type WriteCommandParameters = { [WRITE_COMMANDS.REOPEN_TASK]: Parameters.ReopenTaskParams; [WRITE_COMMANDS.REPLACE_RECEIPT]: Parameters.ReplaceReceiptParams; [WRITE_COMMANDS.REPORT_EXPORT]: Parameters.ReportExportParams; - [WRITE_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD]: Parameters.ReportVirtualExpensifyCardFraudParams; [WRITE_COMMANDS.REQUEST_ACCOUNT_VALIDATION_LINK]: Parameters.RequestAccountValidationLinkParams; [WRITE_COMMANDS.REQUEST_CONTACT_METHOD_VALIDATE_CODE]: Parameters.RequestContactMethodValidateCodeParams; [WRITE_COMMANDS.REQUEST_EXPENSIFY_CARD_LIMIT_INCREASE]: Parameters.RequestExpensifyCardLimitIncreaseParams; @@ -589,7 +586,6 @@ type WriteCommandParameters = { [WRITE_COMMANDS.REQUEST_NEW_VALIDATE_CODE]: Parameters.RequestNewValidateCodeParams; [WRITE_COMMANDS.REQUEST_PHYSICAL_EXPENSIFY_CARD]: Parameters.RequestPhysicalExpensifyCardParams; [WRITE_COMMANDS.REQUEST_REFUND]: null; - [WRITE_COMMANDS.REQUEST_REPLACEMENT_EXPENSIFY_CARD]: Parameters.RequestReplacementExpensifyCardParams; [WRITE_COMMANDS.REQUEST_TAX_EXEMPTION]: null; [WRITE_COMMANDS.REQUEST_UNLINK_VALIDATION_LINK]: Parameters.RequestUnlinkValidationLinkParams; [WRITE_COMMANDS.REQUEST_WORKSPACE_OWNER_CHANGE]: Parameters.RequestWorkspaceOwnerChangeParams; @@ -991,6 +987,8 @@ const SIDE_EFFECT_REQUEST_COMMANDS = { OPEN_OLD_DOT_LINK: 'OpenOldDotLink', OPEN_REPORT: 'OpenReport', RECONNECT_APP: 'ReconnectApp', + REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD: 'ReportVirtualExpensifyCardFraud', + REQUEST_REPLACEMENT_EXPENSIFY_CARD: 'RequestReplacementExpensifyCard', REVEAL_EXPENSIFY_CARD_DETAILS: 'RevealExpensifyCardDetails', TWO_FACTOR_AUTH_VALIDATE: 'TwoFactorAuth_Validate', } as const; @@ -1011,6 +1009,8 @@ type SideEffectRequestCommandParameters = { [SIDE_EFFECT_REQUEST_COMMANDS.OPEN_OLD_DOT_LINK]: Parameters.OpenOldDotLinkParams; [SIDE_EFFECT_REQUEST_COMMANDS.OPEN_REPORT]: Parameters.OpenReportParams; [SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP]: Parameters.ReconnectAppParams; + [SIDE_EFFECT_REQUEST_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD]: Parameters.ReportVirtualExpensifyCardFraudParams; + [SIDE_EFFECT_REQUEST_COMMANDS.REQUEST_REPLACEMENT_EXPENSIFY_CARD]: Parameters.RequestReplacementExpensifyCardParams; [SIDE_EFFECT_REQUEST_COMMANDS.REVEAL_EXPENSIFY_CARD_DETAILS]: Parameters.RevealExpensifyCardDetailsParams; [SIDE_EFFECT_REQUEST_COMMANDS.TWO_FACTOR_AUTH_VALIDATE]: Parameters.ValidateTwoFactorAuthParams; }; From 4e26e41c6701ec2084352861d198e95173a4b3cc Mon Sep 17 00:00:00 2001 From: Youssef Lourayad Date: Mon, 21 Oct 2024 03:24:13 +0100 Subject: [PATCH 059/808] Use a side effect request when report virtual card fraud --- src/libs/actions/Card.ts | 77 +++++++++++-------- .../Wallet/ReportVirtualCardFraudPage.tsx | 27 ++++++- 2 files changed, 71 insertions(+), 33 deletions(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 2a0ab6defa12..04c60703e8fe 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -38,44 +38,59 @@ type IssueNewCardFlowData = { }; function reportVirtualExpensifyCardFraud(cardID: number) { - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: true, + return new Promise((resolve, reject) => { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: true, + }, }, - }, - ]; + ]; - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: false, + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: false, + }, }, - }, - ]; + ]; - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: false, + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: false, + }, }, - }, - ]; + ]; - const parameters: ReportVirtualExpensifyCardFraudParams = { - cardID, - }; + const parameters: ReportVirtualExpensifyCardFraudParams = { + cardID, + }; - API.write(WRITE_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD, parameters, { - optimisticData, - successData, - failureData, + // eslint-disable-next-line rulesdir/no-api-side-effects-method + API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD, parameters, {optimisticData, successData, failureData}) + .then((response) => { + if (response?.jsonCode !== CONST.JSON_CODE.SUCCESS) { + if (response?.jsonCode === CONST.JSON_CODE.INCORRECT_MAGIC_CODE) { + // eslint-disable-next-line prefer-promise-reject-errors + reject('validateCodeForm.error.incorrectMagicCode'); + return; + } + + // eslint-disable-next-line prefer-promise-reject-errors + reject('cardPage.cardDetailsLoadingFailure'); + return; + } + resolve(response as ExpensifyCardDetails); + }) + // eslint-disable-next-line prefer-promise-reject-errors + .catch(() => reject('cardPage.cardDetailsLoadingFailure')); }); } diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx index 373314df08ac..1c80e40f344a 100644 --- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx +++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx @@ -1,11 +1,13 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import React, {useEffect} from 'react'; +import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; +import ValidateCodeModal from '@components/ValidateCode/ValidateCodeModal'; +import ValidateCodeActionModal from '@components/ValidateCodeActionModal'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -30,6 +32,7 @@ function ReportVirtualCardFraudPage({ const {translate} = useLocalize(); const [cardList] = useOnyx(ONYXKEYS.CARD_LIST); const [formData] = useOnyx(ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD); + const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(false); const virtualCard = cardList?.[cardID]; const virtualCardError = ErrorUtils.getLatestErrorMessage(virtualCard); @@ -51,6 +54,18 @@ function ReportVirtualCardFraudPage({ return ; } + const openValidateCodeModal = () => { + setIsValidateCodeActionModalVisible(true); + }; + + const handleValidateCodeEntered = (validateCode: string) => { + Card.reportVirtualExpensifyCardFraud(virtualCard.cardID) + .then((value) => {}) + .catch((error) => { + console.log('error ', error); + }); + }; + return ( {translate('reportFraudPage.description')} Card.reportVirtualExpensifyCardFraud(virtualCard.cardID)} + onSubmit={openValidateCodeModal} message={virtualCardError} isLoading={formData?.isLoading} buttonText={translate('reportFraudPage.deactivateCard')} containerStyles={[styles.m5]} /> + {}} + onClose={() => setIsValidateCodeActionModalVisible(false)} + isVisible={isValidateCodeActionModalVisible} + title={translate('cardPage.validateCardTitle')} + description="" + /> ); } From e631c0afe9df934a9b2692d18fed2091423bc8ac Mon Sep 17 00:00:00 2001 From: Youssef Lourayad Date: Mon, 21 Oct 2024 04:05:22 +0100 Subject: [PATCH 060/808] Navigate back to the card page on error --- .../API/parameters/ReportVirtualExpensifyCardFraudParams.ts | 1 + src/libs/actions/Card.ts | 3 ++- src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libs/API/parameters/ReportVirtualExpensifyCardFraudParams.ts b/src/libs/API/parameters/ReportVirtualExpensifyCardFraudParams.ts index 350795d46355..ebb5abcb5d00 100644 --- a/src/libs/API/parameters/ReportVirtualExpensifyCardFraudParams.ts +++ b/src/libs/API/parameters/ReportVirtualExpensifyCardFraudParams.ts @@ -1,4 +1,5 @@ type ReportVirtualExpensifyCardFraudParams = { cardID: number; + validateCode: string; }; export default ReportVirtualExpensifyCardFraudParams; diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 04c60703e8fe..7541d567c8ca 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -37,7 +37,7 @@ type IssueNewCardFlowData = { data?: Partial; }; -function reportVirtualExpensifyCardFraud(cardID: number) { +function reportVirtualExpensifyCardFraud(cardID: number, validateCode: string) { return new Promise((resolve, reject) => { const optimisticData: OnyxUpdate[] = [ { @@ -71,6 +71,7 @@ function reportVirtualExpensifyCardFraud(cardID: number) { const parameters: ReportVirtualExpensifyCardFraudParams = { cardID, + validateCode, }; // eslint-disable-next-line rulesdir/no-api-side-effects-method diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx index 1c80e40f344a..7d2966ea995d 100644 --- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx +++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx @@ -59,10 +59,13 @@ function ReportVirtualCardFraudPage({ }; const handleValidateCodeEntered = (validateCode: string) => { - Card.reportVirtualExpensifyCardFraud(virtualCard.cardID) + Card.reportVirtualExpensifyCardFraud(virtualCard.cardID, validateCode) .then((value) => {}) .catch((error) => { console.log('error ', error); + }) + .finally(() => { + setIsValidateCodeActionModalVisible(false); }); }; From 172e11f096223d83bc10eb3e3ca77c09544294f0 Mon Sep 17 00:00:00 2001 From: Youssef Lourayad Date: Mon, 21 Oct 2024 04:07:23 +0100 Subject: [PATCH 061/808] Set description of ValidateCodeActionModal --- src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx index 7d2966ea995d..d6667a46b460 100644 --- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx +++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx @@ -6,7 +6,6 @@ import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; -import ValidateCodeModal from '@components/ValidateCode/ValidateCodeModal'; import ValidateCodeActionModal from '@components/ValidateCodeActionModal'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; @@ -30,6 +29,7 @@ function ReportVirtualCardFraudPage({ }: ReportVirtualCardFraudPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + const [account] = useOnyx(ONYXKEYS.ACCOUNT); const [cardList] = useOnyx(ONYXKEYS.CARD_LIST); const [formData] = useOnyx(ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD); const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(false); @@ -92,7 +92,7 @@ function ReportVirtualCardFraudPage({ onClose={() => setIsValidateCodeActionModalVisible(false)} isVisible={isValidateCodeActionModalVisible} title={translate('cardPage.validateCardTitle')} - description="" + description={translate('cardPage.enterMagicCode', {contactMethod: account?.primaryLogin ?? ''})} /> ); From 85a9dd7f699c35c6c152cacc0f9fb70bb38fe57b Mon Sep 17 00:00:00 2001 From: Youssef Lourayad Date: Mon, 21 Oct 2024 04:08:17 +0100 Subject: [PATCH 062/808] Cleanup code --- .../settings/Wallet/ReportVirtualCardFraudPage.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx index d6667a46b460..be6ca088c79e 100644 --- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx +++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx @@ -59,14 +59,9 @@ function ReportVirtualCardFraudPage({ }; const handleValidateCodeEntered = (validateCode: string) => { - Card.reportVirtualExpensifyCardFraud(virtualCard.cardID, validateCode) - .then((value) => {}) - .catch((error) => { - console.log('error ', error); - }) - .finally(() => { - setIsValidateCodeActionModalVisible(false); - }); + Card.reportVirtualExpensifyCardFraud(virtualCard.cardID, validateCode).finally(() => { + setIsValidateCodeActionModalVisible(false); + }); }; return ( From 7e9bf7c70414d2fdefba7a8f51d584c99fad69ce Mon Sep 17 00:00:00 2001 From: c3024 Date: Mon, 21 Oct 2024 11:35:46 +0530 Subject: [PATCH 063/808] add self guided tours to tasks --- src/CONST.ts | 17 ++++++++++++++++- src/libs/actions/Report.ts | 18 +++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 01466d8baf86..4bb90fca7aab 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -83,6 +83,13 @@ const signupQualifiers = { SMB: 'smb', } as const; +const selfGuidedTourTask: OnboardingTaskType = { + type: 'viewTour', + autoCompleted: false, + title: 'Take a 2-minute tour', + description: ({navatticURL}) => `[Take a self-guided product tour](${navatticURL}) and learn about everything Expensify has to offer.`, +}; + const onboardingEmployerOrSubmitMessage: OnboardingMessageType = { message: 'Getting paid back is as easy as sending a message. Let’s go over the basics.', video: { @@ -93,6 +100,7 @@ const onboardingEmployerOrSubmitMessage: OnboardingMessageType = { height: 960, }, tasks: [ + selfGuidedTourTask, { type: 'submitExpense', autoCompleted: false, @@ -149,11 +157,15 @@ const onboardingCompanySize = { type OnboardingInviteType = ValueOf; +type Description = + | string + | ((params: Partial<{adminsRoomLink: string; workspaceCategoriesLink: string; workspaceMoreFeaturesLink: string; workspaceMembersLink: string; navatticURL: string}>) => string); + type OnboardingTaskType = { type: string; autoCompleted: boolean; title: string; - description: string | ((params: Partial<{adminsRoomLink: string; workspaceCategoriesLink: string; workspaceMoreFeaturesLink: string; workspaceMembersLink: string}>) => string); + description: Description; }; type OnboardingMessageType = { @@ -4652,6 +4664,7 @@ const CONST = { '\n' + '*Your new workspace is ready! It’ll keep all of your spend (and chats) in one place.*', }, + selfGuidedTourTask, { type: 'meetGuide', autoCompleted: false, @@ -4748,6 +4761,7 @@ const CONST = { height: 960, }, tasks: [ + selfGuidedTourTask, { type: 'trackExpense', autoCompleted: false, @@ -4776,6 +4790,7 @@ const CONST = { height: 960, }, tasks: [ + selfGuidedTourTask, { type: 'startChat', autoCompleted: false, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 7071c96f8612..bd237908a96e 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -58,6 +58,8 @@ import DateUtils from '@libs/DateUtils'; import {prepareDraftComment} from '@libs/DraftCommentUtils'; import * as EmojiUtils from '@libs/EmojiUtils'; import * as Environment from '@libs/Environment/Environment'; +import getEnvironment from '@libs/Environment/getEnvironment'; +import type EnvironmentType from '@libs/Environment/getEnvironment/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import fileDownload from '@libs/fileDownload'; import HttpUtils from '@libs/HttpUtils'; @@ -83,6 +85,7 @@ import type {OptimisticAddCommentReportAction} from '@libs/ReportUtils'; import * as ReportUtils from '@libs/ReportUtils'; import {doesReportBelongToWorkspace} from '@libs/ReportUtils'; import shouldSkipDeepLinkNavigation from '@libs/shouldSkipDeepLinkNavigation'; +import {getNavatticURL} from '@libs/TourUtils'; import Visibility from '@libs/Visibility'; import CONFIG from '@src/CONFIG'; import type {OnboardingAccountingType, OnboardingCompanySizeType, OnboardingPurposeType} from '@src/CONST'; @@ -102,6 +105,7 @@ import type { ReportActionReactions, ReportUserIsTyping, } from '@src/types/onyx'; +import type IntroSelected from '@src/types/onyx/IntroSelected'; import type {Decision} from '@src/types/onyx/OriginalMessage'; import type {ConnectionName} from '@src/types/onyx/Policy'; import type Report from '@src/types/onyx/Report'; @@ -269,9 +273,21 @@ Onyx.connect({ callback: (value) => (allReportDraftComments = value), }); +let introSelected: IntroSelected | undefined = {}; + +Onyx.connect({ + key: ONYXKEYS.NVP_INTRO_SELECTED, + callback: (val) => (introSelected = val), +}); + let environmentURL: string; Environment.getEnvironmentURL().then((url: string) => (environmentURL = url)); +let environment: EnvironmentType; +getEnvironment().then((env) => { + environment = env; +}); + registerPaginationConfig({ initialCommand: WRITE_COMMANDS.OPEN_REPORT, previousCommand: READ_COMMANDS.GET_OLDER_ACTIONS, @@ -3359,7 +3375,6 @@ function completeOnboarding( reportComment: videoComment.commentText, }; } - const tasksData = data.tasks.map((task, index) => { const taskDescription = typeof task.description === 'function' @@ -3368,6 +3383,7 @@ function completeOnboarding( workspaceCategoriesLink: `${environmentURL}/${ROUTES.WORKSPACE_CATEGORIES.getRoute(onboardingPolicyID ?? '-1')}`, workspaceMembersLink: `${environmentURL}/${ROUTES.WORKSPACE_MEMBERS.getRoute(onboardingPolicyID ?? '-1')}`, workspaceMoreFeaturesLink: `${environmentURL}/${ROUTES.WORKSPACE_MORE_FEATURES.getRoute(onboardingPolicyID ?? '-1')}`, + navatticURL: getNavatticURL(environment, introSelected?.choice), }) : task.description; const currentTask = ReportUtils.buildOptimisticTaskReport( From bc45762119519cf1f1afa2a9c57402f1a0816ee1 Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Mon, 7 Oct 2024 12:47:22 +0530 Subject: [PATCH 064/808] Use small icon in tabs --- src/components/TabSelector/TabIcon.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/TabSelector/TabIcon.tsx b/src/components/TabSelector/TabIcon.tsx index 31833b2fc852..bd4e1b1e2fc3 100644 --- a/src/components/TabSelector/TabIcon.tsx +++ b/src/components/TabSelector/TabIcon.tsx @@ -25,12 +25,14 @@ function TabIcon({icon, activeOpacity = 0, inactiveOpacity = 1}: TabIconProps) { From 10c5dfb2c171d8c26a4ac55c008ff51ae47c95ed Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Fri, 18 Oct 2024 17:09:58 +0530 Subject: [PATCH 065/808] Update --- src/styles/index.ts | 4 ++-- src/styles/variables.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index 3ea14bb14515..2b7e488325d9 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -4310,8 +4310,8 @@ const styles = (theme: ThemeColors) => marginLeft: 8, ...FontUtils.fontFamily.platform.EXP_NEUE_BOLD, color: isSelected ? theme.text : theme.textSupporting, - lineHeight: variables.lineHeightNormal, - fontSize: variables.fontSizeNormal, + lineHeight: variables.lineHeightLarge, + fontSize: variables.fontSizeLabel, } satisfies TextStyle), tabBackground: (hovered: boolean, isFocused: boolean, background: string | Animated.AnimatedInterpolation) => ({ diff --git a/src/styles/variables.ts b/src/styles/variables.ts index dc6655791489..eb52fe2a0534 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -159,7 +159,7 @@ export default { signInLogoWidthLargeScreen: 144, signInLogoHeightLargeScreen: 108, signInLogoWidthPill: 132, - tabSelectorButtonHeight: 42, + tabSelectorButtonHeight: 40, tabSelectorButtonPadding: 12, lhnLogoWidth: 95.09, lhnLogoHeight: 22.33, From 20d46864a9b1c586c36d641f2c5dc4d93f9de425 Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Mon, 21 Oct 2024 20:24:57 +0530 Subject: [PATCH 066/808] Use 8 as icon margin for buttons --- src/components/Button/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 04607ef1cc7f..0a8aa1c69dad 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -290,7 +290,7 @@ function Button( {icon && ( - + Date: Tue, 22 Oct 2024 01:23:28 +0700 Subject: [PATCH 067/808] update getSubmitToAccountID with category and tag approver --- src/libs/Permissions.ts | 1 + src/libs/PolicyUtils.ts | 32 ++++++++++++++++++++++++++++---- src/libs/ReportUtils.ts | 11 ++++++----- src/libs/actions/IOU.ts | 9 ++++----- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 24de2e612208..47fa860af63c 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -4,6 +4,7 @@ import type {IOUType} from '@src/CONST'; import type Beta from '@src/types/onyx/Beta'; function canUseAllBetas(betas: OnyxEntry): boolean { + return true; return !!betas?.includes(CONST.BETAS.ALL); } diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 3e0ae7cba291..5f703bc27879 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -8,7 +8,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import INPUT_IDS from '@src/types/form/NetSuiteCustomFieldForm'; -import type {OnyxInputOrEntry, Policy, PolicyCategories, PolicyEmployeeList, PolicyTagLists, PolicyTags, TaxRate} from '@src/types/onyx'; +import type {OnyxInputOrEntry, Policy, PolicyCategories, PolicyEmployeeList, PolicyTagLists, PolicyTags, Report, TaxRate} from '@src/types/onyx'; import type {CardFeedData} from '@src/types/onyx/CardFeeds'; import type {ErrorFields, PendingAction, PendingFields} from '@src/types/onyx/OnyxCommon'; import type { @@ -31,10 +31,13 @@ import type { import type PolicyEmployee from '@src/types/onyx/PolicyEmployee'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import {hasSynchronizationErrorMessage} from './actions/connections'; +import {getCategoryApproverRule} from './CategoryUtils'; import * as Localize from './Localize'; import Navigation from './Navigation/Navigation'; import * as NetworkStore from './Network/NetworkStore'; import {getAccountIDsByLogins, getLoginsByAccountIDs, getPersonalDetailByEmail} from './PersonalDetailsUtils'; +import {getTransactionDetails} from './ReportUtils'; +import {getAllReportTransactions} from './TransactionUtils'; type MemberEmailsToAccountIDs = Record; @@ -514,10 +517,31 @@ function getDefaultApprover(policy: OnyxEntry): string { /** * Returns the accountID to whom the given employeeAccountID submits reports to in the given Policy. */ -function getSubmitToAccountID(policy: OnyxEntry, employeeAccountID: number): number { +function getSubmitToAccountID(policy: OnyxEntry, expenseReport: OnyxEntry): number { + const employeeAccountID = expenseReport?.ownerAccountID ?? -1; const employeeLogin = getLoginsByAccountIDs([employeeAccountID]).at(0) ?? ''; const defaultApprover = getDefaultApprover(policy); + let categoryAppover; + let tagApprover; + const allTransactions = getAllReportTransactions(expenseReport?.reportID).sort((transA, transB) => (transA.created < transB.created ? -1 : 1)); + + for (let i = 0; i < allTransactions.length; i++) { + const {tag = '', category = ''} = getTransactionDetails(allTransactions.at(i)) ?? {}; + categoryAppover = getCategoryApproverRule(policy?.rules?.approvalRules ?? [], category)?.approver; + if (categoryAppover) { + return getAccountIDsByLogins([categoryAppover]).at(0) ?? -1; + } + + if (!tagApprover && getTagApproverRule(policy?.id ?? '-1', tag)?.approver) { + tagApprover = getTagApproverRule(policy?.id ?? '-1', tag)?.approver; + } + } + + if (tagApprover) { + return getAccountIDsByLogins([tagApprover]).at(0) ?? -1; + } + // For policy using the optional or basic workflow, the manager is the policy default approver. if (([CONST.POLICY.APPROVAL_MODE.OPTIONAL, CONST.POLICY.APPROVAL_MODE.BASIC] as Array>).includes(getApprovalWorkflow(policy))) { return getAccountIDsByLogins([defaultApprover]).at(0) ?? -1; @@ -531,8 +555,8 @@ function getSubmitToAccountID(policy: OnyxEntry, employeeAccountID: numb return getAccountIDsByLogins([employee.submitsTo ?? defaultApprover]).at(0) ?? -1; } -function getSubmitToEmail(policy: OnyxEntry, employeeAccountID: number): string { - const submitToAccountID = getSubmitToAccountID(policy, employeeAccountID); +function getSubmitToEmail(policy: OnyxEntry, expenseReport: OnyxEntry): string { + const submitToAccountID = getSubmitToAccountID(policy, expenseReport); return getLoginsByAccountIDs([submitToAccountID]).at(0) ?? ''; } diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 1ef60b626ac7..306ef147cbd9 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -3081,7 +3081,7 @@ function canEditMoneyRequest(reportAction: OnyxInputOrEntry, approverAcco function isAllowedToSubmitDraftExpenseReport(report: OnyxEntry): boolean { const policy = getPolicy(report?.policyID); - const submitToAccountID = PolicyUtils.getSubmitToAccountID(policy, report?.ownerAccountID ?? -1); + const submitToAccountID = PolicyUtils.getSubmitToAccountID(policy, report); return isAllowedToApproveExpenseReport(report, submitToAccountID); } @@ -8256,15 +8256,16 @@ function isExported(reportActions: OnyxEntry) { return Object.values(reportActions).some((action) => ReportActionsUtils.isExportIntegrationAction(action)); } -function getApprovalChain(policy: OnyxEntry, employeeAccountID: number, reportTotal: number): string[] { +function getApprovalChain(policy: OnyxEntry, expenseReport: OnyxEntry): string[] { const approvalChain: string[] = []; + const reportTotal = expenseReport?.total ?? 0; // If the policy is not on advanced approval mode, we should not use the approval chain even if it exists. if (!PolicyUtils.isControlOnAdvancedApprovalMode(policy)) { return approvalChain; } - let nextApproverEmail = PolicyUtils.getSubmitToEmail(policy, employeeAccountID); + let nextApproverEmail = PolicyUtils.getSubmitToEmail(policy, expenseReport); while (nextApproverEmail && !approvalChain.includes(nextApproverEmail)) { approvalChain.push(nextApproverEmail); diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 0d9a4887bd1d..94e29948e266 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -7080,10 +7080,9 @@ function isLastApprover(approvalChain: string[]): boolean { } function getNextApproverAccountID(report: OnyxEntry) { - const ownerAccountID = report?.ownerAccountID ?? -1; const policy = PolicyUtils.getPolicy(report?.policyID); - const approvalChain = ReportUtils.getApprovalChain(policy, ownerAccountID, report?.total ?? 0); - const submitToAccountID = PolicyUtils.getSubmitToAccountID(policy, ownerAccountID); + const approvalChain = ReportUtils.getApprovalChain(policy, report); + const submitToAccountID = PolicyUtils.getSubmitToAccountID(policy, report); if (approvalChain.length === 0) { return submitToAccountID; @@ -7111,7 +7110,7 @@ function approveMoneyRequest(expenseReport: OnyxEntry, full?: } const optimisticApprovedReportAction = ReportUtils.buildOptimisticApprovedReportAction(total, expenseReport?.currency ?? '', expenseReport?.reportID ?? '-1'); - const approvalChain = ReportUtils.getApprovalChain(PolicyUtils.getPolicy(expenseReport?.policyID), expenseReport?.ownerAccountID ?? -1, expenseReport?.total ?? 0); + const approvalChain = ReportUtils.getApprovalChain(PolicyUtils.getPolicy(expenseReport?.policyID), expenseReport); const predictedNextStatus = isLastApprover(approvalChain) ? CONST.REPORT.STATUS_NUM.APPROVED : CONST.REPORT.STATUS_NUM.SUBMITTED; const predictedNextState = isLastApprover(approvalChain) ? CONST.REPORT.STATE_NUM.APPROVED : CONST.REPORT.STATE_NUM.SUBMITTED; @@ -7472,7 +7471,7 @@ function submitReport(expenseReport: OnyxTypes.Report) { const parameters: SubmitReportParams = { reportID: expenseReport.reportID, - managerAccountID: PolicyUtils.getSubmitToAccountID(policy, expenseReport.ownerAccountID ?? -1) ?? expenseReport.managerID, + managerAccountID: PolicyUtils.getSubmitToAccountID(policy, expenseReport) ?? expenseReport.managerID, reportActionID: optimisticSubmittedReportAction.reportActionID, }; From c93c19da35dd88874dfb14aef9d795f811c6747a Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 22 Oct 2024 01:38:11 +0700 Subject: [PATCH 068/808] revert change --- src/libs/Permissions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 47fa860af63c..24de2e612208 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -4,7 +4,6 @@ import type {IOUType} from '@src/CONST'; import type Beta from '@src/types/onyx/Beta'; function canUseAllBetas(betas: OnyxEntry): boolean { - return true; return !!betas?.includes(CONST.BETAS.ALL); } From d724165360acd97b0866981c583938ace5a98015 Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Mon, 7 Oct 2024 12:47:22 +0530 Subject: [PATCH 069/808] Use small icon in tabs --- src/components/TabSelector/TabIcon.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/TabSelector/TabIcon.tsx b/src/components/TabSelector/TabIcon.tsx index 31833b2fc852..bd4e1b1e2fc3 100644 --- a/src/components/TabSelector/TabIcon.tsx +++ b/src/components/TabSelector/TabIcon.tsx @@ -25,12 +25,14 @@ function TabIcon({icon, activeOpacity = 0, inactiveOpacity = 1}: TabIconProps) { From 94b16372ed5dd3cee8426a2a64f325a9f3165e8c Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Fri, 18 Oct 2024 17:09:58 +0530 Subject: [PATCH 070/808] Update --- src/styles/index.ts | 4 ++-- src/styles/variables.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index 3ea14bb14515..2b7e488325d9 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -4310,8 +4310,8 @@ const styles = (theme: ThemeColors) => marginLeft: 8, ...FontUtils.fontFamily.platform.EXP_NEUE_BOLD, color: isSelected ? theme.text : theme.textSupporting, - lineHeight: variables.lineHeightNormal, - fontSize: variables.fontSizeNormal, + lineHeight: variables.lineHeightLarge, + fontSize: variables.fontSizeLabel, } satisfies TextStyle), tabBackground: (hovered: boolean, isFocused: boolean, background: string | Animated.AnimatedInterpolation) => ({ diff --git a/src/styles/variables.ts b/src/styles/variables.ts index dc6655791489..eb52fe2a0534 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -159,7 +159,7 @@ export default { signInLogoWidthLargeScreen: 144, signInLogoHeightLargeScreen: 108, signInLogoWidthPill: 132, - tabSelectorButtonHeight: 42, + tabSelectorButtonHeight: 40, tabSelectorButtonPadding: 12, lhnLogoWidth: 95.09, lhnLogoHeight: 22.33, From a94d103bcda66b25c6f97f4ba8f56f51411cda71 Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Mon, 21 Oct 2024 20:24:57 +0530 Subject: [PATCH 071/808] Use 8 as icon margin for buttons --- src/components/Button/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 04607ef1cc7f..0a8aa1c69dad 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -290,7 +290,7 @@ function Button( {icon && ( - + Date: Tue, 22 Oct 2024 02:02:31 +0700 Subject: [PATCH 072/808] fix lint --- ios/Podfile.lock | 31 +++++++++---------------------- src/libs/PolicyUtils.ts | 7 ++++--- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1242ab7a5a39..68266651661a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1606,29 +1606,16 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-config (1.5.3): - - react-native-config/App (= 1.5.3) - - react-native-config/App (1.5.3): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.01.01.00) + - react-native-config (1.5.0): + - react-native-config/App (= 1.5.0) + - react-native-config/App (1.5.0): + - RCT-Folly - RCTRequired - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple + - React + - React-Codegen - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - Yoga - react-native-document-picker (9.3.1): - DoubleConversion - glog @@ -1700,7 +1687,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-keyboard-controller (1.14.1): + - react-native-keyboard-controller (1.14.0): - DoubleConversion - glog - hermes-engine @@ -3186,12 +3173,12 @@ SPEC CHECKSUMS: react-native-airship: e10f6823d8da49bbcb2db4bdb16ff954188afccc react-native-blob-util: 221c61c98ae507b758472ac4d2d489119d1a6c44 react-native-cameraroll: 478a0c1fcdd39f08f6ac272b7ed06e92b2c7c129 - react-native-config: 742a9e0a378a78d0eaff1fb3477d8c0ae222eb51 + react-native-config: 5ce986133b07fc258828b20b9506de0e683efc1c react-native-document-picker: e9d83c149bdd72dc01cf8dcb8df0389c6bd5fddb react-native-geolocation: b9bd12beaf0ebca61a01514517ca8455bd26fa06 react-native-image-picker: f8a13ff106bcc7eb00c71ce11fdc36aac2a44440 react-native-key-command: aae312752fcdfaa2240be9a015fc41ce54087546 - react-native-keyboard-controller: 902c07f41a415b632583b384427a71770a8b02a3 + react-native-keyboard-controller: 17d5830f2bd6c6cad44682eb2cc13f9078eff985 react-native-launch-arguments: 5f41e0abf88a15e3c5309b8875d6fd5ac43df49d react-native-netinfo: fb5112b1fa754975485884ae85a3fb6a684f49d5 react-native-pager-view: 94195f1bf32e7f78359fa20057c97e632364a08b diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 5f703bc27879..e49fc2ae41d4 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -36,8 +36,7 @@ import * as Localize from './Localize'; import Navigation from './Navigation/Navigation'; import * as NetworkStore from './Network/NetworkStore'; import {getAccountIDsByLogins, getLoginsByAccountIDs, getPersonalDetailByEmail} from './PersonalDetailsUtils'; -import {getTransactionDetails} from './ReportUtils'; -import {getAllReportTransactions} from './TransactionUtils'; +import {getAllReportTransactions, getCategory, getTag} from './TransactionUtils'; type MemberEmailsToAccountIDs = Record; @@ -527,7 +526,9 @@ function getSubmitToAccountID(policy: OnyxEntry, expenseReport: OnyxEntr const allTransactions = getAllReportTransactions(expenseReport?.reportID).sort((transA, transB) => (transA.created < transB.created ? -1 : 1)); for (let i = 0; i < allTransactions.length; i++) { - const {tag = '', category = ''} = getTransactionDetails(allTransactions.at(i)) ?? {}; + const transaction = allTransactions.at(i); + const tag = getTag(transaction); + const category = getCategory(transaction); categoryAppover = getCategoryApproverRule(policy?.rules?.approvalRules ?? [], category)?.approver; if (categoryAppover) { return getAccountIDsByLogins([categoryAppover]).at(0) ?? -1; From 3682b9f4fd89b755fcb9a9383f0bbd62b2014bc9 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 22 Oct 2024 02:04:04 +0700 Subject: [PATCH 073/808] revert pod file --- ios/Podfile.lock | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 68266651661a..1242ab7a5a39 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1606,16 +1606,29 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-config (1.5.0): - - react-native-config/App (= 1.5.0) - - react-native-config/App (1.5.0): - - RCT-Folly + - react-native-config (1.5.3): + - react-native-config/App (= 1.5.3) + - react-native-config/App (1.5.3): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) - RCTRequired - RCTTypeSafety - - React - - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - Yoga - react-native-document-picker (9.3.1): - DoubleConversion - glog @@ -1687,7 +1700,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-keyboard-controller (1.14.0): + - react-native-keyboard-controller (1.14.1): - DoubleConversion - glog - hermes-engine @@ -3173,12 +3186,12 @@ SPEC CHECKSUMS: react-native-airship: e10f6823d8da49bbcb2db4bdb16ff954188afccc react-native-blob-util: 221c61c98ae507b758472ac4d2d489119d1a6c44 react-native-cameraroll: 478a0c1fcdd39f08f6ac272b7ed06e92b2c7c129 - react-native-config: 5ce986133b07fc258828b20b9506de0e683efc1c + react-native-config: 742a9e0a378a78d0eaff1fb3477d8c0ae222eb51 react-native-document-picker: e9d83c149bdd72dc01cf8dcb8df0389c6bd5fddb react-native-geolocation: b9bd12beaf0ebca61a01514517ca8455bd26fa06 react-native-image-picker: f8a13ff106bcc7eb00c71ce11fdc36aac2a44440 react-native-key-command: aae312752fcdfaa2240be9a015fc41ce54087546 - react-native-keyboard-controller: 17d5830f2bd6c6cad44682eb2cc13f9078eff985 + react-native-keyboard-controller: 902c07f41a415b632583b384427a71770a8b02a3 react-native-launch-arguments: 5f41e0abf88a15e3c5309b8875d6fd5ac43df49d react-native-netinfo: fb5112b1fa754975485884ae85a3fb6a684f49d5 react-native-pager-view: 94195f1bf32e7f78359fa20057c97e632364a08b From 0386167ba59ed536c841eaea1c369caef00dd3e1 Mon Sep 17 00:00:00 2001 From: dominictb Date: Tue, 22 Oct 2024 14:27:43 +0700 Subject: [PATCH 074/808] fix: initial workspace is removed in 3-pane layout --- .../CustomFullScreenRouter.tsx | 8 ++++---- src/libs/PolicyUtils.ts | 9 +++++++-- src/pages/workspace/AccessOrNotFoundWrapper.tsx | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx index e09de8fce287..fa4b22c4ac98 100644 --- a/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomFullScreenNavigator/CustomFullScreenRouter.tsx @@ -16,16 +16,16 @@ function adaptStateIfNecessary(state: StackState) { workspaceCentralPane?.params && 'policyID' in workspaceCentralPane.params && typeof workspaceCentralPane.params.policyID === 'string' ? workspaceCentralPane.params.policyID : undefined; + const policy = PolicyUtils.getPolicy(policyID ?? ''); + const isLoadingReportData = PolicyUtils.getIsLoadingReportData(); + const isPolicyAccessible = PolicyUtils.isPolicyAccessible(policy); // There should always be WORKSPACE.INITIAL screen in the state to make sure go back works properly if we deeplinkg to a subpage of settings. // The only exception is when the workspace is invalid or inaccessible. if (!isAtLeastOneInState(state, SCREENS.WORKSPACE.INITIAL)) { - const policy = PolicyUtils.getPolicy(policyID ?? ''); - const isPolicyAccessible = PolicyUtils.isPolicyAccessible(policy); - if (!isPolicyAccessible) { + if (isNarrowLayout && !isLoadingReportData && !isPolicyAccessible) { return; } - // @ts-expect-error Updating read only property // noinspection JSConstantReassignment state.stale = true; // eslint-disable-line diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 2ca572395aca..707a8387e103 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -1071,8 +1071,12 @@ function getActivePolicy(): OnyxEntry { return getPolicy(activePolicyId); } -function isPolicyAccessible(policy: OnyxEntry) { - return !isLoadingReportData && !isEmptyObject(policy) && (Object.keys(policy).length !== 1 || isEmptyObject(policy.errors)) && policy?.id; +function isPolicyAccessible(policy: OnyxEntry): boolean { + return !isEmptyObject(policy) && (Object.keys(policy).length !== 1 || isEmptyObject(policy.errors)) && !!policy?.id; +} + +function getIsLoadingReportData() { + return isLoadingReportData; } export { @@ -1193,6 +1197,7 @@ export { getAllPoliciesLength, getActivePolicy, isPolicyAccessible, + getIsLoadingReportData, }; export type {MemberEmailsToAccountIDs}; diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx index 952378f4ce14..452bf27e6570 100644 --- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx +++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx @@ -165,11 +165,11 @@ function AccessOrNotFoundWrapper({ const childrenProps = useMemo(() => ({report, policy, isLoadingReportData}), [report, policy, isLoadingReportData]); useEffect(() => { - if (!isPolicyNotAccessible) { + if (isLoadingReportData || !isPolicyNotAccessible) { return; } Navigation.removeScreenFromNavigationState(SCREENS.WORKSPACE.INITIAL); - }, [isPolicyNotAccessible]); + }, [isLoadingReportData, isPolicyNotAccessible]); if (shouldShowFullScreenLoadingIndicator) { return ; From c06b770f02a888cf6a956d8bf6af9920665a119b Mon Sep 17 00:00:00 2001 From: truph01 Date: Tue, 22 Oct 2024 15:18:54 +0700 Subject: [PATCH 075/808] fix: Members are unselected when refresh Add message page and go back --- src/pages/workspace/WorkspaceInvitePage.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index ad48d15aa9df..23a90b4afd3e 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -1,3 +1,4 @@ +import {useNavigation} from '@react-navigation/native'; import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import type {SectionListData} from 'react-native'; @@ -59,6 +60,7 @@ type WorkspaceInvitePageProps = WithPolicyAndFullscreenLoadingProps & function WorkspaceInvitePage({route, betas, invitedEmailsToAccountIDsDraft, policy}: WorkspaceInvitePageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + const navigation = useNavigation(); const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const [selectedOptions, setSelectedOptions] = useState([]); const [personalDetails, setPersonalDetails] = useState([]); @@ -76,11 +78,12 @@ function WorkspaceInvitePage({route, betas, invitedEmailsToAccountIDsDraft, poli }); useEffect(() => { - return () => { + const unsubscribe = navigation.addListener('beforeRemove', () => { Member.setWorkspaceInviteMembersDraft(route.params.policyID, {}); - }; - // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps - }, [route.params.policyID]); + }); + + return unsubscribe; + }, [navigation, route.params.policyID]); useEffect(() => { Policy.clearErrors(route.params.policyID); From 904ca23652fa51ef329deb02c2785f91001b6d85 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 22 Oct 2024 18:44:41 +0900 Subject: [PATCH 076/808] Enable/disable per diem rates --- .../simple-illustration__perdiem.svg | 82 ++++ src/CONST.ts | 2 + src/ROUTES.ts | 4 + src/SCREENS.ts | 1 + .../FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts | 1 + src/components/Icon/Illustrations.ts | 2 + src/languages/en.ts | 24 + src/languages/es.ts | 24 + .../parameters/EnablePolicyPerDiemParams.ts | 6 + .../OpenPolicyPerDiemRatesPageParams.ts | 5 + src/libs/API/parameters/index.ts | 2 + src/libs/API/types.ts | 4 + .../Navigators/FullScreenNavigator.tsx | 1 + src/libs/Navigation/linkingConfig/config.ts | 3 + src/libs/Navigation/types.ts | 3 + src/libs/PolicyUtils.ts | 8 + src/libs/actions/Policy/PerDiem.ts | 104 +++++ src/pages/workspace/WorkspaceInitialPage.tsx | 13 +- .../workspace/WorkspaceMoreFeaturesPage.tsx | 14 + .../perDiem/WorkspacePerDiemPage.tsx | 441 ++++++++++++++++++ src/types/onyx/Policy.ts | 18 + 21 files changed, 761 insertions(+), 1 deletion(-) create mode 100644 assets/images/simple-illustrations/simple-illustration__perdiem.svg create mode 100644 src/libs/API/parameters/EnablePolicyPerDiemParams.ts create mode 100644 src/libs/API/parameters/OpenPolicyPerDiemRatesPageParams.ts create mode 100644 src/libs/actions/Policy/PerDiem.ts create mode 100644 src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx diff --git a/assets/images/simple-illustrations/simple-illustration__perdiem.svg b/assets/images/simple-illustrations/simple-illustration__perdiem.svg new file mode 100644 index 000000000000..ea5a865a2694 --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__perdiem.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CONST.ts b/src/CONST.ts index 440f942e1244..9b82554cfc5b 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2321,6 +2321,7 @@ const CONST = { ARE_INVOICES_ENABLED: 'areInvoicesEnabled', ARE_TAXES_ENABLED: 'tax', ARE_RULES_ENABLED: 'areRulesEnabled', + ARE_PER_DIEM_ENABLED: 'arePerDiemEnabled', }, DEFAULT_CATEGORIES: [ 'Advertising', @@ -2487,6 +2488,7 @@ const CONST = { CUSTOM_UNITS: { NAME_DISTANCE: 'Distance', + NAME_PER_DIEM_INTERNATIONAL: 'Per Diem International', DISTANCE_UNIT_MILES: 'mi', DISTANCE_UNIT_KILOMETERS: 'km', MILEAGE_IRS_RATE: 0.67, diff --git a/src/ROUTES.ts b/src/ROUTES.ts index cf15013fed9b..3de1c21c2ddc 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1198,6 +1198,10 @@ const ROUTES = { route: 'settings/workspaces/:policyID/distance-rates/:rateID/tax-rate/edit', getRoute: (policyID: string, rateID: string) => `settings/workspaces/${policyID}/distance-rates/${rateID}/tax-rate/edit` as const, }, + WORKSPACE_PER_DIEM: { + route: 'settings/workspaces/:policyID/per-diem', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/per-diem` as const, + }, RULES_CUSTOM_NAME: { route: 'settings/workspaces/:policyID/rules/name', getRoute: (policyID: string) => `settings/workspaces/${policyID}/rules/name` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index ff428edcd7eb..404634e8dfac 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -519,6 +519,7 @@ const SCREENS = { RULES_MAX_EXPENSE_AMOUNT: 'Rules_Max_Expense_Amount', RULES_MAX_EXPENSE_AGE: 'Rules_Max_Expense_Age', RULES_BILLABLE_DEFAULT: 'Rules_Billable_Default', + PER_DIEM: 'Per_Diem', }, EDIT_REQUEST: { diff --git a/src/components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts b/src/components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts index 4673b4f269ec..32e063f03109 100644 --- a/src/components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts +++ b/src/components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts @@ -35,6 +35,7 @@ const WIDE_LAYOUT_INACTIVE_SCREENS: string[] = [ SCREENS.SETTINGS.TROUBLESHOOT, SCREENS.SETTINGS.SAVE_THE_WORLD, SCREENS.WORKSPACE.RULES, + SCREENS.WORKSPACE.PER_DIEM, ]; export default WIDE_LAYOUT_INACTIVE_SCREENS; diff --git a/src/components/Icon/Illustrations.ts b/src/components/Icon/Illustrations.ts index 18ae1792686f..1469c6fc222c 100644 --- a/src/components/Icon/Illustrations.ts +++ b/src/components/Icon/Illustrations.ts @@ -129,6 +129,7 @@ import Workflows from '@assets/images/simple-illustrations/simple-illustration__ import ExpensifyApprovedLogoLight from '@assets/images/subscription-details__approvedlogo--light.svg'; import ExpensifyApprovedLogo from '@assets/images/subscription-details__approvedlogo.svg'; import TurtleInShell from '@assets/images/turtle-in-shell.svg'; +import PerDiem from '@assets/simple-illustrations/simple-illustration__per-diem.svg'; export { Abracadabra, @@ -262,4 +263,5 @@ export { OtherCompanyCardDetail, StripeCompanyCardDetail, WellsFargoCompanyCardDetail, + PerDiem, }; diff --git a/src/languages/en.ts b/src/languages/en.ts index 8b9569dc1267..d916d42c255d 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2325,6 +2325,7 @@ const translations = { displayedAs: 'Displayed as', plan: 'Plan', profile: 'Profile', + perDiem: 'Per Diem', bankAccount: 'Bank account', connectBankAccount: 'Connect bank account', testTransactions: 'Test transactions', @@ -2389,6 +2390,25 @@ const translations = { } }, }, + perDiem: { + subtitle: 'Set per diem rates to control daily employee spend.', + destination: 'Destination', + subrate: 'Subrate', + amount: 'Amount', + deleteRates: () => ({ + one: 'Delete rate', + other: 'Delete rates', + }), + deletePerDiemRate: 'Delete per diem rate', + areYouSureDelete: () => ({ + one: 'Are you sure you want to delete this rate?', + other: 'Are you sure you want to delete these rates?', + }), + emptyList: { + title: 'Per diem', + subtitle: 'Set per diem rates to control daily employee spend. Import rates from a spreadsheet to get started.', + }, + }, qbd: { exportOutOfPocketExpensesDescription: 'Set how out-of-pocket expenses export to QuickBooks Desktop.', exportOutOfPocketExpensesCheckToogle: 'Mark checks as “print later”', @@ -3264,6 +3284,10 @@ const translations = { title: 'Distance rates', subtitle: 'Add, update, and enforce rates.', }, + perDiem: { + title: 'Per Diem', + subtitle: 'Set Per diem rates to control daily employee spend.', + }, expensifyCard: { title: 'Expensify Card', subtitle: 'Gain insights and control over spend.', diff --git a/src/languages/es.ts b/src/languages/es.ts index b7f66ef2bec0..275090c4c4d4 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2346,6 +2346,7 @@ const translations = { rules: 'Reglas', plan: 'Plan', profile: 'Perfil', + perDiem: 'Per Diem', bankAccount: 'Cuenta bancaria', displayedAs: 'Mostrado como', connectBankAccount: 'Conectar cuenta bancaria', @@ -2412,6 +2413,25 @@ const translations = { } }, }, + perDiem: { + subtitle: 'Set per diem rates to control daily employee spend.', + destination: 'Destination', + subrate: 'Subrate', + amount: 'Amount', + deleteRates: () => ({ + one: 'Delete rate', + other: 'Delete rates', + }), + deletePerDiemRate: 'Delete per diem rate', + areYouSureDelete: () => ({ + one: 'Are you sure you want to delete this rate?', + other: 'Are you sure you want to delete these rates?', + }), + emptyList: { + title: 'Per diem', + subtitle: 'Set per diem rates to control daily employee spend. Import rates from a spreadsheet to get started.', + }, + }, qbd: { exportOutOfPocketExpensesDescription: 'Establezca cómo se exportan los gastos de bolsillo a QuickBooks Desktop.', exportOutOfPocketExpensesCheckToogle: 'Marcar los cheques como “imprimir más tarde”', @@ -3306,6 +3326,10 @@ const translations = { title: 'Tasas de distancia', subtitle: 'Añade, actualiza y haz cumplir las tasas.', }, + perDiem: { + title: 'Per Diem', + subtitle: 'Set Per diem rates to control daily employee spend.', + }, expensifyCard: { title: 'Tarjeta Expensify', subtitle: 'Obtén información y control sobre tus gastos.', diff --git a/src/libs/API/parameters/EnablePolicyPerDiemParams.ts b/src/libs/API/parameters/EnablePolicyPerDiemParams.ts new file mode 100644 index 000000000000..6c7d88ac231a --- /dev/null +++ b/src/libs/API/parameters/EnablePolicyPerDiemParams.ts @@ -0,0 +1,6 @@ +type EnablePolicyPerDiemParams = { + policyID: string; + enabled: boolean; +}; + +export default EnablePolicyPerDiemParams; diff --git a/src/libs/API/parameters/OpenPolicyPerDiemRatesPageParams.ts b/src/libs/API/parameters/OpenPolicyPerDiemRatesPageParams.ts new file mode 100644 index 000000000000..de2fa3467027 --- /dev/null +++ b/src/libs/API/parameters/OpenPolicyPerDiemRatesPageParams.ts @@ -0,0 +1,5 @@ +type OpenPolicyPerDiemRatesPageParams = { + policyID: string; +}; + +export default OpenPolicyPerDiemRatesPageParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 32a1e01ff3da..86d87e1a47f4 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -341,3 +341,5 @@ export type {default as SetInvoicingTransferBankAccountParams} from './SetInvoic export type {default as ConnectPolicyToQuickBooksDesktopParams} from './ConnectPolicyToQuickBooksDesktopParams'; export type {default as UpdateQuickbooksDesktopExpensesExportDestinationTypeParams} from './UpdateQuickbooksDesktopExpensesExportDestinationTypeParams'; export type {default as UpdateQuickbooksDesktopCompanyCardExpenseAccountTypeParams} from './UpdateQuickbooksDesktopCompanyCardExpenseAccountTypeParams'; +export type {default as EnablePolicyPerDiemParams} from './EnablePolicyPerDiemParams'; +export type {default as OpenPolicyPerDiemRatesPageParams} from './OpenPolicyPerDiemRatesPageParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 929e709559b7..3127ad72f54d 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -218,6 +218,7 @@ const WRITE_COMMANDS = { ENABLE_POLICY_WORKFLOWS: 'EnablePolicyWorkflows', ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields', ENABLE_POLICY_EXPENSIFY_CARDS: 'EnablePolicyExpensifyCards', + ENABLE_POLICY_PER_DIEM: 'EnablePolicyPerDiem', ENABLE_POLICY_COMPANY_CARDS: 'EnablePolicyCompanyCards', ENABLE_POLICY_INVOICING: 'EnablePolicyInvoicing', SET_POLICY_RULES_ENABLED: 'SetPolicyRulesEnabled', @@ -650,6 +651,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS]: Parameters.EnablePolicyWorkflowsParams; [WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS]: Parameters.EnablePolicyReportFieldsParams; [WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS]: Parameters.EnablePolicyExpensifyCardsParams; + [WRITE_COMMANDS.ENABLE_POLICY_PER_DIEM]: Parameters.EnablePolicyPerDiemParams; [WRITE_COMMANDS.ENABLE_POLICY_COMPANY_CARDS]: Parameters.EnablePolicyCompanyCardsParams; [WRITE_COMMANDS.ENABLE_POLICY_INVOICING]: Parameters.EnablePolicyInvoicingParams; [WRITE_COMMANDS.SET_POLICY_RULES_ENABLED]: Parameters.SetPolicyRulesEnabledParams; @@ -918,6 +920,7 @@ const READ_COMMANDS = { OPEN_DRAFT_WORKSPACE_REQUEST: 'OpenDraftWorkspaceRequest', OPEN_POLICY_WORKFLOWS_PAGE: 'OpenPolicyWorkflowsPage', OPEN_POLICY_DISTANCE_RATES_PAGE: 'OpenPolicyDistanceRatesPage', + OPEN_POLICY_PER_DIEM_RATES_PAGE: 'OpenPolicyPerDiemRatesPage', OPEN_POLICY_MORE_FEATURES_PAGE: 'OpenPolicyMoreFeaturesPage', OPEN_POLICY_ACCOUNTING_PAGE: 'OpenPolicyAccountingPage', OPEN_POLICY_PROFILE_PAGE: 'OpenPolicyProfilePage', @@ -974,6 +977,7 @@ type ReadCommandParameters = { [READ_COMMANDS.OPEN_DRAFT_WORKSPACE_REQUEST]: Parameters.OpenDraftWorkspaceRequestParams; [READ_COMMANDS.OPEN_POLICY_WORKFLOWS_PAGE]: Parameters.OpenPolicyWorkflowsPageParams; [READ_COMMANDS.OPEN_POLICY_DISTANCE_RATES_PAGE]: Parameters.OpenPolicyDistanceRatesPageParams; + [READ_COMMANDS.OPEN_POLICY_PER_DIEM_RATES_PAGE]: Parameters.OpenPolicyPerDiemRatesPageParams; [READ_COMMANDS.OPEN_POLICY_MORE_FEATURES_PAGE]: Parameters.OpenPolicyMoreFeaturesPageParams; [READ_COMMANDS.OPEN_POLICY_ACCOUNTING_PAGE]: Parameters.OpenPolicyAccountingPageParams; [READ_COMMANDS.OPEN_POLICY_EXPENSIFY_CARDS_PAGE]: Parameters.OpenPolicyExpensifyCardsPageParams; diff --git a/src/libs/Navigation/AppNavigator/Navigators/FullScreenNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/FullScreenNavigator.tsx index 2f513fe804bb..4aac30587725 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/FullScreenNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/FullScreenNavigator.tsx @@ -29,6 +29,7 @@ const CENTRAL_PANE_WORKSPACE_SCREENS = { [SCREENS.WORKSPACE.REPORT_FIELDS]: () => require('../../../../pages/workspace/reportFields/WorkspaceReportFieldsPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardPage').default, [SCREENS.WORKSPACE.COMPANY_CARDS]: () => require('../../../../pages/workspace/companyCards/WorkspaceCompanyCardsPage').default, + [SCREENS.WORKSPACE.PER_DIEM]: () => require('../../../../pages/workspace/perDiem/WorkspacePerDiemPage').default, [SCREENS.WORKSPACE.DISTANCE_RATES]: () => require('../../../../pages/workspace/distanceRates/PolicyDistanceRatesPage').default, [SCREENS.WORKSPACE.RULES]: () => require('../../../../pages/workspace/rules/PolicyRulesPage').default, } satisfies Screens; diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 72e5f398c1d8..d3205e07c652 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -1327,6 +1327,9 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.COMPANY_CARDS]: { path: ROUTES.WORKSPACE_COMPANY_CARDS.route, }, + [SCREENS.WORKSPACE.PER_DIEM]: { + path: ROUTES.WORKSPACE_PER_DIEM.route, + }, [SCREENS.WORKSPACE.WORKFLOWS]: { path: ROUTES.WORKSPACE_WORKFLOWS.route, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 0aa6e7474329..32052907e397 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1368,6 +1368,9 @@ type FullScreenNavigatorParamList = { [SCREENS.WORKSPACE.COMPANY_CARDS_ADD_NEW]: { policyID: string; }; + [SCREENS.WORKSPACE.PER_DIEM]: { + policyID: string; + }; [SCREENS.WORKSPACE.WORKFLOWS]: { policyID: string; }; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 36e5ccef3308..5f7bc79d07cc 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -136,6 +136,13 @@ function getDistanceRateCustomUnit(policy: OnyxEntry): CustomUnit | unde return Object.values(policy?.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); } +/** + * Retrieves the per diem custom unit object for the given policy + */ +function getPerDiemCustomUnit(policy: OnyxEntry): CustomUnit | undefined { + return Object.values(policy?.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); +} + /** * Retrieves custom unit rate object from the given customUnitRateID */ @@ -1149,6 +1156,7 @@ export { getSageIntacctCreditCards, getSageIntacctBankAccounts, getDistanceRateCustomUnit, + getPerDiemCustomUnit, getDistanceRateCustomUnitRate, sortWorkspacesBySelected, removePendingFieldsFromCustomUnit, diff --git a/src/libs/actions/Policy/PerDiem.ts b/src/libs/actions/Policy/PerDiem.ts new file mode 100644 index 000000000000..557fdb29078e --- /dev/null +++ b/src/libs/actions/Policy/PerDiem.ts @@ -0,0 +1,104 @@ +import type {NullishDeep, OnyxCollection} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; +import * as API from '@libs/API'; +import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; +import getIsNarrowLayout from '@libs/getIsNarrowLayout'; +import {navigateWhenEnableFeature} from '@libs/PolicyUtils'; +import * as ReportUtils from '@libs/ReportUtils'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Policy, Report} from '@src/types/onyx'; +import type {OnyxData} from '@src/types/onyx/Request'; + +const allPolicies: OnyxCollection = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY, + callback: (val, key) => { + if (!key) { + return; + } + if (val === null || val === undefined) { + // If we are deleting a policy, we have to check every report linked to that policy + // and unset the draft indicator (pencil icon) alongside removing any draft comments. Clearing these values will keep the newly archived chats from being displayed in the LHN. + // More info: https://github.com/Expensify/App/issues/14260 + const policyID = key.replace(ONYXKEYS.COLLECTION.POLICY, ''); + const policyReports = ReportUtils.getAllPolicyReports(policyID); + const cleanUpMergeQueries: Record<`${typeof ONYXKEYS.COLLECTION.REPORT}${string}`, NullishDeep> = {}; + const cleanUpSetQueries: Record<`${typeof ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${string}` | `${typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${string}`, null> = {}; + policyReports.forEach((policyReport) => { + if (!policyReport) { + return; + } + const {reportID} = policyReport; + cleanUpSetQueries[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`] = null; + cleanUpSetQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${reportID}`] = null; + }); + Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, cleanUpMergeQueries); + Onyx.multiSet(cleanUpSetQueries); + delete allPolicies[key]; + return; + } + + allPolicies[key] = val; + }, +}); + +function enablePerDiem(policyID: string, enabled: boolean) { + const onyxData: OnyxData = { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + arePerDiemEnabled: enabled, + pendingFields: { + arePerDiemEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + pendingFields: { + arePerDiemEnabled: null, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + arePerDiemEnabled: !enabled, + pendingFields: { + arePerDiemEnabled: null, + }, + }, + }, + ], + }; + + const parameters = {policyID, enabled}; + + API.write(WRITE_COMMANDS.ENABLE_POLICY_PER_DIEM, parameters, onyxData); + + if (enabled && getIsNarrowLayout()) { + navigateWhenEnableFeature(policyID); + } +} + +function openPolicyPerDiemPage(policyID?: string) { + if (!policyID) { + return; + } + + const params = {policyID}; + + API.read(READ_COMMANDS.OPEN_POLICY_PER_DIEM_RATES_PAGE, params); +} + +export {enablePerDiem, openPolicyPerDiemPage}; diff --git a/src/pages/workspace/WorkspaceInitialPage.tsx b/src/pages/workspace/WorkspaceInitialPage.tsx index 6cfc66466da4..0946cc67126a 100644 --- a/src/pages/workspace/WorkspaceInitialPage.tsx +++ b/src/pages/workspace/WorkspaceInitialPage.tsx @@ -62,7 +62,8 @@ type WorkspaceMenuItem = { | typeof SCREENS.WORKSPACE.EXPENSIFY_CARD | typeof SCREENS.WORKSPACE.COMPANY_CARDS | typeof SCREENS.WORKSPACE.REPORT_FIELDS - | typeof SCREENS.WORKSPACE.RULES; + | typeof SCREENS.WORKSPACE.RULES + | typeof SCREENS.WORKSPACE.PER_DIEM; badgeText?: string; }; @@ -111,6 +112,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac [CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED]: policy?.areReportFieldsEnabled, [CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED]: policy?.areRulesEnabled, [CONST.POLICY.MORE_FEATURES.ARE_INVOICES_ENABLED]: policy?.areInvoicesEnabled, + [CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_ENABLED]: policy?.arePerDiemEnabled, }), [policy], ) as PolicyFeatureStates; @@ -221,6 +223,15 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac }); } + if (featureStates?.[CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_ENABLED]) { + protectedCollectPolicyMenuItems.push({ + translationKey: 'workspace.common.perDiem', + icon: Expensicons.CalendarSolid, + action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.WORKSPACE_PER_DIEM.getRoute(policyID)))), + routeName: SCREENS.WORKSPACE.PER_DIEM, + }); + } + if (featureStates?.[CONST.POLICY.MORE_FEATURES.ARE_WORKFLOWS_ENABLED]) { protectedCollectPolicyMenuItems.push({ translationKey: 'workspace.common.workflows', diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index 0bc44a1d2298..c350a6e9ceb5 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -21,6 +21,7 @@ import type {FullScreenNavigatorParamList} from '@libs/Navigation/types'; import {isControlPolicy} from '@libs/PolicyUtils'; import * as Category from '@userActions/Policy/Category'; import * as DistanceRate from '@userActions/Policy/DistanceRate'; +import * as PerDiem from '@userActions/Policy/PerDiem'; import * as Policy from '@userActions/Policy/Policy'; import * as Tag from '@userActions/Policy/Tag'; import * as Report from '@userActions/Report'; @@ -117,6 +118,19 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro setIsDisableExpensifyCardWarningModalOpen(true); }, }, + { + icon: Illustrations.PerDiem, + titleTranslationKey: 'workspace.moreFeatures.perDiem.title', + subtitleTranslationKey: 'workspace.moreFeatures.perDiem.subtitle', + isActive: policy?.arePerDiemEnabled ?? false, + pendingAction: policy?.pendingFields?.arePerDiemEnabled, + action: (isEnabled: boolean) => { + if (!policyID) { + return; + } + PerDiem.enablePerDiem(policyID, isEnabled); + }, + }, ]; if (canUseCompanyCardFeeds) { diff --git a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx new file mode 100644 index 000000000000..59f431142e25 --- /dev/null +++ b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx @@ -0,0 +1,441 @@ +import {useFocusEffect, useIsFocused} from '@react-navigation/native'; +import type {StackScreenProps} from '@react-navigation/stack'; +import lodashSortBy from 'lodash/sortBy'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; +import {ActivityIndicator, View} from 'react-native'; +import Button from '@components/Button'; +import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; +import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types'; +import ConfirmModal from '@components/ConfirmModal'; +import EmptyStateComponent from '@components/EmptyStateComponent'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import * as Expensicons from '@components/Icon/Expensicons'; +import * as Illustrations from '@components/Icon/Illustrations'; +import LottieAnimations from '@components/LottieAnimations'; +import ScreenWrapper from '@components/ScreenWrapper'; +import ListItemRightCaretWithLabel from '@components/SelectionList/ListItemRightCaretWithLabel'; +import TableListItem from '@components/SelectionList/TableListItem'; +import type {ListItem} from '@components/SelectionList/types'; +import SelectionListWithModal from '@components/SelectionListWithModal'; +import TableListItemSkeleton from '@components/Skeletons/TableRowSkeleton'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useMobileSelectionMode from '@hooks/useMobileSelectionMode'; +import useNetwork from '@hooks/useNetwork'; +import usePolicy from '@hooks/usePolicy'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; +import * as CurrencyUtils from '@libs/CurrencyUtils'; +import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import localeCompare from '@libs/LocaleCompare'; +import Navigation from '@libs/Navigation/Navigation'; +import type {FullScreenNavigatorParamList} from '@libs/Navigation/types'; +import {getPerDiemCustomUnit} from '@libs/PolicyUtils'; +import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import * as Modal from '@userActions/Modal'; +// import {deleteWorkspaceCategories, setWorkspaceCategoryEnabled} from '@userActions/Policy/Category'; +import * as Category from '@userActions/Policy/Category'; +import * as PerDiem from '@userActions/Policy/PerDiem'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; +import type {PendingAction} from '@src/types/onyx/OnyxCommon'; +import type {Rate} from '@src/types/onyx/Policy'; +import type DeepValueOf from '@src/types/utils/DeepValueOf'; + +type PolicyOption = ListItem & { + /** subRateID is used as a key for identification of the entry */ + subRateID: string; + + /** rateID is used as a key for identification of the entry */ + rateID: string; +}; + +type SubRateData = { + pendingAction?: PendingAction; + destination: string; + subRateName: string; + rate: number; + currency: string; + rateID: string; + subRateID: string; +}; + +function getSubRatesData(customUnitRates: Rate[]) { + const subRatesData: SubRateData[] = []; + for (const rate of customUnitRates) { + const subRates = rate.subRates; + if (subRates) { + for (const subRate of subRates) { + subRatesData.push({ + pendingAction: rate.pendingAction, + destination: rate.name ?? '', + subRateName: subRate.name, + rate: subRate.rate, + currency: rate.currency ?? CONST.CURRENCY.USD, + rateID: rate.customUnitRateID ?? '', + subRateID: subRate.id, + }); + } + } + } + return subRatesData; +} + +function generateSingleSubRateData(customUnitRates: Rate[], rateID: string, subRateID: string) { + const selectedRate = customUnitRates.find((rate) => rate.customUnitRateID === rateID); + if (!selectedRate) { + return null; + } + const selectedSubRate = selectedRate.subRates?.find((subRate) => subRate.id === subRateID); + if (!selectedSubRate) { + return null; + } + return { + pendingAction: selectedRate.pendingAction, + destination: selectedRate.name ?? '', + subRateName: selectedSubRate.name, + rate: selectedSubRate.rate, + currency: selectedRate.currency ?? CONST.CURRENCY.USD, + rateID: selectedRate.customUnitRateID ?? '', + subRateID: selectedSubRate.id, + }; +} + +type WorkspacePerDiemPageProps = StackScreenProps; + +function WorkspacePerDiemPage({route}: WorkspacePerDiemPageProps) { + const {shouldUseNarrowLayout} = useResponsiveLayout(); + const {windowWidth} = useWindowDimensions(); + const styles = useThemeStyles(); + const theme = useTheme(); + const {translate} = useLocalize(); + const [isOfflineModalVisible, setIsOfflineModalVisible] = useState(false); + const [selectedPerDiem, setSelectedPerDiem] = useState([]); + const [deletePerDiemConfirmModalVisible, setDeletePerDiemConfirmModalVisible] = useState(false); + const isFocused = useIsFocused(); + const policyID = route.params.policyID ?? '-1'; + const backTo = route.params?.backTo; + const policy = usePolicy(policyID); + const {selectionMode} = useMobileSelectionMode(); + + const customUnit = getPerDiemCustomUnit(policy); + const customUnitRates: Record = useMemo(() => customUnit?.rates ?? {}, [customUnit]); + + const allRatesArray = Object.values(customUnitRates); + + const allSubRates = getSubRatesData(allRatesArray); + + // Filter out rates that will be deleted + const allSelectableSubRates = useMemo(() => allSubRates.filter((subRate) => subRate.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE), [allSubRates]); + + const canSelectMultiple = shouldUseNarrowLayout ? selectionMode?.isEnabled : true; + + const fetchPerDiem = useCallback(() => { + PerDiem.openPolicyPerDiemPage(policyID); + }, [policyID]); + + const {isOffline} = useNetwork({onReconnect: fetchPerDiem}); + + useFocusEffect( + useCallback(() => { + fetchPerDiem(); + }, [fetchPerDiem]), + ); + + useEffect(() => { + if (isFocused) { + return; + } + setSelectedPerDiem([]); + }, [isFocused]); + + const subRatesList = useMemo( + () => + (lodashSortBy(allSubRates, 'destination', localeCompare) as SubRateData[]).map((value) => { + const isDisabled = value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; + return { + text: value.destination, + subRateID: value.subRateID, + rateID: value.rateID, + keyForList: value.subRateID, + isSelected: selectedPerDiem.find((rate) => rate.subRateID === value.subRateID) !== undefined && canSelectMultiple, + isDisabled, + pendingAction: value.pendingAction, + // errors: value.errors ?? undefined, + rightElement: ( + <> + + {value.subRateName} + + + + {CurrencyUtils.convertAmountToDisplayString(value.rate, value.currency)} + + + + + ), + }; + }), + [allSubRates, selectedPerDiem, canSelectMultiple, styles.flex1, styles.alignItemsStart, styles.textSupporting, styles.label, styles.alignSelfEnd, styles.pl2], + ); + + const toggleSubRate = (subRate: PolicyOption) => { + if (selectedPerDiem.find((selectedSubRate) => selectedSubRate.subRateID === subRate.subRateID) !== undefined) { + setSelectedPerDiem((prev) => prev.filter((selectedSubRate) => selectedSubRate.subRateID !== subRate.subRateID)); + } else { + const subRateData = generateSingleSubRateData(allRatesArray, subRate.rateID, subRate.subRateID); + if (!subRateData) { + return; + } + setSelectedPerDiem((prev) => [...prev, subRateData]); + } + }; + + const toggleAllSubRates = () => { + if (selectedPerDiem.length === allSelectableSubRates.length) { + setSelectedPerDiem([]); + } else { + setSelectedPerDiem([...allSelectableSubRates]); + } + }; + + const getCustomListHeader = () => ( + + + {translate('workspace.perDiem.destination')} + + + {translate('workspace.perDiem.subrate')} + + + {translate('workspace.perDiem.amount')} + + + ); + + const openSettings = () => { + // Navigation.navigate(ROUTES.WORKSPACE_PER_DIEM_RATES_SETTINGS.getRoute(policyID)); + Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATES_SETTINGS.getRoute(policyID)); + }; + + const openSubRateDetails = (rate: PolicyOption) => { + // Navigation.navigate(ROUTES.WORKSPACE_PER_DIEM_RATE_DETAILS.getRoute(policyID, rate.rateID, rate.subRateID)); + Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATE_DETAILS.getRoute(policyID, rate.subRateID)); + }; + + const dismissError = (item: PolicyOption) => { + Category.clearCategoryErrors(policyID, item.subRateID); + }; + + const handleDeleteCategories = () => { + setSelectedPerDiem([]); + // deleteWorkspaceCategories(policyID, selectedPerDiem); + setDeletePerDiemConfirmModalVisible(false); + }; + + const getHeaderButtons = () => { + const options: Array>> = []; + + if (shouldUseNarrowLayout ? canSelectMultiple : selectedPerDiem.length > 0) { + options.push({ + icon: Expensicons.Trashcan, + text: translate('workspace.perDiem.deleteRates', {count: selectedPerDiem.length}), + value: CONST.POLICY.BULK_ACTION_TYPES.DELETE, + onSelected: () => setDeletePerDiemConfirmModalVisible(true), + }); + + return ( + null} + shouldAlwaysShowDropdownMenu + pressOnEnter + buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM} + customText={translate('workspace.common.selected', {count: selectedPerDiem.length})} + options={options} + isSplitButton={false} + style={[shouldUseNarrowLayout && styles.flexGrow1, shouldUseNarrowLayout && styles.mb3]} + isDisabled={!selectedPerDiem.length} + /> + ); + } + + return ( + +