From 58833a1c59977079b34c594f6f178962c5d0b661 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Sun, 11 Aug 2024 17:42:22 +0300 Subject: [PATCH 001/245] 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/245] 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 ece998d26fe90da12b61ffe3a869189a635eb79b Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 15 Oct 2024 15:27:55 +0200 Subject: [PATCH 003/245] 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 004/245] 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 005/245] 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 006/245] 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 d31cc9cc4446bddcd08c080faf1d6e03c51b3dce Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Fri, 18 Oct 2024 00:49:32 +0530 Subject: [PATCH 007/245] 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 008/245] 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 009/245] 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: Tue, 22 Oct 2024 01:23:28 +0700 Subject: [PATCH 010/245] 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 011/245] 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 7d36a2bdfe2ec300a2a3f2ef2e4714a2b0bae97b Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 22 Oct 2024 02:02:31 +0700 Subject: [PATCH 012/245] 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 013/245] 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 d8cb98fc89ee451cc8a6e951a8ba63928e8cc361 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 23 Oct 2024 21:14:13 +0200 Subject: [PATCH 014/245] improve isLoading to prevent loading for undefined --- src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index 4d3e5a347266..9a20ce24eac6 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -34,8 +34,8 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) { const selectedFeed = CardUtils.getSelectedFeed(lastSelectedFeed, cardFeeds); const [cardsList] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`); - const isLoading = !cardFeeds || !!(cardFeeds.isLoading && !cardFeeds.settings); const companyCards = cardFeeds?.settings?.companyCards ?? {}; + const isLoading = !cardFeeds || !!(cardFeeds.isLoading && !companyCards); const selectedCompanyCard = companyCards[selectedFeed ?? ''] ?? null; const isNoFeed = !selectedCompanyCard; const isPending = !!selectedCompanyCard?.pending; From b75c05605b0db964dba8a8b3f88e83ca854aa190 Mon Sep 17 00:00:00 2001 From: nkdengineer <161821005+nkdengineer@users.noreply.github.com> Date: Fri, 25 Oct 2024 02:17:26 +0700 Subject: [PATCH 015/245] Update src/libs/PolicyUtils.ts Co-authored-by: Alex Beaman --- src/libs/PolicyUtils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 1547c4ddda02..35fb0d6b69eb 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -531,6 +531,8 @@ function getSubmitToAccountID(policy: OnyxEntry, expenseReport: OnyxEntr let tagApprover; const allTransactions = getAllReportTransactions(expenseReport?.reportID).sort((transA, transB) => (transA.created < transB.created ? -1 : 1)); + // Before submitting to their `submitsTo` (in a policy on Advanced Approvals), submit to category/tag approvers. + // Category approvers are prioritized, then tag approvers. for (let i = 0; i < allTransactions.length; i++) { const transaction = allTransactions.at(i); const tag = getTag(transaction); From de7e6a67957292ffbc1171c65c347b572c6a10f1 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 25 Oct 2024 02:24:36 +0700 Subject: [PATCH 016/245] update comment --- src/libs/PolicyUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 35fb0d6b69eb..2e7efd6afc71 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -520,7 +520,7 @@ function getDefaultApprover(policy: OnyxEntry): string { } /** - * Returns the accountID to whom the given employeeAccountID submits reports to in the given Policy. + * Returns the accountID to whom the given expenseReport submits reports to in the given Policy. */ function getSubmitToAccountID(policy: OnyxEntry, expenseReport: OnyxEntry): number { const employeeAccountID = expenseReport?.ownerAccountID ?? -1; From d726dcbfa13d8c8f1c0fe4177561dba2ce9b1a7a Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Thu, 24 Oct 2024 15:51:19 -0600 Subject: [PATCH 017/245] add consts --- src/CONST.ts | 3 +++ src/components/SelectionList/Search/ActionCell.tsx | 3 +++ src/libs/SearchUIUtils.ts | 1 + 3 files changed, 7 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index a3df980ff5dd..f5441e6f942d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5644,6 +5644,9 @@ const CONST = { ACTION_TYPES: { VIEW: 'view', REVIEW: 'review', + SUBMIT: 'submit', + APPROVE: 'approve', + PAY: 'pay', DONE: 'done', PAID: 'paid', }, diff --git a/src/components/SelectionList/Search/ActionCell.tsx b/src/components/SelectionList/Search/ActionCell.tsx index faafa6159dc1..57db7e7d7969 100644 --- a/src/components/SelectionList/Search/ActionCell.tsx +++ b/src/components/SelectionList/Search/ActionCell.tsx @@ -15,6 +15,9 @@ import type {SearchTransactionAction} from '@src/types/onyx/SearchResults'; const actionTranslationsMap: Record = { view: 'common.view', review: 'common.review', + submit: 'common.submit', + approve: 'iou.approve', + pay: 'iou.pay', done: 'common.done', paid: 'iou.settledExpensify', }; diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index a7ce065a6d23..ed865d6eac2d 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -223,6 +223,7 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data'], metadata return { ...transactionItem, + action: 'submit', from, to, formattedFrom, From 2f4c9802966b65fc23163394222aaf8231216707 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Thu, 24 Oct 2024 16:26:25 -0600 Subject: [PATCH 018/245] create getAction --- src/libs/SearchUIUtils.ts | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index ed865d6eac2d..7ce8cfb44c0a 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -4,6 +4,7 @@ import ChatListItem from '@components/SelectionList/ChatListItem'; import ReportListItem from '@components/SelectionList/Search/ReportListItem'; import TransactionListItem from '@components/SelectionList/Search/TransactionListItem'; import type {ListItem, ReportActionListItemType, ReportListItemType, TransactionListItemType} from '@components/SelectionList/types'; +import * as IOU from '@libs/actions/IOU'; import * as Expensicons from '@src/components/Icon/Expensicons'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; @@ -11,7 +12,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import type SearchResults from '@src/types/onyx/SearchResults'; -import type {ListItemDataType, ListItemType, SearchDataTypes, SearchPersonalDetails, SearchReport, SearchTransaction} from '@src/types/onyx/SearchResults'; +import type {ListItemDataType, ListItemType, SearchDataTypes, SearchPersonalDetails, SearchReport, SearchTransaction, SearchTransactionAction} from '@src/types/onyx/SearchResults'; import * as CurrencyUtils from './CurrencyUtils'; import DateUtils from './DateUtils'; import {translateLocal} from './Localize'; @@ -223,7 +224,7 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data'], metadata return { ...transactionItem, - action: 'submit', + action: getAction(data, key), from, to, formattedFrom, @@ -241,6 +242,35 @@ function getTransactionsSections(data: OnyxTypes.SearchResults['data'], metadata }); } +/** + * @private + * Returns the action that can be taken on a given transaction or report + * + * Do not use directly, use only via `getSections()` facade. + */ +function getAction(data: OnyxTypes.SearchResults['data'], key: string): SearchTransactionAction { + if (!isTransactionEntry(key) && !isReportEntry(key)) { + return CONST.SEARCH.ACTION_TYPES.VIEW; + } + + return CONST.SEARCH.ACTION_TYPES.VIEW; + + // const report = isReportEntry(key) ? data[key] : data[data[key].reportID]; + // const chatReport = isReportEntry(key) ? data[key].chatReportID + // iouReport + // chatReport + // policy + // transactions + // if (IOU.canIOUBePaid()) { + // pay + // approve + // submit + // review + // view + // done + // paid +} + /** * @private * Organizes data into List Sections for display, for the ReportActionListItemType of Search Results. From 584a539d4ad69b2dc000765d87178a659931f264 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Thu, 24 Oct 2024 16:49:39 -0600 Subject: [PATCH 019/245] create canReportBeSubmitted --- .../SelectionList/Search/ActionCell.tsx | 4 +-- src/libs/SearchUIUtils.ts | 26 +++++++++++++------ src/libs/actions/IOU.ts | 21 +++++++++++++++ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/components/SelectionList/Search/ActionCell.tsx b/src/components/SelectionList/Search/ActionCell.tsx index 57db7e7d7969..612f515791c0 100644 --- a/src/components/SelectionList/Search/ActionCell.tsx +++ b/src/components/SelectionList/Search/ActionCell.tsx @@ -80,7 +80,7 @@ function ActionCell({action = CONST.SEARCH.ACTION_TYPES.VIEW, isLargeScreenWidth ) : null; } - if (action === CONST.SEARCH.ACTION_TYPES.REVIEW) { + // if (action === CONST.SEARCH.ACTION_TYPES.REVIEW) { return (