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

Update Canceled task flow #24137

Merged
merged 37 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
b862234
Add parent reportAction isDeletedParentAction
thienlnam Jul 31, 2023
fffb864
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 1, 2023
69b6784
Add isDeletedParentAction check
thienlnam Aug 1, 2023
f40a5ac
Update header view on cancelled task
thienlnam Aug 1, 2023
2626fa9
update the header
thienlnam Aug 1, 2023
1c887da
add method to get all reportActions
thienlnam Aug 2, 2023
b765ae3
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 2, 2023
c9df9ce
update cancelTask method
thienlnam Aug 2, 2023
f175265
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 3, 2023
f640ac2
fix message not showing up
thienlnam Aug 3, 2023
24fc6c8
show the parent
thienlnam Aug 3, 2023
26858ed
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 3, 2023
7998e95
Remove the link in Preview isDeletedParentAction
thienlnam Aug 3, 2023
1c9ee15
Update method that checks isCanceledTaskReport
thienlnam Aug 3, 2023
0665968
Update places we check isCancelled task report
thienlnam Aug 3, 2023
b7ba6e9
Update places isCanceledTaskReport
thienlnam Aug 3, 2023
7ea0e80
onyx updates
thienlnam Aug 3, 2023
84d289b
pass the actual report
thienlnam Aug 3, 2023
32d5f1f
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 10, 2023
e5c898a
Make sure we don't include cancelled tasks in the selector
thienlnam Aug 10, 2023
52ea600
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 15, 2023
1796bc8
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 16, 2023
206669d
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 17, 2023
61bc6ae
Add RenderHTML to show deleted reportAction
thienlnam Aug 17, 2023
ec7ea0f
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Aug 30, 2023
1d0064e
Move around Cancel Task check
thienlnam Aug 30, 2023
52b3f9c
Clean up items related to new openTask check
thienlnam Aug 30, 2023
28aa55e
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Sep 11, 2023
29e5e3e
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Sep 11, 2023
ca719a0
add parent update
thienlnam Sep 11, 2023
59e8fff
remove the method for getting all created task reportActions
thienlnam Sep 11, 2023
9440ec2
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Sep 11, 2023
3de64e1
component got converted
thienlnam Sep 11, 2023
4bb1b31
prettier, fix compilation issues
thienlnam Sep 11, 2023
b35d758
Add translations
thienlnam Sep 11, 2023
e80fd05
Add horizontal rule
thienlnam Sep 12, 2023
b4604fb
Merge branch 'main' into jack-updateCancelledTaskUI
thienlnam Sep 15, 2023
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
5 changes: 5 additions & 0 deletions src/components/ReportActionItem/TaskPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ function TaskPreview(props) {
const assigneeDisplayName = lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'displayName'], '');
const taskAssignee = assigneeLogin || assigneeDisplayName;
const htmlForTaskPreview = taskAssignee ? `<comment><mention-user>@${taskAssignee}</mention-user> ${taskTitle}</comment>` : `<comment>${taskTitle}</comment>`;
const isDeletedParentAction = ReportUtils.isCanceledTaskReport(props.taskReport, props.action);

if (isDeletedParentAction) {
return <RenderHTML html={`<comment>${props.translate('parentReportAction.deletedTask')}</comment>`} />;
}

return (
<View style={[styles.chatItemMessage]}>
Expand Down
3 changes: 2 additions & 1 deletion src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1520,7 +1520,7 @@ export default {
completed: 'Completed',
messages: {
completed: 'completed task',
canceled: 'canceled task',
canceled: 'deleted task',
reopened: 'reopened task',
error: 'You do not have the permission to do the requested action.',
},
Expand Down Expand Up @@ -1692,6 +1692,7 @@ export default {
parentReportAction: {
deletedMessage: '[Deleted message]',
deletedRequest: '[Deleted request]',
deletedTask: '[Deleted task]',
hiddenMessage: '[Hidden message]',
},
threads: {
Expand Down
3 changes: 2 additions & 1 deletion src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,7 @@ export default {
completed: 'Completada',
messages: {
completed: 'tarea completada',
canceled: 'tarea cancelada',
canceled: 'tarea eliminado',
Copy link
Contributor

Choose a reason for hiding this comment

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

@thienlnam I don't know where you got this translation from (I checked slack and could not find it anywhere), but it is wrong. Please make sure you always get confirmation in #espanol-tranlsations

Copy link
Contributor

Choose a reason for hiding this comment

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

Sending a PR to fix this

reopened: 'tarea reabrir',
error: 'No tiene permiso para realizar la acción solicitada.',
},
Expand Down Expand Up @@ -2174,6 +2174,7 @@ export default {
parentReportAction: {
deletedMessage: '[Mensaje eliminado]',
deletedRequest: '[Pedido eliminado]',
deletedTask: '[Tarea eliminado]',
hiddenMessage: '[Mensaje oculto]',
},
threads: {
Expand Down
33 changes: 26 additions & 7 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,23 +187,37 @@ function isTaskReport(report) {
}

/**
* Checks if a report is an open task report.
* Checks if a task has been cancelled
* When a task is deleted, the parentReportAction is updated to have a isDeletedParentAction deleted flag
* This is because when you delete a task, we still allow you to chat on the report itself
* There's another situation where you don't have access to the parentReportAction (because it was created in a chat you don't have access to)
* In this case, we have added the key to the report itself
*
* @param {Object} report
* @param {Object} parentReportAction
* @returns {Boolean}
*/
function isOpenTaskReport(report) {
return isTaskReport(report) && report.stateNum === CONST.REPORT.STATE_NUM.OPEN && report.statusNum === CONST.REPORT.STATUS.OPEN;
function isCanceledTaskReport(report = {}, parentReportAction = {}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this method is specific only for task reports. I just tested deleting request money that has a message and thread; the actions also have isDeletedParentAction flagging.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah you are correct, a couple different report types can have the isDeletedParentAction. Though I am planning on keeping this name as task reports are slightly different in that the report can have the isDeletedParentAction key as well

if (!_.isEmpty(parentReportAction) && lodashGet(parentReportAction, ['message', 0, 'isDeletedParentAction'], false)) {
return true;
}

if (!_.isEmpty(report) && report.isDeletedParentAction) {
return true;
}

return false;
}

/**
* Checks if the current user is assigned to the task report
* Checks if a report is an open task report.
*
* @param {Object} report
* @param {Object} parentReportAction - The parent report action of the report (Used to check if the task has been canceled)
* @returns {Boolean}
*/
function isCanceledTaskReport(report) {
return isTaskReport(report) && report.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && report.statusNum === CONST.REPORT.STATUS.CLOSED;
function isOpenTaskReport(report, parentReportAction = {}) {
return isTaskReport(report) && !isCanceledTaskReport(report, parentReportAction) && report.stateNum === CONST.REPORT.STATE_NUM.OPEN && report.statusNum === CONST.REPORT.STATUS.OPEN;
}

/**
Expand Down Expand Up @@ -1600,8 +1614,8 @@ function getParentReport(report) {
*/
function getReportName(report, policy = undefined) {
let formattedName;
const parentReportAction = ReportActionsUtils.getParentReportAction(report);
if (isChatThread(report)) {
const parentReportAction = ReportActionsUtils.getParentReportAction(report);
if (ReportActionsUtils.isTransactionThread(parentReportAction)) {
return getTransactionReportName(parentReportAction);
}
Expand All @@ -1619,6 +1633,11 @@ function getReportName(report, policy = undefined) {
}
return parentReportActionMessage || Localize.translateLocal('parentReportAction.deletedMessage');
}

if (isTaskReport(report) && isCanceledTaskReport(report, parentReportAction)) {
return Localize.translateLocal('parentReportAction.deletedTask');
}

if (isChatRoom(report) || isTaskReport(report)) {
formattedName = report.reportName;
}
Expand Down
43 changes: 36 additions & 7 deletions src/libs/actions/Task.js
Original file line number Diff line number Diff line change
Expand Up @@ -755,26 +755,50 @@ function getShareDestination(reportID, reports, personalDetails) {
* @param {number} originalStatusNum
*/
function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum) {
const message = `canceled task: ${taskTitle}`;
const message = `deleted task: ${taskTitle}`;
const optimisticCancelReportAction = ReportUtils.buildOptimisticTaskReportAction(taskReportID, CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED, message);
const optimisticReportActionID = optimisticCancelReportAction.reportActionID;
const taskReport = ReportUtils.getReport(taskReportID);
const parentReportAction = ReportActionsUtils.getParentReportAction(taskReport);
const parentReport = ReportUtils.getParentReport(taskReport);

const optimisticReportActions = {
[parentReportAction.reportActionID]: {
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
Copy link
Contributor

@alitoshmatov alitoshmatov Jul 26, 2024

Choose a reason for hiding this comment

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

Pending action here could be either update or delete based on if it has thread messages, ref: #44997

previousMessage: parentReportAction.message,
message: [
{
translationKey: '',
type: 'COMMENT',
html: '',
text: '',
isEdited: true,
isDeletedParentAction: true,
},
],
errors: null,
linkMetaData: [],
},
};

const optimisticData = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`,
value: {
stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
statusNum: CONST.REPORT.STATUS.CLOSED,
lastVisibleActionCreated: optimisticCancelReportAction.created,
lastMessageText: message,
lastActorAccountID: optimisticCancelReportAction.actorAccountID,
updateReportInLHN: true,
isDeletedParentAction: true,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT}${parentReport.reportID}`,
value: {
lastVisibleActionCreated: optimisticCancelReportAction.created,
lastMessageText: message,
lastActorAccountID: optimisticCancelReportAction.actorAccountID,
lastMessageText: ReportActionsUtils.getLastVisibleMessage(parentReport.reportID, {[parentReportAction.reportActionID]: null}).lastMessageText,
lastVisibleActionCreated: ReportActionsUtils.getLastVisibleAction(parentReport.reportID, {[parentReportAction.reportActionID]: null}).created,
},
},
{
Expand All @@ -784,6 +808,11 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum
[optimisticReportActionID]: optimisticCancelReportAction,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport.reportID}`,
value: optimisticReportActions,
},
];

const successData = [
Expand Down
5 changes: 4 additions & 1 deletion src/pages/home/HeaderView.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import reportActionPropTypes from './report/reportActionPropTypes';
import PressableWithoutFeedback from '../../components/Pressable/PressableWithoutFeedback';
import PinButton from '../../components/PinButton';
import TaskHeaderActionButton from '../../components/TaskHeaderActionButton';
import * as ReportActionsUtils from '../../libs/ReportActionsUtils';
import ParentNavigationSubtitle from '../../components/ParentNavigationSubtitle';

const propTypes = {
Expand Down Expand Up @@ -93,12 +94,14 @@ function HeaderView(props) {
const isConcierge = ReportUtils.hasSingleParticipant(props.report) && _.contains(participants, CONST.ACCOUNT_ID.CONCIERGE);
const isAutomatedExpensifyAccount = ReportUtils.hasSingleParticipant(props.report) && ReportUtils.hasAutomatedExpensifyAccountIDs(participants);
const guideCalendarLink = lodashGet(props.account, 'guideCalendarLink');
const parentReportAction = ReportActionsUtils.getParentReportAction(props.report);
const isCanceledTaskReport = ReportUtils.isCanceledTaskReport(props.report, parentReportAction);

// We hide the button when we are chatting with an automated Expensify account since it's not possible to contact
// these users via alternative means. It is possible to request a call with Concierge so we leave the option for them.
const shouldShowCallButton = (isConcierge && guideCalendarLink) || (!isAutomatedExpensifyAccount && !isTaskReport);
const threeDotMenuItems = [];
if (isTaskReport) {
if (isTaskReport && !isCanceledTaskReport) {
const canModifyTask = Task.canModifyTask(props.report, props.session.accountID);
if (ReportUtils.isOpenTaskReport(props.report) && canModifyTask) {
threeDotMenuItems.push({
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/ReportScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ function ReportScreen({
needsOffscreenAlphaCompositing
>
{headerView}
{ReportUtils.isTaskReport(report) && isSmallScreenWidth && ReportUtils.isOpenTaskReport(report) && (
{ReportUtils.isTaskReport(report) && isSmallScreenWidth && ReportUtils.isOpenTaskReport(report, parentReportAction) && (
<View style={[styles.borderBottom]}>
<View style={[styles.appBG, styles.pl0]}>
<View style={[styles.ph5, styles.pb3]}>
Expand Down
17 changes: 17 additions & 0 deletions src/pages/home/report/ReportActionItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import * as BankAccounts from '../../../libs/actions/BankAccounts';
import usePrevious from '../../../hooks/usePrevious';
import ReportScreenContext from '../ReportScreenContext';
import Permissions from '../../../libs/Permissions';
import RenderHTML from '../../../components/RenderHTML';
import ReportAttachmentsContext from './ReportAttachmentsContext';

const propTypes = {
Expand Down Expand Up @@ -514,6 +515,22 @@ function ReportActionItem(props) {
);
}
if (ReportUtils.isTaskReport(props.report)) {
if (ReportUtils.isCanceledTaskReport(props.report, parentReportAction)) {
return (
<>
<ReportActionItemSingle
action={parentReportAction}
showHeader={!props.draftMessage}
wrapperStyles={[styles.chatItem]}
report={props.report}
>
<RenderHTML html={`<comment>${props.translate('parentReportAction.deletedTask')}</comment>`} />
</ReportActionItemSingle>
<View style={styles.reportHorizontalRule} />
</>
);
}

return (
<OfflineWithFeedback pendingAction={props.action.pendingAction}>
<TaskView
Expand Down
6 changes: 5 additions & 1 deletion src/pages/tasks/TaskShareDestinationSelectorModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ function TaskShareDestinationSelectorModal(props) {
const filteredReports = useMemo(() => {
const reports = {};
_.keys(props.reports).forEach((reportKey) => {
if (ReportUtils.shouldDisableWriteActions(props.reports[reportKey]) || ReportUtils.isExpensifyOnlyParticipantInReport(props.reports[reportKey])) {
if (
ReportUtils.shouldDisableWriteActions(props.reports[reportKey]) ||
ReportUtils.isExpensifyOnlyParticipantInReport(props.reports[reportKey]) ||
ReportUtils.isCanceledTaskReport(props.reports[reportKey])
) {
return;
}
reports[reportKey] = props.reports[reportKey];
Expand Down
Loading