From 6144f13f140fa33f05032e495f6348ade3d26982 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 1 Feb 2024 00:32:15 +0700 Subject: [PATCH 001/145] fix: Closing receipt view using device navigation redirects user to expense report --- src/ROUTES.ts | 4 ++ src/SCREENS.ts | 1 + .../ReportActionItemImage.tsx | 28 +++------ .../Navigation/AppNavigator/AuthScreens.tsx | 10 ++++ src/libs/Navigation/linkingConfig.ts | 1 + src/libs/Navigation/types.ts | 4 ++ src/pages/TransactionReceiptPage.tsx | 57 +++++++++++++++++++ 7 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 src/pages/TransactionReceiptPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 9c4375b84ab6..6f5361fcd1ce 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -485,6 +485,10 @@ const ROUTES = { getRoute: (contentType: string) => `referral/${contentType}` as const, }, PROCESS_MONEY_REQUEST_HOLD: 'hold-request-educational', + TRANSACTION_RECEIPT: { + route: 'r/:reportID/transaction/:transactionID/receipt', + getRoute: (reportID: string, transactionID: string) => `r/${reportID}/transaction/${transactionID}/receipt` as const, + }, } as const; export {getUrlWithBackToParam}; diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 2bf40caede57..bdb2a1a1ff8c 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -246,6 +246,7 @@ const SCREENS = { GET_ASSISTANCE: 'GetAssistance', REFERRAL_DETAILS: 'Referral_Details', KEYBOARD_SHORTCUTS: 'KeyboardShortcuts', + TRANSACTION_RECEIPT: 'TransactionReceipt', } as const; type Screen = DeepValueOf; diff --git a/src/components/ReportActionItem/ReportActionItemImage.tsx b/src/components/ReportActionItem/ReportActionItemImage.tsx index e71eb6834cc7..82ffed686f0c 100644 --- a/src/components/ReportActionItem/ReportActionItemImage.tsx +++ b/src/components/ReportActionItem/ReportActionItemImage.tsx @@ -11,9 +11,11 @@ import {ShowContextMenuContext} from '@components/ShowContextMenuContext'; import ThumbnailImage from '@components/ThumbnailImage'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; import * as TransactionUtils from '@libs/TransactionUtils'; import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; import type {Transaction} from '@src/types/onyx'; type ReportActionItemImageProps = { @@ -79,26 +81,14 @@ function ReportActionItemImage({thumbnail, image, enablePreviewModal = false, tr return ( {({report}) => ( - Navigation.navigate(ROUTES.TRANSACTION_RECEIPT.getRoute(String(report?.reportID), String(transaction?.transactionID)))} + accessibilityLabel={translate('accessibilityHints.viewAttachment')} + accessibilityRole={CONST.ROLE.BUTTON} > - {({show}) => ( - - {receiptImageComponent} - - )} - + {receiptImageComponent} + )} ); diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index e9fcb57df1da..3c2f9c16f243 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -62,6 +62,7 @@ const loadConciergePage = () => require('../../../pages/ConciergePage').default const loadProfileAvatar = () => require('../../../pages/settings/Profile/ProfileAvatar').default as React.ComponentType; const loadWorkspaceAvatar = () => require('../../../pages/workspace/WorkspaceAvatar').default as React.ComponentType; const loadReportAvatar = () => require('../../../pages/ReportAvatar').default as React.ComponentType; +const loadReceiptView = () => require('../../../pages/TransactionReceiptPage').default as React.ComponentType; let timezone: Timezone | null; let currentAccountID = -1; @@ -350,6 +351,15 @@ function AuthScreens({session, lastOpenedPublicRoomID, isUsingMemoryOnlyKeys = f options={screenOptions.fullScreen} component={DesktopSignInRedirectPage} /> + ); diff --git a/src/libs/Navigation/linkingConfig.ts b/src/libs/Navigation/linkingConfig.ts index 5df2bcf0e57b..1ced563b8dfc 100644 --- a/src/libs/Navigation/linkingConfig.ts +++ b/src/libs/Navigation/linkingConfig.ts @@ -32,6 +32,7 @@ const linkingConfig: LinkingOptions = { [SCREENS.PROFILE_AVATAR]: ROUTES.PROFILE_AVATAR.route, [SCREENS.WORKSPACE_AVATAR]: ROUTES.WORKSPACE_AVATAR.route, [SCREENS.REPORT_AVATAR]: ROUTES.REPORT_AVATAR.route, + [SCREENS.TRANSACTION_RECEIPT]: ROUTES.TRANSACTION_RECEIPT.route, // Sidebar [SCREENS.HOME]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 2371c764f42a..cf0f2a895652 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -424,6 +424,10 @@ type AuthScreensParamList = { [NAVIGATORS.LEFT_MODAL_NAVIGATOR]: NavigatorScreenParams; [NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: NavigatorScreenParams; [SCREENS.DESKTOP_SIGN_IN_REDIRECT]: undefined; + [SCREENS.TRANSACTION_RECEIPT]: { + reportID: string; + transactionID: string; + }; }; type RootStackParamList = PublicScreensParamList & AuthScreensParamList; diff --git a/src/pages/TransactionReceiptPage.tsx b/src/pages/TransactionReceiptPage.tsx new file mode 100644 index 000000000000..1ea85d29e7bf --- /dev/null +++ b/src/pages/TransactionReceiptPage.tsx @@ -0,0 +1,57 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import React from 'react'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import AttachmentModal from '@components/AttachmentModal'; +import Navigation from '@libs/Navigation/Navigation'; +import type {AuthScreensParamList} from '@libs/Navigation/types'; +import * as ReceiptUtils from '@libs/ReceiptUtils'; +import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; +import type {Report, Transaction} from '@src/types/onyx'; + +type TransactionReceiptOnyxProps = { + report: OnyxEntry; + transaction: OnyxEntry; +}; + +type TransactionReceiptProps = TransactionReceiptOnyxProps & StackScreenProps; + +function TransactionReceipt({transaction = {} as Transaction, report = {} as Report}: TransactionReceiptProps) { + const receiptURIs = ReceiptUtils.getThumbnailAndImageURIs(transaction as Transaction); + + const imageSource = tryResolveUrlFromApiRoot(receiptURIs.image); + + const isLocalFile = receiptURIs.isLocalFile; + + // const canEditReceipt = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT); + + return ( + { + Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report?.reportID ?? '')); + }} + > + ); +} + +TransactionReceipt.displayName = 'TransactionReceipt'; + +export default withOnyx({ + report: { + key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID ?? ''}`, + }, + transaction: { + key: ({route}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID ?? ''}`, + }, +})(TransactionReceipt); From 2483bfb7b21dbe6ac26ccb931f0c7747d37cecea Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 1 Feb 2024 10:14:53 +0700 Subject: [PATCH 002/145] update canEditReceipt --- .../ReportActionItem/MoneyRequestView.js | 1 - .../ReportActionItem/ReportActionItemImage.tsx | 6 +----- src/libs/ReceiptUtils.ts | 5 +++-- src/pages/TransactionReceiptPage.tsx | 14 +++++++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index e03dd6e4744c..9142484aa328 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -249,7 +249,6 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate isLocalFile={receiptURIs.isLocalFile} transaction={transaction} enablePreviewModal - canEditReceipt={canEditReceipt} /> diff --git a/src/components/ReportActionItem/ReportActionItemImage.tsx b/src/components/ReportActionItem/ReportActionItemImage.tsx index 82ffed686f0c..f8d6ed16c0ab 100644 --- a/src/components/ReportActionItem/ReportActionItemImage.tsx +++ b/src/components/ReportActionItem/ReportActionItemImage.tsx @@ -3,7 +3,6 @@ import React from 'react'; import type {ReactElement} from 'react'; import type {ImageSourcePropType, ViewStyle} from 'react-native'; import {View} from 'react-native'; -import AttachmentModal from '@components/AttachmentModal'; import EReceiptThumbnail from '@components/EReceiptThumbnail'; import Image from '@components/Image'; import PressableWithoutFocus from '@components/Pressable/PressableWithoutFocus'; @@ -33,9 +32,6 @@ type ReportActionItemImageProps = { /** whether thumbnail is refer the local file or not */ isLocalFile?: boolean; - - /** whether the receipt can be replaced */ - canEditReceipt?: boolean; }; /** @@ -44,7 +40,7 @@ type ReportActionItemImageProps = { * and optional preview modal as well. */ -function ReportActionItemImage({thumbnail, image, enablePreviewModal = false, transaction, canEditReceipt = false, isLocalFile = false}: ReportActionItemImageProps) { +function ReportActionItemImage({thumbnail, image, enablePreviewModal = false, transaction, isLocalFile = false}: ReportActionItemImageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const imageSource = tryResolveUrlFromApiRoot(image ?? ''); diff --git a/src/libs/ReceiptUtils.ts b/src/libs/ReceiptUtils.ts index 70d2d588d229..0b7eb17163f7 100644 --- a/src/libs/ReceiptUtils.ts +++ b/src/libs/ReceiptUtils.ts @@ -1,6 +1,7 @@ import Str from 'expensify-common/lib/str'; import _ from 'lodash'; import type {ImageSourcePropType} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import ReceiptDoc from '@assets/images/receipt-doc.png'; import ReceiptGeneric from '@assets/images/receipt-generic.png'; import ReceiptHTML from '@assets/images/receipt-html.png'; @@ -30,14 +31,14 @@ type FileNameAndExtension = { * @param receiptPath * @param receiptFileName */ -function getThumbnailAndImageURIs(transaction: Transaction, receiptPath: string | null = null, receiptFileName: string | null = null): ThumbnailAndImageURI { +function getThumbnailAndImageURIs(transaction: OnyxEntry, receiptPath: string | null = null, receiptFileName: string | null = null): ThumbnailAndImageURI { if (Object.hasOwn(transaction?.pendingFields ?? {}, 'waypoints')) { return {thumbnail: null, image: ReceiptGeneric, isLocalFile: true}; } // URI to image, i.e. blob:new.expensify.com/9ef3a018-4067-47c6-b29f-5f1bd35f213d or expensify.com/receipts/w_e616108497ef940b7210ec6beb5a462d01a878f4.jpg // If there're errors, we need to display them in preview. We can store many files in errors, but we just need to get the last one - const errors = _.findLast(transaction.errors) as ReceiptError | undefined; + const errors = _.findLast(transaction?.errors) as ReceiptError | undefined; const path = errors?.source ?? transaction?.receipt?.source ?? receiptPath ?? ''; // filename of uploaded image or last part of remote URI const filename = errors?.filename ?? transaction?.filename ?? receiptFileName ?? ''; diff --git a/src/pages/TransactionReceiptPage.tsx b/src/pages/TransactionReceiptPage.tsx index 1ea85d29e7bf..64a4d913986c 100644 --- a/src/pages/TransactionReceiptPage.tsx +++ b/src/pages/TransactionReceiptPage.tsx @@ -6,7 +6,10 @@ import AttachmentModal from '@components/AttachmentModal'; import Navigation from '@libs/Navigation/Navigation'; import type {AuthScreensParamList} from '@libs/Navigation/types'; import * as ReceiptUtils from '@libs/ReceiptUtils'; +import * as ReportActionUtils from '@libs/ReportActionsUtils'; +import * as ReportUtils from '@libs/ReportUtils'; import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; @@ -19,14 +22,15 @@ type TransactionReceiptOnyxProps = { type TransactionReceiptProps = TransactionReceiptOnyxProps & StackScreenProps; -function TransactionReceipt({transaction = {} as Transaction, report = {} as Report}: TransactionReceiptProps) { - const receiptURIs = ReceiptUtils.getThumbnailAndImageURIs(transaction as Transaction); +function TransactionReceipt({transaction, report}: TransactionReceiptProps) { + const receiptURIs = ReceiptUtils.getThumbnailAndImageURIs(transaction); const imageSource = tryResolveUrlFromApiRoot(receiptURIs.image); const isLocalFile = receiptURIs.isLocalFile; - // const canEditReceipt = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT); + const parentReportAction = ReportActionUtils.getReportAction(report?.parentReportID ?? '', report?.parentReportActionID ?? ''); + const canEditReceipt = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT); return ( { Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report?.reportID ?? '')); }} - > + /> ); } From 52883ffd11d448b1ad32ba4a27dfcff3a27430dd Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 2 Feb 2024 16:16:10 +0700 Subject: [PATCH 003/145] add fallback value --- src/pages/TransactionReceiptPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/TransactionReceiptPage.tsx b/src/pages/TransactionReceiptPage.tsx index 64a4d913986c..1ba50c88c5ff 100644 --- a/src/pages/TransactionReceiptPage.tsx +++ b/src/pages/TransactionReceiptPage.tsx @@ -53,9 +53,9 @@ TransactionReceipt.displayName = 'TransactionReceipt'; export default withOnyx({ report: { - key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID ?? ''}`, + key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID ?? '0'}`, }, transaction: { - key: ({route}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID ?? ''}`, + key: ({route}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID ?? '0'}`, }, })(TransactionReceipt); From 0c8a9772c3c68f6d84818be6afc420ed665098b3 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Feb 2024 10:38:26 +0700 Subject: [PATCH 004/145] remove linkingConfig gile --- .../ReportActionItemImage.tsx | 4 - src/libs/Navigation/linkingConfig.ts | 508 ------------------ 2 files changed, 512 deletions(-) delete mode 100644 src/libs/Navigation/linkingConfig.ts diff --git a/src/components/ReportActionItem/ReportActionItemImage.tsx b/src/components/ReportActionItem/ReportActionItemImage.tsx index ecb90f1e11d4..b454cb21c201 100644 --- a/src/components/ReportActionItem/ReportActionItemImage.tsx +++ b/src/components/ReportActionItem/ReportActionItemImage.tsx @@ -3,11 +3,7 @@ import React from 'react'; import type {ReactElement} from 'react'; import type {ImageSourcePropType, ViewStyle} from 'react-native'; import {View} from 'react-native'; -<<<<<<< HEAD -======= import type {OnyxEntry} from 'react-native-onyx'; -import AttachmentModal from '@components/AttachmentModal'; ->>>>>>> main import EReceiptThumbnail from '@components/EReceiptThumbnail'; import Image from '@components/Image'; import PressableWithoutFocus from '@components/Pressable/PressableWithoutFocus'; diff --git a/src/libs/Navigation/linkingConfig.ts b/src/libs/Navigation/linkingConfig.ts deleted file mode 100644 index 1ced563b8dfc..000000000000 --- a/src/libs/Navigation/linkingConfig.ts +++ /dev/null @@ -1,508 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import type {LinkingOptions} from '@react-navigation/native'; -import CONST from '@src/CONST'; -import NAVIGATORS from '@src/NAVIGATORS'; -import ROUTES from '@src/ROUTES'; -import SCREENS from '@src/SCREENS'; -import type {RootStackParamList} from './types'; - -const linkingConfig: LinkingOptions = { - prefixes: [ - 'app://-/', - 'new-expensify://', - 'https://www.expensify.cash', - 'https://staging.expensify.cash', - 'https://dev.new.expensify.com', - CONST.NEW_EXPENSIFY_URL, - CONST.STAGING_NEW_EXPENSIFY_URL, - ], - config: { - initialRouteName: SCREENS.HOME, - screens: { - // Main Routes - [SCREENS.VALIDATE_LOGIN]: ROUTES.VALIDATE_LOGIN, - [SCREENS.UNLINK_LOGIN]: ROUTES.UNLINK_LOGIN, - [SCREENS.TRANSITION_BETWEEN_APPS]: ROUTES.TRANSITION_BETWEEN_APPS, - [SCREENS.CONCIERGE]: ROUTES.CONCIERGE, - [SCREENS.SIGN_IN_WITH_APPLE_DESKTOP]: ROUTES.APPLE_SIGN_IN, - [SCREENS.SIGN_IN_WITH_GOOGLE_DESKTOP]: ROUTES.GOOGLE_SIGN_IN, - [SCREENS.SAML_SIGN_IN]: ROUTES.SAML_SIGN_IN, - [SCREENS.DESKTOP_SIGN_IN_REDIRECT]: ROUTES.DESKTOP_SIGN_IN_REDIRECT, - [SCREENS.REPORT_ATTACHMENTS]: ROUTES.REPORT_ATTACHMENTS.route, - [SCREENS.PROFILE_AVATAR]: ROUTES.PROFILE_AVATAR.route, - [SCREENS.WORKSPACE_AVATAR]: ROUTES.WORKSPACE_AVATAR.route, - [SCREENS.REPORT_AVATAR]: ROUTES.REPORT_AVATAR.route, - [SCREENS.TRANSACTION_RECEIPT]: ROUTES.TRANSACTION_RECEIPT.route, - - // Sidebar - [SCREENS.HOME]: { - path: ROUTES.HOME, - }, - - [NAVIGATORS.CENTRAL_PANE_NAVIGATOR]: { - screens: { - [SCREENS.REPORT]: ROUTES.REPORT_WITH_ID.route, - }, - }, - [SCREENS.NOT_FOUND]: '*', - [NAVIGATORS.LEFT_MODAL_NAVIGATOR]: { - screens: { - [SCREENS.LEFT_MODAL.SEARCH]: { - screens: { - [SCREENS.SEARCH_ROOT]: ROUTES.SEARCH, - }, - }, - }, - }, - [NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: { - screens: { - [SCREENS.RIGHT_MODAL.SETTINGS]: { - screens: { - [SCREENS.SETTINGS.ROOT]: { - path: ROUTES.SETTINGS, - }, - [SCREENS.SETTINGS.WORKSPACES]: { - path: ROUTES.SETTINGS_WORKSPACES, - exact: true, - }, - [SCREENS.SETTINGS.PREFERENCES.ROOT]: { - path: ROUTES.SETTINGS_PREFERENCES, - exact: true, - }, - [SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE]: { - path: ROUTES.SETTINGS_PRIORITY_MODE, - exact: true, - }, - [SCREENS.SETTINGS.PREFERENCES.LANGUAGE]: { - path: ROUTES.SETTINGS_LANGUAGE, - exact: true, - }, - [SCREENS.SETTINGS.PREFERENCES.THEME]: { - path: ROUTES.SETTINGS_THEME, - exact: true, - }, - [SCREENS.SETTINGS.CLOSE]: { - path: ROUTES.SETTINGS_CLOSE, - exact: true, - }, - [SCREENS.SETTINGS.SECURITY]: { - path: ROUTES.SETTINGS_SECURITY, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.ROOT]: { - path: ROUTES.SETTINGS_WALLET, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.DOMAIN_CARD]: { - path: ROUTES.SETTINGS_WALLET_DOMAINCARD.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.REPORT_VIRTUAL_CARD_FRAUD]: { - path: ROUTES.SETTINGS_REPORT_FRAUD.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.CARD_GET_PHYSICAL.NAME]: { - path: ROUTES.SETTINGS_WALLET_CARD_GET_PHYSICAL_NAME.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.CARD_GET_PHYSICAL.PHONE]: { - path: ROUTES.SETTINGS_WALLET_CARD_GET_PHYSICAL_PHONE.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.CARD_GET_PHYSICAL.ADDRESS]: { - path: ROUTES.SETTINGS_WALLET_CARD_GET_PHYSICAL_ADDRESS.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.CARD_GET_PHYSICAL.CONFIRM]: { - path: ROUTES.SETTINGS_WALLET_CARD_GET_PHYSICAL_CONFIRM.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.ENABLE_PAYMENTS]: { - path: ROUTES.SETTINGS_ENABLE_PAYMENTS, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.TRANSFER_BALANCE]: { - path: ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.CHOOSE_TRANSFER_ACCOUNT]: { - path: ROUTES.SETTINGS_WALLET_CHOOSE_TRANSFER_ACCOUNT, - exact: true, - }, - [SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED]: { - path: ROUTES.SETTINGS_WALLET_REPORT_CARD_LOST_OR_DAMAGED.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.CARD_ACTIVATE]: { - path: ROUTES.SETTINGS_WALLET_CARD_ACTIVATE.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS]: { - path: ROUTES.SETTINGS_WALLET_CARD_DIGITAL_DETAILS_UPDATE_ADDRESS.route, - exact: true, - }, - [SCREENS.SETTINGS.ADD_DEBIT_CARD]: { - path: ROUTES.SETTINGS_ADD_DEBIT_CARD, - exact: true, - }, - [SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: { - path: ROUTES.SETTINGS_ADD_BANK_ACCOUNT, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.ROOT]: { - path: ROUTES.SETTINGS_PROFILE, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.PRONOUNS]: { - path: ROUTES.SETTINGS_PRONOUNS, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.DISPLAY_NAME]: { - path: ROUTES.SETTINGS_DISPLAY_NAME, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.TIMEZONE]: { - path: ROUTES.SETTINGS_TIMEZONE, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.TIMEZONE_SELECT]: { - path: ROUTES.SETTINGS_TIMEZONE_SELECT, - exact: true, - }, - [SCREENS.SETTINGS.ABOUT]: { - path: ROUTES.SETTINGS_ABOUT, - exact: true, - }, - [SCREENS.SETTINGS.APP_DOWNLOAD_LINKS]: { - path: ROUTES.SETTINGS_APP_DOWNLOAD_LINKS, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.CONTACT_METHODS]: { - path: ROUTES.SETTINGS_CONTACT_METHODS.route, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.CONTACT_METHOD_DETAILS]: { - path: ROUTES.SETTINGS_CONTACT_METHOD_DETAILS.route, - }, - [SCREENS.SETTINGS.LOUNGE_ACCESS]: { - path: ROUTES.SETTINGS_LOUNGE_ACCESS, - }, - [SCREENS.SETTINGS.PROFILE.NEW_CONTACT_METHOD]: { - path: ROUTES.SETTINGS_NEW_CONTACT_METHOD.route, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.PERSONAL_DETAILS.INITIAL]: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.PERSONAL_DETAILS.LEGAL_NAME]: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS_LEGAL_NAME, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.PERSONAL_DETAILS.DATE_OF_BIRTH]: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS_DATE_OF_BIRTH, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.PERSONAL_DETAILS.ADDRESS]: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.PERSONAL_DETAILS.ADDRESS_COUNTRY]: { - path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_COUNTRY.route, - exact: true, - }, - [SCREENS.SETTINGS.TWO_FACTOR_AUTH]: { - path: ROUTES.SETTINGS_2FA.route, - exact: true, - }, - [SCREENS.SETTINGS.SHARE_CODE]: { - path: ROUTES.SETTINGS_SHARE_CODE, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.STATUS]: { - path: ROUTES.SETTINGS_STATUS, - exact: true, - }, - [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER]: { - path: ROUTES.SETTINGS_STATUS_CLEAR_AFTER, - }, - [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_DATE]: { - path: ROUTES.SETTINGS_STATUS_CLEAR_AFTER_DATE, - }, - [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_TIME]: { - path: ROUTES.SETTINGS_STATUS_CLEAR_AFTER_TIME, - }, - [SCREENS.WORKSPACE.INITIAL]: { - path: ROUTES.WORKSPACE_INITIAL.route, - }, - [SCREENS.WORKSPACE.SETTINGS]: { - path: ROUTES.WORKSPACE_SETTINGS.route, - }, - [SCREENS.WORKSPACE.CURRENCY]: { - path: ROUTES.WORKSPACE_SETTINGS_CURRENCY.route, - }, - [SCREENS.WORKSPACE.CARD]: { - path: ROUTES.WORKSPACE_CARD.route, - }, - [SCREENS.WORKSPACE.REIMBURSE]: { - path: ROUTES.WORKSPACE_REIMBURSE.route, - }, - [SCREENS.WORKSPACE.RATE_AND_UNIT]: { - path: ROUTES.WORKSPACE_RATE_AND_UNIT.route, - }, - [SCREENS.WORKSPACE.BILLS]: { - path: ROUTES.WORKSPACE_BILLS.route, - }, - [SCREENS.WORKSPACE.INVOICES]: { - path: ROUTES.WORKSPACE_INVOICES.route, - }, - [SCREENS.WORKSPACE.TRAVEL]: { - path: ROUTES.WORKSPACE_TRAVEL.route, - }, - [SCREENS.WORKSPACE.MEMBERS]: { - path: ROUTES.WORKSPACE_MEMBERS.route, - }, - [SCREENS.WORKSPACE.INVITE]: { - path: ROUTES.WORKSPACE_INVITE.route, - }, - [SCREENS.WORKSPACE.INVITE_MESSAGE]: { - path: ROUTES.WORKSPACE_INVITE_MESSAGE.route, - }, - [SCREENS.REIMBURSEMENT_ACCOUNT]: { - path: ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.route, - exact: true, - }, - [SCREENS.GET_ASSISTANCE]: { - path: ROUTES.GET_ASSISTANCE.route, - }, - [SCREENS.KEYBOARD_SHORTCUTS]: { - path: ROUTES.KEYBOARD_SHORTCUTS, - }, - }, - }, - [SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: { - screens: { - [SCREENS.PRIVATE_NOTES.LIST]: ROUTES.PRIVATE_NOTES_LIST.route, - [SCREENS.PRIVATE_NOTES.EDIT]: ROUTES.PRIVATE_NOTES_EDIT.route, - }, - }, - [SCREENS.RIGHT_MODAL.REPORT_DETAILS]: { - screens: { - [SCREENS.REPORT_DETAILS.ROOT]: ROUTES.REPORT_WITH_ID_DETAILS.route, - [SCREENS.REPORT_DETAILS.SHARE_CODE]: ROUTES.REPORT_WITH_ID_DETAILS_SHARE_CODE.route, - }, - }, - [SCREENS.RIGHT_MODAL.REPORT_SETTINGS]: { - screens: { - [SCREENS.REPORT_SETTINGS.ROOT]: { - path: ROUTES.REPORT_SETTINGS.route, - }, - [SCREENS.REPORT_SETTINGS.ROOM_NAME]: { - path: ROUTES.REPORT_SETTINGS_ROOM_NAME.route, - }, - [SCREENS.REPORT_SETTINGS.NOTIFICATION_PREFERENCES]: { - path: ROUTES.REPORT_SETTINGS_NOTIFICATION_PREFERENCES.route, - }, - [SCREENS.REPORT_SETTINGS.WRITE_CAPABILITY]: { - path: ROUTES.REPORT_SETTINGS_WRITE_CAPABILITY.route, - }, - }, - }, - [SCREENS.RIGHT_MODAL.REPORT_WELCOME_MESSAGE]: { - screens: { - [SCREENS.REPORT_WELCOME_MESSAGE_ROOT]: ROUTES.REPORT_WELCOME_MESSAGE.route, - }, - }, - [SCREENS.RIGHT_MODAL.NEW_CHAT]: { - screens: { - [SCREENS.NEW_CHAT.ROOT]: { - path: ROUTES.NEW, - exact: true, - screens: { - [SCREENS.NEW_CHAT.NEW_CHAT]: { - path: ROUTES.NEW_CHAT, - exact: true, - }, - [SCREENS.NEW_CHAT.NEW_ROOM]: { - path: ROUTES.NEW_ROOM, - exact: true, - }, - }, - }, - }, - }, - [SCREENS.RIGHT_MODAL.NEW_TASK]: { - screens: { - [SCREENS.NEW_TASK.ROOT]: ROUTES.NEW_TASK, - [SCREENS.NEW_TASK.TASK_ASSIGNEE_SELECTOR]: ROUTES.NEW_TASK_ASSIGNEE, - [SCREENS.NEW_TASK.TASK_SHARE_DESTINATION_SELECTOR]: ROUTES.NEW_TASK_SHARE_DESTINATION, - [SCREENS.NEW_TASK.DETAILS]: ROUTES.NEW_TASK_DETAILS, - [SCREENS.NEW_TASK.TITLE]: ROUTES.NEW_TASK_TITLE, - [SCREENS.NEW_TASK.DESCRIPTION]: ROUTES.NEW_TASK_DESCRIPTION, - }, - }, - [SCREENS.RIGHT_MODAL.TEACHERS_UNITE]: { - screens: { - [SCREENS.SAVE_THE_WORLD.ROOT]: ROUTES.TEACHERS_UNITE, - [SCREENS.I_KNOW_A_TEACHER]: ROUTES.I_KNOW_A_TEACHER, - [SCREENS.INTRO_SCHOOL_PRINCIPAL]: ROUTES.INTRO_SCHOOL_PRINCIPAL, - [SCREENS.I_AM_A_TEACHER]: ROUTES.I_AM_A_TEACHER, - }, - }, - [SCREENS.RIGHT_MODAL.DETAILS]: { - screens: { - [SCREENS.DETAILS_ROOT]: ROUTES.DETAILS.route, - }, - }, - [SCREENS.RIGHT_MODAL.PROFILE]: { - screens: { - [SCREENS.PROFILE_ROOT]: ROUTES.PROFILE.route, - }, - }, - [SCREENS.RIGHT_MODAL.PARTICIPANTS]: { - screens: { - [SCREENS.REPORT_PARTICIPANTS_ROOT]: ROUTES.REPORT_PARTICIPANTS.route, - }, - }, - [SCREENS.RIGHT_MODAL.ROOM_INVITE]: { - screens: { - [SCREENS.ROOM_INVITE_ROOT]: ROUTES.ROOM_INVITE.route, - }, - }, - [SCREENS.RIGHT_MODAL.ROOM_MEMBERS]: { - screens: { - [SCREENS.ROOM_MEMBERS_ROOT]: ROUTES.ROOM_MEMBERS.route, - }, - }, - [SCREENS.RIGHT_MODAL.MONEY_REQUEST]: { - screens: { - [SCREENS.MONEY_REQUEST.START]: ROUTES.MONEY_REQUEST_START.route, - [SCREENS.MONEY_REQUEST.CREATE]: { - path: ROUTES.MONEY_REQUEST_CREATE.route, - exact: true, - screens: { - distance: { - path: ROUTES.MONEY_REQUEST_CREATE_TAB_DISTANCE.route, - exact: true, - }, - manual: { - path: ROUTES.MONEY_REQUEST_CREATE_TAB_MANUAL.route, - exact: true, - }, - scan: { - path: ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.route, - exact: true, - }, - }, - }, - [SCREENS.MONEY_REQUEST.STEP_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_AMOUNT.route, - [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: ROUTES.MONEY_REQUEST_STEP_CATEGORY.route, - [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION]: ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.route, - [SCREENS.MONEY_REQUEST.STEP_CURRENCY]: ROUTES.MONEY_REQUEST_STEP_CURRENCY.route, - [SCREENS.MONEY_REQUEST.STEP_DATE]: ROUTES.MONEY_REQUEST_STEP_DATE.route, - [SCREENS.MONEY_REQUEST.STEP_DESCRIPTION]: ROUTES.MONEY_REQUEST_STEP_DESCRIPTION.route, - [SCREENS.MONEY_REQUEST.STEP_DISTANCE]: ROUTES.MONEY_REQUEST_STEP_DISTANCE.route, - [SCREENS.MONEY_REQUEST.STEP_MERCHANT]: ROUTES.MONEY_REQUEST_STEP_MERCHANT.route, - [SCREENS.MONEY_REQUEST.STEP_PARTICIPANTS]: ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.route, - [SCREENS.MONEY_REQUEST.STEP_SCAN]: ROUTES.MONEY_REQUEST_STEP_SCAN.route, - [SCREENS.MONEY_REQUEST.STEP_TAG]: ROUTES.MONEY_REQUEST_STEP_TAG.route, - [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: ROUTES.MONEY_REQUEST_STEP_WAYPOINT.route, - [SCREENS.MONEY_REQUEST.ROOT]: { - path: ROUTES.MONEY_REQUEST.route, - exact: true, - screens: { - [SCREENS.MONEY_REQUEST.MANUAL_TAB]: { - path: ROUTES.MONEY_REQUEST_MANUAL_TAB, - exact: true, - }, - [SCREENS.MONEY_REQUEST.SCAN_TAB]: { - path: ROUTES.MONEY_REQUEST_SCAN_TAB, - exact: true, - }, - [SCREENS.MONEY_REQUEST.DISTANCE_TAB]: { - path: ROUTES.MONEY_REQUEST_DISTANCE_TAB.route, - exact: true, - }, - }, - }, - [SCREENS.MONEY_REQUEST.AMOUNT]: ROUTES.MONEY_REQUEST_AMOUNT.route, - [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.route, - [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: ROUTES.MONEY_REQUEST_STEP_TAX_RATE.route, - [SCREENS.MONEY_REQUEST.PARTICIPANTS]: ROUTES.MONEY_REQUEST_PARTICIPANTS.route, - [SCREENS.MONEY_REQUEST.CONFIRMATION]: ROUTES.MONEY_REQUEST_CONFIRMATION.route, - [SCREENS.MONEY_REQUEST.DATE]: ROUTES.MONEY_REQUEST_DATE.route, - [SCREENS.MONEY_REQUEST.CURRENCY]: ROUTES.MONEY_REQUEST_CURRENCY.route, - [SCREENS.MONEY_REQUEST.DESCRIPTION]: ROUTES.MONEY_REQUEST_DESCRIPTION.route, - [SCREENS.MONEY_REQUEST.CATEGORY]: ROUTES.MONEY_REQUEST_CATEGORY.route, - [SCREENS.MONEY_REQUEST.TAG]: ROUTES.MONEY_REQUEST_TAG.route, - [SCREENS.MONEY_REQUEST.MERCHANT]: ROUTES.MONEY_REQUEST_MERCHANT.route, - [SCREENS.MONEY_REQUEST.RECEIPT]: ROUTES.MONEY_REQUEST_RECEIPT.route, - [SCREENS.MONEY_REQUEST.DISTANCE]: ROUTES.MONEY_REQUEST_DISTANCE.route, - [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: ROUTES.IOU_SEND_ENABLE_PAYMENTS, - [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT, - [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: ROUTES.IOU_SEND_ADD_DEBIT_CARD, - }, - }, - [SCREENS.RIGHT_MODAL.SPLIT_DETAILS]: { - screens: { - [SCREENS.SPLIT_DETAILS.ROOT]: ROUTES.SPLIT_BILL_DETAILS.route, - [SCREENS.SPLIT_DETAILS.EDIT_REQUEST]: ROUTES.EDIT_SPLIT_BILL.route, - [SCREENS.SPLIT_DETAILS.EDIT_CURRENCY]: ROUTES.EDIT_SPLIT_BILL_CURRENCY.route, - }, - }, - [SCREENS.RIGHT_MODAL.TASK_DETAILS]: { - screens: { - [SCREENS.TASK.TITLE]: ROUTES.TASK_TITLE.route, - [SCREENS.TASK.DESCRIPTION]: ROUTES.TASK_DESCRIPTION.route, - [SCREENS.TASK.ASSIGNEE]: ROUTES.TASK_ASSIGNEE.route, - }, - }, - [SCREENS.RIGHT_MODAL.ADD_PERSONAL_BANK_ACCOUNT]: { - screens: { - [SCREENS.ADD_PERSONAL_BANK_ACCOUNT_ROOT]: ROUTES.BANK_ACCOUNT_PERSONAL, - }, - }, - [SCREENS.RIGHT_MODAL.ENABLE_PAYMENTS]: { - screens: { - [SCREENS.ENABLE_PAYMENTS_ROOT]: ROUTES.ENABLE_PAYMENTS, - }, - }, - [SCREENS.RIGHT_MODAL.WALLET_STATEMENT]: { - screens: { - [SCREENS.WALLET_STATEMENT_ROOT]: ROUTES.WALLET_STATEMENT_WITH_DATE, - }, - }, - [SCREENS.RIGHT_MODAL.FLAG_COMMENT]: { - screens: { - [SCREENS.FLAG_COMMENT_ROOT]: ROUTES.FLAG_COMMENT.route, - }, - }, - [SCREENS.RIGHT_MODAL.EDIT_REQUEST]: { - screens: { - [SCREENS.EDIT_REQUEST.ROOT]: ROUTES.EDIT_REQUEST.route, - [SCREENS.EDIT_REQUEST.CURRENCY]: ROUTES.EDIT_CURRENCY_REQUEST.route, - [SCREENS.EDIT_REQUEST.REPORT_FIELD]: ROUTES.EDIT_REPORT_FIELD_REQUEST.route, - }, - }, - [SCREENS.RIGHT_MODAL.SIGN_IN]: { - screens: { - [SCREENS.SIGN_IN_ROOT]: ROUTES.SIGN_IN_MODAL, - }, - }, - [SCREENS.RIGHT_MODAL.REFERRAL]: { - screens: { - [SCREENS.REFERRAL_DETAILS]: ROUTES.REFERRAL_DETAILS_MODAL.route, - }, - }, - ProcessMoneyRequestHold: { - screens: { - ProcessMoneyRequestHold_Root: ROUTES.PROCESS_MONEY_REQUEST_HOLD, - }, - }, - }, - }, - }, - }, -}; - -export default linkingConfig; From 51af936c63a545ae0379ce2d3ba23074816b391e Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Feb 2024 14:11:47 +0700 Subject: [PATCH 005/145] disable locale picker while signing in --- src/components/LocalePicker.tsx | 14 ++++++++++++-- src/components/Picker/BasePicker.tsx | 14 +++++++++++--- src/components/Picker/types.ts | 6 ++++++ src/styles/index.ts | 4 ++-- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index 3a2d9a0fd7b9..d6b8a6ccd40a 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -7,11 +7,14 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as App from '@userActions/App'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Locale} from '@src/types/onyx'; +import type {Account, Locale} from '@src/types/onyx'; import Picker from './Picker'; import type {PickerSize} from './Picker/types'; type LocalePickerOnyxProps = { + /** The details about the account that the user is signing in with */ + account: OnyxEntry; + /** Indicates which locale the user currently has selected */ preferredLocale: OnyxEntry; }; @@ -21,7 +24,7 @@ type LocalePickerProps = LocalePickerOnyxProps & { size?: PickerSize; }; -function LocalePicker({preferredLocale = CONST.LOCALES.DEFAULT, size = 'normal'}: LocalePickerProps) { +function LocalePicker({account, preferredLocale = CONST.LOCALES.DEFAULT, size = 'normal'}: LocalePickerProps) { const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -31,6 +34,7 @@ function LocalePicker({preferredLocale = CONST.LOCALES.DEFAULT, size = 'normal'} keyForList: language, isSelected: preferredLocale === language, })); + const shouldDisablePicker = account?.isLoading && account.loadingForm === (account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); return ( ({ + account: { + key: ONYXKEYS.ACCOUNT, + }, preferredLocale: { key: ONYXKEYS.NVP_PREFERRED_LOCALE, }, diff --git a/src/components/Picker/BasePicker.tsx b/src/components/Picker/BasePicker.tsx index 1bee95532104..720540182452 100644 --- a/src/components/Picker/BasePicker.tsx +++ b/src/components/Picker/BasePicker.tsx @@ -32,7 +32,9 @@ function BasePicker( containerStyles, placeholder = {}, size = 'normal', + shouldAllowDisabledStyle = true, shouldFocusPicker = false, + shouldShowOnlyTextWhenDisabled = true, onBlur = () => {}, additionalPickerEvents = () => {}, }: BasePickerProps, @@ -154,7 +156,7 @@ function BasePicker( const hasError = !!errorText; - if (isDisabled) { + if (isDisabled && shouldShowOnlyTextWhenDisabled) { return ( {!!label && ( @@ -175,14 +177,20 @@ function BasePicker( <> {label && {label}} ({...item, color: itemColor}))} - style={size === 'normal' ? styles.picker(isDisabled, backgroundColor) : styles.pickerSmall(backgroundColor)} + style={size === 'normal' ? styles.picker(isDisabled, backgroundColor) : styles.pickerSmall(isDisabled, backgroundColor)} useNativeAndroidPickerStyle={false} placeholder={pickerPlaceholder} value={value} diff --git a/src/components/Picker/types.ts b/src/components/Picker/types.ts index edf39a59c9d8..d4a0eb0c392b 100644 --- a/src/components/Picker/types.ts +++ b/src/components/Picker/types.ts @@ -69,9 +69,15 @@ type BasePickerProps = { /** The ID used to uniquely identify the input in a Form */ inputID?: string; + /** Show disabled style when disabled */ + shouldAllowDisabledStyle?: boolean; + /** Saves a draft of the input value when used in a form */ shouldSaveDraft?: boolean; + /** Show only picker's label and value when disabled */ + shouldShowOnlyTextWhenDisabled?: boolean; + /** A callback method that is called when the value changes and it receives the selected value as an argument */ onInputChange: (value: TPickerValue, index?: number) => void; diff --git a/src/styles/index.ts b/src/styles/index.ts index 0d4b420c00e4..8d28e80b490f 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -695,7 +695,7 @@ const styles = (theme: ThemeColors) => width: '100%', }, - pickerSmall: (backgroundColor = theme.highlightBG) => + pickerSmall: (disabled = false, backgroundColor = theme.highlightBG) => ({ inputIOS: { fontFamily: FontUtils.fontFamily.platform.EXP_NEUE, @@ -737,7 +737,7 @@ const styles = (theme: ThemeColors) => height: 26, opacity: 1, backgroundColor, - ...cursor.cursorPointer, + ...(disabled ? cursor.cursorDisabled : cursor.cursorPointer), }, inputAndroid: { fontFamily: FontUtils.fontFamily.platform.EXP_NEUE, From d31d5dc82536a2b7aeb76d19834912fa1f43f4b9 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Feb 2024 14:13:04 +0700 Subject: [PATCH 006/145] set isDisabled --- src/components/LocalePicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index d6b8a6ccd40a..8022efd211b0 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -46,7 +46,7 @@ function LocalePicker({account, preferredLocale = CONST.LOCALES.DEFAULT, size = App.setLocale(locale); }} - isDisabled={true} + isDisabled={shouldDisablePicker} items={localesToLanguages} shouldAllowDisabledStyle={false} shouldShowOnlyTextWhenDisabled={false} From 6db0aa7ad753f460d93242f7385ca5cfef870484 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 6 Feb 2024 07:45:51 +0700 Subject: [PATCH 007/145] fix auto select category and tag --- ...oraryForRefactorRequestConfirmationList.js | 20 +++++++++++++++++-- .../step/IOURequestStepConfirmation.js | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index be5cec7a2c0d..f13e2bc651c8 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -477,6 +477,22 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ IOU.setMoneyRequestMerchant_temporaryForRefactor(transaction.transactionID, distanceMerchant); }, [hasRoute, distance, unit, rate, currency, translate, toLocaleDigit, isDistanceRequest, transaction]); + useEffect(() => { + const enabledCategories = _.filter(policyCategories, (category) => category.enabled); + if (iouCategory || !shouldShowCategories || enabledCategories.length !== 1) { + return; + } + IOU.setMoneyRequestCategory_temporaryForRefactor(transaction.transactionID, enabledCategories[0].name); + }, [iouCategory, shouldShowCategories, policyCategories, transaction]); + + useEffect(() => { + const enabledTags = _.filter(policyTagList, (tag) => tag.enabled); + if (iouTag || !shouldShowTags || enabledTags.length !== 1) { + return; + } + IOU.setMoneyRequestTag(transaction.transactionID, enabledTags[0].name); + }, [shouldShowTags, policyTagList, iouTag, transaction]); + /** * @param {Object} option */ @@ -885,10 +901,10 @@ export default compose( key: ONYXKEYS.SESSION, }, policyCategories: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${'76EBA6DE3ECECC33'}`, }, policyTags: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${'76EBA6DE3ECECC33'}`, }, mileageRate: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.js b/src/pages/iou/request/step/IOURequestStepConfirmation.js index 0f1c2b27ad2e..13a57073667f 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.js +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.js @@ -399,7 +399,7 @@ export default compose( key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, policyCategories: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${"76EBA6DE3ECECC33"}`, }, policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, From 61f9d38188051c61398ae88c7f916c4150a5964d Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 6 Feb 2024 08:27:11 +0700 Subject: [PATCH 008/145] fix remove hardcode --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 4 ++-- src/pages/iou/request/step/IOURequestStepConfirmation.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index f13e2bc651c8..19ae722237ff 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -901,10 +901,10 @@ export default compose( key: ONYXKEYS.SESSION, }, policyCategories: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${'76EBA6DE3ECECC33'}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, }, policyTags: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${'76EBA6DE3ECECC33'}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, }, mileageRate: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.js b/src/pages/iou/request/step/IOURequestStepConfirmation.js index 13a57073667f..0eb9cc9c84e6 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.js +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.js @@ -399,7 +399,7 @@ export default compose( key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, policyCategories: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${"76EBA6DE3ECECC33"}`, + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report.policyID}`, }, policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, From 142587c87f015fdc03464ce9ddc9534d9dbaa12f Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 6 Feb 2024 08:28:31 +0700 Subject: [PATCH 009/145] fix typo --- src/pages/iou/request/step/IOURequestStepConfirmation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.js b/src/pages/iou/request/step/IOURequestStepConfirmation.js index 0eb9cc9c84e6..0f1c2b27ad2e 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.js +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.js @@ -399,7 +399,7 @@ export default compose( key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, policyCategories: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report.policyID}`, + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, }, policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, From a2eb3fcda12cad432e91e0c3f6b53b45f6e73334 Mon Sep 17 00:00:00 2001 From: Dylan Date: Tue, 6 Feb 2024 16:03:49 +0700 Subject: [PATCH 010/145] add pending action member for report --- src/libs/actions/Policy.ts | 36 +++++++++++++++++++++++++++++ src/libs/actions/Report.ts | 33 +++++++++++++++++++++++--- src/pages/ReportParticipantsPage.js | 2 ++ src/pages/RoomMembersPage.js | 2 ++ src/types/onyx/Report.ts | 10 +++++++- 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index b47891e64350..5ae4e320d95b 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -26,6 +26,7 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; type AnnounceRoomMembersOnyxData = { onyxOptimisticData: OnyxUpdate[]; + onyxSuccessData: OnyxUpdate[]; onyxFailureData: OnyxUpdate[]; }; @@ -305,6 +306,7 @@ function buildAnnounceRoomMembersOnyxData(policyID: string, accountIDs: number[] const announceRoomMembers: AnnounceRoomMembersOnyxData = { onyxOptimisticData: [], onyxFailureData: [], + onyxSuccessData: [], }; if (!announceReport) { @@ -314,6 +316,13 @@ function buildAnnounceRoomMembersOnyxData(policyID: string, accountIDs: number[] if (announceReport?.participantAccountIDs) { // Everyone in special policy rooms is visible const participantAccountIDs = [...announceReport.participantAccountIDs, ...accountIDs]; + const pendingAccountIDs = accountIDs.map((accountID) => { + return { + accountID: accountID.toString(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }; + }); + const pendingVisibleChatMembers = [...(announceReport?.pendingVisibleChatMembers || []), ...pendingAccountIDs]; announceRoomMembers.onyxOptimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -321,6 +330,7 @@ function buildAnnounceRoomMembersOnyxData(policyID: string, accountIDs: number[] value: { participantAccountIDs, visibleChatMemberAccountIDs: participantAccountIDs, + pendingVisibleChatMembers, }, }); } @@ -331,6 +341,14 @@ function buildAnnounceRoomMembersOnyxData(policyID: string, accountIDs: number[] value: { participantAccountIDs: announceReport?.participantAccountIDs, visibleChatMemberAccountIDs: announceReport?.visibleChatMemberAccountIDs, + pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers, + }, + }); + announceRoomMembers.onyxSuccessData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${announceReport?.reportID}`, + value: { + pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers, }, }); return announceRoomMembers; @@ -344,6 +362,7 @@ function removeOptimisticAnnounceRoomMembers(policyID: string, accountIDs: numbe const announceRoomMembers: AnnounceRoomMembersOnyxData = { onyxOptimisticData: [], onyxFailureData: [], + onyxSuccessData: [], }; if (!announceReport) { @@ -352,12 +371,21 @@ function removeOptimisticAnnounceRoomMembers(policyID: string, accountIDs: numbe if (announceReport?.participantAccountIDs) { const remainUsers = announceReport.participantAccountIDs.filter((e) => !accountIDs.includes(e)); + const pendingAccountIDs = accountIDs.map((accountID) => { + return { + accountID: accountID.toString(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + }; + }); + const pendingVisibleChatMembers = [...(announceReport?.pendingVisibleChatMembers || []), ...pendingAccountIDs]; + announceRoomMembers.onyxOptimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${announceReport.reportID}`, value: { participantAccountIDs: [...remainUsers], visibleChatMemberAccountIDs: [...remainUsers], + pendingVisibleChatMembers, }, }); @@ -367,6 +395,14 @@ function removeOptimisticAnnounceRoomMembers(policyID: string, accountIDs: numbe value: { participantAccountIDs: announceReport.participantAccountIDs, visibleChatMemberAccountIDs: announceReport.visibleChatMemberAccountIDs, + pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers, + }, + }); + announceRoomMembers.onyxSuccessData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${announceReport.reportID}`, + value: { + pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers, }, }); } diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 36ac445a78d4..bd302e4be446 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -34,7 +34,7 @@ import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type {PersonalDetails, PersonalDetailsList, ReportActionReactions, ReportUserIsTyping} from '@src/types/onyx'; import type {Decision, OriginalMessageIOU} from '@src/types/onyx/OriginalMessage'; -import type {NotificationPreference, WriteCapability} from '@src/types/onyx/Report'; +import type {NotificationPreference, PendingChatMember, WriteCapability} from '@src/types/onyx/Report'; import type Report from '@src/types/onyx/Report'; import type {Message, ReportActionBase, ReportActions} from '@src/types/onyx/ReportAction'; import type ReportAction from '@src/types/onyx/ReportAction'; @@ -2202,6 +2202,13 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin)); const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, inviteeAccountIDs); + const pendingAccountIDs = inviteeAccountIDs.map((accountID) => { + return { + accountID: accountID.toString(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }; + }); + const pendingVisibleChatMembers = [...(report?.pendingVisibleChatMembers || []), ...pendingAccountIDs]; const optimisticData: OnyxUpdate[] = [ { @@ -2210,13 +2217,22 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record !targetAccountIDs.includes(id)); const visibleChatMemberAccountIDsAfterRemoval = report?.visibleChatMemberAccountIDs?.filter((id: number) => !targetAccountIDs.includes(id)); + const pendingAccountIDs = targetAccountIDs.map((accountID) => { + return { + accountID: accountID.toString(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + }; + }); + const pendingVisibleChatMembers = [...(report?.pendingVisibleChatMembers || []), ...pendingAccountIDs]; const optimisticData: OnyxUpdate[] = [ { @@ -2256,6 +2280,7 @@ function removeFromRoom(reportID: string, targetAccountIDs: number[]) { value: { participantAccountIDs: participantAccountIDsAfterRemoval, visibleChatMemberAccountIDs: visibleChatMemberAccountIDsAfterRemoval, + pendingVisibleChatMembers, }, }, ]; @@ -2267,6 +2292,7 @@ function removeFromRoom(reportID: string, targetAccountIDs: number[]) { value: { participantAccountIDs: report?.participantAccountIDs, visibleChatMemberAccountIDs: report?.visibleChatMemberAccountIDs, + pendingVisibleChatMembers: report?.pendingVisibleChatMembers, }, }, ]; @@ -2280,6 +2306,7 @@ function removeFromRoom(reportID: string, targetAccountIDs: number[]) { value: { participantAccountIDs: participantAccountIDsAfterRemoval, visibleChatMemberAccountIDs: visibleChatMemberAccountIDsAfterRemoval, + pendingVisibleChatMembers: report?.pendingVisibleChatMembers, }, }, ]; diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index 7dbc1c7036c4..e4239fe422a0 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -62,8 +62,10 @@ const getAllParticipants = (report, personalDetails, translate) => const userLogin = LocalePhoneNumber.formatPhoneNumber(userPersonalDetail.login || '') || translate('common.hidden'); const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail); + const pendingVisibleChatMember = _.find(report.pendingVisibleChatMemberAccountIDs, (member) => member.accountID === accountID); return { alternateText: userLogin, + pendingAction: pendingVisibleChatMember.pendingAction || null, displayName, accountID: userPersonalDetail.accountID, icons: [ diff --git a/src/pages/RoomMembersPage.js b/src/pages/RoomMembersPage.js index 30ffd60aa4ac..f4a89fd0fa79 100644 --- a/src/pages/RoomMembersPage.js +++ b/src/pages/RoomMembersPage.js @@ -205,6 +205,7 @@ function RoomMembersPage(props) { return; } } + const pendingVisibleChatMember = _.find(props.report.pendingVisibleChatMemberAccountIDs, (member) => member.accountID === accountID); result.push({ keyForList: String(accountID), @@ -220,6 +221,7 @@ function RoomMembersPage(props) { type: CONST.ICON_TYPE_AVATAR, }, ], + pendingAction: pendingVisibleChatMember.pendingAction || null, }); }); diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index 5a22313a3f48..a8b8bf0f4a76 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -13,6 +13,11 @@ type Note = { pendingAction?: OnyxCommon.PendingAction; }; +type PendingChatMember = { + accountID: string; + pendingAction: OnyxCommon.PendingAction; +}; + type Report = { /** The specific type of chat */ chatType?: ValueOf; @@ -161,8 +166,11 @@ type Report = { /** If the report contains reportFields, save the field id and its value */ reportFields?: Record; + + /** Pending member of the report */ + pendingVisibleChatMembers: PendingChatMember[]; }; export default Report; -export type {NotificationPreference, WriteCapability, Note}; +export type {NotificationPreference, WriteCapability, Note, PendingChatMember}; From cdc42c52973f46cedb943bd77753998eadb22697 Mon Sep 17 00:00:00 2001 From: Dylan Date: Tue, 6 Feb 2024 16:19:18 +0700 Subject: [PATCH 011/145] optional --- src/types/onyx/Report.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index 36c39d52f28f..bd7a517226d0 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -181,7 +181,7 @@ type Report = { reportFields?: Record; /** Pending member of the report */ - pendingVisibleChatMembers: PendingChatMember[]; + pendingVisibleChatMembers?: PendingChatMember[]; }; export default Report; From 45aa3c57c8c9199e392740de949d28e5e695944e Mon Sep 17 00:00:00 2001 From: Dylan Date: Tue, 6 Feb 2024 16:30:27 +0700 Subject: [PATCH 012/145] fix type check --- src/pages/ReportParticipantsPage.tsx | 5 +++-- src/pages/RoomMembersPage.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pages/ReportParticipantsPage.tsx b/src/pages/ReportParticipantsPage.tsx index 56dc3e1204b2..37c21423a5f2 100755 --- a/src/pages/ReportParticipantsPage.tsx +++ b/src/pages/ReportParticipantsPage.tsx @@ -2,6 +2,7 @@ import React from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; +import lodashFind from 'lodash/find'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import OptionsList from '@components/OptionsList'; @@ -48,10 +49,10 @@ const getAllParticipants = ( const userLogin = LocalePhoneNumber.formatPhoneNumber(userPersonalDetail?.login ?? '') ?? translate('common.hidden'); const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail); - const pendingVisibleChatMember = _.find(report.pendingVisibleChatMemberAccountIDs, (member) => member.accountID === accountID); + const pendingVisibleChatMember = lodashFind(report?.pendingVisibleChatMembers, (member) => member.accountID === accountID.toString()); return { alternateText: userLogin, - pendingAction: pendingVisibleChatMember.pendingAction || null, + pendingAction: pendingVisibleChatMember?.pendingAction || undefined, displayName, accountID: userPersonalDetail?.accountID ?? accountID, icons: [ diff --git a/src/pages/RoomMembersPage.js b/src/pages/RoomMembersPage.js index f4a89fd0fa79..14df38dc0410 100644 --- a/src/pages/RoomMembersPage.js +++ b/src/pages/RoomMembersPage.js @@ -205,7 +205,7 @@ function RoomMembersPage(props) { return; } } - const pendingVisibleChatMember = _.find(props.report.pendingVisibleChatMemberAccountIDs, (member) => member.accountID === accountID); + const pendingVisibleChatMember = _.find(props.report.pendingVisibleChatMembers, (member) => member.accountID === accountID); result.push({ keyForList: String(accountID), @@ -221,7 +221,7 @@ function RoomMembersPage(props) { type: CONST.ICON_TYPE_AVATAR, }, ], - pendingAction: pendingVisibleChatMember.pendingAction || null, + pendingAction: pendingVisibleChatMember.pendingAction || undefined, }); }); From 26b612fe5a79a7298093f1b17d47fd2d0b741399 Mon Sep 17 00:00:00 2001 From: Dylan Date: Tue, 6 Feb 2024 17:00:55 +0700 Subject: [PATCH 013/145] fix type check --- src/libs/actions/Policy.ts | 21 +++++++-------------- src/libs/actions/Report.ts | 20 +++++--------------- src/pages/ReportParticipantsPage.tsx | 6 +++--- 3 files changed, 15 insertions(+), 32 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 6d8e729d7825..f4b198711759 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -329,13 +329,8 @@ function buildAnnounceRoomMembersOnyxData(policyID: string, accountIDs: number[] if (announceReport?.participantAccountIDs) { // Everyone in special policy rooms is visible const participantAccountIDs = [...announceReport.participantAccountIDs, ...accountIDs]; - const pendingAccountIDs = accountIDs.map((accountID) => { - return { - accountID: accountID.toString(), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }; - }); - const pendingVisibleChatMembers = [...(announceReport?.pendingVisibleChatMembers || []), ...pendingAccountIDs]; + const pendingAccountIDs = accountIDs.map((accountID) => ({accountID: accountID.toString(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD})); + const pendingVisibleChatMembers = [...(announceReport?.pendingVisibleChatMembers ?? []), ...pendingAccountIDs]; announceRoomMembers.onyxOptimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -384,13 +379,11 @@ function removeOptimisticAnnounceRoomMembers(policyID: string, accountIDs: numbe if (announceReport?.participantAccountIDs) { const remainUsers = announceReport.participantAccountIDs.filter((e) => !accountIDs.includes(e)); - const pendingAccountIDs = accountIDs.map((accountID) => { - return { - accountID: accountID.toString(), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - }; - }); - const pendingVisibleChatMembers = [...(announceReport?.pendingVisibleChatMembers || []), ...pendingAccountIDs]; + const pendingAccountIDs = accountIDs.map((accountID) => ({ + accountID: accountID.toString(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + })); + const pendingVisibleChatMembers = [...(announceReport?.pendingVisibleChatMembers ?? []), ...pendingAccountIDs]; announceRoomMembers.onyxOptimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index a44fe1e81a84..f1c7e13bcd07 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -68,7 +68,7 @@ import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type {PersonalDetails, PersonalDetailsList, PolicyReportField, RecentlyUsedReportFields, ReportActionReactions, ReportMetadata, ReportUserIsTyping} from '@src/types/onyx'; import type {Decision, OriginalMessageIOU} from '@src/types/onyx/OriginalMessage'; -import type {NotificationPreference, PendingChatMember, WriteCapability} from '@src/types/onyx/Report'; +import type {NotificationPreference, WriteCapability} from '@src/types/onyx/Report'; import type Report from '@src/types/onyx/Report'; import type {Message, ReportActionBase, ReportActions} from '@src/types/onyx/ReportAction'; import type ReportAction from '@src/types/onyx/ReportAction'; @@ -2308,13 +2308,8 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin)); const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, inviteeAccountIDs); - const pendingAccountIDs = inviteeAccountIDs.map((accountID) => { - return { - accountID: accountID.toString(), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }; - }); - const pendingVisibleChatMembers = [...(report?.pendingVisibleChatMembers || []), ...pendingAccountIDs]; + const pendingAccountIDs = inviteeAccountIDs.map((accountID) => ({accountID: accountID.toString(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD})); + const pendingVisibleChatMembers = [...(report?.pendingVisibleChatMembers ?? []), ...pendingAccountIDs]; const optimisticData: OnyxUpdate[] = [ { @@ -2366,13 +2361,8 @@ function removeFromRoom(reportID: string, targetAccountIDs: number[]) { const participantAccountIDsAfterRemoval = report?.participantAccountIDs?.filter((id: number) => !targetAccountIDs.includes(id)); const visibleChatMemberAccountIDsAfterRemoval = report?.visibleChatMemberAccountIDs?.filter((id: number) => !targetAccountIDs.includes(id)); - const pendingAccountIDs = targetAccountIDs.map((accountID) => { - return { - accountID: accountID.toString(), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - }; - }); - const pendingVisibleChatMembers = [...(report?.pendingVisibleChatMembers || []), ...pendingAccountIDs]; + const pendingAccountIDs = targetAccountIDs.map((accountID) => ({accountID: accountID.toString(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE})); + const pendingVisibleChatMembers = [...(report?.pendingVisibleChatMembers ?? []), ...pendingAccountIDs]; const optimisticData: OnyxUpdate[] = [ { diff --git a/src/pages/ReportParticipantsPage.tsx b/src/pages/ReportParticipantsPage.tsx index 37c21423a5f2..87e658694cdf 100755 --- a/src/pages/ReportParticipantsPage.tsx +++ b/src/pages/ReportParticipantsPage.tsx @@ -1,8 +1,8 @@ +import lodashFind from 'lodash/find'; import React from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import lodashFind from 'lodash/find'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import OptionsList from '@components/OptionsList'; @@ -49,10 +49,10 @@ const getAllParticipants = ( const userLogin = LocalePhoneNumber.formatPhoneNumber(userPersonalDetail?.login ?? '') ?? translate('common.hidden'); const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail); - const pendingVisibleChatMember = lodashFind(report?.pendingVisibleChatMembers, (member) => member.accountID === accountID.toString()); + const pendingVisibleChatMember = (report?.pendingVisibleChatMembers ?? []).find((member) => member.accountID === accountID.toString()); return { alternateText: userLogin, - pendingAction: pendingVisibleChatMember?.pendingAction || undefined, + pendingAction: pendingVisibleChatMember?.pendingAction, displayName, accountID: userPersonalDetail?.accountID ?? accountID, icons: [ From f61c018c08c455a0e59e0de82164808077737681 Mon Sep 17 00:00:00 2001 From: Dylan Date: Tue, 6 Feb 2024 17:06:01 +0700 Subject: [PATCH 014/145] fix type check --- src/pages/ReportParticipantsPage.tsx | 1 - src/pages/RoomMembersPage.js | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/ReportParticipantsPage.tsx b/src/pages/ReportParticipantsPage.tsx index 87e658694cdf..434757d00da4 100755 --- a/src/pages/ReportParticipantsPage.tsx +++ b/src/pages/ReportParticipantsPage.tsx @@ -1,4 +1,3 @@ -import lodashFind from 'lodash/find'; import React from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; diff --git a/src/pages/RoomMembersPage.js b/src/pages/RoomMembersPage.js index 14df38dc0410..26407cf6e9fc 100644 --- a/src/pages/RoomMembersPage.js +++ b/src/pages/RoomMembersPage.js @@ -3,6 +3,7 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; +import lodashGet from 'lodash/get'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import Button from '@components/Button'; import ConfirmModal from '@components/ConfirmModal'; @@ -221,7 +222,7 @@ function RoomMembersPage(props) { type: CONST.ICON_TYPE_AVATAR, }, ], - pendingAction: pendingVisibleChatMember.pendingAction || undefined, + pendingAction: lodashGet(pendingVisibleChatMember, 'pendingAction', undefined) }); }); From 952005b7249ab81c140beb88da872839f3b7b695 Mon Sep 17 00:00:00 2001 From: Dylan Date: Tue, 6 Feb 2024 17:23:33 +0700 Subject: [PATCH 015/145] fix lint --- src/pages/RoomMembersPage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/RoomMembersPage.js b/src/pages/RoomMembersPage.js index 26407cf6e9fc..6dec2b410001 100644 --- a/src/pages/RoomMembersPage.js +++ b/src/pages/RoomMembersPage.js @@ -1,9 +1,9 @@ +import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; -import lodashGet from 'lodash/get'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import Button from '@components/Button'; import ConfirmModal from '@components/ConfirmModal'; @@ -206,7 +206,7 @@ function RoomMembersPage(props) { return; } } - const pendingVisibleChatMember = _.find(props.report.pendingVisibleChatMembers, (member) => member.accountID === accountID); + const pendingVisibleChatMember = _.find(props.report.pendingVisibleChatMembers, (member) => member.accountID === accountID.toString()); result.push({ keyForList: String(accountID), @@ -222,7 +222,7 @@ function RoomMembersPage(props) { type: CONST.ICON_TYPE_AVATAR, }, ], - pendingAction: lodashGet(pendingVisibleChatMember, 'pendingAction', undefined) + pendingAction: lodashGet(pendingVisibleChatMember, 'pendingAction', undefined), }); }); From 76a2811093232bb11402d650b96bb473f805be01 Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 6 Feb 2024 23:24:41 +0700 Subject: [PATCH 016/145] create util function --- src/components/LocalePicker.tsx | 3 ++- src/libs/FormUtils.ts | 7 ++++++- src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index 8022efd211b0..17520a467d3c 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -4,6 +4,7 @@ import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import FormUtils from '@libs/FormUtils'; import * as App from '@userActions/App'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -34,7 +35,7 @@ function LocalePicker({account, preferredLocale = CONST.LOCALES.DEFAULT, size = keyForList: language, isSelected: preferredLocale === language, })); - const shouldDisablePicker = account?.isLoading && account.loadingForm === (account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); + const shouldDisablePicker = FormUtils.isValidateCodeFormSubmitting(account ?? {}); return ( + account.isLoading && account.loadingForm === (account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); function getDraftKey(formID: OnyxFormKeyWithoutDraft): `${OnyxFormKeyWithoutDraft}Draft` { return `${formID}Draft`; } -export default {getDraftKey}; +export default {getDraftKey, isValidateCodeFormSubmitting}; diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js index fd5e9b952612..b1423555ee7d 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js @@ -22,6 +22,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; import compose from '@libs/compose'; import * as ErrorUtils from '@libs/ErrorUtils'; +import FormUtils from '@libs/FormUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; import ChangeExpensifyLoginLink from '@pages/signin/ChangeExpensifyLoginLink'; import Terms from '@pages/signin/Terms'; @@ -105,8 +106,7 @@ function BaseValidateCodeForm(props) { const hasError = Boolean(props.account) && !_.isEmpty(props.account.errors) && !needToClearError; const isLoadingResendValidationForm = props.account.loadingForm === CONST.FORMS.RESEND_VALIDATE_CODE_FORM; const shouldDisableResendValidateCode = props.network.isOffline || props.account.isLoading; - const isValidateCodeFormSubmitting = - props.account.isLoading && props.account.loadingForm === (props.account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); + const isValidateCodeFormSubmitting = FormUtils.isValidateCodeFormSubmitting(props.account); useEffect(() => { if (!(inputValidateCodeRef.current && hasError && (props.session.autoAuthState === CONST.AUTO_AUTH_STATE.FAILED || props.account.isLoading))) { From 0ddffd142089c5a13e78fd6ad5257a18f7a7ca1d Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 7 Feb 2024 00:31:50 +0700 Subject: [PATCH 017/145] =?UTF-8?q?fix:=20Approving=20a=20report=20causes?= =?UTF-8?q?=20the=20workspace=20chat=20to=20=E2=80=9Cflash=E2=80=9D=20in?= =?UTF-8?q?=20the=20LHN=20before=20disappearing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/actions/IOU.ts | 60 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index a7a82e642e62..f46451d810bf 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -3253,8 +3253,49 @@ function sendMoneyWithWallet(report: OnyxTypes.Report, amount: number, currency: Report.notifyNewAction(params.chatReportID, managerID); } +function shouldShowSettlementButton(iouReportID: string, isPaidGroupPolicy: boolean, isPolicyExpenseChat: boolean, iouCanceled: boolean) { + const iouReport = ReportUtils.getReport(iouReportID) as OnyxTypes.Report; + const isApproved = ReportUtils.isReportApproved(iouReport); + const policy = ReportUtils.getPolicy(iouReport.policyID); + const policyType = policy?.type; + const isPolicyAdmin = policyType !== CONST.POLICY.TYPE.PERSONAL && policy?.role === CONST.POLICY.ROLE.ADMIN; + const managerID = iouReport?.managerID ?? 0; + const isCurrentUserManager = managerID === userAccountID; + const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(iouReport); + + const isPayer = isPaidGroupPolicy + ? // In a paid group policy, the admin approver can pay the report directly by skipping the approval step + isPolicyAdmin && (isApproved || isCurrentUserManager) + : isPolicyAdmin || (isMoneyRequestReport && isCurrentUserManager); + + const isDraftExpenseReport = isPolicyExpenseChat && ReportUtils.isDraftExpenseReport(iouReport); + const iouSettled = ReportUtils.isSettled(iouReport.reportID); + const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(iouReport); + const isAutoReimbursable = ReportUtils.canBeAutoReimbursed(iouReport, policy as OnyxEntry); + + const shouldShowPayButton = isPayer && !isDraftExpenseReport && !iouSettled && !iouReport?.isWaitingOnBankAccount && reimbursableSpend !== 0 && !iouCanceled && !isAutoReimbursable; + + const shouldShowApproveButton = isPaidGroupPolicy && isCurrentUserManager && !isDraftExpenseReport && !isApproved && !iouSettled; + + return shouldShowPayButton || shouldShowApproveButton; +} + +function hasIOUToApproveOrPay(chatReport: OnyxEntry, excludedIOUReportID: string): boolean { + const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(chatReport); + const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(chatReport); + const iouCanceled = ReportUtils.isArchivedRoom(chatReport); + const chatReportActions = ReportActionsUtils.getAllReportActions(chatReport?.reportID ?? ''); + return !!Object.values(chatReportActions).find( + (action) => + action.childReportID?.toString() !== excludedIOUReportID && + action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW && + shouldShowSettlementButton(action.childReportID ?? '', isPaidGroupPolicy, isPolicyExpenseChat, iouCanceled), + ); +} + function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject) { const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`] ?? null; + const chatReport = ReportUtils.getReport(expenseReport.chatReportID) as OnyxEntry; const optimisticApprovedReportAction = ReportUtils.buildOptimisticApprovedReportAction(expenseReport.total ?? 0, expenseReport.currency ?? '', expenseReport.reportID); @@ -3279,7 +3320,16 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject) { statusNum: CONST.REPORT.STATUS_NUM.APPROVED, }, }; - const optimisticData: OnyxUpdate[] = [optimisticIOUReportData, optimisticReportActionsData]; + + const optimisticChatReportData: OnyxUpdate = { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.chatReportID}`, + value: { + hasOutstandingChildRequest: hasIOUToApproveOrPay(chatReport, expenseReport.reportID), + }, + }; + + const optimisticData: OnyxUpdate[] = [optimisticIOUReportData, optimisticReportActionsData, optimisticChatReportData]; const successData: OnyxUpdate[] = [ { @@ -3303,6 +3353,13 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject) { }, }, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.chatReportID}`, + value: { + hasOutstandingChildRequest: chatReport?.hasOutstandingChildRequest, + }, + }, ]; if (currentNextStep) { @@ -3727,4 +3784,5 @@ export { editMoneyRequest, navigateToStartStepIfScanFileCannotBeRead, savePreferredPaymentMethod, + shouldShowSettlementButton, }; From 5a3120b07ee9c8236f1bdf8ea71deaec90af7f49 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 7 Feb 2024 17:59:27 +0700 Subject: [PATCH 018/145] fix add comment --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 19ae722237ff..54802f9fb6fb 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -477,6 +477,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ IOU.setMoneyRequestMerchant_temporaryForRefactor(transaction.transactionID, distanceMerchant); }, [hasRoute, distance, unit, rate, currency, translate, toLocaleDigit, isDistanceRequest, transaction]); + // Auto select the category if there is only one enabled category useEffect(() => { const enabledCategories = _.filter(policyCategories, (category) => category.enabled); if (iouCategory || !shouldShowCategories || enabledCategories.length !== 1) { @@ -485,6 +486,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ IOU.setMoneyRequestCategory_temporaryForRefactor(transaction.transactionID, enabledCategories[0].name); }, [iouCategory, shouldShowCategories, policyCategories, transaction]); + // Auto select the tag if there is only one enabled tag useEffect(() => { const enabledTags = _.filter(policyTagList, (tag) => tag.enabled); if (iouTag || !shouldShowTags || enabledTags.length !== 1) { From 21c0c56ec6f6eda7c4111e3af1d19d688807e82b Mon Sep 17 00:00:00 2001 From: Dylan Date: Fri, 9 Feb 2024 02:03:21 +0700 Subject: [PATCH 019/145] update pending member for workspace expense chat --- src/libs/actions/Policy.ts | 57 ++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index f4b198711759..4d0575c40ad8 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -451,6 +451,25 @@ function removeMembers(accountIDs: number[], policyID: string) { ...announceRoomMembers.onyxOptimisticData, ]; + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: membersListKey, + value: successMembersState, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: membersListKey, + value: failureMembersState, + }, + ...announceRoomMembers.onyxFailureData, + ]; + + const pendingVisibleChatMembers = accountIDs.map((accountID) => ({accountID: accountID.toString(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD})); + workspaceChats.forEach((report) => { optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -460,6 +479,21 @@ function removeMembers(accountIDs: number[], policyID: string) { stateNum: CONST.REPORT.STATE_NUM.APPROVED, oldPolicyName: policy.name, hasDraft: false, + pendingVisibleChatMembers, + }, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${report?.reportID}`, + value: { + pendingVisibleChatMembers: null, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${report?.reportID}`, + value: { + pendingVisibleChatMembers: null, }, }); }); @@ -496,23 +530,7 @@ function removeMembers(accountIDs: number[], policyID: string) { } } - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, - value: successMembersState, - }, - ]; - const filteredWorkspaceChats = workspaceChats.filter((report): report is Report => report !== null); - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: membersListKey, - value: failureMembersState, - }, - ...announceRoomMembers.onyxFailureData, - ]; filteredWorkspaceChats.forEach(({reportID, stateNum, statusNum, hasDraft, oldPolicyName = null}) => { failureData.push({ @@ -579,7 +597,10 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: R } const optimisticReport = ReportUtils.buildOptimisticChatReport([sessionAccountID, cleanAccountID], undefined, CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, policyID, cleanAccountID); const optimisticCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(login); - + const pendingVisibleChatMembers = Object.values(invitedEmailsToAccountIDs).map((accountID) => ({ + accountID: accountID.toString(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + })); workspaceMembersChats.reportCreationData[login] = { reportID: optimisticReport.reportID, reportActionID: optimisticCreatedAction.reportActionID, @@ -595,6 +616,7 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: R }, isOptimisticReport: true, hasOutstandingChildRequest, + pendingVisibleChatMembers, }, }); workspaceMembersChats.onyxOptimisticData.push({ @@ -614,6 +636,7 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: R createChat: null, }, isOptimisticReport: false, + pendingVisibleChatMembers: null, }, }); workspaceMembersChats.onyxSuccessData.push({ From c7bc82de25b3ff5cbd434223e23fd5c8dcce9287 Mon Sep 17 00:00:00 2001 From: Dylan Date: Fri, 9 Feb 2024 02:12:57 +0700 Subject: [PATCH 020/145] update --- src/libs/actions/Policy.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 4d0575c40ad8..8f0db9fbc9ac 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -597,10 +597,6 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: R } const optimisticReport = ReportUtils.buildOptimisticChatReport([sessionAccountID, cleanAccountID], undefined, CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, policyID, cleanAccountID); const optimisticCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(login); - const pendingVisibleChatMembers = Object.values(invitedEmailsToAccountIDs).map((accountID) => ({ - accountID: accountID.toString(), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - })); workspaceMembersChats.reportCreationData[login] = { reportID: optimisticReport.reportID, reportActionID: optimisticCreatedAction.reportActionID, @@ -616,7 +612,10 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: R }, isOptimisticReport: true, hasOutstandingChildRequest, - pendingVisibleChatMembers, + pendingVisibleChatMembers: [{ + accountID: accountID.toString(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }] }, }); workspaceMembersChats.onyxOptimisticData.push({ From 22199b731bfbb11d0171f089d0bd909ffe65c72c Mon Sep 17 00:00:00 2001 From: Dylan Date: Fri, 9 Feb 2024 02:56:41 +0700 Subject: [PATCH 021/145] fix lint --- src/libs/actions/Policy.ts | 21 ++++++++++++--------- src/libs/actions/Report.ts | 8 ++++---- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 8f0db9fbc9ac..74311cc1b6fa 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -349,14 +349,14 @@ function buildAnnounceRoomMembersOnyxData(policyID: string, accountIDs: number[] value: { participantAccountIDs: announceReport?.participantAccountIDs, visibleChatMemberAccountIDs: announceReport?.visibleChatMemberAccountIDs, - pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers, + pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers ?? null, }, }); announceRoomMembers.onyxSuccessData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${announceReport?.reportID}`, value: { - pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers, + pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers ?? null, }, }); return announceRoomMembers; @@ -401,14 +401,14 @@ function removeOptimisticAnnounceRoomMembers(policyID: string, accountIDs: numbe value: { participantAccountIDs: announceReport.participantAccountIDs, visibleChatMemberAccountIDs: announceReport.visibleChatMemberAccountIDs, - pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers, + pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers ?? null, }, }); announceRoomMembers.onyxSuccessData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${announceReport.reportID}`, value: { - pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers, + pendingVisibleChatMembers: announceReport?.pendingVisibleChatMembers ?? null, }, }); } @@ -457,6 +457,7 @@ function removeMembers(accountIDs: number[], policyID: string) { key: membersListKey, value: successMembersState, }, + ...announceRoomMembers.onyxSuccessData, ]; const failureData: OnyxUpdate[] = [ @@ -612,10 +613,12 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: R }, isOptimisticReport: true, hasOutstandingChildRequest, - pendingVisibleChatMembers: [{ - accountID: accountID.toString(), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }] + pendingVisibleChatMembers: [ + { + accountID: accountID.toString(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + ], }, }); workspaceMembersChats.onyxOptimisticData.push({ @@ -666,7 +669,6 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: Record const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, accountIDs); const announceRoomMembers = buildAnnounceRoomMembersOnyxData(policyID, accountIDs); - // create onyx data for policy expense chats for each new member const membersChats = createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs); @@ -712,6 +714,7 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: Record }, ...newPersonalDetailsOnyxData.finallyData, ...membersChats.onyxSuccessData, + ...announceRoomMembers.onyxSuccessData, ]; const failureData: OnyxUpdate[] = [ diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index f1c7e13bcd07..dd9b9b99894a 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2329,7 +2329,7 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record Date: Sat, 10 Feb 2024 19:37:38 +0700 Subject: [PATCH 022/145] dry code --- src/libs/ReportUtils.ts | 8 +++++++- src/libs/actions/Policy.ts | 11 +++-------- src/libs/actions/Report.ts | 6 ++---- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 965ee5d8433b..9324ca75c3a8 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -33,7 +33,7 @@ import type {Participant} from '@src/types/onyx/IOU'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; import type {ChangeLog, IOUMessage, OriginalMessageActionName, OriginalMessageCreated, PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type {Status} from '@src/types/onyx/PersonalDetails'; -import type {NotificationPreference} from '@src/types/onyx/Report'; +import type {NotificationPreference, PendingChatMember} from '@src/types/onyx/Report'; import type {Message, ReportActionBase, ReportActions} from '@src/types/onyx/ReportAction'; import type {Receipt, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; @@ -4768,6 +4768,11 @@ function canBeAutoReimbursed(report: OnyxEntry, policy: OnyxEntry ({accountID: accountID.toString(), pendingAction})); + return [...previousPendingVisibleChatMembers, ...pendingVisibleChatMembers]; +} + export { getReportParticipantsTitle, isReportMessageAttachment, @@ -4959,6 +4964,7 @@ export { isReportFieldDisabled, getAvailableReportFields, getAllAncestorReportActionIDs, + getPendingVisibleChatMembers }; export type { diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 74311cc1b6fa..91e9ef436e5b 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -329,8 +329,7 @@ function buildAnnounceRoomMembersOnyxData(policyID: string, accountIDs: number[] if (announceReport?.participantAccountIDs) { // Everyone in special policy rooms is visible const participantAccountIDs = [...announceReport.participantAccountIDs, ...accountIDs]; - const pendingAccountIDs = accountIDs.map((accountID) => ({accountID: accountID.toString(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD})); - const pendingVisibleChatMembers = [...(announceReport?.pendingVisibleChatMembers ?? []), ...pendingAccountIDs]; + const pendingVisibleChatMembers = ReportUtils.getPendingVisibleChatMembers(accountIDs, announceReport?.pendingVisibleChatMembers ?? [], CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); announceRoomMembers.onyxOptimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -379,11 +378,7 @@ function removeOptimisticAnnounceRoomMembers(policyID: string, accountIDs: numbe if (announceReport?.participantAccountIDs) { const remainUsers = announceReport.participantAccountIDs.filter((e) => !accountIDs.includes(e)); - const pendingAccountIDs = accountIDs.map((accountID) => ({ - accountID: accountID.toString(), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - })); - const pendingVisibleChatMembers = [...(announceReport?.pendingVisibleChatMembers ?? []), ...pendingAccountIDs]; + const pendingVisibleChatMembers = ReportUtils.getPendingVisibleChatMembers(accountIDs, announceReport?.pendingVisibleChatMembers ?? [], CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); announceRoomMembers.onyxOptimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -469,7 +464,7 @@ function removeMembers(accountIDs: number[], policyID: string) { ...announceRoomMembers.onyxFailureData, ]; - const pendingVisibleChatMembers = accountIDs.map((accountID) => ({accountID: accountID.toString(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD})); + const pendingVisibleChatMembers = ReportUtils.getPendingVisibleChatMembers(accountIDs, [], CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); workspaceChats.forEach((report) => { optimisticData.push({ diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index dd9b9b99894a..da0f89408f47 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2308,8 +2308,7 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: Record OptionsListUtils.addSMSDomainIfPhoneNumber(memberLogin)); const newPersonalDetailsOnyxData = PersonalDetailsUtils.getNewPersonalDetailsOnyxData(logins, inviteeAccountIDs); - const pendingAccountIDs = inviteeAccountIDs.map((accountID) => ({accountID: accountID.toString(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD})); - const pendingVisibleChatMembers = [...(report?.pendingVisibleChatMembers ?? []), ...pendingAccountIDs]; + const pendingVisibleChatMembers = ReportUtils.getPendingVisibleChatMembers(inviteeAccountIDs, report?.pendingVisibleChatMembers ?? [], CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); const optimisticData: OnyxUpdate[] = [ { @@ -2361,8 +2360,7 @@ function removeFromRoom(reportID: string, targetAccountIDs: number[]) { const participantAccountIDsAfterRemoval = report?.participantAccountIDs?.filter((id: number) => !targetAccountIDs.includes(id)); const visibleChatMemberAccountIDsAfterRemoval = report?.visibleChatMemberAccountIDs?.filter((id: number) => !targetAccountIDs.includes(id)); - const pendingAccountIDs = targetAccountIDs.map((accountID) => ({accountID: accountID.toString(), pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE})); - const pendingVisibleChatMembers = [...(report?.pendingVisibleChatMembers ?? []), ...pendingAccountIDs]; + const pendingVisibleChatMembers = ReportUtils.getPendingVisibleChatMembers(targetAccountIDs, report?.pendingVisibleChatMembers ?? [], CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); const optimisticData: OnyxUpdate[] = [ { From 58a58e452524945973d6d9c5f5b2481f8b632d6d Mon Sep 17 00:00:00 2001 From: Dylan Date: Sat, 10 Feb 2024 20:04:22 +0700 Subject: [PATCH 023/145] lint fix --- 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 9324ca75c3a8..7508a2641fc3 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4964,7 +4964,7 @@ export { isReportFieldDisabled, getAvailableReportFields, getAllAncestorReportActionIDs, - getPendingVisibleChatMembers + getPendingVisibleChatMembers, }; export type { From 7356236c4c40468f3c677c8dae81d1fcd3e0f374 Mon Sep 17 00:00:00 2001 From: Dylan Date: Mon, 12 Feb 2024 09:05:31 +0700 Subject: [PATCH 024/145] add comment --- src/libs/ReportUtils.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7508a2641fc3..64e1eb9bbbd9 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4768,6 +4768,9 @@ function canBeAutoReimbursed(report: OnyxEntry, policy: OnyxEntry ({accountID: accountID.toString(), pendingAction})); return [...previousPendingVisibleChatMembers, ...pendingVisibleChatMembers]; From a13c201269ee29e91c41190829f4898fce70f123 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 12 Feb 2024 14:22:32 +0100 Subject: [PATCH 025/145] migrate logger to typescript --- tests/e2e/utils/logger.ts | 102 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 tests/e2e/utils/logger.ts diff --git a/tests/e2e/utils/logger.ts b/tests/e2e/utils/logger.ts new file mode 100644 index 000000000000..73f1228fc730 --- /dev/null +++ b/tests/e2e/utils/logger.ts @@ -0,0 +1,102 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import {LOG_FILE} from '../config'; + +let isVerbose = true; +const setLogLevelVerbose = (value: boolean) => { + isVerbose = value; +}; + +// On CI systems when using .progressInfo, the current line won't reset but a new line gets added +// Which can flood the logs. You can increase this rate to mitigate this effect. +const LOGGER_PROGRESS_REFRESH_RATE = process.env.LOGGER_PROGRESS_REFRESH_RATE ?? 250; +const COLOR_DIM = '\x1b[2m'; +const COLOR_RESET = '\x1b[0m'; +const COLOR_YELLOW = '\x1b[33m'; +const COLOR_RED = '\x1b[31m'; +const COLOR_BLUE = '\x1b[34m'; +const COLOR_GREEN = '\x1b[32m'; + +const log = (...args: string[]) => { + if (isVerbose) { + console.debug(...args); + } + + // Write to log file + if (!fs.existsSync(LOG_FILE)) { + // Check that the directory exists + const logDir = path.dirname(LOG_FILE); + if (!fs.existsSync(logDir)) { + fs.mkdirSync(logDir); + } + + fs.writeFileSync(LOG_FILE, ''); + } + const time = new Date(); + const timeStr = `${time.getHours()}:${time.getMinutes()}:${time.getSeconds()} ${time.getMilliseconds()}`; + fs.appendFileSync(LOG_FILE, `[${timeStr}] ${args.join(' ')}\n`); +}; + +const info = (...args: string[]) => { + log('> ', ...args); +}; + +const important = (...args: string[]) => { + const lines = [`🟦 ${COLOR_BLUE}`, ...args, `${COLOR_RESET}\n`]; + log(...lines); +}; + +const success = (...args: string[]) => { + const lines = [`🟦 ${COLOR_GREEN}`, ...args, `${COLOR_RESET}\n`]; + log(...lines); +}; + +const warn = (...args: string[]) => { + const lines = [`\n${COLOR_YELLOW}⚠️`, ...args, `${COLOR_RESET}\n`]; + log(...lines); +}; + +const note = (...args: string[]) => { + const lines = [`${COLOR_DIM}`, ...args, `${COLOR_RESET}\n`]; + log(...lines); +}; + +const error = (...args: string[]) => { + const lines = [`\n🔴 ${COLOR_RED}`, ...args, `${COLOR_RESET}\n`]; + log(...lines); +}; + +const progressInfo = (textParam: string) => { + let text = textParam || ''; + const getTexts = () => [`🕛 ${text}`, `🕔 ${text}`, `🕗 ${text}`, `🕙 ${text}`]; + log(textParam); + + const startTime = Date.now(); + let i = 0; + const timer = setInterval(() => { + process.stdout.write(`\r${getTexts()[i++]}`); + // eslint-disable-next-line no-bitwise + i &= 3; + }, Number(LOGGER_PROGRESS_REFRESH_RATE)); + + const getTimeText = () => { + const timeInSeconds = Math.round((Date.now() - startTime) / 1000).toFixed(0); + return `(${COLOR_DIM}took: ${timeInSeconds}s${COLOR_RESET})`; + }; + return { + updateText: (newText: string) => { + text = newText; + log(newText); + }, + done: () => { + clearInterval(timer); + success(`\r✅ ${text} ${getTimeText()}\n`); + }, + error: () => { + clearInterval(timer); + error(`\r❌ ${text} ${getTimeText()}\n`); + }, + }; +}; + +export {log, info, warn, note, error, success, important, progressInfo, setLogLevelVerbose}; From 01b3f8a710bb932930ed87b4f6c0f27d9b741592 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 12 Feb 2024 15:11:58 +0100 Subject: [PATCH 026/145] delete logger.js --- tests/e2e/utils/logger.js | 112 -------------------------------------- 1 file changed, 112 deletions(-) delete mode 100644 tests/e2e/utils/logger.js diff --git a/tests/e2e/utils/logger.js b/tests/e2e/utils/logger.js deleted file mode 100644 index 7da1e8330bfc..000000000000 --- a/tests/e2e/utils/logger.js +++ /dev/null @@ -1,112 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const {LOG_FILE} = require('../config'); - -let isVerbose = true; -const setLogLevelVerbose = (value) => { - isVerbose = value; -}; - -// On CI systems when using .progressInfo, the current line won't reset but a new line gets added -// Which can flood the logs. You can increase this rate to mitigate this effect. -const LOGGER_PROGRESS_REFRESH_RATE = process.env.LOGGER_PROGRESS_REFRESH_RATE || 250; -const COLOR_DIM = '\x1b[2m'; -const COLOR_RESET = '\x1b[0m'; -const COLOR_YELLOW = '\x1b[33m'; -const COLOR_RED = '\x1b[31m'; -const COLOR_BLUE = '\x1b[34m'; -const COLOR_GREEN = '\x1b[32m'; - -const log = (...args) => { - if (isVerbose) { - console.debug(...args); - } - - // Write to log file - if (!fs.existsSync(LOG_FILE)) { - // Check that the directory exists - const logDir = path.dirname(LOG_FILE); - if (!fs.existsSync(logDir)) { - fs.mkdirSync(logDir); - } - - fs.writeFileSync(LOG_FILE, ''); - } - const time = new Date(); - const timeStr = `${time.getHours()}:${time.getMinutes()}:${time.getSeconds()} ${time.getMilliseconds()}`; - fs.appendFileSync(LOG_FILE, `[${timeStr}] ${args.join(' ')}\n`); -}; - -const info = (...args) => { - log('> ', ...args); -}; - -const important = (...args) => { - const lines = [`🟦 ${COLOR_BLUE}`, ...args, `${COLOR_RESET}\n`]; - log(...lines); -}; - -const success = (...args) => { - const lines = [`🟦 ${COLOR_GREEN}`, ...args, `${COLOR_RESET}\n`]; - log(...lines); -}; - -const warn = (...args) => { - const lines = [`\n${COLOR_YELLOW}⚠️`, ...args, `${COLOR_RESET}\n`]; - log(...lines); -}; - -const note = (...args) => { - const lines = [`${COLOR_DIM}`, ...args, `${COLOR_RESET}\n`]; - log(...lines); -}; - -const error = (...args) => { - const lines = [`\n🔴 ${COLOR_RED}`, ...args, `${COLOR_RESET}\n`]; - log(...lines); -}; - -const progressInfo = (textParam) => { - let text = textParam || ''; - const getTexts = () => [`🕛 ${text}`, `🕔 ${text}`, `🕗 ${text}`, `🕙 ${text}`]; - log(textParam); - - const startTime = Date.now(); - let i = 0; - const timer = setInterval(() => { - process.stdout.write(`\r${getTexts()[i++]}`); - // eslint-disable-next-line no-bitwise - i &= 3; - }, Number(LOGGER_PROGRESS_REFRESH_RATE)); - - const getTimeText = () => { - const timeInSeconds = Math.round((Date.now() - startTime) / 1000).toFixed(0); - return `(${COLOR_DIM}took: ${timeInSeconds}s${COLOR_RESET})`; - }; - return { - updateText: (newText) => { - text = newText; - log(newText); - }, - done: () => { - clearInterval(timer); - success(`\r✅ ${text} ${getTimeText()}\n`); - }, - error: () => { - clearInterval(timer); - error(`\r❌ ${text} ${getTimeText()}\n`); - }, - }; -}; - -module.exports = { - log, - info, - warn, - note, - error, - success, - important, - progressInfo, - setLogLevelVerbose, -}; From 11800a4aa05605b191b461e6f07fc7a8475a1dde Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 14 Feb 2024 10:13:45 +0700 Subject: [PATCH 027/145] lint fix --- src/libs/actions/IOU.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index ff1de08e3ca0..24e423b3956c 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -3569,8 +3569,8 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject) { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`, value: currentNextStep, - }) - }; + }); + } const parameters: ApproveMoneyRequestParams = { reportID: expenseReport.reportID, From a96b14dd1184de68dc64b8a332b8b459fe444be4 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 14 Feb 2024 21:17:33 +0700 Subject: [PATCH 028/145] show notfound page --- src/pages/TransactionReceiptPage.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pages/TransactionReceiptPage.tsx b/src/pages/TransactionReceiptPage.tsx index 6f7d2e085740..4c02c1f0c309 100644 --- a/src/pages/TransactionReceiptPage.tsx +++ b/src/pages/TransactionReceiptPage.tsx @@ -15,16 +15,17 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Report, Transaction} from '@src/types/onyx'; +import type {Report, ReportMetadata, Transaction} from '@src/types/onyx'; type TransactionReceiptOnyxProps = { report: OnyxEntry; transaction: OnyxEntry; + reportMetadata: OnyxEntry; }; type TransactionReceiptProps = TransactionReceiptOnyxProps & StackScreenProps; -function TransactionReceipt({transaction, report, route}: TransactionReceiptProps) { +function TransactionReceipt({transaction, report, reportMetadata = {isLoadingInitialReportActions: true}, route}: TransactionReceiptProps) { const receiptURIs = ReceiptUtils.getThumbnailAndImageURIs(transaction); const imageSource = tryResolveUrlFromApiRoot(receiptURIs.image); @@ -57,7 +58,8 @@ function TransactionReceipt({transaction, report, route}: TransactionReceiptProp onModalClose={() => { Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report?.reportID ?? '')); }} - isLoading={!transaction || !report || report.parentReportID !== transaction.reportID} + isLoading={reportMetadata?.isLoadingInitialReportActions} + shouldShowNotFoundPage={(report?.parentReportID ?? '') !== transaction?.reportID} /> ); } @@ -71,4 +73,7 @@ export default withOnyx({ transaction: { key: ({route}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID ?? '0'}`, }, + reportMetadata: { + key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT_METADATA}${route.params.reportID ?? '0'}`, + }, })(TransactionReceipt); From b0ff3ca7e87574ba72dbcf5d32796bff1c86ad71 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 14 Feb 2024 22:14:31 +0700 Subject: [PATCH 029/145] Move to AccountUtils --- src/components/LocalePicker.tsx | 4 ++-- src/libs/AccountUtils.ts | 7 +++++++ src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 src/libs/AccountUtils.ts diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index 17520a467d3c..5753af9a2a5d 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -4,7 +4,7 @@ import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import FormUtils from '@libs/FormUtils'; +import * as AccountUtils from '@libs/AccountUtils'; import * as App from '@userActions/App'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -35,7 +35,7 @@ function LocalePicker({account, preferredLocale = CONST.LOCALES.DEFAULT, size = keyForList: language, isSelected: preferredLocale === language, })); - const shouldDisablePicker = FormUtils.isValidateCodeFormSubmitting(account ?? {}); + const shouldDisablePicker = AccountUtils.isValidateCodeFormSubmitting(account ?? {}); return ( + account.isLoading && account.loadingForm === (account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); + +export {isValidateCodeFormSubmitting}; diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js index f36720a68fe8..a2252f339ca7 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js @@ -19,10 +19,10 @@ import usePrevious from '@hooks/usePrevious'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as AccountUtils from '@libs/AccountUtils'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; import compose from '@libs/compose'; import * as ErrorUtils from '@libs/ErrorUtils'; -import FormUtils from '@libs/FormUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; import ChangeExpensifyLoginLink from '@pages/signin/ChangeExpensifyLoginLink'; import Terms from '@pages/signin/Terms'; @@ -106,7 +106,7 @@ function BaseValidateCodeForm(props) { const hasError = Boolean(props.account) && !_.isEmpty(props.account.errors) && !needToClearError; const isLoadingResendValidationForm = props.account.loadingForm === CONST.FORMS.RESEND_VALIDATE_CODE_FORM; const shouldDisableResendValidateCode = props.network.isOffline || props.account.isLoading; - const isValidateCodeFormSubmitting = FormUtils.isValidateCodeFormSubmitting(props.account); + const isValidateCodeFormSubmitting = AccountUtils.isValidateCodeFormSubmitting(props.account); useEffect(() => { if (!(inputValidateCodeRef.current && hasError && (props.session.autoAuthState === CONST.AUTO_AUTH_STATE.FAILED || props.account.isLoading))) { From 27f4dd0fd7f4969084a39d86c8467bdaa5d75130 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 14 Feb 2024 22:21:02 +0700 Subject: [PATCH 030/145] fix lint --- src/components/LocalePicker.tsx | 2 +- src/libs/AccountUtils.ts | 2 +- src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index 5753af9a2a5d..c411ac7a02c9 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -4,7 +4,7 @@ import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as AccountUtils from '@libs/AccountUtils'; +import AccountUtils from '@libs/AccountUtils'; import * as App from '@userActions/App'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; diff --git a/src/libs/AccountUtils.ts b/src/libs/AccountUtils.ts index 97ddf13f1ad5..96fb634e92d1 100644 --- a/src/libs/AccountUtils.ts +++ b/src/libs/AccountUtils.ts @@ -4,4 +4,4 @@ import type {Account} from '@src/types/onyx'; const isValidateCodeFormSubmitting = (account: Account) => account.isLoading && account.loadingForm === (account.requiresTwoFactorAuth ? CONST.FORMS.VALIDATE_TFA_CODE_FORM : CONST.FORMS.VALIDATE_CODE_FORM); -export {isValidateCodeFormSubmitting}; +export default {isValidateCodeFormSubmitting}; diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js index a2252f339ca7..e88ce68049ba 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.js @@ -19,7 +19,7 @@ import usePrevious from '@hooks/usePrevious'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as AccountUtils from '@libs/AccountUtils'; +import AccountUtils from '@libs/AccountUtils'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; import compose from '@libs/compose'; import * as ErrorUtils from '@libs/ErrorUtils'; From c127e19774a1776fb9ec019961c2ced95bd8939f Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Sat, 17 Feb 2024 21:27:09 +0100 Subject: [PATCH 031/145] Backwards Compatibility: Update UI for closed expense reports with no expenses --- src/components/MoneyReportHeader.tsx | 2 +- .../ReportActionItem/MoneyReportView.tsx | 172 +++++++++--------- src/languages/en.ts | 1 + src/languages/es.ts | 1 + src/libs/ReportUtils.ts | 21 +++ src/pages/home/report/ReportActionItem.js | 32 ++-- .../home/report/ReportActionItemSingle.tsx | 5 +- 7 files changed, 134 insertions(+), 100 deletions(-) diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 3f551da788f5..1fcb0421757c 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -92,7 +92,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton; const shouldShowSubmitButton = isDraft && reimbursableSpend !== 0; const isFromPaidPolicy = policyType === CONST.POLICY.TYPE.TEAM || policyType === CONST.POLICY.TYPE.CORPORATE; - const shouldShowNextStep = isFromPaidPolicy && !!nextStep?.message?.length; + const shouldShowNextStep = !ReportUtils.isClosedExpenseReportWithNoExpenses(moneyRequestReport) && isFromPaidPolicy && !!nextStep?.message?.length; const shouldShowAnyButton = shouldShowSettlementButton || shouldShowApproveButton || shouldShowSubmitButton || shouldShowNextStep; const bankAccountRoute = ReportUtils.getBankAccountRoute(chatReport); const formattedAmount = CurrencyUtils.convertToDisplayString(reimbursableSpend, moneyRequestReport.currency); diff --git a/src/components/ReportActionItem/MoneyReportView.tsx b/src/components/ReportActionItem/MoneyReportView.tsx index f0cd8dc1b4b5..d58a2c9f0224 100644 --- a/src/components/ReportActionItem/MoneyReportView.tsx +++ b/src/components/ReportActionItem/MoneyReportView.tsx @@ -67,107 +67,111 @@ function MoneyReportView({report, policy, policyReportFields, shouldShowHorizont - {ReportUtils.reportFieldsEnabled(report) && - sortedPolicyReportFields.map((reportField) => { - const isTitleField = ReportUtils.isReportFieldOfTypeTitle(reportField); - const fieldValue = isTitleField ? report.reportName : reportField.value ?? reportField.defaultValue; - const isFieldDisabled = ReportUtils.isReportFieldDisabled(report, reportField, policy); - - return ( - - Navigation.navigate(ROUTES.EDIT_REPORT_FIELD_REQUEST.getRoute(report.reportID, report.policyID ?? '', reportField.fieldID))} - shouldShowRightIcon - disabled={isFieldDisabled} - wrapperStyle={[styles.pv2, styles.taskDescriptionMenuItem]} - shouldGreyOutWhenDisabled={false} - numberOfLinesTitle={0} - interactive - shouldStackHorizontally={false} - onSecondaryInteraction={() => {}} - hoverAndPressStyle={false} - titleWithTooltips={[]} - /> - - ); - })} - - - - {translate('common.total')} - - - - {isSettled && ( - - - - )} - - {formattedTotalAmount} - - - - {Boolean(shouldShowBreakdown) && ( + {!ReportUtils.isClosedExpenseReportWithNoExpenses(report) && ( <> - - - - {translate('cardTransactions.outOfPocket')} - - - - - {formattedOutOfPocketAmount} - - - - + {ReportUtils.reportFieldsEnabled(report) && + sortedPolicyReportFields.map((reportField) => { + const isTitleField = ReportUtils.isReportFieldOfTypeTitle(reportField); + const fieldValue = isTitleField ? report.reportName : reportField.value ?? reportField.defaultValue; + const isFieldDisabled = ReportUtils.isReportFieldDisabled(report, reportField, policy); + + return ( + + Navigation.navigate(ROUTES.EDIT_REPORT_FIELD_REQUEST.getRoute(report.reportID, report.policyID ?? '', reportField.fieldID))} + shouldShowRightIcon + disabled={isFieldDisabled} + wrapperStyle={[styles.pv2, styles.taskDescriptionMenuItem]} + shouldGreyOutWhenDisabled={false} + numberOfLinesTitle={0} + interactive + shouldStackHorizontally={false} + onSecondaryInteraction={() => {}} + hoverAndPressStyle={false} + titleWithTooltips={[]} + /> + + ); + })} + - {translate('cardTransactions.companySpend')} + {translate('common.total')} + {isSettled && ( + + + + )} - {formattedCompanySpendAmount} + {formattedTotalAmount} + {Boolean(shouldShowBreakdown) && ( + <> + + + + {translate('cardTransactions.outOfPocket')} + + + + + {formattedOutOfPocketAmount} + + + + + + + {translate('cardTransactions.companySpend')} + + + + + {formattedCompanySpendAmount} + + + + + )} + )} - ); diff --git a/src/languages/en.ts b/src/languages/en.ts index 82aedf16aac5..dd5fbcbcbdad 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2126,6 +2126,7 @@ export default { viewAttachment: 'View attachment', }, parentReportAction: { + deletedReport: '[Deleted report]', deletedMessage: '[Deleted message]', deletedRequest: '[Deleted request]', reversedTransaction: '[Reversed transaction]', diff --git a/src/languages/es.ts b/src/languages/es.ts index 466ff1298200..9c760fbeff31 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2614,6 +2614,7 @@ export default { viewAttachment: 'Ver archivo adjunto', }, parentReportAction: { + deletedReport: '[Informe eliminado]', deletedMessage: '[Mensaje eliminado]', deletedRequest: '[Solicitud eliminada]', reversedTransaction: '[Transacción anulada]', diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 453de7219315..04af99bce51d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1063,6 +1063,13 @@ function findLastAccessedReport( return adminReport ?? sortedReports.at(-1) ?? null; } +/** + * Whether the provided report is a closed expense report with no expenses + */ +function isClosedExpenseReportWithNoExpenses(report: OnyxEntry): boolean { + return report?.statusNum === CONST.REPORT.STATUS_NUM.CLOSED && report?.stateNum === CONST.REPORT.STATE_NUM.OPEN; +} + /** * Whether the provided report is an archived room */ @@ -1512,6 +1519,9 @@ function getIcons( if (isExpenseRequest(report)) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); const workspaceIcon = getWorkspaceIcon(report, policy); + if (isClosedExpenseReportWithNoExpenses(report)) { + return [workspaceIcon]; + } const memberIcon = { source: UserUtils.getAvatar(personalDetails?.[parentReportAction.actorAccountID ?? -1]?.avatar ?? '', parentReportAction.actorAccountID ?? -1), id: parentReportAction.actorAccountID, @@ -1575,6 +1585,9 @@ function getIcons( } if (isPolicyExpenseChat(report) || isExpenseReport(report)) { const workspaceIcon = getWorkspaceIcon(report, policy); + if (isClosedExpenseReportWithNoExpenses(report)) { + return [workspaceIcon]; + } const memberIcon = { source: UserUtils.getAvatar(personalDetails?.[report?.ownerAccountID ?? -1]?.avatar ?? '', report?.ownerAccountID ?? -1), id: report?.ownerAccountID, @@ -1592,6 +1605,9 @@ function getIcons( name: personalDetails?.[report?.managerID ?? -1]?.displayName ?? '', fallbackIcon: personalDetails?.[report?.managerID ?? -1]?.fallbackIcon, }; + if (isClosedExpenseReportWithNoExpenses(report)) { + return [managerIcon]; + } const ownerIcon = { id: report?.ownerAccountID, source: UserUtils.getAvatar(personalDetails?.[report?.ownerAccountID ?? -1]?.avatar ?? '', report?.ownerAccountID ?? -1), @@ -2532,6 +2548,10 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu return parentReportActionMessage; } + if (isClosedExpenseReportWithNoExpenses(report)) { + return Localize.translateLocal('parentReportAction.deletedReport'); + } + if (isTaskReport(report) && isCanceledTaskReport(report, parentReportAction)) { return Localize.translateLocal('parentReportAction.deletedTask'); } @@ -5030,6 +5050,7 @@ export { getPolicyName, getPolicyType, isArchivedRoom, + isClosedExpenseReportWithNoExpenses, isExpensifyOnlyParticipantInReport, canCreateTaskInReport, isPolicyExpenseChatAdmin, diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 39a5fcaa4ee0..bcdb2a7ca17c 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -379,20 +379,24 @@ function ReportActionItem(props) { /> ); } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW) { - children = ( - - ); + if (ReportUtils.isClosedExpenseReportWithNoExpenses(ReportUtils.getReport(ReportActionsUtils.getIOUReportIDFromReportActionPreview(props.action) ?? ''))) { + children = ( + + ); + } else { + children = ${translate('parentReportAction.deletedReport')}`} />; + } } else if ( props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED || props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED || diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index 18f261024fd6..bedcff546dad 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -82,7 +82,10 @@ function ReportActionItemSingle({ const {avatar, login, pendingFields, status, fallbackIcon} = personalDetails[actorAccountID ?? -1] ?? {}; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing let actorHint = (login || (displayName ?? '')).replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); - const displayAllActors = useMemo(() => action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW && iouReport, [action.actionName, iouReport]); + const displayAllActors = useMemo( + () => action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW && iouReport && !ReportUtils.isClosedExpenseReportWithNoExpenses(iouReport), + [action.actionName, iouReport], + ); const isWorkspaceActor = ReportUtils.isPolicyExpenseChat(report) && (!actorAccountID || displayAllActors); let avatarSource = UserUtils.getAvatar(avatar ?? '', actorAccountID); From 55c837daaac8d6d09b6b196fe0ae7ece06dcd03a Mon Sep 17 00:00:00 2001 From: Dylan Date: Mon, 19 Feb 2024 10:44:29 +0700 Subject: [PATCH 032/145] fix lint --- src/pages/RoomMembersPage.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/RoomMembersPage.tsx b/src/pages/RoomMembersPage.tsx index 2376d66a6e1c..070c10a35253 100644 --- a/src/pages/RoomMembersPage.tsx +++ b/src/pages/RoomMembersPage.tsx @@ -1,5 +1,3 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; @@ -183,7 +181,7 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) { return; } } - const pendingVisibleChatMember = _.find(props.report.pendingVisibleChatMembers, (member) => member.accountID === accountID.toString()); + const pendingVisibleChatMember = report?.pendingVisibleChatMembers ? report?.pendingVisibleChatMembers.find((member) => member.accountID === accountID.toString()) : undefined; result.push({ keyForList: String(accountID), @@ -200,7 +198,7 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) { id: Number(accountID), }, ], - pendingAction: lodashGet(pendingVisibleChatMember, 'pendingAction', undefined), + pendingAction: pendingVisibleChatMember?.pendingAction ?? undefined }); }); From 93091e712f1781fd53172b544d3c03c161e6cff0 Mon Sep 17 00:00:00 2001 From: Dylan Date: Mon, 19 Feb 2024 10:58:51 +0700 Subject: [PATCH 033/145] fix lint --- src/pages/ReportParticipantsPage.tsx | 4 ++-- src/pages/RoomMembersPage.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/ReportParticipantsPage.tsx b/src/pages/ReportParticipantsPage.tsx index c3bd9d762170..2904e4e550d0 100755 --- a/src/pages/ReportParticipantsPage.tsx +++ b/src/pages/ReportParticipantsPage.tsx @@ -49,10 +49,10 @@ const getAllParticipants = ( !!userPersonalDetail?.login && !CONST.RESTRICTED_ACCOUNT_IDS.includes(accountID) ? LocalePhoneNumber.formatPhoneNumber(userPersonalDetail.login) : translate('common.hidden'); const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail); - const pendingVisibleChatMember = (report?.pendingVisibleChatMembers ?? []).find((member) => member.accountID === accountID.toString()); + const pendingVisibleChatMember = report?.pendingVisibleChatMembers ? report?.pendingVisibleChatMembers.find((member) => member.accountID === accountID.toString()) : undefined return { alternateText: userLogin, - pendingAction: pendingVisibleChatMember?.pendingAction, + pendingAction: pendingVisibleChatMember?.pendingAction ?? undefined, displayName, accountID: userPersonalDetail?.accountID ?? accountID, icons: [ diff --git a/src/pages/RoomMembersPage.tsx b/src/pages/RoomMembersPage.tsx index 070c10a35253..c697100e7d2e 100644 --- a/src/pages/RoomMembersPage.tsx +++ b/src/pages/RoomMembersPage.tsx @@ -198,7 +198,7 @@ function RoomMembersPage({report, session, policies}: RoomMembersPageProps) { id: Number(accountID), }, ], - pendingAction: pendingVisibleChatMember?.pendingAction ?? undefined + pendingAction: pendingVisibleChatMember?.pendingAction ?? undefined, }); }); From 5dc88556870b881b58a3d7bf402897ecf974d326 Mon Sep 17 00:00:00 2001 From: Dylan Date: Mon, 19 Feb 2024 11:13:00 +0700 Subject: [PATCH 034/145] fix lint --- src/pages/ReportParticipantsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReportParticipantsPage.tsx b/src/pages/ReportParticipantsPage.tsx index 2904e4e550d0..2988677f6be8 100755 --- a/src/pages/ReportParticipantsPage.tsx +++ b/src/pages/ReportParticipantsPage.tsx @@ -49,7 +49,7 @@ const getAllParticipants = ( !!userPersonalDetail?.login && !CONST.RESTRICTED_ACCOUNT_IDS.includes(accountID) ? LocalePhoneNumber.formatPhoneNumber(userPersonalDetail.login) : translate('common.hidden'); const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail); - const pendingVisibleChatMember = report?.pendingVisibleChatMembers ? report?.pendingVisibleChatMembers.find((member) => member.accountID === accountID.toString()) : undefined + const pendingVisibleChatMember = report?.pendingVisibleChatMembers ? report?.pendingVisibleChatMembers.find((member) => member.accountID === accountID.toString()) : undefined; return { alternateText: userLogin, pendingAction: pendingVisibleChatMember?.pendingAction ?? undefined, From 5bb6c8089c287d3d9589d9c845cca7fa04ad1490 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 19 Feb 2024 14:38:59 +0700 Subject: [PATCH 035/145] lint fix --- .../ReportActionItem/ReportActionItemImage.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/components/ReportActionItem/ReportActionItemImage.tsx b/src/components/ReportActionItem/ReportActionItemImage.tsx index 2caa4b2094f3..800d5b17896e 100644 --- a/src/components/ReportActionItem/ReportActionItemImage.tsx +++ b/src/components/ReportActionItem/ReportActionItemImage.tsx @@ -46,14 +46,7 @@ type ReportActionItemImageProps = { * and optional preview modal as well. */ -function ReportActionItemImage({ - thumbnail, - image, - enablePreviewModal = false, - transaction, - isLocalFile = false, - isSingleImage = true, -}: ReportActionItemImageProps) { +function ReportActionItemImage({thumbnail, image, enablePreviewModal = false, transaction, isLocalFile = false, isSingleImage = true}: ReportActionItemImageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const imageSource = tryResolveUrlFromApiRoot(image ?? ''); @@ -91,7 +84,6 @@ function ReportActionItemImage({ ); } - console.log('transaction22', transaction); if (enablePreviewModal) { return ( From 6241f859dabd9c70909c71d1b3c38a11dab48056 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Mon, 19 Feb 2024 14:49:56 +0700 Subject: [PATCH 036/145] fix handle multiple tags --- ...oraryForRefactorRequestConfirmationList.js | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 25692e07ff99..e93f4bdf8783 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -481,23 +481,29 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ IOU.setMoneyRequestMerchant(transaction.transactionID, distanceMerchant, true); }, [isDistanceRequestWithPendingRoute, hasRoute, distance, unit, rate, currency, translate, toLocaleDigit, isDistanceRequest, transaction]); - // Auto select the category if there is only one enabled category + // Auto select the category if there is only one enabled category and it is required useEffect(() => { const enabledCategories = _.filter(policyCategories, (category) => category.enabled); - if (iouCategory || !shouldShowCategories || enabledCategories.length !== 1) { + if (iouCategory || !shouldShowCategories || enabledCategories.length !== 1 || !isCategoryRequired) { return; } IOU.setMoneyRequestCategory_temporaryForRefactor(transaction.transactionID, enabledCategories[0].name); - }, [iouCategory, shouldShowCategories, policyCategories, transaction]); + }, [iouCategory, shouldShowCategories, policyCategories, transaction, isCategoryRequired]); - // Auto select the tag if there is only one enabled tag + // Auto select the tag if there is only one enabled tag and it is required useEffect(() => { - const enabledTags = _.filter(policyTagList, (tag) => tag.enabled); - if (iouTag || !shouldShowTags || enabledTags.length !== 1) { - return; + let updatedTagsString = ''; + policyTagLists.forEach((tagList, index) => { + const enabledTags = _.filter(tagList.tags, (tag) => tag.enabled); + if (enabledTags.length !== 1 || !tagList.required || TransactionUtils.getTag(transaction, index)) { + return; + } + updatedTagsString = IOUUtils.insertTagIntoReportTagsString(updatedTagsString, enabledTags[0].name, index); + }); + if (updatedTagsString !== TransactionUtils.getTag(transaction) && updatedTagsString) { + IOU.setMoneyRequestTag(transaction.transactionID, updatedTagsString); } - IOU.setMoneyRequestTag(transaction.transactionID, enabledTags[0].name); - }, [shouldShowTags, policyTagList, iouTag, transaction]); + }, [policyTagLists, transaction]); /** * @param {Object} option @@ -554,17 +560,20 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const decimals = CurrencyUtils.getCurrencyDecimals(iouCurrencyCode); if (isDistanceRequest && !isDistanceRequestWithPendingRoute && !MoneyRequestUtils.validateAmount(String(iouAmount), decimals)) { setFormError('common.error.invalidAmount'); + console.log('333333333333333333 step 2', {selectedParticipants}); return; } if (isEditingSplitBill && TransactionUtils.areRequiredFieldsEmpty(transaction)) { setDidConfirmSplit(true); setFormError('iou.error.genericSmartscanFailureMessage'); + console.log('333333333333333333 step 3', {selectedParticipants}); return; } playSound(SOUNDS.DONE); setDidConfirm(true); + console.log('111111111111111111111111'); onConfirm(selectedParticipants); } }, @@ -938,17 +947,17 @@ export default compose( key: ONYXKEYS.SESSION, }, policyCategories: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${'062D53707053B5B9'}`, }, policyTags: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${'062D53707053B5B9'}`, }, mileageRate: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, selector: DistanceRequestUtils.getDefaultMileageRate, }, policy: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${'062D53707053B5B9'}`, }, policyTaxRates: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, From 7c5fa7f0faf8c393b79db9d8544e2e321d0e989b Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Mon, 19 Feb 2024 14:50:59 +0700 Subject: [PATCH 037/145] fix remove hardcode --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index e93f4bdf8783..0f968780073a 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -947,17 +947,17 @@ export default compose( key: ONYXKEYS.SESSION, }, policyCategories: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${'062D53707053B5B9'}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, }, policyTags: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${'062D53707053B5B9'}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, }, mileageRate: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, selector: DistanceRequestUtils.getDefaultMileageRate, }, policy: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${'062D53707053B5B9'}`, + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, policyTaxRates: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, From 7729a29ec0bf3d184a3ae56c5e97945d95e9b386 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Mon, 19 Feb 2024 14:51:51 +0700 Subject: [PATCH 038/145] fix remove console log --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 0f968780073a..8131bc5a6710 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -560,20 +560,17 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const decimals = CurrencyUtils.getCurrencyDecimals(iouCurrencyCode); if (isDistanceRequest && !isDistanceRequestWithPendingRoute && !MoneyRequestUtils.validateAmount(String(iouAmount), decimals)) { setFormError('common.error.invalidAmount'); - console.log('333333333333333333 step 2', {selectedParticipants}); return; } if (isEditingSplitBill && TransactionUtils.areRequiredFieldsEmpty(transaction)) { setDidConfirmSplit(true); setFormError('iou.error.genericSmartscanFailureMessage'); - console.log('333333333333333333 step 3', {selectedParticipants}); return; } playSound(SOUNDS.DONE); setDidConfirm(true); - console.log('111111111111111111111111'); onConfirm(selectedParticipants); } }, From b3827a32990d192141f5d13aba748c3f965e93e8 Mon Sep 17 00:00:00 2001 From: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Mon, 19 Feb 2024 20:31:09 +0100 Subject: [PATCH 039/145] fix lint error --- src/pages/home/report/ReportActionItem.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index bcdb2a7ca17c..78fe0732d21a 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -379,7 +379,7 @@ function ReportActionItem(props) { /> ); } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW) { - if (ReportUtils.isClosedExpenseReportWithNoExpenses(ReportUtils.getReport(ReportActionsUtils.getIOUReportIDFromReportActionPreview(props.action) ?? ''))) { + if (ReportUtils.isClosedExpenseReportWithNoExpenses(ReportUtils.getReport(ReportActionsUtils.getIOUReportIDFromReportActionPreview(props.action)))) { children = ( ); } else { - children = ${translate('parentReportAction.deletedReport')}`} />; + children = ${props.translate('parentReportAction.deletedReport')}`} />; } } else if ( props.action.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED || From b7f38fc66b95955f21c47015fb27974d5c47b5fc Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 22 Feb 2024 14:17:08 +0700 Subject: [PATCH 040/145] fix required field --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 8131bc5a6710..29cfb34583eb 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -493,9 +493,10 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ // Auto select the tag if there is only one enabled tag and it is required useEffect(() => { let updatedTagsString = ''; + const isMultipleLevelsTags = policyTagLists && policyTagLists.length > 1; policyTagLists.forEach((tagList, index) => { const enabledTags = _.filter(tagList.tags, (tag) => tag.enabled); - if (enabledTags.length !== 1 || !tagList.required || TransactionUtils.getTag(transaction, index)) { + if (enabledTags.length !== 1 || isMultipleLevelsTags ? !tagList.required : !isTagRequired || TransactionUtils.getTag(transaction, index)) { return; } updatedTagsString = IOUUtils.insertTagIntoReportTagsString(updatedTagsString, enabledTags[0].name, index); @@ -503,7 +504,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ if (updatedTagsString !== TransactionUtils.getTag(transaction) && updatedTagsString) { IOU.setMoneyRequestTag(transaction.transactionID, updatedTagsString); } - }, [policyTagLists, transaction]); + }, [policyTagLists, transaction, policyTags, isTagRequired]); /** * @param {Object} option From 36b43f1e7dcc798227b20b606087de29205040df Mon Sep 17 00:00:00 2001 From: tienifr Date: Sat, 24 Feb 2024 16:28:39 +0700 Subject: [PATCH 041/145] fix perf-test --- src/components/LocalePicker.tsx | 11 ++++------- src/pages/signin/Licenses.tsx | 13 +++++++++++-- src/pages/signin/SignInPage.tsx | 1 + src/pages/signin/SignInPageLayout/Footer.tsx | 10 +++++++--- src/pages/signin/SignInPageLayout/index.tsx | 11 +++++++++-- src/pages/signin/SignInPageLayout/types.ts | 4 ++++ 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/components/LocalePicker.tsx b/src/components/LocalePicker.tsx index c411ac7a02c9..0080213785f2 100644 --- a/src/components/LocalePicker.tsx +++ b/src/components/LocalePicker.tsx @@ -13,14 +13,14 @@ import Picker from './Picker'; import type {PickerSize} from './Picker/types'; type LocalePickerOnyxProps = { - /** The details about the account that the user is signing in with */ - account: OnyxEntry; - /** Indicates which locale the user currently has selected */ preferredLocale: OnyxEntry; }; type LocalePickerProps = LocalePickerOnyxProps & { + /** The details about the account that the user is signing in with */ + account: Account; + /** Indicates size of a picker component and whether to render the label or not */ size?: PickerSize; }; @@ -35,7 +35,7 @@ function LocalePicker({account, preferredLocale = CONST.LOCALES.DEFAULT, size = keyForList: language, isSelected: preferredLocale === language, })); - const shouldDisablePicker = AccountUtils.isValidateCodeFormSubmitting(account ?? {}); + const shouldDisablePicker = AccountUtils.isValidateCodeFormSubmitting(account); return ( ({ - account: { - key: ONYXKEYS.ACCOUNT, - }, preferredLocale: { key: ONYXKEYS.NVP_PREFERRED_LOCALE, }, diff --git a/src/pages/signin/Licenses.tsx b/src/pages/signin/Licenses.tsx index 87271e3df6b2..d705cae197ba 100644 --- a/src/pages/signin/Licenses.tsx +++ b/src/pages/signin/Licenses.tsx @@ -6,10 +6,16 @@ import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; +import {Account} from '@src/types/onyx'; const currentYear = new Date().getFullYear(); -function Licenses() { +type LicensesProps = { + /** The details about the account that the user is signing in with */ + account: Account; +}; + +function Licenses({account}: LicensesProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); return ( @@ -27,7 +33,10 @@ function Licenses() { . - + ); diff --git a/src/pages/signin/SignInPage.tsx b/src/pages/signin/SignInPage.tsx index 6672ccbd0ebc..9519ee763784 100644 --- a/src/pages/signin/SignInPage.tsx +++ b/src/pages/signin/SignInPage.tsx @@ -250,6 +250,7 @@ function SignInPageInner({credentials, account, activeClients = [], preferredLoc testID={SignInPageInner.displayName} > ; +type FooterProps = Pick & { + /** The details about the account that the user is signing in with */ + account: Account; +}; type FooterColumnRow = (LinkProps | PressProps) & { translationPath: TranslationPaths; @@ -143,7 +147,7 @@ const columns = ({navigateFocus = () => {}}: Pick) }, ]; -function Footer({navigateFocus}: FooterProps) { +function Footer({account, navigateFocus}: FooterProps) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -209,7 +213,7 @@ function Footer({navigateFocus}: FooterProps) { )} {i === 3 && ( - + )} diff --git a/src/pages/signin/SignInPageLayout/index.tsx b/src/pages/signin/SignInPageLayout/index.tsx index b65da7eba0a5..527d4fd3b594 100644 --- a/src/pages/signin/SignInPageLayout/index.tsx +++ b/src/pages/signin/SignInPageLayout/index.tsx @@ -22,6 +22,7 @@ import type {SignInPageLayoutProps, SignInPageLayoutRef} from './types'; function SignInPageLayout( { + account, customHeadline, customHeroBody, shouldShowWelcomeHeader = false, @@ -129,7 +130,10 @@ function SignInPageLayout( customHeadline={customHeadline} customHeroBody={customHeroBody} /> -