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

Handle deleted reports for Quick Actions #41474

Merged
merged 17 commits into from
May 6, 2024
2 changes: 2 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,8 @@ export default {
trackManual: 'Track expense',
trackScan: 'Track receipt',
trackDistance: 'Track distance',
noLongerHaveReportAccess: 'You no longer have access to your previous quick action destination. Pick a new one below.',
updateDestination: 'Update destination',
},
iou: {
amount: 'Amount',
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,8 @@ export default {
trackManual: 'Crear gasto',
trackScan: 'Crear gasto por recibo',
trackDistance: 'Crear gasto por desplazamiento',
noLongerHaveReportAccess: 'Ya no tienes acceso al destino previo de esta acción rápida. Escoge uno nuevo a continuación.',
updateDestination: 'Actualiza el destino',
},
iou: {
amount: 'Importe',
Expand Down
5 changes: 3 additions & 2 deletions src/libs/actions/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ function setAssigneeValue(
shareToReportID?: string,
chatReport?: OnyxEntry<OnyxTypes.Report>,
isCurrentUser = false,
skipShareDestination = false,
): OnyxEntry<OnyxTypes.Report> | undefined {
let report: OnyxEntry<OnyxTypes.Report> | undefined = chatReport;
if (!isCurrentUser) {
Expand Down Expand Up @@ -703,7 +704,7 @@ function setAssigneeValue(

// If there is no share destination set, automatically set it to the assignee chat report
// This allows for a much quicker process when creating a new task and is likely the desired share destination most times
if (!shareToReportID) {
if (!shareToReportID && !skipShareDestination) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I may be missing something here but as shareToReportID will be empty in our case, will this not work without the need for skipShareDestination?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, not quite. If skipShareDestination is set, we do NOT want to populate this, as it populates by default to the user's chat, which is not what we want in this flow

setShareDestinationValue(report?.reportID ?? '');
}
}
Expand Down Expand Up @@ -735,7 +736,7 @@ function clearOutTaskInfoAndNavigate(reportID?: string, chatReport?: OnyxEntry<O
}
if (accountID > 0) {
const accountLogin = allPersonalDetails?.[accountID]?.login ?? '';
setAssigneeValue(accountLogin, accountID, reportID, chatReport);
setAssigneeValue(accountLogin, accountID, reportID, chatReport, false, skipConfirmation);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should had checked if accountID === currentUserAccountID instead of directly passing false here, this caused #47680

}
Navigation.navigate(ROUTES.NEW_TASK_DETAILS);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRo
import Navigation from '@libs/Navigation/Navigation';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import {isArchivedRoom} from '@libs/ReportUtils';
import * as App from '@userActions/App';
import * as IOU from '@userActions/IOU';
import * as Policy from '@userActions/Policy';
Expand Down Expand Up @@ -199,39 +200,41 @@ function FloatingActionButtonAndPopover(
}, [quickAction, translate]);

const navigateToQuickAction = () => {
const isValidReport = !(isEmptyObject(quickActionReport) || isArchivedRoom(quickActionReport));
const quickActionReportID = isValidReport ? quickActionReport?.reportID ?? '' : ReportUtils.generateReportID();
switch (quickAction?.action) {
case CONST.QUICK_ACTIONS.REQUEST_MANUAL:
IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.MANUAL, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true);
return;
case CONST.QUICK_ACTIONS.REQUEST_SCAN:
IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.SCAN, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true);
return;
case CONST.QUICK_ACTIONS.REQUEST_DISTANCE:
IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.DISTANCE, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.SUBMIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, true);
return;
case CONST.QUICK_ACTIONS.SPLIT_MANUAL:
IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.MANUAL, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true);
return;
case CONST.QUICK_ACTIONS.SPLIT_SCAN:
IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.SCAN, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true);
return;
case CONST.QUICK_ACTIONS.SPLIT_DISTANCE:
IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.DISTANCE, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.SPLIT, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, true);
return;
case CONST.QUICK_ACTIONS.SEND_MONEY:
IOU.startMoneyRequest(CONST.IOU.TYPE.PAY, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.MANUAL, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.PAY, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true);
return;
case CONST.QUICK_ACTIONS.ASSIGN_TASK:
Task.clearOutTaskInfoAndNavigate(quickAction?.chatReportID ?? '', quickActionReport, quickAction.targetAccountID ?? 0, true);
Task.clearOutTaskInfoAndNavigate(isValidReport ? quickActionReportID : '', isValidReport ? quickActionReport : undefined, quickAction.targetAccountID ?? 0, true);
Gonals marked this conversation as resolved.
Show resolved Hide resolved
break;
case CONST.QUICK_ACTIONS.TRACK_MANUAL:
IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.MANUAL, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.MANUAL, true);
break;
case CONST.QUICK_ACTIONS.TRACK_SCAN:
IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.SCAN, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.SCAN, true);
break;
case CONST.QUICK_ACTIONS.TRACK_DISTANCE:
IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickAction?.chatReportID ?? '', CONST.IOU.REQUEST_TYPE.DISTANCE, true);
IOU.startMoneyRequest(CONST.IOU.TYPE.TRACK, quickActionReportID, CONST.IOU.REQUEST_TYPE.DISTANCE, true);
break;
default:
}
Expand Down Expand Up @@ -436,7 +439,7 @@ function FloatingActionButtonAndPopover(
isLabelHoverable: false,
floatRightAvatars: quickActionAvatars,
floatRightAvatarSize: CONST.AVATAR_SIZE.SMALL,
description: !isEmptyObject(quickActionReport) ? ReportUtils.getReportName(quickActionReport) : '',
description: ReportUtils.getReportName(quickActionReport) ?? translate('quickAction.updateDestination'),
numberOfLinesDescription: 1,
onSelected: () => interceptAnonymousUser(() => navigateToQuickAction()),
shouldShowSubscriptRightAvatar: ReportUtils.isPolicyExpenseChat(quickActionReport),
Expand Down
30 changes: 26 additions & 4 deletions src/pages/iou/request/step/IOURequestStepParticipants.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React, {useCallback, useEffect, useMemo, useRef} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import FormHelpMessage from '@components/FormHelpMessage';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import DistanceRequestUtils from '@libs/DistanceRequestUtils';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as TransactionUtils from '@libs/TransactionUtils';
import MoneyRequestParticipantsSelector from '@pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector';
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 {Transaction} from '@src/types/onyx';
import type {Participant} from '@src/types/onyx/IOU';
import StepScreenWrapper from './StepScreenWrapper';
import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound';
Expand All @@ -19,8 +22,8 @@ import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotF
import withWritableReportOrNotFound from './withWritableReportOrNotFound';

type IOURequestStepParticipantsOnyxProps = {
/** The transaction object being modified in Onyx */
transaction: OnyxEntry<Transaction>;
/** Whether the confirmation step should be skipped */
skipConfirmation: OnyxEntry<boolean>;
};

type IOURequestStepParticipantsProps = IOURequestStepParticipantsOnyxProps &
Expand All @@ -32,9 +35,11 @@ function IOURequestStepParticipants({
params: {iouType, reportID, transactionID, action},
},
transaction,
skipConfirmation,
}: IOURequestStepParticipantsProps) {
const participants = transaction?.participants;
const {translate} = useLocalize();
const styles = useThemeStyles();
const selectedReportID = useRef<string>(reportID);
const numberOfParticipants = useRef(participants?.length ?? 0);
const iouRequestType = TransactionUtils.getRequestType(transaction);
Expand Down Expand Up @@ -122,6 +127,14 @@ function IOURequestStepParticipants({
testID={IOURequestStepParticipants.displayName}
includeSafeAreaPaddingBottom={false}
>
{skipConfirmation && (
<FormHelpMessage
style={[styles.ph4, styles.mb4]}
isError={false}
shouldShowRedDotIndicator={false}
message={translate('quickAction.noLongerHaveReportAccess')}
/>
)}
<MoneyRequestParticipantsSelector
participants={isSplitRequest ? participants : []}
onParticipantsAdded={addParticipant}
Expand All @@ -136,4 +149,13 @@ function IOURequestStepParticipants({

IOURequestStepParticipants.displayName = 'IOURequestStepParticipants';

export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepParticipants));
const IOURequestStepParticipantsWithOnyx = withOnyx<IOURequestStepParticipantsProps, IOURequestStepParticipantsOnyxProps>({
skipConfirmation: {
key: ({route}) => {
const transactionID = route.params.transactionID ?? 0;
return `${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`;
},
},
})(IOURequestStepParticipants);

export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepParticipantsWithOnyx));
10 changes: 10 additions & 0 deletions src/pages/tasks/NewTaskPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {withOnyx} from 'react-native-onyx';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton';
import FormHelpMessage from '@components/FormHelpMessage';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import MenuItem from '@components/MenuItem';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
Expand Down Expand Up @@ -52,6 +53,7 @@ function NewTaskPage({task, reports, personalDetails}: NewTaskPageProps) {
const [errorMessage, setErrorMessage] = useState('');
const [parentReport, setParentReport] = useState<OnyxEntry<Report>>(null);

const hasDestinationError = task?.skipConfirmation && !task?.parentReportID;
const isAllowedToCreateTask = useMemo(() => isEmptyObject(parentReport) || ReportUtils.isAllowedToComment(parentReport), [parentReport]);

useEffect(() => {
Expand Down Expand Up @@ -138,6 +140,14 @@ function NewTaskPage({task, reports, personalDetails}: NewTaskPageProps) {
Navigation.goBack(ROUTES.NEW_TASK_DETAILS);
}}
/>
{hasDestinationError && (
<FormHelpMessage
style={[styles.ph4, styles.mb4]}
isError={false}
shouldShowRedDotIndicator={false}
message={translate('quickAction.noLongerHaveReportAccess')}
/>
)}
<ScrollView
contentContainerStyle={styles.flexGrow1}
// on iOS, navigation animation sometimes cause the scrollbar to appear
Expand Down
Loading