Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix - RHN throws error if tags are deleted by admin while member is selecting #49506

Merged
merged 8 commits into from
Sep 25, 2024
Merged
4 changes: 4 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,10 @@ const ROUTES = {
getRoute: (action: IOUAction, iouType: IOUType, orderWeight: number, transactionID: string, reportID: string, backTo = '', reportActionID?: string) =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/tag/${orderWeight}/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo),
},
SETTINGS_TAGS_ROOT: {
route: 'settings/:policyID/tags',
getRoute: (policyID: string, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/tags`, backTo),
},
Comment on lines +498 to +501
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The routes stack should have been wider to cover all the nested pages navigation. See #50416 for the eventual changes.

MONEY_REQUEST_STEP_WAYPOINT: {
route: ':action/:iouType/waypoint/:transactionID/:reportID/:pageIndex',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID?: string, pageIndex = '', backTo = '') =>
Expand Down
2 changes: 2 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ const SCREENS = {
SETTINGS_CATEGORIES_ROOT: 'Settings_Categories',
},

SETTINGS_TAGS_ROOT: 'Settings_Tags',

REPORT_SETTINGS: {
ROOT: 'Report_Settings_Root',
NAME: 'Report_Settings_Name',
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3171,6 +3171,7 @@ export default {
disableTags: 'Disable tags',
addTag: 'Add tag',
editTag: 'Edit tag',
editTags: 'Edit tags',
subtitle: 'Tags add more detailed ways to classify costs.',
emptyTags: {
title: "You haven't created any tags",
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3220,6 +3220,7 @@ export default {
disableTags: 'Desactivar etiquetas',
addTag: 'Añadir etiqueta',
editTag: 'Editar etiqueta',
editTags: 'Editar etiquetas',
subtitle: 'Las etiquetas añaden formas más detalladas de clasificar los costos.',
emptyTags: {
title: 'No has creado ninguna etiqueta',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
[SCREENS.MONEY_REQUEST.STEP_MERCHANT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepMerchant').default,
[SCREENS.MONEY_REQUEST.STEP_PARTICIPANTS]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepParticipants').default,
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORIES_ROOT]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/WorkspaceCategoriesPage').default,
[SCREENS.SETTINGS_TAGS_ROOT]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/WorkspaceTagsPage').default,
[SCREENS.MONEY_REQUEST.STEP_SCAN]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepScan').default,
[SCREENS.MONEY_REQUEST.STEP_TAG]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTag').default,
[SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepWaypoint').default,
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,7 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
},
},
[SCREENS.SETTINGS_CATEGORIES.SETTINGS_CATEGORIES_ROOT]: ROUTES.SETTINGS_CATEGORIES_ROOT.route,
[SCREENS.SETTINGS_TAGS_ROOT]: ROUTES.SETTINGS_TAGS_ROOT.route,
[SCREENS.MONEY_REQUEST.STEP_SEND_FROM]: ROUTES.MONEY_REQUEST_STEP_SEND_FROM.route,
[SCREENS.MONEY_REQUEST.STEP_COMPANY_INFO]: ROUTES.MONEY_REQUEST_STEP_COMPANY_INFO.route,
[SCREENS.MONEY_REQUEST.STEP_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_AMOUNT.route,
Expand Down
148 changes: 65 additions & 83 deletions src/pages/iou/request/step/IOURequestStepTag.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import React, {useMemo} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import Button from '@components/Button';
import FixedFooter from '@components/FixedFooter';
import * as Illustrations from '@components/Icon/Illustrations';
import {useSession} from '@components/OnyxProvider';
import TagPicker from '@components/TagPicker';
import Text from '@components/Text';
import WorkspaceEmptyStateSection from '@components/WorkspaceEmptyStateSection';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as IOUUtils from '@libs/IOUUtils';
Expand All @@ -15,52 +20,34 @@ import * as TransactionUtils from '@libs/TransactionUtils';
import * as IOU from '@userActions/IOU';
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 {isEmptyObject} from '@src/types/utils/EmptyObject';
import StepScreenWrapper from './StepScreenWrapper';
import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound';
import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
import withWritableReportOrNotFound from './withWritableReportOrNotFound';

type IOURequestStepTagOnyxProps = {
/** The draft transaction that holds data to be persisted on the current transaction */
splitDraftTransaction: OnyxEntry<OnyxTypes.Transaction>;

/** The policy of the report */
policy: OnyxEntry<OnyxTypes.Policy>;

/** The category configuration of the report's policy */
policyCategories: OnyxEntry<OnyxTypes.PolicyCategories>;

/** Collection of tags attached to a policy */
policyTags: OnyxEntry<OnyxTypes.PolicyTagLists>;

/** The actions from the parent report */
reportActions: OnyxEntry<OnyxTypes.ReportActions>;

/** Session info for the currently logged in user. */
session: OnyxEntry<OnyxTypes.Session>;
};

type IOURequestStepTagProps = IOURequestStepTagOnyxProps &
WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAG> &
WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAG>;
type IOURequestStepTagProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAG> & WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAG>;

function IOURequestStepTag({
policy,
policyCategories,
policyTags,
report,
route: {
params: {action, orderWeight: rawTagIndex, transactionID, backTo, iouType, reportActionID},
},
transaction,
splitDraftTransaction,
reportActions,
session,
}: IOURequestStepTagProps) {
const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID ?? 0}`);
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '-1'}`);
const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '-1'}`);
const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '-1'}`);
let reportID: string | undefined = '-1';
if (action === CONST.IOU.ACTION.EDIT) {
reportID = iouType === CONST.IOU.TYPE.SPLIT ? report?.reportID : report?.parentReportID;
}
const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {canEvict: false});
const session = useSession();
const styles = useThemeStyles();
const {translate} = useLocalize();

Expand All @@ -77,11 +64,12 @@ function IOURequestStepTag({
const canEditSplitBill = isSplitBill && reportAction && session?.accountID === reportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction);
const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags), [policyTags]);

const shouldShowTag = ReportUtils.isReportInGroupPolicy(report) && (transactionTag || OptionsListUtils.hasEnabledTags(policyTagLists));
const shouldShowTag = transactionTag || OptionsListUtils.hasEnabledTags(policyTagLists);

// eslint-disable-next-line rulesdir/no-negated-variables
const shouldShowNotFoundPage =
!shouldShowTag || (isEditing && (isSplitBill ? !canEditSplitBill : !ReportActionsUtils.isMoneyRequestAction(reportAction) || !ReportUtils.canEditMoneyRequest(reportAction)));
!ReportUtils.isReportInGroupPolicy(report) ||
(isEditing && (isSplitBill ? !canEditSplitBill : !ReportActionsUtils.isMoneyRequestAction(reportAction) || !ReportUtils.canEditMoneyRequest(reportAction)));

const navigateBack = () => {
Navigation.goBack(backTo);
Expand Down Expand Up @@ -113,58 +101,52 @@ function IOURequestStepTag({
testID={IOURequestStepTag.displayName}
shouldShowNotFoundPage={shouldShowNotFoundPage}
>
<>
<Text style={[styles.ph5, styles.pv3]}>{translate('iou.tagSelection')}</Text>
<TagPicker
policyID={report?.policyID ?? '-1'}
tagListName={policyTagListName}
tagListIndex={tagListIndex}
selectedTag={tag}
onSubmit={updateTag}
/>
</>
{!shouldShowTag && (
<View style={[styles.flex1]}>
<WorkspaceEmptyStateSection
shouldStyleAsCard={false}
icon={Illustrations.EmptyStateExpenses}
title={translate('workspace.tags.emptyTags.title')}
subtitle={translate('workspace.tags.emptyTags.subtitle')}
containerStyle={[styles.flex1, styles.justifyContentCenter]}
/>
{PolicyUtils.isPolicyAdmin(policy) && (
<FixedFooter style={[styles.mtAuto, styles.pt5]}>
<Button
large
success
style={[styles.w100]}
onPress={() =>
Navigation.navigate(
ROUTES.SETTINGS_TAGS_ROOT.getRoute(
policy?.id ?? '-1',
ROUTES.MONEY_REQUEST_STEP_TAG.getRoute(action, iouType, tagListIndex, transactionID, report?.reportID ?? '-1', backTo, reportActionID),
),
)
}
text={translate('workspace.tags.editTags')}
pressOnEnter
/>
</FixedFooter>
)}
</View>
)}
{shouldShowTag && (
<>
<Text style={[styles.ph5, styles.pv3]}>{translate('iou.tagSelection')}</Text>
<TagPicker
policyID={report?.policyID ?? '-1'}
tagListName={policyTagListName}
tagListIndex={tagListIndex}
selectedTag={tag}
onSubmit={updateTag}
/>
</>
)}
</StepScreenWrapper>
);
}

IOURequestStepTag.displayName = 'IOURequestStepTag';

export default withWritableReportOrNotFound(
withFullTransactionOrNotFound(
withOnyx<IOURequestStepTagProps, IOURequestStepTagOnyxProps>({
splitDraftTransaction: {
key: ({route}) => {
const transactionID = route.params.transactionID ?? 0;
return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`;
},
},
policy: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '-1'}`,
},
policyCategories: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '-1'}`,
},
policyTags: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '-1'}`,
},
reportActions: {
key: ({
report,
route: {
params: {action, iouType},
},
}) => {
let reportID: string | undefined = '-1';
if (action === CONST.IOU.ACTION.EDIT) {
reportID = iouType === CONST.IOU.TYPE.SPLIT ? report?.reportID : report?.parentReportID;
}
return `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`;
},
canEvict: false,
},
session: {
key: ONYXKEYS.SESSION,
},
})(IOURequestStepTag),
),
);
export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepTag));
Loading