From 371c92a8f21b5709b9006e8762d0487f3e94f69f Mon Sep 17 00:00:00 2001 From: Pedro Guerreiro Date: Mon, 14 Oct 2024 21:47:12 +0100 Subject: [PATCH 01/40] feat(debug mode): add debug transaction page --- src/CONST.ts | 1 + src/ROUTES.ts | 16 ++++ src/SCREENS.ts | 1 + src/components/TabSelector/TabSelector.tsx | 2 + src/languages/en.ts | 2 + src/languages/es.ts | 2 + .../ModalStackNavigators/index.tsx | 1 + src/libs/Navigation/linkingConfig/config.ts | 18 +++++ src/libs/Navigation/types.ts | 6 ++ src/pages/Debug/DebugDetails.tsx | 4 +- .../Transaction/DebugTransactionPage.tsx | 77 +++++++++++++++++++ .../DebugTransactionViolations.tsx | 71 +++++++++++++++++ 12 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 src/pages/Debug/Transaction/DebugTransactionPage.tsx create mode 100644 src/pages/Debug/Transaction/DebugTransactionViolations.tsx diff --git a/src/CONST.ts b/src/CONST.ts index b6b297f7fb47..ff0ee69d31bc 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5858,6 +5858,7 @@ const CONST = { JSON: 'json', REPORT_ACTIONS: 'actions', REPORT_ACTION_PREVIEW: 'preview', + TRANSACTION_VIOLATIONS: 'violations', }, REPORT_IN_LHN_REASONS: { diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 07a772aa9390..30c73dc9eaa6 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1622,6 +1622,22 @@ const ROUTES = { route: 'debug/details/datetime/:fieldName', getRoute: (fieldName: string, fieldValue?: string, backTo?: string) => getUrlWithBackToParam(`debug/details/datetime/${fieldName}?fieldValue=${fieldValue}`, backTo), }, + DEBUG_TRANSACTION: { + route: 'debug/transaction/:transactionID', + getRoute: (transactionID: string) => `debug/transaction/${transactionID}` as const, + }, + DEBUG_TRANSACTION_TAB_DETAILS: { + route: 'debug/transaction/:transactionID/details', + getRoute: (transactionID: string) => `debug/transaction/${transactionID}/details` as const, + }, + DEBUG_TRANSACTION_TAB_JSON: { + route: 'debug/transaction/:transactionID/json', + getRoute: (transactionID: string) => `debug/transaction/${transactionID}/json` as const, + }, + DEBUG_TRANSACTION_TAB_VIOLATIONS: { + route: 'debug/transaction/:transactionID/violations', + getRoute: (transactionID: string) => `debug/transaction/${transactionID}/violations` as const, + }, } as const; /** diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 09cfbca3de9b..34fabe39a4cb 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -584,6 +584,7 @@ const SCREENS = { REPORT_ACTION_CREATE: 'Debug_Report_Action_Create', DETAILS_CONSTANT_PICKER_PAGE: 'Debug_Details_Constant_Picker_Page', DETAILS_DATE_TIME_PICKER_PAGE: 'Debug_Details_Date_Time_Picker_Page', + TRANSACTION: 'Debug_Transaction', }, } as const; diff --git a/src/components/TabSelector/TabSelector.tsx b/src/components/TabSelector/TabSelector.tsx index 1bf753cd4aa4..84e2f2f2ee6a 100644 --- a/src/components/TabSelector/TabSelector.tsx +++ b/src/components/TabSelector/TabSelector.tsx @@ -35,6 +35,8 @@ function getIconAndTitle(route: string, translate: LocaleContextProps['translate return {icon: Expensicons.Document, title: translate('debug.reportActions')}; case CONST.DEBUG.REPORT_ACTION_PREVIEW: return {icon: Expensicons.Document, title: translate('debug.reportActionPreview')}; + case CONST.DEBUG.TRANSACTION_VIOLATIONS: + return {icon: Expensicons.Exclamation, title: translate('debug.violations')}; case CONST.TAB_REQUEST.MANUAL: return {icon: Expensicons.Pencil, title: translate('tabSelector.manual')}; case CONST.TAB_REQUEST.SCAN: diff --git a/src/languages/en.ts b/src/languages/en.ts index 343990813197..b1eee495c6de 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -5026,6 +5026,8 @@ const translations = { createReportAction: 'Create Report Action', reportAction: 'Report Action', report: 'Report', + transaction: 'Transaction', + violations: 'Violations', hint: "Data changes won't be sent to the backend", textFields: 'Text fields', numberFields: 'Number fields', diff --git a/src/languages/es.ts b/src/languages/es.ts index 50ee28d488c6..099a008c431e 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -5541,6 +5541,8 @@ const translations = { createReportAction: 'Crear Report Action', reportAction: 'Report Action', report: 'Report', + transaction: 'Transacción', + violations: 'Violaciones', hint: 'Los cambios de datos no se enviarán al backend', textFields: 'Campos de texto', numberFields: 'Campos numéricos', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 3d1b4e3d95b6..7fc39cb97bfb 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -617,6 +617,7 @@ const DebugModalStackNavigator = createModalStackNavigator({ [SCREENS.DEBUG.REPORT_ACTION_CREATE]: () => require('../../../../pages/Debug/ReportAction/DebugReportActionCreatePage').default, [SCREENS.DEBUG.DETAILS_CONSTANT_PICKER_PAGE]: () => require('../../../../pages/Debug/DebugDetailsConstantPickerPage').default, [SCREENS.DEBUG.DETAILS_DATE_TIME_PICKER_PAGE]: () => require('../../../../pages/Debug/DebugDetailsDateTimePickerPage').default, + [SCREENS.DEBUG.TRANSACTION]: () => require('../../../../pages/Debug/Transaction/DebugTransactionPage').default, }); export { diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 45d93cd8f57d..1cf2adb17e96 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -1298,6 +1298,24 @@ const config: LinkingOptions['config'] = { path: ROUTES.DETAILS_DATE_TIME_PICKER_PAGE.route, exact: true, }, + [SCREENS.DEBUG.TRANSACTION]: { + path: ROUTES.DEBUG_TRANSACTION.route, + exact: true, + screens: { + details: { + path: ROUTES.DEBUG_TRANSACTION_TAB_DETAILS.route, + exact: true, + }, + json: { + path: ROUTES.DEBUG_TRANSACTION_TAB_JSON.route, + exact: true, + }, + violations: { + path: ROUTES.DEBUG_TRANSACTION_TAB_VIOLATIONS.route, + exact: true, + }, + }, + }, }, }, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 372a8cfc27bb..7c87aa811b38 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1558,6 +1558,12 @@ type DebugParamList = { fieldValue?: string; backTo?: string; }; + [SCREENS.DEBUG.TRANSACTION]: { + transactionID: string; + }; + [SCREENS.DEBUG.TRANSACTION]: { + transactionID: string; + }; }; type RootStackParamList = PublicScreensParamList & AuthScreensParamList & LeftModalNavigatorParamList; diff --git a/src/pages/Debug/DebugDetails.tsx b/src/pages/Debug/DebugDetails.tsx index c64e8e3a9331..5515b58655b8 100644 --- a/src/pages/Debug/DebugDetails.tsx +++ b/src/pages/Debug/DebugDetails.tsx @@ -18,7 +18,7 @@ import Navigation from '@libs/Navigation/Navigation'; import Debug from '@userActions/Debug'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Report, ReportAction} from '@src/types/onyx'; +import type {Report, ReportAction, Transaction} from '@src/types/onyx'; import type {DetailsConstantFieldsKeys, DetailsDatetimeFieldsKeys, DetailsDisabledKeys} from './const'; import {DETAILS_CONSTANT_FIELDS, DETAILS_DATETIME_FIELDS, DETAILS_DISABLED_KEYS} from './const'; import ConstantSelector from './ConstantSelector'; @@ -26,7 +26,7 @@ import DateTimeSelector from './DateTimeSelector'; type DebugDetailsProps = { /** The report or report action data to be displayed and editted. */ - data: OnyxEntry | OnyxEntry; + data: OnyxEntry | OnyxEntry | OnyxEntry; children?: React.ReactNode; diff --git a/src/pages/Debug/Transaction/DebugTransactionPage.tsx b/src/pages/Debug/Transaction/DebugTransactionPage.tsx new file mode 100644 index 000000000000..3b97d87245a8 --- /dev/null +++ b/src/pages/Debug/Transaction/DebugTransactionPage.tsx @@ -0,0 +1,77 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import TabSelector from '@components/TabSelector/TabSelector'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Debug from '@libs/actions/Debug'; +import DebugUtils from '@libs/DebugUtils'; +import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import Navigation from '@libs/Navigation/Navigation'; +import OnyxTabNavigator, {TopTab} from '@libs/Navigation/OnyxTabNavigator'; +import type {DebugParamList} from '@libs/Navigation/types'; +import DebugDetails from '@pages/Debug/DebugDetails'; +import DebugJSON from '@pages/Debug/DebugJSON'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; +import DebugTransactionViolations from './DebugTransactionViolations'; + +type DebugTransactionPageProps = StackScreenProps; + +function DebugTransactionPage({ + route: { + params: {transactionID}, + }, +}: DebugTransactionPageProps) { + const {translate} = useLocalize(); + const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`); + const styles = useThemeStyles(); + + return ( + + {({safeAreaPaddingBottomStyle}) => ( + + + + + {() => ( + { + Debug.mergeDebugData(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, data); + }} + onDelete={() => { + Debug.mergeDebugData(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, null); + }} + // TODO: Create DebugUtils.validateTransactionDraftProperty + validate={DebugUtils.validateReportDraftProperty} + /> + )} + + {() => } + {() => } + + + )} + + ); +} + +DebugTransactionPage.displayName = 'DebugTransactionPage'; + +export default DebugTransactionPage; diff --git a/src/pages/Debug/Transaction/DebugTransactionViolations.tsx b/src/pages/Debug/Transaction/DebugTransactionViolations.tsx new file mode 100644 index 000000000000..10e7b9076d31 --- /dev/null +++ b/src/pages/Debug/Transaction/DebugTransactionViolations.tsx @@ -0,0 +1,71 @@ +import React, {useState} from 'react'; +import type {ListRenderItemInfo} from 'react-native'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; +import FlatList from '@components/FlatList'; +import ScrollView from '@components/ScrollView'; +import Text from '@components/Text'; +import TextInput from '@components/TextInput'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import DebugUtils from '@libs/DebugUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type {TransactionViolation} from '@src/types/onyx'; + +type DebugTransactionViolationsProps = { + transactionID: string; +}; + +function DebugTransactionViolations({transactionID}: DebugTransactionViolationsProps) { + const [transactionViolations] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`); + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const [transactionViolationsJSON, setTransactionViolationsJSON] = useState(DebugUtils.onyxDataToString(transactionViolations)); + const numberOfLines = DebugUtils.getNumberOfLinesFromString(transactionViolationsJSON); + + return ( + + {/*