From 631a576be75984c18dff54084f18dfc0ae30bcf7 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Thu, 18 Jan 2024 14:50:50 +0000 Subject: [PATCH 1/2] [TS Migration] Migrate FlagCommentPage --- src/pages/FlagCommentPage.js | 209 ------------------ src/pages/FlagCommentPage.tsx | 185 ++++++++++++++++ .../withReportAndReportActionOrNotFound.tsx | 8 +- 3 files changed, 191 insertions(+), 211 deletions(-) delete mode 100644 src/pages/FlagCommentPage.js create mode 100644 src/pages/FlagCommentPage.tsx diff --git a/src/pages/FlagCommentPage.js b/src/pages/FlagCommentPage.js deleted file mode 100644 index 47d2ad356dad..000000000000 --- a/src/pages/FlagCommentPage.js +++ /dev/null @@ -1,209 +0,0 @@ -import PropTypes from 'prop-types'; -import React, {useCallback} from 'react'; -import {ScrollView, View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import * as Expensicons from '@components/Icon/Expensicons'; -import MenuItem from '@components/MenuItem'; -import ScreenWrapper from '@components/ScreenWrapper'; -import Text from '@components/Text'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; -import Navigation from '@libs/Navigation/Navigation'; -import * as ReportUtils from '@libs/ReportUtils'; -import * as Report from '@userActions/Report'; -import * as Session from '@userActions/Session'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import reportActionPropTypes from './home/report/reportActionPropTypes'; -import withReportAndReportActionOrNotFound from './home/report/withReportAndReportActionOrNotFound'; -import reportPropTypes from './reportPropTypes'; - -const propTypes = { - /** Array of report actions for this report */ - reportActions: PropTypes.shape(reportActionPropTypes), - - /** The active report */ - report: reportPropTypes, - - /** Route params */ - route: PropTypes.shape({ - params: PropTypes.shape({ - /** Report ID passed via route r/:reportID/:reportActionID */ - reportID: PropTypes.string, - - /** ReportActionID passed via route r/:reportID/:reportActionID */ - reportActionID: PropTypes.string, - }), - }).isRequired, - - ...withLocalizePropTypes, - - /* Onyx Props */ - /** All the report actions from the parent report */ - parentReportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)), -}; - -const defaultProps = { - reportActions: {}, - parentReportActions: {}, - report: {}, -}; - -/** - * Get the reportID for the associated chatReport - * - * @param {Object} route - * @param {Object} route.params - * @param {String} route.params.reportID - * @returns {String} - */ -function getReportID(route) { - return route.params.reportID.toString(); -} - -function FlagCommentPage(props) { - const styles = useThemeStyles(); - const severities = [ - { - severity: CONST.MODERATION.FLAG_SEVERITY_SPAM, - name: props.translate('moderation.spam'), - icon: Expensicons.FlagLevelOne, - description: props.translate('moderation.spamDescription'), - furtherDetails: props.translate('moderation.levelOneResult'), - furtherDetailsIcon: Expensicons.FlagLevelOne, - }, - { - severity: CONST.MODERATION.FLAG_SEVERITY_INCONSIDERATE, - name: props.translate('moderation.inconsiderate'), - icon: Expensicons.FlagLevelOne, - description: props.translate('moderation.inconsiderateDescription'), - furtherDetails: props.translate('moderation.levelOneResult'), - furtherDetailsIcon: Expensicons.FlagLevelOne, - }, - { - severity: CONST.MODERATION.FLAG_SEVERITY_INTIMIDATION, - name: props.translate('moderation.intimidation'), - icon: Expensicons.FlagLevelTwo, - description: props.translate('moderation.intimidationDescription'), - furtherDetails: props.translate('moderation.levelTwoResult'), - furtherDetailsIcon: Expensicons.FlagLevelTwo, - }, - { - severity: CONST.MODERATION.FLAG_SEVERITY_BULLYING, - name: props.translate('moderation.bullying'), - icon: Expensicons.FlagLevelTwo, - description: props.translate('moderation.bullyingDescription'), - furtherDetails: props.translate('moderation.levelTwoResult'), - furtherDetailsIcon: Expensicons.FlagLevelTwo, - }, - { - severity: CONST.MODERATION.FLAG_SEVERITY_HARASSMENT, - name: props.translate('moderation.harassment'), - icon: Expensicons.FlagLevelThree, - description: props.translate('moderation.harassmentDescription'), - furtherDetails: props.translate('moderation.levelThreeResult'), - furtherDetailsIcon: Expensicons.FlagLevelThree, - }, - { - severity: CONST.MODERATION.FLAG_SEVERITY_ASSAULT, - name: props.translate('moderation.assault'), - icon: Expensicons.FlagLevelThree, - description: props.translate('moderation.assaultDescription'), - furtherDetails: props.translate('moderation.levelThreeResult'), - furtherDetailsIcon: Expensicons.FlagLevelThree, - }, - ]; - - const getActionToFlag = useCallback(() => { - let reportAction = props.reportActions[`${props.route.params.reportActionID.toString()}`]; - - // Handle threads if needed - if (reportAction === undefined || reportAction.reportActionID === undefined) { - reportAction = props.parentReportActions[props.report.parentReportActionID] || {}; - } - - return reportAction; - }, [props.report, props.reportActions, props.route.params.reportActionID, props.parentReportActions]); - - const flagComment = (severity) => { - let reportID = getReportID(props.route); - const reportAction = getActionToFlag(); - const parentReportAction = props.parentReportActions[props.report.parentReportActionID] || {}; - - // Handle threads if needed - if (ReportUtils.isChatThread(props.report) && reportAction.reportActionID === parentReportAction.reportActionID) { - reportID = ReportUtils.getParentReport(props.report).reportID; - } - - if (ReportUtils.canFlagReportAction(reportAction, reportID)) { - Report.flagComment(reportID, reportAction, severity); - } - - Navigation.dismissModal(); - }; - - const severityMenuItems = _.map(severities, (item, index) => ( - flagComment(item.severity))} - style={[styles.pt2, styles.pb4, styles.ph5, styles.flexRow]} - furtherDetails={item.furtherDetails} - furtherDetailsIcon={item.furtherDetailsIcon} - /> - )); - - return ( - - {({safeAreaPaddingBottomStyle}) => ( - - { - Navigation.goBack(); - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(props.report.reportID)); - }} - /> - - - - {props.translate('moderation.flagDescription')} - - - {props.translate('moderation.chooseAReason')} - {severityMenuItems} - - - )} - - ); -} - -FlagCommentPage.propTypes = propTypes; -FlagCommentPage.defaultProps = defaultProps; -FlagCommentPage.displayName = 'FlagCommentPage'; - -export default compose( - withLocalize, - withReportAndReportActionOrNotFound, - withOnyx({ - parentReportActions: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID || report.reportID}`, - canEvict: false, - }, - }), -)(FlagCommentPage); diff --git a/src/pages/FlagCommentPage.tsx b/src/pages/FlagCommentPage.tsx new file mode 100644 index 000000000000..4bc581e9a2dc --- /dev/null +++ b/src/pages/FlagCommentPage.tsx @@ -0,0 +1,185 @@ +import type {RouteProp} from '@react-navigation/native'; +import React, {useCallback} from 'react'; +import {ScrollView, View} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import * as Expensicons from '@components/Icon/Expensicons'; +import MenuItem from '@components/MenuItem'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; +import * as ReportUtils from '@libs/ReportUtils'; +import * as Report from '@userActions/Report'; +import * as Session from '@userActions/Session'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type * as OnyxTypes from '@src/types/onyx'; +import withReportAndReportActionOrNotFound from './home/report/withReportAndReportActionOrNotFound'; +import type {WithReportAndReportActionOrNotFoundProps} from './home/report/withReportAndReportActionOrNotFound'; + +type FlagCommentPageWithOnyxProps = { + /** All the report actions from the parent report */ + parentReportActions: OnyxEntry; +}; + +type FlagCommentPageProps = WithReportAndReportActionOrNotFoundProps & FlagCommentPageWithOnyxProps; + +type FlagCommentRouteProp = RouteProp<{params: {reportID: string; reportActionID: string}}>; + +/** + * Get the reportID for the associated chatReport + */ +function getReportID(route: FlagCommentRouteProp) { + return route.params.reportID.toString(); +} + +function FlagCommentPage({parentReportActions, route, report, reportActions}: FlagCommentPageProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const severities = [ + { + severity: CONST.MODERATION.FLAG_SEVERITY_SPAM, + name: translate('moderation.spam'), + icon: Expensicons.FlagLevelOne, + description: translate('moderation.spamDescription'), + furtherDetails: translate('moderation.levelOneResult'), + furtherDetailsIcon: Expensicons.FlagLevelOne, + }, + { + severity: CONST.MODERATION.FLAG_SEVERITY_INCONSIDERATE, + name: translate('moderation.inconsiderate'), + icon: Expensicons.FlagLevelOne, + description: translate('moderation.inconsiderateDescription'), + furtherDetails: translate('moderation.levelOneResult'), + furtherDetailsIcon: Expensicons.FlagLevelOne, + }, + { + severity: CONST.MODERATION.FLAG_SEVERITY_INTIMIDATION, + name: translate('moderation.intimidation'), + icon: Expensicons.FlagLevelTwo, + description: translate('moderation.intimidationDescription'), + furtherDetails: translate('moderation.levelTwoResult'), + furtherDetailsIcon: Expensicons.FlagLevelTwo, + }, + { + severity: CONST.MODERATION.FLAG_SEVERITY_BULLYING, + name: translate('moderation.bullying'), + icon: Expensicons.FlagLevelTwo, + description: translate('moderation.bullyingDescription'), + furtherDetails: translate('moderation.levelTwoResult'), + furtherDetailsIcon: Expensicons.FlagLevelTwo, + }, + { + severity: CONST.MODERATION.FLAG_SEVERITY_HARASSMENT, + name: translate('moderation.harassment'), + icon: Expensicons.FlagLevelThree, + description: translate('moderation.harassmentDescription'), + furtherDetails: translate('moderation.levelThreeResult'), + furtherDetailsIcon: Expensicons.FlagLevelThree, + }, + { + severity: CONST.MODERATION.FLAG_SEVERITY_ASSAULT, + name: translate('moderation.assault'), + icon: Expensicons.FlagLevelThree, + description: translate('moderation.assaultDescription'), + furtherDetails: translate('moderation.levelThreeResult'), + furtherDetailsIcon: Expensicons.FlagLevelThree, + }, + ]; + + const getActionToFlag = useCallback(() => { + let reportAction = reportActions?.[`${route.params.reportActionID.toString()}`]; + + // Handle threads if needed + if (reportAction?.reportActionID === undefined) { + reportAction = parentReportActions?.[report?.parentReportActionID ?? ''] ?? undefined; + } + + return reportAction; + }, [report, reportActions, route.params.reportActionID, parentReportActions]); + + const flagComment = (severity: ValueOf) => { + let reportID: string | undefined = getReportID(route); + const reportAction = getActionToFlag(); + const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? ''] ?? undefined; + + // Handle threads if needed + if (ReportUtils.isChatThread(report) && reportAction?.reportActionID === parentReportAction?.reportActionID) { + reportID = ReportUtils.getParentReport(report)?.reportID; + } + + if (reportAction && ReportUtils.canFlagReportAction(reportAction, reportID)) { + Report.flagComment(reportID ?? '', reportAction, severity); + } + + Navigation.dismissModal(); + }; + + const severityMenuItems = severities.map((item) => ( + flagComment(item.severity))} + style={[styles.pt2, styles.pb4, styles.ph5, styles.flexRow]} + furtherDetails={item.furtherDetails} + furtherDetailsIcon={item.furtherDetailsIcon} + /> + )); + + return ( + + {({safeAreaPaddingBottomStyle}) => { + const actionToFlag = getActionToFlag(); + const shouldShowFlagComment = actionToFlag && ReportUtils.shouldShowFlagComment(actionToFlag, report); + + return ( + + { + Navigation.goBack(); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report?.reportID ?? '')); + }} + /> + + + + {translate('moderation.flagDescription')} + + + {translate('moderation.chooseAReason')} + {severityMenuItems} + + + ); + }} + + ); +} + +FlagCommentPage.displayName = 'FlagCommentPage'; + +export default withReportAndReportActionOrNotFound( + withOnyx({ + parentReportActions: { + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID ?? report?.reportID}`, + canEvict: false, + }, + })(FlagCommentPage), +); diff --git a/src/pages/home/report/withReportAndReportActionOrNotFound.tsx b/src/pages/home/report/withReportAndReportActionOrNotFound.tsx index fb0a00e2d10d..994141b2a815 100644 --- a/src/pages/home/report/withReportAndReportActionOrNotFound.tsx +++ b/src/pages/home/report/withReportAndReportActionOrNotFound.tsx @@ -37,12 +37,14 @@ type OnyxProps = { isLoadingReportData: OnyxEntry; }; -type ComponentProps = OnyxProps & +type WithReportAndReportActionOrNotFoundProps = OnyxProps & WindowDimensionsProps & { route: RouteProp<{params: {reportID: string; reportActionID: string}}>; }; -export default function (WrappedComponent: ComponentType>): ComponentType> { +export default function ( + WrappedComponent: ComponentType>, +): ComponentType> { function WithReportOrNotFound(props: TProps, ref: ForwardedRef) { const getReportAction = useCallback(() => { let reportAction: OnyxTypes.ReportAction | Record | undefined = props.reportActions?.[`${props.route.params.reportActionID}`]; @@ -118,3 +120,5 @@ export default function (WrappedComponent: withWindowDimensions, )(React.forwardRef(WithReportOrNotFound)); } + +export type {WithReportAndReportActionOrNotFoundProps}; From 2c257482c0a940a0dc2f04e8b095e630330b1d35 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Mon, 22 Jan 2024 16:35:08 +0000 Subject: [PATCH 2/2] [TS migration] FlagCommentPage code improvements --- src/pages/FlagCommentPage.tsx | 89 +++++++++++-------- .../withReportAndReportActionOrNotFound.tsx | 9 +- 2 files changed, 56 insertions(+), 42 deletions(-) diff --git a/src/pages/FlagCommentPage.tsx b/src/pages/FlagCommentPage.tsx index 4bc581e9a2dc..9543c48cff25 100644 --- a/src/pages/FlagCommentPage.tsx +++ b/src/pages/FlagCommentPage.tsx @@ -1,8 +1,9 @@ -import type {RouteProp} from '@react-navigation/native'; +import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback} from 'react'; import {ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; +import type {SvgProps} from 'react-native-svg'; import type {ValueOf} from 'type-fest'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -13,12 +14,14 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; +import type {FlagCommentNavigatorParamList} from '@libs/Navigation/types'; import * as ReportUtils from '@libs/ReportUtils'; import * as Report from '@userActions/Report'; import * as Session from '@userActions/Session'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import withReportAndReportActionOrNotFound from './home/report/withReportAndReportActionOrNotFound'; import type {WithReportAndReportActionOrNotFoundProps} from './home/report/withReportAndReportActionOrNotFound'; @@ -28,14 +31,27 @@ type FlagCommentPageWithOnyxProps = { parentReportActions: OnyxEntry; }; -type FlagCommentPageProps = WithReportAndReportActionOrNotFoundProps & FlagCommentPageWithOnyxProps; +type FlagCommentPageNavigationProps = StackScreenProps; -type FlagCommentRouteProp = RouteProp<{params: {reportID: string; reportActionID: string}}>; +type FlagCommentPageProps = FlagCommentPageNavigationProps & WithReportAndReportActionOrNotFoundProps & FlagCommentPageWithOnyxProps; + +type Severity = ValueOf; + +type SeverityItem = { + severity: Severity; + name: string; + icon: React.FC; + description: string; + furtherDetails: string; + furtherDetailsIcon: React.FC; +}; + +type SeverityItemList = SeverityItem[]; /** * Get the reportID for the associated chatReport */ -function getReportID(route: FlagCommentRouteProp) { +function getReportID(route: FlagCommentPageNavigationProps['route']) { return route.params.reportID.toString(); } @@ -43,7 +59,7 @@ function FlagCommentPage({parentReportActions, route, report, reportActions}: Fl const styles = useThemeStyles(); const {translate} = useLocalize(); - const severities = [ + const severities: SeverityItemList = [ { severity: CONST.MODERATION.FLAG_SEVERITY_SPAM, name: translate('moderation.spam'), @@ -94,21 +110,25 @@ function FlagCommentPage({parentReportActions, route, report, reportActions}: Fl }, ]; - const getActionToFlag = useCallback(() => { + const getActionToFlag = useCallback((): OnyxTypes.ReportAction | null => { let reportAction = reportActions?.[`${route.params.reportActionID.toString()}`]; // Handle threads if needed if (reportAction?.reportActionID === undefined) { - reportAction = parentReportActions?.[report?.parentReportActionID ?? ''] ?? undefined; + reportAction = parentReportActions?.[report?.parentReportActionID ?? '']; + } + + if (!reportAction) { + return null; } return reportAction; }, [report, reportActions, route.params.reportActionID, parentReportActions]); - const flagComment = (severity: ValueOf) => { + const flagComment = (severity: Severity) => { let reportID: string | undefined = getReportID(route); const reportAction = getActionToFlag(); - const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? ''] ?? undefined; + const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? '']; // Handle threads if needed if (ReportUtils.isChatThread(report) && reportAction?.reportActionID === parentReportAction?.reportActionID) { @@ -140,35 +160,30 @@ function FlagCommentPage({parentReportActions, route, report, reportActions}: Fl includeSafeAreaPaddingBottom={false} testID={FlagCommentPage.displayName} > - {({safeAreaPaddingBottomStyle}) => { - const actionToFlag = getActionToFlag(); - const shouldShowFlagComment = actionToFlag && ReportUtils.shouldShowFlagComment(actionToFlag, report); - - return ( - - { - Navigation.goBack(); - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report?.reportID ?? '')); - }} - /> - - - - {translate('moderation.flagDescription')} - + {({safeAreaPaddingBottomStyle}) => ( + + { + Navigation.goBack(); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report?.reportID ?? '')); + }} + /> + + + + {translate('moderation.flagDescription')} - {translate('moderation.chooseAReason')} - {severityMenuItems} - - - ); - }} + + {translate('moderation.chooseAReason')} + {severityMenuItems} + + + )} ); } diff --git a/src/pages/home/report/withReportAndReportActionOrNotFound.tsx b/src/pages/home/report/withReportAndReportActionOrNotFound.tsx index 994141b2a815..43023f15fa17 100644 --- a/src/pages/home/report/withReportAndReportActionOrNotFound.tsx +++ b/src/pages/home/report/withReportAndReportActionOrNotFound.tsx @@ -1,5 +1,5 @@ /* eslint-disable rulesdir/no-negated-variables */ -import type {RouteProp} from '@react-navigation/native'; +import type {StackScreenProps} from '@react-navigation/stack'; import type {ComponentType, ForwardedRef, RefAttributes} from 'react'; import React, {useCallback, useEffect} from 'react'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; @@ -9,11 +9,13 @@ import withWindowDimensions from '@components/withWindowDimensions'; import type {WindowDimensionsProps} from '@components/withWindowDimensions/types'; import compose from '@libs/compose'; import getComponentDisplayName from '@libs/getComponentDisplayName'; +import type {FlagCommentNavigatorParamList} from '@libs/Navigation/types'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import * as Report from '@userActions/Report'; import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import {isEmptyObject, isNotEmptyObject} from '@src/types/utils/EmptyObject'; @@ -37,10 +39,7 @@ type OnyxProps = { isLoadingReportData: OnyxEntry; }; -type WithReportAndReportActionOrNotFoundProps = OnyxProps & - WindowDimensionsProps & { - route: RouteProp<{params: {reportID: string; reportActionID: string}}>; - }; +type WithReportAndReportActionOrNotFoundProps = OnyxProps & WindowDimensionsProps & StackScreenProps; export default function ( WrappedComponent: ComponentType>,