diff --git a/android/app/build.gradle b/android/app/build.gradle
index 18ef2984f67a..38ba58bb6a86 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -98,8 +98,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1001042500
- versionName "1.4.25-0"
+ versionCode 1001042505
+ versionName "1.4.25-5"
}
flavorDimensions "default"
diff --git a/android/app/src/main/res/drawable/ic_launcher_monochrome.png b/android/app/src/main/res/drawable/ic_launcher_monochrome.png
index b1a286b6f8dd..0af99b087923 100644
Binary files a/android/app/src/main/res/drawable/ic_launcher_monochrome.png and b/android/app/src/main/res/drawable/ic_launcher_monochrome.png differ
diff --git a/assets/images/expensify-logo--adhoc.svg b/assets/images/expensify-logo--adhoc.svg
index 273002deca9b..52b381dc4b78 100644
--- a/assets/images/expensify-logo--adhoc.svg
+++ b/assets/images/expensify-logo--adhoc.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/assets/images/expensify-logo--dev.svg b/assets/images/expensify-logo--dev.svg
index e8e3fb5033d9..2c9ae142e283 100644
--- a/assets/images/expensify-logo--dev.svg
+++ b/assets/images/expensify-logo--dev.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/assets/images/expensify-logo--staging.svg b/assets/images/expensify-logo--staging.svg
index 78dcc1581f99..a1e7482c133b 100644
--- a/assets/images/expensify-logo--staging.svg
+++ b/assets/images/expensify-logo--staging.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/assets/images/home-background--mobile-new.svg b/assets/images/home-background--mobile-new.svg
index 0da937cae059..d81f2a18cc78 100644
--- a/assets/images/home-background--mobile-new.svg
+++ b/assets/images/home-background--mobile-new.svg
@@ -1,8835 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/images/new-expensify.svg b/assets/images/new-expensify.svg
index 89102ecbc5e4..7bfef1fd38b4 100644
--- a/assets/images/new-expensify.svg
+++ b/assets/images/new-expensify.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/assets/images/product-illustrations/telescope.svg b/assets/images/product-illustrations/telescope.svg
index 95617c801789..1830dff0fe3c 100644
--- a/assets/images/product-illustrations/telescope.svg
+++ b/assets/images/product-illustrations/telescope.svg
@@ -1,79 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/images/signIn/google-logo.svg b/assets/images/signIn/google-logo.svg
index 4fbdc804a0a2..169ea34b23ee 100644
--- a/assets/images/signIn/google-logo.svg
+++ b/assets/images/signIn/google-logo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/images/simple-illustrations/simple-illustration__bigrocket.svg b/assets/images/simple-illustrations/simple-illustration__bigrocket.svg
index 1afd5f66b6ea..64d6dc2200f0 100644
--- a/assets/images/simple-illustrations/simple-illustration__bigrocket.svg
+++ b/assets/images/simple-illustrations/simple-illustration__bigrocket.svg
@@ -1,100 +1 @@
-
+
\ No newline at end of file
diff --git a/assets/images/simple-illustrations/simple-illustration__commentbubbles.svg b/assets/images/simple-illustrations/simple-illustration__commentbubbles.svg
index 829d3ee2e3fe..ab9d3ae4db70 100644
--- a/assets/images/simple-illustrations/simple-illustration__commentbubbles.svg
+++ b/assets/images/simple-illustrations/simple-illustration__commentbubbles.svg
@@ -1,22 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/images/simple-illustrations/simple-illustration__handcard.svg b/assets/images/simple-illustrations/simple-illustration__handcard.svg
index 7419b33d425c..a49e0ee5b77f 100644
--- a/assets/images/simple-illustrations/simple-illustration__handcard.svg
+++ b/assets/images/simple-illustrations/simple-illustration__handcard.svg
@@ -1,41 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/images/simple-illustrations/simple-illustration__hotdogstand.svg b/assets/images/simple-illustrations/simple-illustration__hotdogstand.svg
index 471b978bb97e..5b5e12a99a9b 100644
--- a/assets/images/simple-illustrations/simple-illustration__hotdogstand.svg
+++ b/assets/images/simple-illustrations/simple-illustration__hotdogstand.svg
@@ -1,98 +1 @@
-
+
\ No newline at end of file
diff --git a/assets/images/simple-illustrations/simple-illustration__hourglass.svg b/assets/images/simple-illustrations/simple-illustration__hourglass.svg
index 539e1e45b795..683e74a657e8 100644
--- a/assets/images/simple-illustrations/simple-illustration__hourglass.svg
+++ b/assets/images/simple-illustrations/simple-illustration__hourglass.svg
@@ -1,56 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/images/simple-illustrations/simple-illustration__mailbox.svg b/assets/images/simple-illustrations/simple-illustration__mailbox.svg
index 81b1f508fb52..7af7c71e24f3 100644
--- a/assets/images/simple-illustrations/simple-illustration__mailbox.svg
+++ b/assets/images/simple-illustrations/simple-illustration__mailbox.svg
@@ -1,71 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/images/simple-illustrations/simple-illustration__smallrocket.svg b/assets/images/simple-illustrations/simple-illustration__smallrocket.svg
index 0f8f166c849f..388bb968a762 100644
--- a/assets/images/simple-illustrations/simple-illustration__smallrocket.svg
+++ b/assets/images/simple-illustrations/simple-illustration__smallrocket.svg
@@ -1,45 +1 @@
-
+
\ No newline at end of file
diff --git a/assets/images/simple-illustrations/simple-illustration__trashcan.svg b/assets/images/simple-illustrations/simple-illustration__trashcan.svg
index 4e66efa0a67e..66cc9ee27550 100644
--- a/assets/images/simple-illustrations/simple-illustration__trashcan.svg
+++ b/assets/images/simple-illustrations/simple-illustration__trashcan.svg
@@ -1,52 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/assets/images/thumbs-up.svg b/assets/images/thumbs-up.svg
index ef81c88fc854..3e2a4a5125b6 100644
--- a/assets/images/thumbs-up.svg
+++ b/assets/images/thumbs-up.svg
@@ -1,8 +1 @@
-
-
+
\ No newline at end of file
diff --git a/docs/assets/images/send-money.svg b/docs/assets/images/send-money.svg
index e858f0d5c327..7abce818f09e 100644
--- a/docs/assets/images/send-money.svg
+++ b/docs/assets/images/send-money.svg
@@ -1,25 +1 @@
-
+
\ No newline at end of file
diff --git a/docs/assets/images/subscription-annual.svg b/docs/assets/images/subscription-annual.svg
index a4b99a43b16e..f74ce086b2c7 100644
--- a/docs/assets/images/subscription-annual.svg
+++ b/docs/assets/images/subscription-annual.svg
@@ -1,23 +1 @@
-
+
\ No newline at end of file
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index b4056989a1c4..f361946c2584 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -40,7 +40,7 @@
CFBundleVersion
- 1.4.25.0
+ 1.4.25.5
ITSAppUsesNonExemptEncryption
LSApplicationQueriesSchemes
diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist
index 4f75315fb1ec..bf9e98fec664 100644
--- a/ios/NewExpensifyTests/Info.plist
+++ b/ios/NewExpensifyTests/Info.plist
@@ -19,6 +19,6 @@
CFBundleSignature
????
CFBundleVersion
- 1.4.25.0
+ 1.4.25.5
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index a0328855047b..5ee62047829d 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -5,7 +5,7 @@
CFBundleShortVersionString
1.4.25
CFBundleVersion
- 1.4.25.0
+ 1.4.25.5
NSExtension
NSExtensionPointIdentifier
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 379194a70fd9..f433c4f1e1e2 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1180,7 +1180,7 @@ PODS:
- React-Core
- react-native-pager-view (6.2.2):
- React-Core
- - react-native-pdf (6.7.4):
+ - react-native-pdf (6.7.3):
- React-Core
- react-native-performance (5.1.0):
- React-Core
@@ -1911,7 +1911,7 @@ SPEC CHECKSUMS:
react-native-key-command: 5af6ee30ff4932f78da6a2109017549042932aa5
react-native-netinfo: 8a7fd3f7130ef4ad2fb4276d5c9f8d3f28d2df3d
react-native-pager-view: 02a5c4962530f7efc10dd51ee9cdabeff5e6c631
- react-native-pdf: 79aa75e39a80c1d45ffe58aa500f3cf08f267a2e
+ react-native-pdf: b4ca3d37a9a86d9165287741c8b2ef4d8940c00e
react-native-performance: cef2b618d47b277fb5c3280b81a3aad1e72f2886
react-native-plaid-link-sdk: df1618a85a615d62ff34e34b76abb7a56497fbc1
react-native-quick-sqlite: bcc7a7a250a40222f18913a97cd356bf82d0a6c4
diff --git a/package-lock.json b/package-lock.json
index 0acbc00bf99d..e9d4c4f90b2d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "1.4.25-0",
+ "version": "1.4.25-5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "1.4.25-0",
+ "version": "1.4.25-5",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -96,7 +96,7 @@
"react-native-modal": "^13.0.0",
"react-native-onyx": "1.0.126",
"react-native-pager-view": "6.2.2",
- "react-native-pdf": "^6.7.4",
+ "react-native-pdf": "6.7.3",
"react-native-performance": "^5.1.0",
"react-native-permissions": "^3.9.3",
"react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#7a407cd4174d9838a944c1c2e1cb4a9737ac69c5",
@@ -47079,9 +47079,9 @@
}
},
"node_modules/react-native-pdf": {
- "version": "6.7.4",
- "resolved": "https://registry.npmjs.org/react-native-pdf/-/react-native-pdf-6.7.4.tgz",
- "integrity": "sha512-sBeNcsrTRnLjmiU9Wx7Uk0K2kPSQtKIIG+FECdrEG16TOdtmQ3iqqEwt0dmy0pJegpg07uES5BXqiKsKkRUIFw==",
+ "version": "6.7.3",
+ "resolved": "https://registry.npmjs.org/react-native-pdf/-/react-native-pdf-6.7.3.tgz",
+ "integrity": "sha512-bK1fVkj18kBA5YlRFNJ3/vJ1bEX3FDHyAPY6ArtIdVs+vv0HzcK5WH9LSd2bxUsEMIyY9CSjP4j8BcxNXTiQkQ==",
"dependencies": {
"crypto-js": "4.2.0",
"deprecated-react-native-prop-types": "^2.3.0"
@@ -89718,9 +89718,9 @@
"requires": {}
},
"react-native-pdf": {
- "version": "6.7.4",
- "resolved": "https://registry.npmjs.org/react-native-pdf/-/react-native-pdf-6.7.4.tgz",
- "integrity": "sha512-sBeNcsrTRnLjmiU9Wx7Uk0K2kPSQtKIIG+FECdrEG16TOdtmQ3iqqEwt0dmy0pJegpg07uES5BXqiKsKkRUIFw==",
+ "version": "6.7.3",
+ "resolved": "https://registry.npmjs.org/react-native-pdf/-/react-native-pdf-6.7.3.tgz",
+ "integrity": "sha512-bK1fVkj18kBA5YlRFNJ3/vJ1bEX3FDHyAPY6ArtIdVs+vv0HzcK5WH9LSd2bxUsEMIyY9CSjP4j8BcxNXTiQkQ==",
"requires": {
"crypto-js": "4.2.0",
"deprecated-react-native-prop-types": "^2.3.0"
diff --git a/package.json b/package.json
index 8682d4ad7385..237d64e25b4a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "1.4.25-0",
+ "version": "1.4.25-5",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
@@ -144,7 +144,7 @@
"react-native-modal": "^13.0.0",
"react-native-onyx": "1.0.126",
"react-native-pager-view": "6.2.2",
- "react-native-pdf": "^6.7.4",
+ "react-native-pdf": "6.7.3",
"react-native-performance": "^5.1.0",
"react-native-permissions": "^3.9.3",
"react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#7a407cd4174d9838a944c1c2e1cb4a9737ac69c5",
diff --git a/src/CONST.ts b/src/CONST.ts
index f0f7ab736b78..d6f3d3cdcef6 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -639,18 +639,13 @@ const CONST = {
ANNOUNCE: '#announce',
ADMINS: '#admins',
},
- STATE: {
- OPEN: 'OPEN',
- SUBMITTED: 'SUBMITTED',
- PROCESSING: 'PROCESSING',
- },
STATE_NUM: {
OPEN: 0,
- PROCESSING: 1,
- SUBMITTED: 2,
+ SUBMITTED: 1,
+ APPROVED: 2,
BILLING: 3,
},
- STATUS: {
+ STATUS_NUM: {
OPEN: 0,
SUBMITTED: 1,
CLOSED: 2,
@@ -1449,6 +1444,8 @@ const CONST = {
INVISIBLE_CHARACTERS_GROUPS: /[\p{C}\p{Z}]/gu,
OTHER_INVISIBLE_CHARACTERS: /[\u3164]/g,
+
+ REPORT_FIELD_TITLE: /{report:([a-zA-Z]+)}/g,
},
PRONOUNS: {
diff --git a/src/components/AvatarCropModal/ImageCropView.js b/src/components/AvatarCropModal/ImageCropView.js
index 92cbe3a4da04..f69fe7eb5ecb 100644
--- a/src/components/AvatarCropModal/ImageCropView.js
+++ b/src/components/AvatarCropModal/ImageCropView.js
@@ -6,7 +6,6 @@ import Animated, {interpolate, useAnimatedStyle} from 'react-native-reanimated';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import useStyleUtils from '@hooks/useStyleUtils';
-import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import ControlSelection from '@libs/ControlSelection';
import gestureHandlerPropTypes from './gestureHandlerPropTypes';
@@ -51,7 +50,6 @@ const defaultProps = {
};
function ImageCropView(props) {
- const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const containerStyle = StyleUtils.getWidthAndHeightStyle(props.containerSize, props.containerSize);
@@ -90,7 +88,8 @@ function ImageCropView(props) {
diff --git a/src/components/BlockingViews/FullPageNotFoundView.tsx b/src/components/BlockingViews/FullPageNotFoundView.tsx
index 5993e60861f5..807029addf5e 100644
--- a/src/components/BlockingViews/FullPageNotFoundView.tsx
+++ b/src/components/BlockingViews/FullPageNotFoundView.tsx
@@ -33,10 +33,10 @@ type FullPageNotFoundViewProps = {
linkKey?: TranslationPaths;
/** Method to trigger when pressing the back button of the header */
- onBackButtonPress: () => void;
+ onBackButtonPress?: () => void;
/** Function to call when pressing the navigation link */
- onLinkPress: () => void;
+ onLinkPress?: () => void;
};
// eslint-disable-next-line rulesdir/no-negated-variables
diff --git a/src/components/LHNOptionsList/LHNOptionsList.js b/src/components/LHNOptionsList/LHNOptionsList.js
index 71b14b6fadcd..6bb4973d0c64 100644
--- a/src/components/LHNOptionsList/LHNOptionsList.js
+++ b/src/components/LHNOptionsList/LHNOptionsList.js
@@ -118,7 +118,7 @@ function LHNOptionsList({
const transactionID = lodashGet(itemParentReportAction, ['originalMessage', 'IOUTransactionID'], '');
const itemTransaction = transactionID ? transactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] : {};
const itemComment = draftComments[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`] || '';
- const participants = [...ReportUtils.getParticipantsIDs(itemFullReport), itemFullReport.ownerAccountID];
+ const participants = [...ReportUtils.getParticipantsIDs(itemFullReport), itemFullReport.ownerAccountID, itemParentReportAction.actorAccountID];
const participantsPersonalDetails = OptionsListUtils.getPersonalDetailsForAccountIDs(participants, personalDetails);
diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js
index 197829bb1ea9..412aeedcf965 100755
--- a/src/components/OptionsSelector/BaseOptionsSelector.js
+++ b/src/components/OptionsSelector/BaseOptionsSelector.js
@@ -7,12 +7,9 @@ import ArrowKeyFocusManager from '@components/ArrowKeyFocusManager';
import Button from '@components/Button';
import FixedFooter from '@components/FixedFooter';
import FormHelpMessage from '@components/FormHelpMessage';
-import Icon from '@components/Icon';
-import {Info} from '@components/Icon/Expensicons';
import OptionsList from '@components/OptionsList';
-import {PressableWithoutFeedback} from '@components/Pressable';
+import ReferralProgramCTA from '@components/ReferralProgramCTA';
import ShowMoreButton from '@components/ShowMoreButton';
-import Text from '@components/Text';
import TextInput from '@components/TextInput';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import withNavigationFocus from '@components/withNavigationFocus';
@@ -21,10 +18,8 @@ import withThemeStyles, {withThemeStylesPropTypes} from '@components/withThemeSt
import compose from '@libs/compose';
import getPlatform from '@libs/getPlatform';
import KeyboardShortcut from '@libs/KeyboardShortcut';
-import Navigation from '@libs/Navigation/Navigation';
import setSelection from '@libs/setSelection';
import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
import {defaultProps as optionsSelectorDefaultProps, propTypes as optionsSelectorPropTypes} from './optionsSelectorPropTypes';
const propTypes = {
@@ -667,39 +662,7 @@ class BaseOptionsSelector extends Component {
{this.props.shouldShowReferralCTA && (
- {
- Navigation.navigate(ROUTES.REFERRAL_DETAILS_MODAL.getRoute(this.props.referralContentType));
- }}
- style={[
- this.props.themeStyles.p5,
- this.props.themeStyles.w100,
- this.props.themeStyles.br2,
- this.props.themeStyles.highlightBG,
- this.props.themeStyles.flexRow,
- this.props.themeStyles.justifyContentBetween,
- this.props.themeStyles.alignItemsCenter,
- {gap: 10},
- ]}
- accessibilityLabel="referral"
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
- >
-
- {this.props.translate(`referralProgram.${this.props.referralContentType}.buttonText1`)}
-
- {this.props.translate(`referralProgram.${this.props.referralContentType}.buttonText2`)}
-
-
-
-
+
)}
diff --git a/src/pages/iou/MoneyRequestReferralProgramCTA.tsx b/src/components/ReferralProgramCTA.tsx
similarity index 68%
rename from src/pages/iou/MoneyRequestReferralProgramCTA.tsx
rename to src/components/ReferralProgramCTA.tsx
index 31394e1bd0e1..473d5cdbed08 100644
--- a/src/pages/iou/MoneyRequestReferralProgramCTA.tsx
+++ b/src/components/ReferralProgramCTA.tsx
@@ -1,20 +1,24 @@
import React from 'react';
-import Icon from '@components/Icon';
-import {Info} from '@components/Icon/Expensicons';
-import {PressableWithoutFeedback} from '@components/Pressable';
-import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import Navigation from '@src/libs/Navigation/Navigation';
import ROUTES from '@src/ROUTES';
+import Icon from './Icon';
+import {Info} from './Icon/Expensicons';
+import {PressableWithoutFeedback} from './Pressable';
+import Text from './Text';
-type MoneyRequestReferralProgramCTAProps = {
- referralContentType: typeof CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY | typeof CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST;
+type ReferralProgramCTAProps = {
+ referralContentType:
+ | typeof CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST
+ | typeof CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT
+ | typeof CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY
+ | typeof CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND;
};
-function MoneyRequestReferralProgramCTA({referralContentType}: MoneyRequestReferralProgramCTAProps) {
+function ReferralProgramCTA({referralContentType}: ReferralProgramCTAProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const theme = useTheme();
@@ -41,9 +45,10 @@ function MoneyRequestReferralProgramCTA({referralContentType}: MoneyRequestRefer
src={Info}
height={20}
width={20}
+ fill={theme.icon}
/>
);
}
-export default MoneyRequestReferralProgramCTA;
+export default ReferralProgramCTA;
diff --git a/src/components/ReportActionItem/MoneyReportView.tsx b/src/components/ReportActionItem/MoneyReportView.tsx
index 16ea27b17f42..4fcca3e518a5 100644
--- a/src/components/ReportActionItem/MoneyReportView.tsx
+++ b/src/components/ReportActionItem/MoneyReportView.tsx
@@ -1,11 +1,14 @@
-import React from 'react';
+import React, {useMemo} from 'react';
import type {StyleProp, TextStyle} from 'react-native';
import {View} from 'react-native';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import OfflineWithFeedback from '@components/OfflineWithFeedback';
import SpacerView from '@components/SpacerView';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
+import usePermissions from '@hooks/usePermissions';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
@@ -14,22 +17,26 @@ import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import AnimatedEmptyStateBackground from '@pages/home/report/AnimatedEmptyStateBackground';
import variables from '@styles/variables';
-import type {Report} from '@src/types/onyx';
+import type {PolicyReportField, Report} from '@src/types/onyx';
type MoneyReportViewProps = {
/** The report currently being looked at */
report: Report;
+ /** Policy report fields */
+ policyReportFields: PolicyReportField[];
+
/** Whether we should display the horizontal rule below the component */
shouldShowHorizontalRule: boolean;
};
-function MoneyReportView({report, shouldShowHorizontalRule}: MoneyReportViewProps) {
+function MoneyReportView({report, policyReportFields, shouldShowHorizontalRule}: MoneyReportViewProps) {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const {isSmallScreenWidth} = useWindowDimensions();
+ const {canUseReportFields} = usePermissions();
const isSettled = ReportUtils.isSettled(report.reportID);
const {totalDisplaySpend, nonReimbursableSpend, reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(report);
@@ -46,10 +53,41 @@ function MoneyReportView({report, shouldShowHorizontalRule}: MoneyReportViewProp
StyleUtils.getColorStyle(theme.textSupporting),
];
+ const sortedPolicyReportFields = useMemo(
+ () => policyReportFields.sort(({orderWeight: firstOrderWeight}, {orderWeight: secondOrderWeight}) => firstOrderWeight - secondOrderWeight),
+ [policyReportFields],
+ );
+
return (
+ {canUseReportFields &&
+ sortedPolicyReportFields.map((reportField) => {
+ const title = ReportUtils.getReportFieldTitle(report, reportField);
+ return (
+
+ {}}
+ shouldShowRightIcon
+ disabled={false}
+ wrapperStyle={[styles.pv2, styles.taskDescriptionMenuItem]}
+ shouldGreyOutWhenDisabled={false}
+ numberOfLinesTitle={0}
+ interactive
+ shouldStackHorizontally={false}
+ onSecondaryInteraction={() => {}}
+ hoverAndPressStyle={false}
+ titleWithTooltips={[]}
+ />
+
+ );
+ })}
({
+ hasMissingSmartscanFields: ReportUtils.hasMissingSmartscanFields(props.iouReportID),
+ areAllRequestsBeingSmartScanned: ReportUtils.areAllRequestsBeingSmartScanned(props.iouReportID, props.action),
+ hasOnlyDistanceRequests: ReportUtils.hasOnlyDistanceRequestTransactions(props.iouReportID),
+ hasNonReimbursableTransactions: ReportUtils.hasNonReimbursableTransactions(props.iouReportID),
+ }),
+ // When transactions get updated these status may have changed, so that is a case where we also want to run this.
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [props.transactions, props.iouReportID, props.action],
+ );
const managerID = props.iouReport.managerID || 0;
const isCurrentUserManager = managerID === lodashGet(props.session, 'accountID');
@@ -162,7 +173,7 @@ function ReportPreview(props) {
const previewSubtitle =
formattedMerchant ||
props.translate('iou.requestCount', {
- count: numberOfRequests,
+ count: numberOfRequests - numberOfScanningReceipts,
scanningReceipts: numberOfScanningReceipts,
});
@@ -218,28 +229,6 @@ function ReportPreview(props) {
const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport);
- useEffect(() => {
- const unsubscribeOnyxTransaction = onyxSubscribe({
- key: ONYXKEYS.COLLECTION.TRANSACTION,
- waitForCollectionCallback: true,
- callback: (allTransactions) => {
- if (_.isEmpty(allTransactions)) {
- return;
- }
-
- sethasMissingSmartscanFields(ReportUtils.hasMissingSmartscanFields(props.iouReportID));
- setAreAllRequestsBeingSmartScanned(ReportUtils.areAllRequestsBeingSmartScanned(props.iouReportID, props.action));
- setHasOnlyDistanceRequests(ReportUtils.hasOnlyDistanceRequestTransactions(props.iouReportID));
- setHasNonReimbursableTransactions(ReportUtils.hasNonReimbursableTransactions(props.iouReportID));
- },
- });
-
- return () => {
- unsubscribeOnyxTransaction();
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(props.chatReport);
const isPolicyAdmin = policyType !== CONST.POLICY.TYPE.PERSONAL && lodashGet(props.policy, 'role') === CONST.POLICY.ROLE.ADMIN;
const isPayer = isPaidGroupPolicy
@@ -370,5 +359,8 @@ export default compose(
session: {
key: ONYXKEYS.SESSION,
},
+ transactions: {
+ key: ONYXKEYS.COLLECTION.TRANSACTION,
+ },
}),
)(ReportPreview);
diff --git a/src/components/ReportActionItem/TaskPreview.tsx b/src/components/ReportActionItem/TaskPreview.tsx
index fbc58a381318..a509d8d922e1 100644
--- a/src/components/ReportActionItem/TaskPreview.tsx
+++ b/src/components/ReportActionItem/TaskPreview.tsx
@@ -84,12 +84,13 @@ function TaskPreview({
const StyleUtils = useStyleUtils();
const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const {translate} = useLocalize();
+
// The reportAction might not contain details regarding the taskReport
// Only the direct parent reportAction will contain details about the taskReport
// Other linked reportActions will only contain the taskReportID and we will grab the details from there
const isTaskCompleted = !isEmptyObject(taskReport)
- ? taskReport?.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && taskReport.statusNum === CONST.REPORT.STATUS.APPROVED
- : action?.childStateNum === CONST.REPORT.STATE_NUM.SUBMITTED && action?.childStatusNum === CONST.REPORT.STATUS.APPROVED;
+ ? taskReport?.stateNum === CONST.REPORT.STATE_NUM.APPROVED && taskReport.statusNum === CONST.REPORT.STATUS_NUM.APPROVED
+ : action?.childStateNum === CONST.REPORT.STATE_NUM.APPROVED && action?.childStatusNum === CONST.REPORT.STATUS_NUM.APPROVED;
const taskTitle = Str.htmlEncode(TaskUtils.getTaskTitle(taskReportID, action?.childReportName ?? ''));
const taskAssigneeAccountID = Task.getTaskAssigneeAccountID(taskReport ?? {}) ?? action?.childManagerAccountID ?? '';
const assigneeLogin = personalDetails[taskAssigneeAccountID]?.login ?? '';
diff --git a/src/hooks/useDragAndDrop.ts b/src/hooks/useDragAndDrop.ts
index 8c9054dc0bf1..7644d7bba5f0 100644
--- a/src/hooks/useDragAndDrop.ts
+++ b/src/hooks/useDragAndDrop.ts
@@ -1,6 +1,6 @@
import {useIsFocused} from '@react-navigation/native';
import type React from 'react';
-import {useCallback, useContext, useEffect, useState} from 'react';
+import {useCallback, useContext, useEffect, useRef, useState} from 'react';
import type {View} from 'react-native';
import {PopoverContext} from '@components/PopoverProvider';
@@ -31,6 +31,8 @@ export default function useDragAndDrop({dropZone, onDrop = () => {}, shouldAllow
const [isDraggingOver, setIsDraggingOver] = useState(false);
const {close: closePopover} = useContext(PopoverContext);
+ const enterTarget = useRef(null);
+
useEffect(() => {
if (isFocused && !isDisabled) {
return;
@@ -76,6 +78,7 @@ export default function useDragAndDrop({dropZone, onDrop = () => {}, shouldAllow
break;
case DRAG_ENTER_EVENT:
handleDragEvent(event);
+ enterTarget.current = event.target;
if (isDraggingOver) {
return;
}
@@ -86,7 +89,7 @@ export default function useDragAndDrop({dropZone, onDrop = () => {}, shouldAllow
return;
}
// This is necessary because dragging over children will cause dragleave to execute on the parent.
- if ((event.currentTarget as HTMLElement | null)?.contains(event.relatedTarget as HTMLElement | null)) {
+ if (enterTarget.current !== event.target) {
return;
}
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 09fd295cb859..b6fa37560536 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1,4 +1,5 @@
import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST';
+import Str from 'expensify-common/lib/str';
import CONST from '@src/CONST';
import type {
AddressLineParams,
@@ -588,7 +589,8 @@ export default {
receiptStatusText: "Only you can see this receipt when it's scanning. Check back later or enter the details now.",
receiptScanningFailed: 'Receipt scanning failed. Enter the details manually.',
transactionPendingText: 'It takes a few days from the date the card was used for the transaction to post.',
- requestCount: ({count, scanningReceipts = 0}: RequestCountParams) => `${count} requests${scanningReceipts > 0 ? `, ${scanningReceipts} scanning` : ''}`,
+ requestCount: ({count, scanningReceipts = 0}: RequestCountParams) =>
+ `${count} ${Str.pluralize('request', 'requests', count)}${scanningReceipts > 0 ? `, ${scanningReceipts} scanning` : ''}`,
deleteRequest: 'Delete request',
deleteConfirmation: 'Are you sure that you want to delete this request?',
settledExpensify: 'Paid',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index b977a614ae7e..271f0787bfde 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1,3 +1,4 @@
+import Str from 'expensify-common/lib/str';
import CONST from '@src/CONST';
import type {
AddressLineParams,
@@ -581,7 +582,8 @@ export default {
receiptStatusText: 'Solo tú puedes ver este recibo cuando se está escaneando. Vuelve más tarde o introduce los detalles ahora.',
receiptScanningFailed: 'El escaneo de recibo ha fallado. Introduce los detalles manualmente.',
transactionPendingText: 'La transacción tarda unos dÃas en contabilizarse desde la fecha en que se utilizó la tarjeta.',
- requestCount: ({count, scanningReceipts = 0}: RequestCountParams) => `${count} solicitudes${scanningReceipts > 0 ? `, ${scanningReceipts} escaneando` : ''}`,
+ requestCount: ({count, scanningReceipts = 0}: RequestCountParams) =>
+ `${count} ${Str.pluralize('solicitude', 'solicitudes', count)}${scanningReceipts > 0 ? `, ${scanningReceipts} escaneando` : ''}`,
deleteRequest: 'Eliminar pedido',
deleteConfirmation: '¿Estás seguro de que quieres eliminar este pedido?',
settledExpensify: 'Pagado',
diff --git a/src/libs/E2E/apiMocks/openApp.ts b/src/libs/E2E/apiMocks/openApp.ts
index ec714d693666..d6dd4a8f8003 100644
--- a/src/libs/E2E/apiMocks/openApp.ts
+++ b/src/libs/E2E/apiMocks/openApp.ts
@@ -2043,10 +2043,10 @@ const openApp = (): Response => ({
managerID: 16,
currency: 'USD',
chatReportID: '98817646',
- state: 'SUBMITTED',
cachedTotal: '($1,473.11)',
total: 147311,
stateNum: 1,
+ statusNum: 1,
},
report_4249286573496381: {
reportID: '4249286573496381',
@@ -2054,10 +2054,10 @@ const openApp = (): Response => ({
managerID: 21,
currency: 'USD',
chatReportID: '4867098979334014',
- state: 'SUBMITTED',
cachedTotal: '($212.78)',
total: 21278,
stateNum: 1,
+ statusNum: 1,
},
},
},
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 8563db7db172..8d227fa6f697 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -3,6 +3,7 @@ import type {CommonActions, NavigationContainerRefWithCurrent, NavigationHelpers
import type {ValueOf} from 'type-fest';
import type CONST from '@src/CONST';
import type NAVIGATORS from '@src/NAVIGATORS';
+import type {Route as Routes} from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
type NavigationRef = NavigationContainerRefWithCurrent;
@@ -378,10 +379,11 @@ type RightModalNavigatorParamList = {
type PublicScreensParamList = {
[SCREENS.HOME]: undefined;
[SCREENS.TRANSITION_BETWEEN_APPS]: {
- shouldForceLogin: string;
- email: string;
- shortLivedAuthToken: string;
- exitTo: string;
+ email?: string;
+ error?: string;
+ shortLivedAuthToken?: string;
+ shortLivedToken?: string;
+ exitTo?: Routes;
};
[SCREENS.VALIDATE_LOGIN]: {
accountID: string;
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index b632dbd1fd03..ba1e33360af1 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -14,7 +14,7 @@ import CONST from '@src/CONST';
import type {ParentNavigationSummaryParams, TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
-import type {Beta, Login, PersonalDetails, PersonalDetailsList, Policy, Report, ReportAction, ReportMetadata, Session, Transaction} from '@src/types/onyx';
+import type {Beta, Login, PersonalDetails, PersonalDetailsList, Policy, PolicyReportField, Report, ReportAction, ReportMetadata, Session, Transaction} from '@src/types/onyx';
import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon';
import type {IOUMessage, OriginalMessageActionName, OriginalMessageCreated, ReimbursementDeQueuedMessage} from '@src/types/onyx/OriginalMessage';
import type {Status} from '@src/types/onyx/PersonalDetails';
@@ -112,7 +112,6 @@ type OptimisticExpenseReport = Pick<
| 'ownerAccountID'
| 'currency'
| 'reportName'
- | 'state'
| 'stateNum'
| 'statusNum'
| 'total'
@@ -311,13 +310,12 @@ type OptimisticIOUReport = Pick<
| 'participantAccountIDs'
| 'visibleChatMemberAccountIDs'
| 'reportID'
- | 'state'
| 'stateNum'
+ | 'statusNum'
| 'total'
| 'reportName'
| 'notificationPreference'
| 'parentReportID'
- | 'statusNum'
| 'lastVisibleActionCreated'
>;
type DisplayNameWithTooltips = Array>;
@@ -590,14 +588,16 @@ function isCanceledTaskReport(report: OnyxEntry | EmptyObject = {}, pare
* @param parentReportAction - The parent report action of the report (Used to check if the task has been canceled)
*/
function isOpenTaskReport(report: OnyxEntry, parentReportAction: OnyxEntry | EmptyObject = {}): boolean {
- return isTaskReport(report) && !isCanceledTaskReport(report, parentReportAction) && report?.stateNum === CONST.REPORT.STATE_NUM.OPEN && report?.statusNum === CONST.REPORT.STATUS.OPEN;
+ return (
+ isTaskReport(report) && !isCanceledTaskReport(report, parentReportAction) && report?.stateNum === CONST.REPORT.STATE_NUM.OPEN && report?.statusNum === CONST.REPORT.STATUS_NUM.OPEN
+ );
}
/**
* Checks if a report is a completed task report.
*/
function isCompletedTaskReport(report: OnyxEntry): boolean {
- return isTaskReport(report) && report?.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && report?.statusNum === CONST.REPORT.STATUS.APPROVED;
+ return isTaskReport(report) && report?.stateNum === CONST.REPORT.STATE_NUM.APPROVED && report?.statusNum === CONST.REPORT.STATUS_NUM.APPROVED;
}
/**
@@ -612,14 +612,14 @@ function isReportManager(report: OnyxEntry): boolean {
*/
function isReportApproved(reportOrID: OnyxEntry | string | EmptyObject): boolean {
const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID;
- return report?.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && report?.statusNum === CONST.REPORT.STATUS.APPROVED;
+ return report?.stateNum === CONST.REPORT.STATE_NUM.APPROVED && report?.statusNum === CONST.REPORT.STATUS_NUM.APPROVED;
}
/**
* Checks if the supplied report is an expense report in Open state and status.
*/
function isDraftExpenseReport(report: OnyxEntry | EmptyObject): boolean {
- return isExpenseReport(report) && report?.stateNum === CONST.REPORT.STATE_NUM.OPEN && report?.statusNum === CONST.REPORT.STATUS.OPEN;
+ return isExpenseReport(report) && report?.stateNum === CONST.REPORT.STATE_NUM.OPEN && report?.statusNum === CONST.REPORT.STATUS_NUM.OPEN;
}
/**
@@ -650,11 +650,11 @@ function isSettled(reportID: string | undefined): boolean {
// In case the payment is scheduled and we are waiting for the payee to set up their wallet,
// consider the report as paid as well.
- if (report.isWaitingOnBankAccount && report.statusNum === CONST.REPORT.STATUS.APPROVED) {
+ if (report.isWaitingOnBankAccount && report.statusNum === CONST.REPORT.STATUS_NUM.APPROVED) {
return true;
}
- return report?.statusNum === CONST.REPORT.STATUS.REIMBURSED;
+ return report?.statusNum === CONST.REPORT.STATUS_NUM.REIMBURSED;
}
/**
@@ -837,7 +837,7 @@ function isConciergeChatReport(report: OnyxEntry): boolean {
* Returns true if report is still being processed
*/
function isProcessingReport(report: OnyxEntry | EmptyObject): boolean {
- return report?.stateNum === CONST.REPORT.STATE_NUM.PROCESSING && report?.statusNum === CONST.REPORT.STATUS.SUBMITTED;
+ return report?.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && report?.statusNum === CONST.REPORT.STATUS_NUM.SUBMITTED;
}
/**
@@ -943,7 +943,7 @@ function findLastAccessedReport(
* Whether the provided report is an archived room
*/
function isArchivedRoom(report: OnyxEntry | EmptyObject): boolean {
- return report?.statusNum === CONST.REPORT.STATUS.CLOSED && report?.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED;
+ return report?.statusNum === CONST.REPORT.STATUS_NUM.CLOSED && report?.stateNum === CONST.REPORT.STATE_NUM.APPROVED;
}
/**
@@ -1102,13 +1102,25 @@ function getReportNotificationPreference(report: OnyxEntry): string | nu
}
/**
- * Returns whether or not the author of the action is this user
- *
+ * Checks if the current user is the action's author
*/
-function isActionCreator(reportAction: OnyxEntry): boolean {
+function isActionCreator(reportAction: OnyxEntry | Partial): boolean {
return reportAction?.actorAccountID === currentUserAccountID;
}
+/**
+ * Returns the notification preference of the action's child report if it exists.
+ * Otherwise, calculates it based on the action's authorship.
+ */
+function getChildReportNotificationPreference(reportAction: OnyxEntry | Partial): NotificationPreference {
+ const childReportNotificationPreference = reportAction?.childReportNotificationPreference ?? '';
+ if (childReportNotificationPreference) {
+ return childReportNotificationPreference;
+ }
+
+ return isActionCreator(reportAction) ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
+}
+
/**
* Can only delete if the author is this user and the action is an ADDCOMMENT action or an IOU action in an unsettled report, or if the user is a
* policy admin
@@ -2531,7 +2543,7 @@ function buildOptimisticTaskCommentReportAction(taskReportID: string, taskTitle:
reportAction.reportAction.childType = CONST.REPORT.TYPE.TASK;
reportAction.reportAction.childReportName = taskTitle;
reportAction.reportAction.childManagerAccountID = taskAssigneeAccountID;
- reportAction.reportAction.childStatusNum = CONST.REPORT.STATUS.OPEN;
+ reportAction.reportAction.childStatusNum = CONST.REPORT.STATUS_NUM.OPEN;
reportAction.reportAction.childStateNum = CONST.REPORT.STATE_NUM.OPEN;
return reportAction;
@@ -2566,9 +2578,8 @@ function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number
participantAccountIDs: participantsAccountIDs,
visibleChatMemberAccountIDs: participantsAccountIDs,
reportID: generateReportID(),
- state: CONST.REPORT.STATE.SUBMITTED,
- stateNum: isSendingMoney ? CONST.REPORT.STATE_NUM.SUBMITTED : CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: isSendingMoney ? CONST.REPORT.STATUS.REIMBURSED : CONST.REPORT.STATE_NUM.PROCESSING,
+ stateNum: isSendingMoney ? CONST.REPORT.STATE_NUM.APPROVED : CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: isSendingMoney ? CONST.REPORT.STATUS_NUM.REIMBURSED : CONST.REPORT.STATE_NUM.SUBMITTED,
total,
// We don't translate reportName because the server response is always in English
@@ -2599,9 +2610,8 @@ function buildOptimisticExpenseReport(chatReportID: string, policyID: string, pa
const isFree = policy?.type === CONST.POLICY.TYPE.FREE;
// Define the state and status of the report based on whether the policy is free or paid
- const state = isFree ? CONST.REPORT.STATE.SUBMITTED : CONST.REPORT.STATE.OPEN;
- const stateNum = isFree ? CONST.REPORT.STATE_NUM.PROCESSING : CONST.REPORT.STATE_NUM.OPEN;
- const statusNum = isFree ? CONST.REPORT.STATUS.SUBMITTED : CONST.REPORT.STATUS.OPEN;
+ const stateNum = isFree ? CONST.REPORT.STATE_NUM.SUBMITTED : CONST.REPORT.STATE_NUM.OPEN;
+ const statusNum = isFree ? CONST.REPORT.STATUS_NUM.SUBMITTED : CONST.REPORT.STATUS_NUM.OPEN;
return {
reportID: generateReportID(),
@@ -2613,7 +2623,6 @@ function buildOptimisticExpenseReport(chatReportID: string, policyID: string, pa
// We don't translate reportName because the server response is always in English
reportName: `${policyName} owes ${formattedTotal}`,
- state,
stateNum,
statusNum,
total: storedTotal,
@@ -3353,7 +3362,7 @@ function buildOptimisticTaskReport(
parentReportID,
policyID,
stateNum: CONST.REPORT.STATE_NUM.OPEN,
- statusNum: CONST.REPORT.STATUS.OPEN,
+ statusNum: CONST.REPORT.STATUS_NUM.OPEN,
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
lastVisibleActionCreated: DateUtils.getDBTime(),
};
@@ -3590,7 +3599,7 @@ function getChatByParticipantsAndPolicy(newParticipantList: number[], policyID:
if (!report?.participantAccountIDs) {
return false;
}
- const sortedParticipanctsAccountIDs = report.parentReportActionIDs?.sort();
+ const sortedParticipanctsAccountIDs = report.participantAccountIDs?.sort();
// Only return the room if it has all the participants and is not a policy room
return report.policyID === policyID && lodashIsEqual(newParticipantList, sortedParticipanctsAccountIDs);
}) ?? null
@@ -4375,6 +4384,25 @@ function navigateToPrivateNotes(report: Report, session: Session) {
Navigation.navigate(ROUTES.PRIVATE_NOTES_LIST.getRoute(report.reportID));
}
+/**
+ * Given a report field and a report, get the title of the field.
+ * This is specially useful when we have a report field of type formula.
+ */
+function getReportFieldTitle(report: OnyxEntry, reportField: PolicyReportField): string {
+ const value = report?.reportFields?.[reportField.fieldID] ?? reportField.defaultValue;
+
+ if (reportField.type !== 'formula') {
+ return value;
+ }
+
+ return value.replaceAll(CONST.REGEX.REPORT_FIELD_TITLE, (match, property) => {
+ if (report && property in report) {
+ return report[property as keyof Report]?.toString() ?? match;
+ }
+ return match;
+ });
+}
+
/**
* Checks if thread replies should be displayed
*/
@@ -4583,8 +4611,10 @@ export {
canEditWriteCapability,
hasSmartscanError,
shouldAutoFocusOnKeyPress,
+ getReportFieldTitle,
shouldDisplayThreadReplies,
shouldDisableThread,
+ getChildReportNotificationPreference,
};
export type {ExpenseOriginalMessage, OptionData, OptimisticChatReport, OptimisticCreatedReportAction};
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index ca572452cc82..49b6a3b445e1 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -945,6 +945,7 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t
const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.parentReportID}`];
const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport);
+ const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction);
const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport);
const transactionDetails = ReportUtils.getTransactionDetails(updatedTransaction);
@@ -1030,6 +1031,30 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t
},
});
+ if (isScanning && (_.has(transactionChanges, 'amount') || _.has(transactionChanges, 'currency'))) {
+ optimisticData.push(
+ ...[
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
+ value: {
+ [transactionThread.parentReportActionID]: {
+ whisperedToAccountIDs: [],
+ },
+ },
+ },
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.parentReportID}`,
+ value: {
+ [iouReport.parentReportActionID]: {
+ whisperedToAccountIDs: [],
+ },
+ },
+ },
+ ],
+ );
+ }
// Update recently used categories if the category is changed
if (_.has(transactionChanges, 'category')) {
const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport.policyID, transactionChanges.category);
@@ -1158,6 +1183,21 @@ function updateMoneyRequestTag(transactionID, transactionThreadReportID, tag) {
API.write('UpdateMoneyRequestTag', params, onyxData);
}
+/**
+ * Updates the description of a money request
+ *
+ * @param {String} transactionID
+ * @param {Number} transactionThreadReportID
+ * @param {String} comment
+ */
+function updateMoneyRequestDescription(transactionID, transactionThreadReportID, comment) {
+ const transactionChanges = {
+ comment,
+ };
+ const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
+ API.write('UpdateMoneyRequestDescription', params, onyxData);
+}
+
/**
* Edits an existing distance request
*
@@ -3016,7 +3056,7 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
lastMessageText: optimisticIOUReportAction.message[0].text,
lastMessageHtml: optimisticIOUReportAction.message[0].html,
hasOutstandingChildRequest: false,
- statusNum: CONST.REPORT.STATUS.REIMBURSED,
+ statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED,
},
},
{
@@ -3164,8 +3204,8 @@ function approveMoneyRequest(expenseReport) {
...expenseReport,
lastMessageText: optimisticApprovedReportAction.message[0].text,
lastMessageHtml: optimisticApprovedReportAction.message[0].html,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
- statusNum: CONST.REPORT.STATUS.APPROVED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
+ statusNum: CONST.REPORT.STATUS_NUM.APPROVED,
},
};
const optimisticData = [optimisticIOUReportData, optimisticReportActionsData];
@@ -3238,9 +3278,8 @@ function submitReport(expenseReport) {
...expenseReport,
lastMessageText: lodashGet(optimisticSubmittedReportAction, 'message.0.text', ''),
lastMessageHtml: lodashGet(optimisticSubmittedReportAction, 'message.0.html', ''),
- state: CONST.REPORT.STATE.SUBMITTED,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
},
},
...(parentReport.reportID
@@ -3286,7 +3325,7 @@ function submitReport(expenseReport) {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`,
value: {
- statusNum: CONST.REPORT.STATUS.OPEN,
+ statusNum: CONST.REPORT.STATUS_NUM.OPEN,
stateNum: CONST.REPORT.STATE_NUM.OPEN,
},
},
@@ -3354,9 +3393,8 @@ function cancelPayment(expenseReport, chatReport) {
...expenseReport,
lastMessageText: lodashGet(optimisticReportAction, 'message.0.text', ''),
lastMessageHtml: lodashGet(optimisticReportAction, 'message.0.html', ''),
- state: isFree ? CONST.REPORT.STATE.SUBMITTED : CONST.REPORT.STATE.OPEN,
- stateNum: isFree ? CONST.REPORT.STATE_NUM.PROCESSING : CONST.REPORT.STATE.OPEN,
- statusNum: isFree ? CONST.REPORT.STATUS.SUBMITTED : CONST.REPORT.STATE.OPEN,
+ stateNum: isFree ? CONST.REPORT.STATE_NUM.SUBMITTED : CONST.REPORT.STATE_NUM.OPEN,
+ statusNum: isFree ? CONST.REPORT.STATUS_NUM.SUBMITTED : CONST.REPORT.STATUS_NUM.OPEN,
},
},
...(chatReport.reportID
@@ -3401,7 +3439,7 @@ function cancelPayment(expenseReport, chatReport) {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`,
value: {
- statusNum: CONST.REPORT.STATUS.REIMBURSED,
+ statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED,
},
},
...(chatReport.reportID
@@ -3756,6 +3794,7 @@ export {
updateMoneyRequestMerchant,
updateMoneyRequestTag,
updateMoneyRequestAmountAndCurrency,
+ updateMoneyRequestDescription,
replaceReceipt,
detachReceipt,
getIOUReportID,
diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js
index a21b795fa89a..25c8cf5ade80 100644
--- a/src/libs/actions/Policy.js
+++ b/src/libs/actions/Policy.js
@@ -173,8 +173,8 @@ function deleteWorkspace(policyID, reports, policyName) {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
- statusNum: CONST.REPORT.STATUS.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
hasDraft: false,
oldPolicyName: allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`].name,
},
@@ -368,8 +368,8 @@ function removeMembers(accountIDs, policyID) {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`,
value: {
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
oldPolicyName: policy.name,
hasDraft: false,
},
@@ -475,7 +475,7 @@ function createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs, hasOutsta
key: `${ONYXKEYS.COLLECTION.REPORT}${oldChat.reportID}`,
value: {
stateNum: CONST.REPORT.STATE_NUM.OPEN,
- statusNum: CONST.REPORT.STATUS.OPEN,
+ statusNum: CONST.REPORT.STATUS_NUM.OPEN,
},
});
return;
diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index b182b7019846..9067e5592937 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -741,7 +741,7 @@ function navigateToAndOpenChildReport(childReportID = '0', parentReportAction: P
'',
undefined,
undefined,
- CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
+ ReportUtils.getChildReportNotificationPreference(parentReportAction),
parentReportAction.reportActionID,
parentReportID,
);
@@ -2095,8 +2095,8 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal
}
: {
reportID: null,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
- statusNum: CONST.REPORT.STATUS.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
},
},
diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js
index e46c9fc380cd..a135c2c8fa94 100644
--- a/src/libs/actions/Task.js
+++ b/src/libs/actions/Task.js
@@ -246,8 +246,8 @@ function completeTask(taskReport) {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`,
value: {
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
- statusNum: CONST.REPORT.STATUS.APPROVED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
+ statusNum: CONST.REPORT.STATUS_NUM.APPROVED,
},
},
@@ -275,7 +275,7 @@ function completeTask(taskReport) {
key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`,
value: {
stateNum: CONST.REPORT.STATE_NUM.OPEN,
- statusNum: CONST.REPORT.STATUS.OPEN,
+ statusNum: CONST.REPORT.STATUS_NUM.OPEN,
},
},
{
@@ -314,7 +314,7 @@ function reopenTask(taskReport) {
key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`,
value: {
stateNum: CONST.REPORT.STATE_NUM.OPEN,
- statusNum: CONST.REPORT.STATUS.OPEN,
+ statusNum: CONST.REPORT.STATUS_NUM.OPEN,
lastVisibleActionCreated: reopenedTaskReportAction.created,
lastMessageText: message,
lastActorAccountID: reopenedTaskReportAction.actorAccountID,
@@ -344,8 +344,8 @@ function reopenTask(taskReport) {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`,
value: {
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
- statusNum: CONST.REPORT.STATUS.APPROVED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
+ statusNum: CONST.REPORT.STATUS_NUM.APPROVED,
},
},
{
diff --git a/src/libs/actions/Welcome.ts b/src/libs/actions/Welcome.ts
index 5046449c7389..3e3cba49480d 100644
--- a/src/libs/actions/Welcome.ts
+++ b/src/libs/actions/Welcome.ts
@@ -132,7 +132,7 @@ function show({routes, showCreateMenu = () => {}, showPopoverMenu = () => false}
const workspaceChatReport = Object.values(allReports ?? {}).find((report) => {
if (report) {
- return ReportUtils.isPolicyExpenseChat(report) && report.ownerAccountID === currentUserAccountID && report.statusNum !== CONST.REPORT.STATUS.CLOSED;
+ return ReportUtils.isPolicyExpenseChat(report) && report.ownerAccountID === currentUserAccountID && report.statusNum !== CONST.REPORT.STATUS_NUM.CLOSED;
}
return false;
});
diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js
index fe43d96001a0..606d3da1ddb9 100644
--- a/src/pages/EditRequestPage.js
+++ b/src/pages/EditRequestPage.js
@@ -176,18 +176,22 @@ function EditRequestPage({report, route, policyCategories, policyTags, parentRep
[transactionTag, transaction.transactionID, report.reportID],
);
+ const saveComment = useCallback(
+ ({comment: newComment}) => {
+ // Only update comment if it has changed
+ if (newComment.trim() !== transactionDescription) {
+ IOU.updateMoneyRequestDescription(transaction.transactionID, report.reportID, newComment.trim());
+ }
+ Navigation.dismissModal();
+ },
+ [transactionDescription, transaction.transactionID, report.reportID],
+ );
+
if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.DESCRIPTION) {
return (
{
- // In case the comment hasn't been changed, do not make the API request.
- if (transactionChanges.comment.trim() === transactionDescription) {
- Navigation.dismissModal();
- return;
- }
- editMoneyRequest({comment: transactionChanges.comment.trim()});
- }}
+ onSubmit={saveComment}
/>
);
}
diff --git a/src/pages/ErrorPage/ErrorBodyText/index.js b/src/pages/ErrorPage/ErrorBodyText/index.tsx
similarity index 54%
rename from src/pages/ErrorPage/ErrorBodyText/index.js
rename to src/pages/ErrorPage/ErrorBodyText/index.tsx
index 47b765f8f5e8..e675e0447361 100644
--- a/src/pages/ErrorPage/ErrorBodyText/index.js
+++ b/src/pages/ErrorPage/ErrorBodyText/index.tsx
@@ -1,29 +1,27 @@
import React from 'react';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
-import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
-const propTypes = {
- ...withLocalizePropTypes,
-};
-
-function ErrorBodyText(props) {
+function ErrorBodyText() {
const styles = useThemeStyles();
+ const {translate} = useLocalize();
+
return (
- {`${props.translate('genericErrorPage.body.helpTextMobile')} `}
+ {`${translate('genericErrorPage.body.helpTextMobile')} `}
- {props.translate('genericErrorPage.body.helpTextWeb')}
+ {translate('genericErrorPage.body.helpTextWeb')}
);
}
ErrorBodyText.displayName = 'ErrorBodyText';
-ErrorBodyText.propTypes = propTypes;
-export default withLocalize(ErrorBodyText);
+
+export default ErrorBodyText;
diff --git a/src/pages/ErrorPage/ErrorBodyText/index.website.js b/src/pages/ErrorPage/ErrorBodyText/index.website.tsx
similarity index 100%
rename from src/pages/ErrorPage/ErrorBodyText/index.website.js
rename to src/pages/ErrorPage/ErrorBodyText/index.website.tsx
diff --git a/src/pages/ErrorPage/GenericErrorPage.js b/src/pages/ErrorPage/GenericErrorPage.tsx
similarity index 91%
rename from src/pages/ErrorPage/GenericErrorPage.js
rename to src/pages/ErrorPage/GenericErrorPage.tsx
index 56fb5b970084..f4f1d91418c7 100644
--- a/src/pages/ErrorPage/GenericErrorPage.js
+++ b/src/pages/ErrorPage/GenericErrorPage.tsx
@@ -9,7 +9,7 @@ import ImageSVG from '@components/ImageSVG';
import SafeAreaConsumer from '@components/SafeAreaConsumer';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
-import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
@@ -18,20 +18,18 @@ import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ErrorBodyText from './ErrorBodyText';
-const propTypes = {
- ...withLocalizePropTypes,
-};
-
-function GenericErrorPage({translate}) {
+function GenericErrorPage() {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
+ const {translate} = useLocalize();
+
const {resetBoundary} = useErrorBoundary();
return (
{({paddingBottom}) => (
-
+
@@ -78,7 +76,7 @@ function GenericErrorPage({translate}) {
-
+
void;
};
// eslint-disable-next-line rulesdir/no-negated-variables
-function NotFoundPage(props) {
+function NotFoundPage({onBackButtonPress}: NotFoundPageProps) {
return (
);
}
NotFoundPage.displayName = 'NotFoundPage';
-NotFoundPage.propTypes = propTypes;
-NotFoundPage.defaultProps = defaultProps;
export default NotFoundPage;
diff --git a/src/pages/LogInWithShortLivedAuthTokenPage.js b/src/pages/LogInWithShortLivedAuthTokenPage.tsx
similarity index 65%
rename from src/pages/LogInWithShortLivedAuthTokenPage.js
rename to src/pages/LogInWithShortLivedAuthTokenPage.tsx
index 1fe9b67eef16..c5f8a9c20d5b 100644
--- a/src/pages/LogInWithShortLivedAuthTokenPage.js
+++ b/src/pages/LogInWithShortLivedAuthTokenPage.tsx
@@ -1,7 +1,7 @@
-import lodashGet from 'lodash/get';
-import PropTypes from 'prop-types';
+import type {StackScreenProps} from '@react-navigation/stack';
import React, {useEffect} from 'react';
import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import Icon from '@components/Icon';
@@ -13,62 +13,40 @@ import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
+import type {PublicScreensParamList} from '@libs/Navigation/types';
import * as Session from '@userActions/Session';
import ONYXKEYS from '@src/ONYXKEYS';
+import type SCREENS from '@src/SCREENS';
+import type {Account} from '@src/types/onyx';
-const propTypes = {
- /** The parameters needed to authenticate with a short-lived token are in the URL */
- route: PropTypes.shape({
- /** Each parameter passed via the URL */
- params: PropTypes.shape({
- /** Short-lived authToken to sign in a user */
- shortLivedAuthToken: PropTypes.string,
-
- /** Short-lived authToken to sign in as a user, if they are coming from the old mobile app */
- shortLivedToken: PropTypes.string,
-
- /** The email of the transitioning user */
- email: PropTypes.string,
- }),
- }).isRequired,
-
+type LogInWithShortLivedAuthTokenPageOnyxProps = {
/** The details about the account that the user is signing in with */
- account: PropTypes.shape({
- /** Whether a sign is loading */
- isLoading: PropTypes.bool,
- }),
+ account: OnyxEntry;
};
-const defaultProps = {
- account: {
- isLoading: false,
- },
-};
+type LogInWithShortLivedAuthTokenPageProps = LogInWithShortLivedAuthTokenPageOnyxProps & StackScreenProps;
-function LogInWithShortLivedAuthTokenPage(props) {
+function LogInWithShortLivedAuthTokenPage({route, account}: LogInWithShortLivedAuthTokenPageProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
+ const {email = '', shortLivedAuthToken = '', shortLivedToken = '', exitTo, error} = route?.params ?? {};
useEffect(() => {
- const email = lodashGet(props, 'route.params.email', '');
-
// We have to check for both shortLivedAuthToken and shortLivedToken, as the old mobile app uses shortLivedToken, and is not being actively updated.
- const shortLivedAuthToken = lodashGet(props, 'route.params.shortLivedAuthToken', '') || lodashGet(props, 'route.params.shortLivedToken', '');
+ const token = shortLivedAuthToken || shortLivedToken;
// Try to authenticate using the shortLivedToken if we're not already trying to load the accounts
- if (shortLivedAuthToken && !props.account.isLoading) {
- Session.signInWithShortLivedAuthToken(email, shortLivedAuthToken);
+ if (token && !account?.isLoading) {
+ Session.signInWithShortLivedAuthToken(email, token);
return;
}
// If an error is returned as part of the route, ensure we set it in the onyxData for the account
- const error = lodashGet(props, 'route.params.error', '');
if (error) {
Session.setAccountError(error);
}
- const exitTo = lodashGet(props, 'route.params.exitTo', '');
if (exitTo) {
Navigation.isNavigationReady().then(() => {
Navigation.navigate(exitTo);
@@ -76,9 +54,9 @@ function LogInWithShortLivedAuthTokenPage(props) {
}
// The only dependencies of the effect are based on props.route
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [props.route]);
+ }, [route]);
- if (props.account.isLoading) {
+ if (account?.isLoading) {
return ;
}
@@ -94,7 +72,7 @@ function LogInWithShortLivedAuthTokenPage(props) {
{translate('deeplinkWrapper.launching')}
-
+
{translate('deeplinkWrapper.expired')}{' '}
{
@@ -119,10 +97,8 @@ function LogInWithShortLivedAuthTokenPage(props) {
);
}
-LogInWithShortLivedAuthTokenPage.propTypes = propTypes;
-LogInWithShortLivedAuthTokenPage.defaultProps = defaultProps;
LogInWithShortLivedAuthTokenPage.displayName = 'LogInWithShortLivedAuthTokenPage';
-export default withOnyx({
+export default withOnyx({
account: {key: ONYXKEYS.ACCOUNT},
})(LogInWithShortLivedAuthTokenPage);
diff --git a/src/pages/SearchPage/SearchPageFooter.tsx b/src/pages/SearchPage/SearchPageFooter.tsx
index 69429962869b..e0ef67ad9ec3 100644
--- a/src/pages/SearchPage/SearchPageFooter.tsx
+++ b/src/pages/SearchPage/SearchPageFooter.tsx
@@ -1,55 +1,15 @@
import React from 'react';
import {View} from 'react-native';
-import Icon from '@components/Icon';
-import {Info} from '@components/Icon/Expensicons';
-import {PressableWithoutFeedback} from '@components/Pressable';
-import Text from '@components/Text';
-import useLocalize from '@hooks/useLocalize';
-import useTheme from '@hooks/useTheme';
+import ReferralProgramCTA from '@components/ReferralProgramCTA';
import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
function SearchPageFooter() {
const themeStyles = useThemeStyles();
- const theme = useTheme();
- const {translate} = useLocalize();
return (
- {
- Navigation.navigate(ROUTES.REFERRAL_DETAILS_MODAL.getRoute(CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND));
- }}
- style={[
- themeStyles.p5,
- themeStyles.w100,
- themeStyles.br2,
- themeStyles.highlightBG,
- themeStyles.flexRow,
- themeStyles.justifyContentBetween,
- themeStyles.alignItemsCenter,
- {gap: 10},
- ]}
- accessibilityLabel="referral"
- role={CONST.ACCESSIBILITY_ROLE.BUTTON}
- >
-
- {translate(`referralProgram.${CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND}.buttonText1`)}
-
- {translate(`referralProgram.${CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND}.buttonText2`)}
-
-
-
-
+
);
}
diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js
index edf6b65b2f4a..9b2765718250 100644
--- a/src/pages/home/HeaderView.js
+++ b/src/pages/home/HeaderView.js
@@ -109,9 +109,7 @@ function HeaderView(props) {
const isAutomatedExpensifyAccount = ReportUtils.hasSingleParticipant(props.report) && ReportUtils.hasAutomatedExpensifyAccountIDs(participants);
const parentReportAction = ReportActionsUtils.getParentReportAction(props.report);
const isCanceledTaskReport = ReportUtils.isCanceledTaskReport(props.report, parentReportAction);
- const lastVisibleMessage = ReportActionsUtils.getLastVisibleMessage(props.report.reportID);
const isWhisperAction = ReportActionsUtils.isWhisperAction(parentReportAction);
- const isEmptyChat = !props.report.lastMessageText && !props.report.lastMessageTranslationKey && !lastVisibleMessage.lastMessageText && !lastVisibleMessage.lastMessageTranslationKey;
const isUserCreatedPolicyRoom = ReportUtils.isUserCreatedPolicyRoom(props.report);
const isPolicyMember = useMemo(() => !_.isEmpty(props.policy), [props.policy]);
const canLeaveRoom = ReportUtils.canLeaveRoom(props.report, isPolicyMember);
@@ -133,7 +131,7 @@ function HeaderView(props) {
}
// Task is not closed
- if (props.report.stateNum !== CONST.REPORT.STATE_NUM.SUBMITTED && props.report.statusNum !== CONST.REPORT.STATUS.CLOSED && canModifyTask) {
+ if (props.report.stateNum !== CONST.REPORT.STATE_NUM.APPROVED && props.report.statusNum !== CONST.REPORT.STATUS_NUM.CLOSED && canModifyTask) {
threeDotMenuItems.push({
icon: Expensicons.Trashcan,
text: translate('common.delete'),
@@ -153,7 +151,7 @@ function HeaderView(props) {
),
);
- const canJoinOrLeave = (isChatThread && !isEmptyChat) || isUserCreatedPolicyRoom || canLeaveRoom;
+ const canJoinOrLeave = isChatThread || isUserCreatedPolicyRoom || canLeaveRoom;
const canJoin = canJoinOrLeave && !isWhisperAction && props.report.notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
const canLeave = canJoinOrLeave && ((isChatThread && props.report.notificationPreference.length) || isUserCreatedPolicyRoom || canLeaveRoom);
if (canJoin) {
diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js
index 64e48ecd5509..b35d9240f3f7 100644
--- a/src/pages/home/ReportScreen.js
+++ b/src/pages/home/ReportScreen.js
@@ -187,7 +187,7 @@ function ReportScreen({
// There are no reportActions at all to display and we are still in the process of loading the next set of actions.
const isLoadingInitialReportActions = _.isEmpty(reportActions) && reportMetadata.isLoadingInitialReportActions;
- const isOptimisticDelete = lodashGet(report, 'statusNum') === CONST.REPORT.STATUS.CLOSED;
+ const isOptimisticDelete = lodashGet(report, 'statusNum') === CONST.REPORT.STATUS_NUM.CLOSED;
const shouldHideReport = !ReportUtils.canAccessReport(report, policies, betas);
const isLoading = !reportID || !isSidebarLoaded || _.isEmpty(personalDetails);
const isSingleTransactionView = ReportUtils.isMoneyRequest(report);
@@ -383,8 +383,8 @@ function ReportScreen({
(prevOnyxReportID &&
prevOnyxReportID === routeReportID &&
!onyxReportID &&
- prevReport.statusNum === CONST.REPORT.STATUS.OPEN &&
- (report.statusNum === CONST.REPORT.STATUS.CLOSED || (!report.statusNum && !prevReport.parentReportID && prevReport.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ROOM))) ||
+ prevReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN &&
+ (report.statusNum === CONST.REPORT.STATUS_NUM.CLOSED || (!report.statusNum && !prevReport.parentReportID && prevReport.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ROOM))) ||
((ReportUtils.isMoneyRequest(prevReport) || ReportUtils.isMoneyRequestReport(prevReport)) && _.isEmpty(report))
) {
Navigation.dismissModal();
diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js
index 7db39c1ed856..aa815b0b32dc 100644
--- a/src/pages/home/report/ContextMenu/ContextMenuActions.js
+++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js
@@ -156,14 +156,10 @@ export default [
successTextTranslateKey: '',
successIcon: null,
shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID) => {
- let childReportNotificationPreference = lodashGet(reportAction, 'childReportNotificationPreference', '');
- if (!childReportNotificationPreference) {
- const isActionCreator = ReportUtils.isActionCreator(reportAction);
- childReportNotificationPreference = isActionCreator ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
- }
+ const childReportNotificationPreference = ReportUtils.getChildReportNotificationPreference(reportAction);
const isDeletedAction = ReportActionsUtils.isDeletedAction(reportAction);
const shouldDisplayThreadReplies = ReportUtils.shouldDisplayThreadReplies(reportAction, reportID);
- const subscribed = childReportNotificationPreference !== 'hidden';
+ const subscribed = childReportNotificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
const isCommentAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT && !ReportUtils.isThreadFirstChat(reportAction, reportID);
const isReportPreviewAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW;
const isIOUAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && !ReportActionsUtils.isSplitBillAction(reportAction);
@@ -171,11 +167,7 @@ export default [
return !subscribed && !isWhisperAction && (isCommentAction || isReportPreviewAction || isIOUAction) && (!isDeletedAction || shouldDisplayThreadReplies);
},
onPress: (closePopover, {reportAction, reportID}) => {
- let childReportNotificationPreference = lodashGet(reportAction, 'childReportNotificationPreference', '');
- if (!childReportNotificationPreference) {
- const isActionCreator = ReportUtils.isActionCreator(reportAction);
- childReportNotificationPreference = isActionCreator ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
- }
+ const childReportNotificationPreference = ReportUtils.getChildReportNotificationPreference(reportAction);
if (closePopover) {
hideContextMenu(false, () => {
ReportActionComposeFocusManager.focus();
@@ -196,14 +188,10 @@ export default [
successTextTranslateKey: '',
successIcon: null,
shouldShow: (type, reportAction, isArchivedRoom, betas, anchor, isChronosReport, reportID) => {
- let childReportNotificationPreference = lodashGet(reportAction, 'childReportNotificationPreference', '');
- if (!childReportNotificationPreference) {
- const isActionCreator = ReportUtils.isActionCreator(reportAction);
- childReportNotificationPreference = isActionCreator ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
- }
+ const childReportNotificationPreference = ReportUtils.getChildReportNotificationPreference(reportAction);
const isDeletedAction = ReportActionsUtils.isDeletedAction(reportAction);
const shouldDisplayThreadReplies = ReportUtils.shouldDisplayThreadReplies(reportAction, reportID);
- const subscribed = childReportNotificationPreference !== 'hidden';
+ const subscribed = childReportNotificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
if (type !== CONST.CONTEXT_MENU_TYPES.REPORT_ACTION) {
return false;
}
@@ -213,11 +201,7 @@ export default [
return subscribed && (isCommentAction || isReportPreviewAction || isIOUAction) && (!isDeletedAction || shouldDisplayThreadReplies);
},
onPress: (closePopover, {reportAction, reportID}) => {
- let childReportNotificationPreference = lodashGet(reportAction, 'childReportNotificationPreference', '');
- if (!childReportNotificationPreference) {
- const isActionCreator = ReportUtils.isActionCreator(reportAction);
- childReportNotificationPreference = isActionCreator ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
- }
+ const childReportNotificationPreference = ReportUtils.getChildReportNotificationPreference(reportAction);
if (closePopover) {
hideContextMenu(false, () => {
ReportActionComposeFocusManager.focus();
diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js
index 6c1d71625dc9..413807b1f992 100644
--- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js
+++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js
@@ -127,8 +127,8 @@ function ComposerWithSuggestions({
const maxComposerLines = isSmallScreenWidth ? CONST.COMPOSER.MAX_LINES_SMALL_SCREEN : CONST.COMPOSER.MAX_LINES;
const isEmptyChat = useMemo(() => _.size(reportActions) === 1, [reportActions]);
- const parentAction = ReportActionsUtils.getParentReportAction(report);
- const shouldAutoFocus = !modal.isVisible && (shouldFocusInputOnScreenFocus || (isEmptyChat && !ReportActionsUtils.isTransactionThread(parentAction))) && shouldShowComposeInput;
+ const parentReportAction = lodashGet(parentReportActions, [report.parentReportActionID]);
+ const shouldAutoFocus = !modal.isVisible && (shouldFocusInputOnScreenFocus || (isEmptyChat && !ReportActionsUtils.isTransactionThread(parentReportAction))) && shouldShowComposeInput;
const valueRef = useRef(value);
valueRef.current = value;
@@ -344,9 +344,6 @@ function ComposerWithSuggestions({
const valueLength = valueRef.current.length;
if (e.key === CONST.KEYBOARD_SHORTCUTS.ARROW_UP.shortcutKey && textInputRef.current.selectionStart === 0 && valueLength === 0 && !ReportUtils.chatIncludesChronos(report)) {
e.preventDefault();
-
- const parentReportActionID = lodashGet(report, 'parentReportActionID', '');
- const parentReportAction = lodashGet(parentReportActions, [parentReportActionID], {});
const lastReportAction = _.find(
[...reportActions, parentReportAction],
(action) => ReportUtils.canEditReportAction(action) && !ReportActionsUtils.isMoneyRequestAction(action),
@@ -356,7 +353,7 @@ function ComposerWithSuggestions({
}
}
},
- [isKeyboardShown, isSmallScreenWidth, parentReportActions, report, reportActions, reportID, handleSendMessage, suggestionsRef, valueRef],
+ [isKeyboardShown, isSmallScreenWidth, parentReportAction, report, reportActions, reportID, handleSendMessage, suggestionsRef, valueRef],
);
const onChangeText = useCallback(
diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js
index 1f6455ea6630..9573d4a4ff1a 100644
--- a/src/pages/home/report/ReportActionItem.js
+++ b/src/pages/home/report/ReportActionItem.js
@@ -645,6 +645,7 @@ function ReportActionItem(props) {
@@ -793,6 +794,10 @@ export default compose(
},
initialValue: {},
},
+ policyReportFields: {
+ key: ({report}) => (report && 'policyID' in report ? `${ONYXKEYS.COLLECTION.POLICY_REPORT_FIELDS}${report.policyID}` : undefined),
+ initialValue: [],
+ },
emojiReactions: {
key: ({action}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${action.reportActionID}`,
initialValue: {},
@@ -834,6 +839,8 @@ export default compose(
prevProps.shouldHideThreadDividerLine === nextProps.shouldHideThreadDividerLine &&
lodashGet(prevProps.report, 'total', 0) === lodashGet(nextProps.report, 'total', 0) &&
lodashGet(prevProps.report, 'nonReimbursableTotal', 0) === lodashGet(nextProps.report, 'nonReimbursableTotal', 0) &&
- prevProps.linkedReportActionID === nextProps.linkedReportActionID,
+ prevProps.linkedReportActionID === nextProps.linkedReportActionID &&
+ _.isEqual(prevProps.policyReportFields, nextProps.policyReportFields) &&
+ _.isEqual(prevProps.report.reportFields, nextProps.report.reportFields),
),
);
diff --git a/src/pages/home/report/ReportAttachments.js b/src/pages/home/report/ReportAttachments.tsx
similarity index 55%
rename from src/pages/home/report/ReportAttachments.js
rename to src/pages/home/report/ReportAttachments.tsx
index 8ecbb036a756..42ca51cabe0b 100644
--- a/src/pages/home/report/ReportAttachments.js
+++ b/src/pages/home/report/ReportAttachments.tsx
@@ -1,43 +1,47 @@
-import PropTypes from 'prop-types';
+import type {StackScreenProps} from '@react-navigation/stack';
import React, {useCallback} from 'react';
-import _ from 'underscore';
import AttachmentModal from '@components/AttachmentModal';
import ComposerFocusManager from '@libs/ComposerFocusManager';
import Navigation from '@libs/Navigation/Navigation';
+import type {AuthScreensParamList} from '@libs/Navigation/types';
import * as ReportUtils from '@libs/ReportUtils';
import ROUTES from '@src/ROUTES';
+import type SCREENS from '@src/SCREENS';
-const propTypes = {
- /** Navigation route context info provided by react navigation */
- route: PropTypes.shape({
- /** Route specific parameters used on this screen */
- params: PropTypes.shape({
- /** The report ID which the attachment is associated with */
- reportID: PropTypes.string.isRequired,
- /** The uri encoded source of the attachment */
- source: PropTypes.string.isRequired,
- }).isRequired,
- }).isRequired,
+type File = {
+ name: string;
};
-function ReportAttachments(props) {
- const reportID = _.get(props, ['route', 'params', 'reportID']);
+type Attachment = {
+ file: File;
+ hasBeenFlagged: boolean;
+ isAuthTokenRequired: boolean;
+ isReceipt: boolean;
+ reportActionID: string;
+ source: string;
+};
+
+type ReportAttachmentsProps = StackScreenProps;
+
+function ReportAttachments({route}: ReportAttachmentsProps) {
+ const reportID = route.params.reportID;
const report = ReportUtils.getReport(reportID);
// In native the imported images sources are of type number. Ref: https://reactnative.dev/docs/image#imagesource
- const decodedSource = decodeURI(_.get(props, ['route', 'params', 'source']));
+ const decodedSource = decodeURI(route.params.source);
const source = Number(decodedSource) || decodedSource;
const onCarouselAttachmentChange = useCallback(
- (attachment) => {
- const route = ROUTES.REPORT_ATTACHMENTS.getRoute(reportID, attachment.source);
- Navigation.navigate(route);
+ (attachment: Attachment) => {
+ const routeToNavigate = ROUTES.REPORT_ATTACHMENTS.getRoute(reportID, attachment.source);
+ Navigation.navigate(routeToNavigate);
},
[reportID],
);
return (
(
-
+
{shouldShowSplitBillErrorMessage && (
diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js
index 9edede770233..9567b17ecdf5 100755
--- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js
+++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js
@@ -8,6 +8,7 @@ import Button from '@components/Button';
import FormHelpMessage from '@components/FormHelpMessage';
import {usePersonalDetails} from '@components/OnyxProvider';
import {PressableWithFeedback} from '@components/Pressable';
+import ReferralProgramCTA from '@components/ReferralProgramCTA';
import SelectCircle from '@components/SelectCircle';
import SelectionList from '@components/SelectionList';
import useLocalize from '@hooks/useLocalize';
@@ -16,7 +17,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
import * as Report from '@libs/actions/Report';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as OptionsListUtils from '@libs/OptionsListUtils';
-import MoneyRequestReferralProgramCTA from '@pages/iou/MoneyRequestReferralProgramCTA';
import reportPropTypes from '@pages/reportPropTypes';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -285,7 +285,7 @@ function MoneyRequestParticipantsSelector({
() => (
-
+
{shouldShowSplitBillErrorMessage && (
diff --git a/src/pages/reportPropTypes.js b/src/pages/reportPropTypes.js
index 329bf66f7275..3a056ee7c0a3 100644
--- a/src/pages/reportPropTypes.js
+++ b/src/pages/reportPropTypes.js
@@ -63,11 +63,14 @@ export default PropTypes.shape({
stateNum: PropTypes.oneOf(_.values(CONST.REPORT.STATE_NUM)),
/** The status of the current report */
- statusNum: PropTypes.oneOf(_.values(CONST.REPORT.STATUS)),
+ statusNum: PropTypes.oneOf(_.values(CONST.REPORT.STATUS_NUM)),
/** Which user role is capable of posting messages on the report */
writeCapability: PropTypes.oneOf(_.values(CONST.REPORT.WRITE_CAPABILITIES)),
/** Field-specific pending states for offline UI status */
pendingFields: PropTypes.objectOf(PropTypes.string),
+
+ /** Custom fields attached to the report */
+ reportFields: PropTypes.objectOf(PropTypes.string),
});
diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.js b/src/pages/tasks/TaskAssigneeSelectorModal.js
index a4fc61910be2..1a526a9cdd9b 100644
--- a/src/pages/tasks/TaskAssigneeSelectorModal.js
+++ b/src/pages/tasks/TaskAssigneeSelectorModal.js
@@ -184,29 +184,29 @@ function TaskAssigneeSelectorModal(props) {
return sectionsList;
}, [filteredCurrentUserOption, filteredPersonalDetails, filteredRecentReports, filteredUserToInvite, props]);
- const selectReport = (option) => {
- if (!option) {
- return;
- }
-
- // Check to see if we're creating a new task
- // If there's no route params, we're creating a new task
- if (!props.route.params && option.accountID) {
- Task.setAssigneeValue(option.login, option.accountID, props.task.shareDestination, OptionsListUtils.isCurrentUser(option));
- return Navigation.goBack(ROUTES.NEW_TASK);
- }
-
- // Check to see if we're editing a task and if so, update the assignee
- if (report) {
- if (option.accountID !== report.managerID) {
- const assigneeChatReport = Task.setAssigneeValue(option.login, option.accountID, props.route.params.reportID, OptionsListUtils.isCurrentUser(option));
+ const selectReport = useCallback(
+ (option) => {
+ if (!option) {
+ return;
+ }
- // Pass through the selected assignee
- Task.editTaskAssignee(report, props.session.accountID, option.login, option.accountID, assigneeChatReport);
+ // Check to see if we're editing a task and if so, update the assignee
+ if (report) {
+ if (option.accountID !== report.managerID) {
+ const assigneeChatReport = Task.setAssigneeValue(option.login, option.accountID, report.reportID, OptionsListUtils.isCurrentUser(option));
+
+ // Pass through the selected assignee
+ Task.editTaskAssignee(report, props.session.accountID, option.login, option.accountID, assigneeChatReport);
+ }
+ Navigation.dismissModal(report.reportID);
+ // If there's no report, we're creating a new task
+ } else if (option.accountID) {
+ Task.setAssigneeValue(option.login, option.accountID, props.task.shareDestination, OptionsListUtils.isCurrentUser(option));
+ Navigation.goBack(ROUTES.NEW_TASK);
}
- return Navigation.dismissModal(report.reportID);
- }
- };
+ },
+ [props.session.accountID, props.task.shareDestination, report],
+ );
const isOpen = ReportUtils.isOpenTaskReport(report);
const canModifyTask = Task.canModifyTask(report, props.currentUserPersonalDetails.accountID, lodashGet(props.rootParentReportPolicy, 'role', ''));
diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts
index f6af87038d00..7cc3c508d926 100644
--- a/src/types/onyx/Report.ts
+++ b/src/types/onyx/Report.ts
@@ -83,14 +83,11 @@ type Report = {
/** ID of the chat report */
chatReportID?: string;
- /** The state of the report */
- state?: ValueOf;
-
/** The state that the report is currently in */
stateNum?: ValueOf;
/** The status of the current report */
- statusNum?: ValueOf;
+ statusNum?: ValueOf;
/** Which user role is capable of posting messages on the report */
writeCapability?: WriteCapability;
diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts
index b2dc340af606..d5c0e19f9373 100644
--- a/src/types/onyx/ReportAction.ts
+++ b/src/types/onyx/ReportAction.ts
@@ -158,7 +158,7 @@ type ReportActionBase = {
childManagerAccountID?: number;
/** The status of the child report */
- childStatusNum?: ValueOf;
+ childStatusNum?: ValueOf;
/** Report action child status name */
childStateNum?: ValueOf;
diff --git a/tests/actions/IOUTest.js b/tests/actions/IOUTest.js
index 3ba19199c30a..5b304346f38f 100644
--- a/tests/actions/IOUTest.js
+++ b/tests/actions/IOUTest.js
@@ -1237,9 +1237,8 @@ describe('actions/IOU', () => {
expect(chatReport.pendingFields).toBeFalsy();
expect(iouReport.pendingFields).toBeFalsy();
- // expect(iouReport.status).toBe(CONST.REPORT.STATUS.SUBMITTED);
- // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.SUBMITTED);
- // expect(iouReport.state).toBe(CONST.REPORT.STATE.SUBMITTED);
+ // expect(iouReport.status).toBe(CONST.REPORT.STATUS_NUM.SUBMITTED);
+ // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.APPROVED);
resolve();
},
@@ -1306,9 +1305,8 @@ describe('actions/IOU', () => {
expect(chatReport.iouReportID).toBeFalsy();
- // expect(iouReport.status).toBe(CONST.REPORT.STATUS.REIMBURSED);
- // expect(iouReport.state).toBe(CONST.REPORT.STATE.MANUALREIMBURSED);
- // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.SUBMITTED);
+ // expect(iouReport.status).toBe(CONST.REPORT.STATUS_NUM.REIMBURSED);
+ // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.APPROVED);
resolve();
},
@@ -1356,9 +1354,8 @@ describe('actions/IOU', () => {
expect(chatReport.iouReportID).toBeFalsy();
- // expect(iouReport.status).toBe(CONST.REPORT.STATUS.REIMBURSED);
- // expect(iouReport.state).toBe(CONST.REPORT.STATE.MANUALREIMBURSED);
- // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.SUBMITTED);
+ // expect(iouReport.status).toBe(CONST.REPORT.STATUS_NUM.REIMBURSED);
+ // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.APPROVED);
resolve();
},
@@ -1770,9 +1767,8 @@ describe('actions/IOU', () => {
expect.objectContaining({
lastMessageHtml: `paid $${amount / 100}.00 with Expensify`,
lastMessageText: `paid $${amount / 100}.00 with Expensify`,
- state: CONST.REPORT.STATE.SUBMITTED,
- statusNum: CONST.REPORT.STATUS.REIMBURSED,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
+ statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
}),
);
expect(updatedChatReport).toEqual(
diff --git a/tests/perf-test/OptionsSelector.perf-test.js b/tests/perf-test/OptionsSelector.perf-test.js
index 3959ed87460a..b30169b8b53f 100644
--- a/tests/perf-test/OptionsSelector.perf-test.js
+++ b/tests/perf-test/OptionsSelector.perf-test.js
@@ -82,7 +82,7 @@ test('[OptionsSelector] should render 1 section', () => {
measurePerformance(, {runs});
});
-test('[OptionsSelector] should render mutliple sections', () => {
+test('[OptionsSelector] should render multiple sections', () => {
const sections = generateSections(mutlipleSectionsConfig);
measurePerformance(, {runs});
});
diff --git a/tests/perf-test/ReportActionsUtils.perf-test.ts b/tests/perf-test/ReportActionsUtils.perf-test.ts
index ea3b48bacf47..2a96a5959942 100644
--- a/tests/perf-test/ReportActionsUtils.perf-test.ts
+++ b/tests/perf-test/ReportActionsUtils.perf-test.ts
@@ -9,18 +9,6 @@ import createCollection from '../utils/collections/createCollection';
import createRandomReportAction from '../utils/collections/reportActions';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
-beforeAll(() =>
- Onyx.init({
- keys: ONYXKEYS,
- safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
- }),
-);
-
-// Clear out Onyx after each test so that each test starts with a clean slate
-afterEach(() => {
- Onyx.clear();
-});
-
const getMockedReportActionsMap = (reportsLength = 10, actionsPerReportLength = 100) => {
const mockReportActions = Array.from({length: actionsPerReportLength}, (v, i) => {
const reportActionKey = i + 1;
@@ -49,120 +37,113 @@ const reportId = '1';
const runs = CONST.PERFORMANCE_TESTS.RUNS;
-/**
- * This function will be executed 20 times and the average time will be used on the comparison.
- * It will fail based on the CI configuration around Reassure:
- * @see /.github/workflows/reassurePerformanceTests.yml
- *
- * Max deviation on the duration is set to 20% at the time of writing.
- *
- * More on the measureFunction API:
- * @see https://callstack.github.io/reassure/docs/api#measurefunction-function
- */
-test('[ReportActionsUtils] getLastVisibleAction on 10k reportActions', async () => {
- await Onyx.multiSet({
- ...mockedReportActionsMap,
+describe('ReportActionsUtils', () => {
+ beforeAll(() => {
+ Onyx.init({
+ keys: ONYXKEYS,
+ safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
+ });
+
+ Onyx.multiSet({
+ ...mockedReportActionsMap,
+ });
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportActionsUtils.getLastVisibleAction(reportId), {runs});
-});
+ afterAll(() => {
+ Onyx.clear();
+ });
-test('[ReportActionsUtils] getLastVisibleAction on 10k reportActions with actionsToMerge', async () => {
- const parentReportActionId = '1';
- const fakeParentAction = reportActions[parentReportActionId];
- const actionsToMerge = {
- [parentReportActionId]: {
- pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
- previousMessage: fakeParentAction.message,
- message: [
- {
- translationKey: '',
- type: 'COMMENT',
- html: '',
- text: '',
- isEdited: true,
- isDeletedParentAction: true,
- },
- ],
- errors: null,
- linkMetaData: [],
- },
- } as unknown as ReportActions;
-
- await Onyx.multiSet({
- ...mockedReportActionsMap,
+ /**
+ * This function will be executed 20 times and the average time will be used on the comparison.
+ * It will fail based on the CI configuration around Reassure:
+ * @see /.github/workflows/reassurePerformanceTests.yml
+ *
+ * Max deviation on the duration is set to 20% at the time of writing.
+ *
+ * More on the measureFunction API:
+ * @see https://callstack.github.io/reassure/docs/api#measurefunction-function
+ */
+ test('[ReportActionsUtils] getLastVisibleAction on 10k reportActions', async () => {
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportActionsUtils.getLastVisibleAction(reportId), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportActionsUtils.getLastVisibleAction(reportId, actionsToMerge), {runs});
-});
-test('[ReportActionsUtils] getMostRecentIOURequestActionID on 10k ReportActions', async () => {
- const reportActionsArray = ReportActionsUtils.getSortedReportActionsForDisplay(reportActions);
- await Onyx.multiSet({
- ...mockedReportActionsMap,
+ test('[ReportActionsUtils] getLastVisibleAction on 10k reportActions with actionsToMerge', async () => {
+ const parentReportActionId = '1';
+ const fakeParentAction = reportActions[parentReportActionId];
+ const actionsToMerge = {
+ [parentReportActionId]: {
+ pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ previousMessage: fakeParentAction.message,
+ message: [
+ {
+ translationKey: '',
+ type: 'COMMENT',
+ html: '',
+ text: '',
+ isEdited: true,
+ isDeletedParentAction: true,
+ },
+ ],
+ errors: null,
+ linkMetaData: [],
+ },
+ } as unknown as ReportActions;
+
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportActionsUtils.getLastVisibleAction(reportId, actionsToMerge), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportActionsUtils.getMostRecentIOURequestActionID(reportActionsArray), {runs});
-});
-test('[ReportActionsUtils] getLastVisibleMessage on 10k ReportActions', async () => {
- await Onyx.multiSet({
- ...mockedReportActionsMap,
+ test('[ReportActionsUtils] getMostRecentIOURequestActionID on 10k ReportActions', async () => {
+ const reportActionsArray = ReportActionsUtils.getSortedReportActionsForDisplay(reportActions);
+
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportActionsUtils.getMostRecentIOURequestActionID(reportActionsArray), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportActionsUtils.getLastVisibleMessage(reportId), {runs});
-});
-test('[ReportActionsUtils] getLastVisibleMessage on 10k ReportActions with actionsToMerge', async () => {
- const parentReportActionId = '1';
- const fakeParentAction = reportActions[parentReportActionId];
- const actionsToMerge = {
- [parentReportActionId]: {
- pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
- previousMessage: fakeParentAction.message,
- message: [
- {
- translationKey: '',
- type: 'COMMENT',
- html: '',
- text: '',
- isEdited: true,
- isDeletedParentAction: true,
- },
- ],
- errors: null,
- linkMetaData: [],
- },
- } as unknown as ReportActions;
-
- await Onyx.multiSet({
- ...mockedReportActionsMap,
+ test('[ReportActionsUtils] getLastVisibleMessage on 10k ReportActions', async () => {
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportActionsUtils.getLastVisibleMessage(reportId), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportActionsUtils.getLastVisibleMessage(reportId, actionsToMerge), {runs});
-});
-test('[ReportActionsUtils] getSortedReportActionsForDisplay on 10k ReportActions', async () => {
- await Onyx.multiSet({
- ...mockedReportActionsMap,
+ test('[ReportActionsUtils] getLastVisibleMessage on 10k ReportActions with actionsToMerge', async () => {
+ const parentReportActionId = '1';
+ const fakeParentAction = reportActions[parentReportActionId];
+ const actionsToMerge = {
+ [parentReportActionId]: {
+ pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ previousMessage: fakeParentAction.message,
+ message: [
+ {
+ translationKey: '',
+ type: 'COMMENT',
+ html: '',
+ text: '',
+ isEdited: true,
+ isDeletedParentAction: true,
+ },
+ ],
+ errors: null,
+ linkMetaData: [],
+ },
+ } as unknown as ReportActions;
+
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportActionsUtils.getLastVisibleMessage(reportId, actionsToMerge), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportActionsUtils.getSortedReportActionsForDisplay(reportActions), {runs});
-});
-test('[ReportActionsUtils] getLastClosedReportAction on 10k ReportActions', async () => {
- await Onyx.multiSet({
- ...mockedReportActionsMap,
+ test('[ReportActionsUtils] getSortedReportActionsForDisplay on 10k ReportActions', async () => {
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportActionsUtils.getSortedReportActionsForDisplay(reportActions), {runs});
+ });
+
+ test('[ReportActionsUtils] getLastClosedReportAction on 10k ReportActions', async () => {
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportActionsUtils.getLastClosedReportAction(reportActions), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportActionsUtils.getLastClosedReportAction(reportActions), {runs});
-});
-test('[ReportActionsUtils] getMostRecentReportActionLastModified', async () => {
- await Onyx.multiSet({
- ...mockedReportActionsMap,
+ test('[ReportActionsUtils] getMostRecentReportActionLastModified', async () => {
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportActionsUtils.getMostRecentReportActionLastModified(), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportActionsUtils.getMostRecentReportActionLastModified(), {runs});
});
diff --git a/tests/perf-test/ReportUtils.perf-test.ts b/tests/perf-test/ReportUtils.perf-test.ts
index 62b911fb0417..30f874c669ab 100644
--- a/tests/perf-test/ReportUtils.perf-test.ts
+++ b/tests/perf-test/ReportUtils.perf-test.ts
@@ -13,19 +13,6 @@ import createRandomTransaction from '../utils/collections/transaction';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
const runs = CONST.PERFORMANCE_TESTS.RUNS;
-
-beforeAll(() =>
- Onyx.init({
- keys: ONYXKEYS,
- safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
- }),
-);
-
-// Clear out Onyx after each test so that each test starts with a clean state
-afterEach(() => {
- Onyx.clear();
-});
-
const getMockedReports = (length = 500) =>
createCollection(
(item) => `${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`,
@@ -50,195 +37,169 @@ const mockedReportsMap = getMockedReports(5000) as Record<`${typeof ONYXKEYS.COL
const mockedPoliciesMap = getMockedPolicies(5000) as Record<`${typeof ONYXKEYS.COLLECTION.POLICY}`, Policy>;
const participantAccountIDs = Array.from({length: 1000}, (v, i) => i + 1);
-test('[ReportUtils] findLastAccessedReport on 2k reports and policies', async () => {
- const ignoreDomainRooms = true;
- const isFirstTimeNewExpensifyUser = true;
- const reports = getMockedReports(2000);
- const policies = getMockedPolicies(2000);
- const openOnAdminRoom = true;
-
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.findLastAccessedReport(reports, ignoreDomainRooms, policies, isFirstTimeNewExpensifyUser, openOnAdminRoom), {runs});
-});
+describe('ReportUtils', () => {
+ beforeAll(() => {
+ Onyx.init({
+ keys: ONYXKEYS,
+ safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
+ });
+
+ Onyx.multiSet({
+ ...mockedPoliciesMap,
+ ...mockedReportsMap,
+ });
+ });
-test('[ReportUtils] canDeleteReportAction on 5k reports and policies', async () => {
- const reportID = '1';
+ afterAll(() => {
+ Onyx.clear();
+ });
- const reportAction = {...createRandomReportAction(1), actionName: CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT} as unknown as ReportAction;
+ test('[ReportUtils] findLastAccessedReport on 2k reports and policies', async () => {
+ const ignoreDomainRooms = true;
+ const isFirstTimeNewExpensifyUser = true;
+ const reports = getMockedReports(2000);
+ const policies = getMockedPolicies(2000);
+ const openOnAdminRoom = true;
- await Onyx.multiSet({
- ...mockedPoliciesMap,
- ...mockedReportsMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.findLastAccessedReport(reports, ignoreDomainRooms, policies, isFirstTimeNewExpensifyUser, openOnAdminRoom), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.canDeleteReportAction(reportAction, reportID), {runs});
-});
+ test('[ReportUtils] canDeleteReportAction on 5k reports and policies', async () => {
+ const reportID = '1';
+ const reportAction = {...createRandomReportAction(1), actionName: CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT} as unknown as ReportAction;
-test('[ReportUtils] getReportRecipientAccountID on 1k participants', async () => {
- const report = {...createRandomReport(1), participantAccountIDs};
- const currentLoginAccountID = 1;
-
- await Onyx.multiSet({
- ...mockedReportsMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.canDeleteReportAction(reportAction, reportID), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getReportRecipientAccountIDs(report, currentLoginAccountID), {runs});
-});
-
-test('[ReportUtils] getIconsForParticipants on 1k participants', async () => {
- const participants = Array.from({length: 1000}, (v, i) => i + 1);
+ test('[ReportUtils] getReportRecipientAccountID on 1k participants', async () => {
+ const report = {...createRandomReport(1), participantAccountIDs};
+ const currentLoginAccountID = 1;
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getIconsForParticipants(participants, personalDetails), {runs});
-});
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getReportRecipientAccountIDs(report, currentLoginAccountID), {runs});
+ });
-test('[ReportUtils] getIcons on 1k participants', async () => {
- const report = {...createRandomReport(1), parentReportID: '1', parentReportActionID: '1', type: CONST.REPORT.TYPE.CHAT};
- const policy = createRandomPolicy(1);
- const defaultIcon = null;
- const defaultName = '';
- const defaultIconId = -1;
+ test('[ReportUtils] getIconsForParticipants on 1k participants', async () => {
+ const participants = Array.from({length: 1000}, (v, i) => i + 1);
- await Onyx.multiSet({
- [ONYXKEYS.PERSONAL_DETAILS_LIST]: personalDetails,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getIconsForParticipants(participants, personalDetails), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getIcons(report, personalDetails, defaultIcon, defaultName, defaultIconId, policy), {runs});
-});
-
-test('[ReportUtils] getDisplayNamesWithTooltips 1k participants', async () => {
- const isMultipleParticipantReport = true;
- const shouldFallbackToHidden = true;
+ test('[ReportUtils] getIcons on 1k participants', async () => {
+ const report = {...createRandomReport(1), parentReportID: '1', parentReportActionID: '1', type: CONST.REPORT.TYPE.CHAT};
+ const policy = createRandomPolicy(1);
+ const defaultIcon = null;
+ const defaultName = '';
+ const defaultIconId = -1;
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getDisplayNamesWithTooltips(personalDetails, isMultipleParticipantReport, shouldFallbackToHidden), {runs});
-});
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getIcons(report, personalDetails, defaultIcon, defaultName, defaultIconId, policy), {runs});
+ });
-test('[ReportUtils] getReportPreviewMessage on 5k policies', async () => {
- const reportAction = createRandomReportAction(1);
- const report = createRandomReport(1);
- const policy = createRandomPolicy(1);
- const shouldConsiderReceiptBeingScanned = true;
- const isPreviewMessageForParentChatReport = true;
+ test('[ReportUtils] getDisplayNamesWithTooltips 1k participants', async () => {
+ const isMultipleParticipantReport = true;
+ const shouldFallbackToHidden = true;
- await Onyx.multiSet({
- ...mockedPoliciesMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getDisplayNamesWithTooltips(personalDetails, isMultipleParticipantReport, shouldFallbackToHidden), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getReportPreviewMessage(report, reportAction, shouldConsiderReceiptBeingScanned, isPreviewMessageForParentChatReport, policy), {runs});
-});
+ test('[ReportUtils] getReportPreviewMessage on 5k policies', async () => {
+ const reportAction = createRandomReportAction(1);
+ const report = createRandomReport(1);
+ const policy = createRandomPolicy(1);
+ const shouldConsiderReceiptBeingScanned = true;
+ const isPreviewMessageForParentChatReport = true;
-test('[ReportUtils] getReportName on 1k participants', async () => {
- const report = {...createRandomReport(1), chatType: undefined, participantAccountIDs};
- const policy = createRandomPolicy(1);
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getReportPreviewMessage(report, reportAction, shouldConsiderReceiptBeingScanned, isPreviewMessageForParentChatReport, policy), {runs});
+ });
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getReportName(report, policy), {runs});
-});
+ test('[ReportUtils] getReportName on 1k participants', async () => {
+ const report = {...createRandomReport(1), chatType: undefined, participantAccountIDs};
+ const policy = createRandomPolicy(1);
-test('[ReportUtils] canShowReportRecipientLocalTime on 1k participants', async () => {
- const report = {...createRandomReport(1), participantAccountIDs};
- const accountID = 1;
- await Onyx.multiSet({
- ...mockedReportsMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getReportName(report, policy), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.canShowReportRecipientLocalTime(personalDetails, report, accountID), {runs});
-});
-
-test('[ReportUtils] shouldReportBeInOptionList on 1k participant', async () => {
- const report = {...createRandomReport(1), participantAccountIDs, type: CONST.REPORT.TYPE.CHAT};
- const currentReportId = '2';
- const isInGSDMode = true;
- const betas = [CONST.BETAS.DEFAULT_ROOMS];
- const policies = getMockedPolicies();
+ test('[ReportUtils] canShowReportRecipientLocalTime on 1k participants', async () => {
+ const report = {...createRandomReport(1), participantAccountIDs};
+ const accountID = 1;
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies), {runs});
-});
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.canShowReportRecipientLocalTime(personalDetails, report, accountID), {runs});
+ });
-test('[ReportUtils] getWorkspaceIcon on 5k policies', async () => {
- const report = createRandomReport(1);
- const policy = createRandomPolicy(1);
+ test('[ReportUtils] shouldReportBeInOptionList on 1k participant', async () => {
+ const report = {...createRandomReport(1), participantAccountIDs, type: CONST.REPORT.TYPE.CHAT};
+ const currentReportId = '2';
+ const isInGSDMode = true;
+ const betas = [CONST.BETAS.DEFAULT_ROOMS];
+ const policies = getMockedPolicies();
- await Onyx.multiSet({
- ...mockedPoliciesMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getWorkspaceIcon(report, policy), {runs});
-});
-
-test('[ReportUtils] getMoneyRequestOptions on 1k participants', async () => {
- const report = {...createRandomReport(1), type: CONST.REPORT.TYPE.CHAT, chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, isOwnPolicyExpenseChat: true};
- const policy = createRandomPolicy(1);
- const reportParticipants = Array.from({length: 1000}, (v, i) => i + 1);
+ test('[ReportUtils] getWorkspaceIcon on 5k policies', async () => {
+ const report = createRandomReport(1);
+ const policy = createRandomPolicy(1);
- await Onyx.multiSet({
- ...mockedPoliciesMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getWorkspaceIcon(report, policy), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getMoneyRequestOptions(report, policy, reportParticipants), {runs});
-});
-
-test('[ReportUtils] getWorkspaceAvatar on 5k policies', async () => {
- const report = createRandomReport(1);
+ test('[ReportUtils] getMoneyRequestOptions on 1k participants', async () => {
+ const report = {...createRandomReport(1), type: CONST.REPORT.TYPE.CHAT, chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, isOwnPolicyExpenseChat: true};
+ const policy = createRandomPolicy(1);
+ const reportParticipants = Array.from({length: 1000}, (v, i) => i + 1);
- await Onyx.multiSet({
- ...mockedPoliciesMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getMoneyRequestOptions(report, policy, reportParticipants), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getWorkspaceAvatar(report), {runs});
-});
-test('[ReportUtils] getWorkspaceChat on 5k policies', async () => {
- const policyID = '1';
- const accountsID = Array.from({length: 20}, (v, i) => i + 1);
+ test('[ReportUtils] getWorkspaceAvatar on 5k policies', async () => {
+ const report = createRandomReport(1);
- await Onyx.multiSet({
- ...mockedReportsMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getWorkspaceAvatar(report), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getWorkspaceChats(policyID, accountsID), {runs});
-});
-
-test('[ReportUtils] getTransactionDetails on 5k reports', async () => {
- const transaction = createRandomTransaction(1);
+ test('[ReportUtils] getWorkspaceChat on 5k policies', async () => {
+ const policyID = '1';
+ const accountsID = Array.from({length: 20}, (v, i) => i + 1);
- await Onyx.multiSet({
- ...mockedReportsMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getWorkspaceChats(policyID, accountsID), {runs});
});
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getTransactionDetails(transaction, 'yyyy-MM-dd'), {runs});
-});
+ test('[ReportUtils] getTransactionDetails on 5k reports', async () => {
+ const transaction = createRandomTransaction(1);
+
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getTransactionDetails(transaction, 'yyyy-MM-dd'), {runs});
+ });
-test('[ReportUtils] getIOUReportActionDisplayMessage on 5k policies', async () => {
- const reportAction = {
- ...createRandomReportAction(1),
- actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
- originalMessage: {
- IOUReportID: '1',
- IOUTransactionID: '1',
- amount: 100,
- participantAccountID: 1,
- currency: CONST.CURRENCY.USD,
- type: CONST.IOU.REPORT_ACTION_TYPE.PAY,
- paymentType: CONST.IOU.PAYMENT_TYPE.EXPENSIFY,
- },
- };
-
- await Onyx.multiSet({
- ...mockedPoliciesMap,
- });
-
- await waitForBatchedUpdates();
- await measureFunction(() => ReportUtils.getIOUReportActionDisplayMessage(reportAction), {runs});
+ test('[ReportUtils] getIOUReportActionDisplayMessage on 5k policies', async () => {
+ const reportAction = {
+ ...createRandomReportAction(1),
+ actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+ originalMessage: {
+ IOUReportID: '1',
+ IOUTransactionID: '1',
+ amount: 100,
+ participantAccountID: 1,
+ currency: CONST.CURRENCY.USD,
+ type: CONST.IOU.REPORT_ACTION_TYPE.PAY,
+ paymentType: CONST.IOU.PAYMENT_TYPE.EXPENSIFY,
+ },
+ };
+
+ await waitForBatchedUpdates();
+ await measureFunction(() => ReportUtils.getIOUReportActionDisplayMessage(reportAction), {runs});
+ });
});
diff --git a/tests/perf-test/SidebarLinks.perf-test.js b/tests/perf-test/SidebarLinks.perf-test.js
index 1f529b08e6b3..1bc674045c23 100644
--- a/tests/perf-test/SidebarLinks.perf-test.js
+++ b/tests/perf-test/SidebarLinks.perf-test.js
@@ -15,25 +15,6 @@ jest.mock('../../src/components/Icon/Expensicons');
jest.mock('@react-navigation/native');
-beforeAll(() =>
- Onyx.init({
- keys: ONYXKEYS,
- safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
- registerStorageEventListener: () => {},
- }),
-);
-
-// Initialize the network key for OfflineWithFeedback
-beforeEach(() => {
- wrapOnyxWithWaitForBatchedUpdates(Onyx);
- return Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false});
-});
-
-// Clear out Onyx after each test so that each test starts with a clean slate
-afterEach(() => {
- Onyx.clear();
-});
-
const getMockedReportsMap = (length = 100) => {
const mockReports = Array.from({length}, (__, i) => {
const reportID = i + 1;
@@ -51,71 +32,81 @@ const mockedResponseMap = getMockedReportsMap(500);
const runs = CONST.PERFORMANCE_TESTS.RUNS;
-test('[SidebarLinks] should render Sidebar with 500 reports stored', () => {
- const scenario = async () => {
- // Query for the sidebar
- await screen.findByTestId('lhn-options-list');
- /**
- * Query for display names of participants [1, 2].
- * This will ensure that the sidebar renders a list of items.
- */
- await screen.findAllByText('One, Two');
- };
-
- return waitForBatchedUpdates()
- .then(() =>
- Onyx.multiSet({
- [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
- [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
- [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS],
- [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
- [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
- ...mockedResponseMap,
- }),
- )
- .then(() => measurePerformance(, {scenario, runs}));
-});
+describe('SidebarLinks', () => {
+ beforeAll(() => {
+ Onyx.init({
+ keys: ONYXKEYS,
+ safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
+ registerStorageEventListener: () => {},
+ });
+
+ Onyx.multiSet({
+ [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
+ [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+ [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS],
+ [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
+ [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
+ ...mockedResponseMap,
+ });
+ });
-test('[SidebarLinks] should scroll and click some of the items', () => {
- const scenario = async () => {
- const eventData = {
- nativeEvent: {
- contentOffset: {
- y: variables.optionRowHeight * 5,
- },
- contentSize: {
- // Dimensions of the scrollable content
- height: variables.optionRowHeight * 10,
- width: 100,
- },
- layoutMeasurement: {
- // Dimensions of the device
- height: variables.optionRowHeight * 5,
- width: 100,
+ // Initialize the network key for OfflineWithFeedback
+ beforeEach(() => {
+ wrapOnyxWithWaitForBatchedUpdates(Onyx);
+ return Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false});
+ });
+
+ afterAll(() => {
+ Onyx.clear();
+ });
+
+ test('[SidebarLinks] should render Sidebar with 500 reports stored', async () => {
+ const scenario = async () => {
+ // Query for the sidebar
+ await screen.findByTestId('lhn-options-list');
+ /**
+ * Query for display names of participants [1, 2].
+ * This will ensure that the sidebar renders a list of items.
+ */
+ await screen.findAllByText('One, Two');
+ };
+
+ await waitForBatchedUpdates();
+ await measurePerformance(, {scenario, runs});
+ });
+
+ test('[SidebarLinks] should scroll and click some of the items', async () => {
+ const scenario = async () => {
+ const eventData = {
+ nativeEvent: {
+ contentOffset: {
+ y: variables.optionRowHeight * 5,
+ },
+ contentSize: {
+ // Dimensions of the scrollable content
+ height: variables.optionRowHeight * 10,
+ width: 100,
+ },
+ layoutMeasurement: {
+ // Dimensions of the device
+ height: variables.optionRowHeight * 5,
+ width: 100,
+ },
},
- },
+ };
+
+ const lhnOptionsList = await screen.findByTestId('lhn-options-list');
+
+ fireEvent.scroll(lhnOptionsList, eventData);
+ // find elements that are currently visible in the viewport
+ const button1 = await screen.findByTestId('7');
+ const button2 = await screen.findByTestId('8');
+ fireEvent.press(button1);
+ fireEvent.press(button2);
};
- const lhnOptionsList = await screen.findByTestId('lhn-options-list');
-
- fireEvent.scroll(lhnOptionsList, eventData);
- // find elements that are currently visible in the viewport
- const button1 = await screen.findByTestId('7');
- const button2 = await screen.findByTestId('8');
- fireEvent.press(button1);
- fireEvent.press(button2);
- };
-
- return waitForBatchedUpdates()
- .then(() =>
- Onyx.multiSet({
- [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
- [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
- [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS],
- [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
- [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
- ...mockedResponseMap,
- }),
- )
- .then(() => measurePerformance(, {scenario, runs}));
+ await waitForBatchedUpdates();
+
+ await measurePerformance(, {scenario, runs});
+ });
});
diff --git a/tests/perf-test/SidebarUtils.perf-test.ts b/tests/perf-test/SidebarUtils.perf-test.ts
index 6722cbf493a5..6ca81796d3ac 100644
--- a/tests/perf-test/SidebarUtils.perf-test.ts
+++ b/tests/perf-test/SidebarUtils.perf-test.ts
@@ -15,18 +15,6 @@ import createRandomReportAction from '../utils/collections/reportActions';
import createRandomReport from '../utils/collections/reports';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
-beforeAll(() =>
- Onyx.init({
- keys: ONYXKEYS,
- safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
- }),
-);
-
-// Clear out Onyx after each test so that each test starts with a clean slate
-afterEach(() => {
- Onyx.clear();
-});
-
const getMockedReports = (length = 500) =>
createCollection(
(item) => `${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`,
@@ -47,52 +35,61 @@ const personalDetails = createCollection(
const mockedResponseMap = getMockedReports(5000) as Record<`${typeof ONYXKEYS.COLLECTION.REPORT}`, Report>;
const runs = CONST.PERFORMANCE_TESTS.RUNS;
-test('[SidebarUtils] getOptionData on 5k reports', async () => {
- const report = createRandomReport(1);
- const preferredLocale = 'en';
- const policy = createRandomPolicy(1);
- const parentReportAction = createRandomReportAction(1);
+describe('SidebarUtils', () => {
+ beforeAll(() => {
+ Onyx.init({
+ keys: ONYXKEYS,
+ safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
+ });
- Onyx.multiSet({
- ...mockedResponseMap,
+ Onyx.multiSet({
+ ...mockedResponseMap,
+ });
});
- await waitForBatchedUpdates();
- await measureFunction(() => SidebarUtils.getOptionData(report, reportActions, personalDetails, preferredLocale, policy, parentReportAction), {runs});
-});
+ afterAll(() => {
+ Onyx.clear();
+ });
-test('[SidebarUtils] getOrderedReportIDs on 5k reports', async () => {
- const currentReportId = '1';
- const allReports = getMockedReports();
- const betas = [CONST.BETAS.DEFAULT_ROOMS];
+ test('[SidebarUtils] getOptionData on 5k reports', async () => {
+ const report = createRandomReport(1);
+ const preferredLocale = 'en';
+ const policy = createRandomPolicy(1);
+ const parentReportAction = createRandomReportAction(1);
- const policies = createCollection(
- (item) => `${ONYXKEYS.COLLECTION.POLICY}${item.id}`,
- (index) => createRandomPolicy(index),
- );
+ await waitForBatchedUpdates();
+ await measureFunction(() => SidebarUtils.getOptionData(report, reportActions, personalDetails, preferredLocale, policy, parentReportAction), {runs});
+ });
+
+ test('[SidebarUtils] getOrderedReportIDs on 5k reports', async () => {
+ const currentReportId = '1';
+ const allReports = getMockedReports();
+ const betas = [CONST.BETAS.DEFAULT_ROOMS];
- const allReportActions = Object.fromEntries(
- Object.keys(reportActions).map((key) => [
- key,
- [
- {
- errors: reportActions[key].errors ?? [],
- message: [
- {
- moderationDecision: {
- decision: reportActions[key].message?.[0]?.moderationDecision?.decision,
+ const policies = createCollection(
+ (item) => `${ONYXKEYS.COLLECTION.POLICY}${item.id}`,
+ (index) => createRandomPolicy(index),
+ );
+
+ const allReportActions = Object.fromEntries(
+ Object.keys(reportActions).map((key) => [
+ key,
+ [
+ {
+ errors: reportActions[key].errors ?? [],
+ message: [
+ {
+ moderationDecision: {
+ decision: reportActions[key].message?.[0]?.moderationDecision?.decision,
+ },
},
- },
- ],
- },
- ],
- ]),
- ) as unknown as OnyxCollection;
+ ],
+ },
+ ],
+ ]),
+ ) as unknown as OnyxCollection;
- Onyx.multiSet({
- ...mockedResponseMap,
+ await waitForBatchedUpdates();
+ await measureFunction(() => SidebarUtils.getOrderedReportIDs(currentReportId, allReports, betas, policies, CONST.PRIORITY_MODE.DEFAULT, allReportActions), {runs});
});
-
- await waitForBatchedUpdates();
- await measureFunction(() => SidebarUtils.getOrderedReportIDs(currentReportId, allReports, betas, policies, CONST.PRIORITY_MODE.DEFAULT, allReportActions), {runs});
});
diff --git a/tests/unit/ReportUtilsTest.js b/tests/unit/ReportUtilsTest.js
index d700aa4724f1..c9e8053e3146 100644
--- a/tests/unit/ReportUtilsTest.js
+++ b/tests/unit/ReportUtilsTest.js
@@ -149,8 +149,8 @@ describe('ReportUtils', () => {
test('Archived', () => {
const archivedAdminsRoom = {
...baseAdminsRoom,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
expect(ReportUtils.getReportName(archivedAdminsRoom)).toBe('#admins (archived)');
@@ -172,8 +172,8 @@ describe('ReportUtils', () => {
test('Archived', () => {
const archivedPolicyRoom = {
...baseUserCreatedRoom,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
expect(ReportUtils.getReportName(archivedPolicyRoom)).toBe('#VikingsChat (archived)');
@@ -213,8 +213,8 @@ describe('ReportUtils', () => {
ownerAccountID: 1,
policyID: policy.policyID,
oldPolicyName: policy.name,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
test('as member', () => {
@@ -307,7 +307,7 @@ describe('ReportUtils', () => {
managerID: currentUserAccountID,
isUnreadWithMention: false,
stateNum: CONST.REPORT.STATE_NUM.OPEN,
- statusNum: CONST.REPORT.STATUS.OPEN,
+ statusNum: CONST.REPORT.STATUS_NUM.OPEN,
};
expect(ReportUtils.requiresAttentionFromCurrentUser(report)).toBe(true);
});
@@ -368,7 +368,7 @@ describe('ReportUtils', () => {
const report = {
...LHNTestUtils.getFakeReport(),
type: CONST.REPORT.TYPE.IOU,
- statusNum: CONST.REPORT.STATUS.REIMBURSED,
+ statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED,
};
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]);
expect(moneyRequestOptions.length).toBe(0);
@@ -378,8 +378,8 @@ describe('ReportUtils', () => {
const report = {
...LHNTestUtils.getFakeReport(),
type: CONST.REPORT.TYPE.EXPENSE,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
- statusNum: CONST.REPORT.STATUS.APPROVED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
+ statusNum: CONST.REPORT.STATUS_NUM.APPROVED,
};
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]);
expect(moneyRequestOptions.length).toBe(0);
@@ -389,7 +389,7 @@ describe('ReportUtils', () => {
const report = {
...LHNTestUtils.getFakeReport(),
type: CONST.REPORT.TYPE.EXPENSE,
- statusNum: CONST.REPORT.STATUS.REIMBURSED,
+ statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED,
};
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]);
expect(moneyRequestOptions.length).toBe(0);
@@ -419,8 +419,8 @@ describe('ReportUtils', () => {
const report = {
...LHNTestUtils.getFakeReport(),
type: CONST.REPORT.TYPE.EXPENSE,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
parentReportID: '101',
};
const paidPolicy = {
@@ -508,7 +508,7 @@ describe('ReportUtils', () => {
...LHNTestUtils.getFakeReport(),
type: CONST.REPORT.TYPE.EXPENSE,
stateNum: CONST.REPORT.STATE_NUM.OPEN,
- statusNum: CONST.REPORT.STATUS.OPEN,
+ statusNum: CONST.REPORT.STATUS_NUM.OPEN,
parentReportID: '103',
};
const paidPolicy = {
@@ -523,9 +523,8 @@ describe('ReportUtils', () => {
const report = {
...LHNTestUtils.getFakeReport(),
type: CONST.REPORT.TYPE.IOU,
- state: CONST.REPORT.STATE.SUBMITTED,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, participantsAccountIDs[0]]);
expect(moneyRequestOptions.length).toBe(1);
@@ -536,9 +535,8 @@ describe('ReportUtils', () => {
const report = {
...LHNTestUtils.getFakeReport(),
type: CONST.REPORT.TYPE.IOU,
- state: CONST.REPORT.STATE.SUBMITTED,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, participantsAccountIDs[0]]);
expect(moneyRequestOptions.length).toBe(1);
diff --git a/tests/unit/SidebarFilterTest.js b/tests/unit/SidebarFilterTest.js
index 088e5a1af4d0..83ccf3e92752 100644
--- a/tests/unit/SidebarFilterTest.js
+++ b/tests/unit/SidebarFilterTest.js
@@ -457,20 +457,20 @@ describe('Sidebar', () => {
// Given an archived chat report, an archived default policy room, and an archived user created policy room
const archivedReport = {
...LHNTestUtils.getFakeReport([1, 2]),
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
const archivedPolicyRoomReport = {
...LHNTestUtils.getFakeReport([1, 2]),
chatType: CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
const archivedUserCreatedPolicyRoomReport = {
...LHNTestUtils.getFakeReport([1, 2]),
chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
LHNTestUtils.getDefaultRenderedSidebarLinks();
@@ -681,8 +681,8 @@ describe('Sidebar', () => {
const report = {
...LHNTestUtils.getFakeReport(),
lastVisibleActionCreated: '2022-11-22 03:48:27.267',
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
// Given the user is in all betas
@@ -732,8 +732,8 @@ describe('Sidebar', () => {
// Given an archived report that has all comments read
const report = {
...LHNTestUtils.getFakeReport(),
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
// Given the user is in all betas
@@ -781,8 +781,8 @@ describe('Sidebar', () => {
const report = {
...LHNTestUtils.getFakeReport(),
isPinned: false,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
// Given the user is in all betas
@@ -826,8 +826,8 @@ describe('Sidebar', () => {
// Given an archived report that is not the active report
const report = {
...LHNTestUtils.getFakeReport(),
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
// Given the user is in all betas
diff --git a/tests/unit/SidebarOrderTest.js b/tests/unit/SidebarOrderTest.js
index 4d49cb3ad516..ed50c32559a7 100644
--- a/tests/unit/SidebarOrderTest.js
+++ b/tests/unit/SidebarOrderTest.js
@@ -255,7 +255,7 @@ describe('Sidebar', () => {
reportName: taskReportName,
managerID: 2,
stateNum: CONST.REPORT.STATE_NUM.OPEN,
- statusNum: CONST.REPORT.STATUS.OPEN,
+ statusNum: CONST.REPORT.STATUS_NUM.OPEN,
};
// Each report has at least one ADDCOMMENT action so should be rendered in the LNH
@@ -313,8 +313,8 @@ describe('Sidebar', () => {
total: 10000,
currency: 'USD',
chatReportID: report3.reportID,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
report3.iouReportID = iouReport.reportID;
@@ -374,9 +374,8 @@ describe('Sidebar', () => {
policyName: 'Workspace',
total: -10000,
currency: 'USD',
- state: CONST.REPORT.STATE.SUBMITTED,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
chatReportID: report3.reportID,
parentReportID: report3.reportID,
};
@@ -575,9 +574,8 @@ describe('Sidebar', () => {
total: 10000,
currency: 'USD',
chatReportID: report3.reportID,
- state: CONST.REPORT.STATE.SUBMITTED,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
report3.iouReportID = iouReport.reportID;
const currentReportId = report2.reportID;
@@ -740,8 +738,8 @@ describe('Sidebar', () => {
const report1 = {
...LHNTestUtils.getFakeReport([1, 2]),
chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
const report2 = LHNTestUtils.getFakeReport([3, 4]);
const report3 = LHNTestUtils.getFakeReport([5, 6]);
@@ -837,8 +835,8 @@ describe('Sidebar', () => {
const report1 = {
...LHNTestUtils.getFakeReport([1, 2], 3, true),
chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
const report2 = LHNTestUtils.getFakeReport([3, 4], 2, true);
const report3 = LHNTestUtils.getFakeReport([5, 6], 1, true);
@@ -914,8 +912,8 @@ describe('Sidebar', () => {
total: 10000,
currency: 'USD',
chatReportID: report3.reportID,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
const iouReport2 = {
...LHNTestUtils.getFakeReport([9, 10]),
@@ -926,8 +924,8 @@ describe('Sidebar', () => {
total: 10000,
currency: 'USD',
chatReportID: report3.reportID,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
const iouReport3 = {
...LHNTestUtils.getFakeReport([11, 12]),
@@ -938,8 +936,8 @@ describe('Sidebar', () => {
total: 100000,
currency: 'USD',
chatReportID: report3.reportID,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
const iouReport4 = {
...LHNTestUtils.getFakeReport([11, 12]),
@@ -950,8 +948,8 @@ describe('Sidebar', () => {
total: 10000,
currency: 'USD',
chatReportID: report3.reportID,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
const iouReport5 = {
...LHNTestUtils.getFakeReport([11, 12]),
@@ -962,8 +960,8 @@ describe('Sidebar', () => {
total: 10000,
currency: 'USD',
chatReportID: report3.reportID,
- stateNum: CONST.REPORT.STATE_NUM.PROCESSING,
- statusNum: CONST.REPORT.STATUS.SUBMITTED,
+ stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
};
report1.iouReportID = iouReport1.reportID;
diff --git a/tests/unit/SidebarTest.js b/tests/unit/SidebarTest.js
index 56009ee382d5..1101c5732707 100644
--- a/tests/unit/SidebarTest.js
+++ b/tests/unit/SidebarTest.js
@@ -51,8 +51,8 @@ describe('Sidebar', () => {
const report = {
...LHNTestUtils.getFakeReport(['email1@test.com', 'email2@test.com'], 3, true),
chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
// Given the user is in all betas
@@ -86,8 +86,8 @@ describe('Sidebar', () => {
...LHNTestUtils.getFakeReport(['email1@test.com', 'email2@test.com'], 3, true),
policyName: 'Vikings Policy',
chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
- statusNum: CONST.REPORT.STATUS.CLOSED,
- stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+ statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+ stateNum: CONST.REPORT.STATE_NUM.APPROVED,
};
const action = {
...LHNTestUtils.getFakeReportAction('email1@test.com', 3, true),
diff --git a/tests/utils/LHNTestUtils.js b/tests/utils/LHNTestUtils.js
index 535fb018dbc3..900a7852c92d 100644
--- a/tests/utils/LHNTestUtils.js
+++ b/tests/utils/LHNTestUtils.js
@@ -209,8 +209,8 @@ function getAdvancedFakeReport(isArchived, isUserCreatedPolicyRoom, hasAddWorksp
...getFakeReport([1, 2], 0, isUnread),
type: CONST.REPORT.TYPE.CHAT,
chatType: isUserCreatedPolicyRoom ? CONST.REPORT.CHAT_TYPE.POLICY_ROOM : CONST.REPORT.CHAT_TYPE.POLICY_ADMINS,
- statusNum: isArchived ? CONST.REPORT.STATUS.CLOSED : 0,
- stateNum: isArchived ? CONST.REPORT.STATE_NUM.SUBMITTED : 0,
+ statusNum: isArchived ? CONST.REPORT.STATUS_NUM.CLOSED : 0,
+ stateNum: isArchived ? CONST.REPORT.STATE_NUM.APPROVED : 0,
errorFields: hasAddWorkspaceError ? {addWorkspaceRoom: 'blah'} : null,
isPinned,
hasDraft,
diff --git a/web/index.html b/web/index.html
index 967873fe586c..7c02614d17b2 100644
--- a/web/index.html
+++ b/web/index.html
@@ -96,6 +96,11 @@
caret-color: #ffffff;
}
+ /* Customize Plaid iframe */
+ [id^="plaid-link-iframe"] {
+ color-scheme: dark !important;
+ }
+
/* Prevent autofill from overlapping with the input label in Chrome */
div:has(input:-webkit-autofill, input[chrome-autofilled]) > label {
transform: translateY(var(--active-label-translate-y)) scale(var(--active-label-scale)) !important;