Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions src/components/ReportActionItem/TaskPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,19 @@ function TaskPreview({
const {translate} = useLocalize();
const theme = useTheme();
const taskReportID = taskReport?.reportID ?? action?.childReportID;
const taskTitle = action?.childReportName ?? taskReport?.reportName ?? '';
// Prefer the live task report name so offline title edits are reflected immediately.
const taskTitle = taskReport?.reportName ?? action?.childReportName ?? '';
const taskContextReport =
taskReport ??
({
reportID: taskReportID,
parentReportID: chatReportID,
parentReportActionID: action?.reportActionID,
ownerAccountID: action?.childOwnerAccountID,
managerID: action?.childManagerAccountID,
stateNum: action?.childStateNum,
statusNum: action?.childStatusNum,
} as Report);

const taskTitleWithoutImage = Parser.replace(Parser.htmlToMarkdown(taskTitle), {disabledRules: [...CONST.TASK_TITLE_DISABLED_RULES]});

Expand All @@ -96,20 +108,20 @@ function TaskPreview({
const isTaskCompleted = !isEmptyObject(taskReport)
? 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 parentReportAction = useParentReportAction(taskReport);
const taskAssigneeAccountID = getTaskAssigneeAccountID(taskReport, parentReportAction) ?? action?.childManagerAccountID ?? CONST.DEFAULT_NUMBER_ID;
const parentReport = useParentReport(taskReport?.reportID);
const parentReportAction = useParentReportAction(taskContextReport);
const taskAssigneeAccountID = getTaskAssigneeAccountID(taskContextReport, parentReportAction) ?? action?.childManagerAccountID ?? CONST.DEFAULT_NUMBER_ID;
const parentReport = useParentReport(taskContextReport?.reportID);
const isParentReportArchived = useReportIsArchived(parentReport?.reportID);
const hasOutstandingChildTask = useHasOutstandingChildTask(taskReport);
const isTaskActionable = canActionTask(taskReport, parentReportAction, currentUserPersonalDetails.accountID, parentReport, isParentReportArchived);
const hasOutstandingChildTask = useHasOutstandingChildTask(taskContextReport);
const isTaskActionable = canActionTask(taskContextReport, parentReportAction, currentUserPersonalDetails.accountID, parentReport, isParentReportArchived);
const hasAssignee = taskAssigneeAccountID > 0;
const personalDetails = usePersonalDetails();
const avatar = personalDetails?.[taskAssigneeAccountID]?.avatar ?? icons.FallbackAvatar;
const avatarSize = CONST.AVATAR_SIZE.SMALL;
const isDeletedParentAction = isCanceledTaskReport(taskReport, action);
const iconWrapperStyle = StyleUtils.getTaskPreviewIconWrapper(hasAssignee ? avatarSize : undefined);

const shouldShowGreenDotIndicator = isOpenTaskReport(taskReport, action) && isReportManager(taskReport);
const shouldShowGreenDotIndicator = isOpenTaskReport(taskContextReport, action) && isReportManager(taskContextReport);
if (isDeletedParentAction) {
return <RenderHTML html={`<deleted-action>${translate('parentReportAction.deletedTask')}</deleted-action>`} />;
}
Expand Down Expand Up @@ -150,9 +162,9 @@ function TaskPreview({
disabled={!isTaskActionable}
onPress={callFunctionIfActionIsAllowed(() => {
if (isTaskCompleted) {
reopenTask(taskReport, parentReport, currentUserPersonalDetails.accountID, taskReportID);
reopenTask(taskContextReport, parentReport, currentUserPersonalDetails.accountID, taskReportID);
} else {
completeTask(taskReport, parentReport?.hasOutstandingChildTask ?? false, hasOutstandingChildTask, parentReportAction, taskReportID);
completeTask(taskContextReport, parentReport?.hasOutstandingChildTask ?? false, hasOutstandingChildTask, parentReportAction, taskReportID);
}
})}
accessibilityLabel={translate('task.task')}
Expand Down
8 changes: 7 additions & 1 deletion src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {canUseTouchScreen} from '@libs/DeviceCapabilities';
import Log from '@libs/Log';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import {isCreatedTaskReportAction} from '@libs/ReportActionsUtils';
import {isSplitAction} from '@libs/ReportSecondaryActionUtils';
import {canEditFieldOfMoneyRequest, canHoldUnholdReportAction, canRejectReportAction, isOneTransactionReport, selectFilteredReportActions} from '@libs/ReportUtils';
import {buildCannedSearchQuery, buildSearchQueryString} from '@libs/SearchQueryUtils';
Expand Down Expand Up @@ -1056,7 +1057,12 @@ function Search({
}

if (isReportActionListItemType(item)) {
const reportActionID = reportActionItem.reportActionID;
// Keep deep-linking for persisted actions, but avoid anchoring to optimistic created-task actions that may not be resolvable offline.
const isOptimisticCreatedTaskAction = reportActionItem.isOptimisticAction ?? false;
const shouldSkipReportActionID =
isCreatedTaskReportAction(reportActionItem) && (isOptimisticCreatedTaskAction || reportActionItem.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);

const reportActionID = shouldSkipReportActionID ? undefined : reportActionItem.reportActionID;
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID, reportActionID, backTo}));
return;
}
Expand Down
11 changes: 9 additions & 2 deletions src/libs/SearchUIUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2169,9 +2169,15 @@ function getReportActionsSections(data: OnyxTypes.SearchResults['data'], visible
const reportActions = Object.values(data[key]);
n += reportActions.length;
for (const reportAction of reportActions) {
const reportID = reportAction.reportID ?? reportIDFromKey;
// Always use the container reportID so "In <chat name>" rows open the parent chat, not a child task/thread report.
const reportID = reportIDFromKey;
const from = reportAction.accountID ? (data.personalDetailsList?.[reportAction.accountID] ?? emptyPersonalDetails) : emptyPersonalDetails;
const report = data[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? {};
const report =
getReportOrDraftReport(reportID) ??
getReportOrDraftReport(reportAction.reportID) ??
data[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ??
data[`${ONYXKEYS.COLLECTION.REPORT}${reportAction.reportID}`] ??
{};
const policy = data[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`] ?? {};
const originalMessage = isMoneyRequestAction(reportAction) ? getOriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.IOU>(reportAction) : undefined;
const isSendingMoney = isMoneyRequestAction(reportAction) && originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY && originalMessage?.IOUDetails;
Expand All @@ -2193,6 +2199,7 @@ function getReportActionsSections(data: OnyxTypes.SearchResults['data'], visible

reportActionItems.push({
...reportAction,
reportID,
from,
// eslint-disable-next-line @typescript-eslint/no-deprecated
reportName: getSearchReportName({report, policy, personalDetails: data.personalDetailsList, transactions, invoiceReceiverPolicy, reports, policies, isReportArchived}),
Expand Down
2 changes: 1 addition & 1 deletion src/libs/actions/Report/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@
// map of reportID to all reportActions for that report
const allReportActions: OnyxCollection<ReportActions> = {};

Onyx.connect({

Check warning on line 371 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
callback: (actions, key) => {
if (!key || !actions) {
Expand All @@ -380,7 +380,7 @@
});

let allReports: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 383 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -389,7 +389,7 @@
});

let allPersonalDetails: OnyxEntry<PersonalDetailsList> = {};
Onyx.connect({

Check warning on line 392 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand All @@ -407,7 +407,7 @@
});

let onboarding: OnyxEntry<Onboarding>;
Onyx.connect({

Check warning on line 410 in src/libs/actions/Report/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_ONBOARDING,
callback: (val) => {
if (Array.isArray(val)) {
Expand Down Expand Up @@ -871,7 +871,7 @@
failureReportActions[pregeneratedResponseParams.optimisticConciergeReportActionID] = null;
}

const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.SNAPSHOT>> = [
const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
Expand Down
71 changes: 59 additions & 12 deletions src/libs/actions/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,7 @@ function createTaskAndNavigate(params: CreateTaskAndNavigateParams) {
// task report/action on API failure so the task stays visible until the user dismiss the
// error from chat.
const failureData: Array<
OnyxUpdate<
| typeof ONYXKEYS.COLLECTION.REPORT
| typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS
| typeof ONYXKEYS.PERSONAL_DETAILS_LIST
| typeof ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE
| typeof ONYXKEYS.COLLECTION.SNAPSHOT
>
OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.PERSONAL_DETAILS_LIST | typeof ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE>
> = [];

if (assigneeChatReport && assigneeChatReportID) {
Expand Down Expand Up @@ -424,12 +418,15 @@ function buildTaskData(
},
];

if (parentReportAction) {
const parentReportID = taskReport?.parentReportID;
const parentReportActionID = parentReportAction?.reportActionID ?? taskReport?.parentReportActionID;

if (parentReportID && parentReportActionID) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReport?.parentReportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`,
value: {
[parentReportAction.reportActionID]: {
[parentReportActionID]: {
childStateNum: CONST.REPORT.STATE_NUM.APPROVED,
childStatusNum: CONST.REPORT.STATUS_NUM.APPROVED,
},
Expand All @@ -438,9 +435,9 @@ function buildTaskData(

failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReport?.parentReportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`,
value: {
[parentReportAction.reportActionID]: {
[parentReportActionID]: {
childStateNum: CONST.REPORT.STATE_NUM.OPEN,
childStatusNum: CONST.REPORT.STATUS_NUM.OPEN,
},
Expand Down Expand Up @@ -541,6 +538,19 @@ function reopenTask(taskReport: OnyxEntry<OnyxTypes.Report>, parentReport: OnyxE
},
];

if (taskReport?.parentReportID && taskReport?.parentReportActionID) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReport.parentReportID}`,
value: {
[taskReport.parentReportActionID]: {
childStateNum: CONST.REPORT.STATE_NUM.OPEN,
childStatusNum: CONST.REPORT.STATUS_NUM.OPEN,
},
},
});
}

const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [
{
onyxMethod: Onyx.METHOD.MERGE,
Expand Down Expand Up @@ -579,6 +589,19 @@ function reopenTask(taskReport: OnyxEntry<OnyxTypes.Report>, parentReport: OnyxE
},
];

if (taskReport?.parentReportID && taskReport?.parentReportActionID) {
failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReport.parentReportID}`,
value: {
[taskReport.parentReportActionID]: {
childStateNum: CONST.REPORT.STATE_NUM.APPROVED,
childStatusNum: CONST.REPORT.STATUS_NUM.APPROVED,
},
},
});
}

const parameters: ReopenTaskParams = {
taskReportID,
reopenedTaskReportActionID: reopenedTaskReportAction.reportActionID,
Expand Down Expand Up @@ -621,6 +644,18 @@ function editTask(report: OnyxTypes.Report, {title, description}: OnyxTypes.Task
},
];

if (title && report.parentReportID && report.parentReportActionID) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`,
value: {
[report.parentReportActionID]: {
childReportName: parsedTitle,
},
},
});
}

const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>> = [
{
onyxMethod: Onyx.METHOD.MERGE,
Expand Down Expand Up @@ -657,6 +692,18 @@ function editTask(report: OnyxTypes.Report, {title, description}: OnyxTypes.Task
},
];

if (title && report.parentReportID && report.parentReportActionID) {
failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`,
value: {
[report.parentReportActionID]: {
childReportName: report.reportName,
},
},
});
}

const parameters: EditTaskParams = {
taskReportID: report.reportID,
htmlTitle: parsedTitle,
Expand Down
Loading