From 21c0ae56d1d318e620ae1e50ee97627ab105be99 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 27 Sep 2023 10:53:59 +0200 Subject: [PATCH 01/42] ref: started migrating Task lib to TS --- src/libs/actions/{Task.js => Task.ts} | 65 ++++++++++++--------------- src/types/onyx/Report.ts | 2 + 2 files changed, 31 insertions(+), 36 deletions(-) rename src/libs/actions/{Task.js => Task.ts} (93%) diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.ts similarity index 93% rename from src/libs/actions/Task.js rename to src/libs/actions/Task.ts index 963bfebb7eb2..b5c813e14521 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.ts @@ -14,21 +14,22 @@ import * as ReportActionsUtils from '../ReportActionsUtils'; import * as Expensicons from '../../components/Icon/Expensicons'; import * as LocalePhoneNumber from '../LocalePhoneNumber'; import * as Localize from '../Localize'; +import {PersonalDetails, Report, Task} from '../../types/onyx'; -let currentUserEmail; -let currentUserAccountID; +let currentUserEmail: string; +let currentUserAccountID: number; Onyx.connect({ key: ONYXKEYS.SESSION, - callback: (val) => { - currentUserEmail = lodashGet(val, 'email', ''); - currentUserAccountID = lodashGet(val, 'accountID', 0); + callback: (value) => { + currentUserEmail = value?.email ?? ''; + currentUserAccountID = value?.accountID ?? 0; }, }); -let allPersonalDetails; +let allPersonalDetails: Record | null; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, - callback: (val) => (allPersonalDetails = val), + callback: (value) => (allPersonalDetails = value), }); /** @@ -52,16 +53,16 @@ function clearOutTaskInfo() { * 3. The chat report between you and the assignee * 3a. The CreatedReportAction for the assignee chat report * 3b. The TaskReportAction on the assignee chat report - * - * @param {String} parentReportID - * @param {String} title - * @param {String} description - * @param {String} assigneeEmail - * @param {Number} assigneeAccountID - * @param {Object} assigneeChatReport - The chat report between you and the assignee - * @param {String} policyID - the policyID of the parent report */ -function createTaskAndNavigate(parentReportID, title, description, assigneeEmail, assigneeAccountID = 0, assigneeChatReport = null, policyID = CONST.POLICY.OWNER_EMAIL_FAKE) { +function createTaskAndNavigate( + parentReportID: string, + title: string, + description: string, + assigneeEmail: string, + assigneeAccountID = 0, + assigneeChatReport: Report | null = null, + policyID = CONST.POLICY.OWNER_EMAIL_FAKE, +) { const optimisticTaskReport = ReportUtils.buildOptimisticTaskReport(currentUserAccountID, assigneeAccountID, parentReportID, title, description, policyID); const assigneeChatReportID = assigneeChatReport ? assigneeChatReport.reportID : 0; @@ -203,12 +204,8 @@ function createTaskAndNavigate(parentReportID, title, description, assigneeEmail assignee: assigneeEmail, assigneeAccountID, assigneeChatReportID, - assigneeChatReportActionID: - assigneeChatReportOnyxData && assigneeChatReportOnyxData.optimisticAssigneeAddComment - ? assigneeChatReportOnyxData.optimisticAssigneeAddComment.reportAction.reportActionID - : 0, - assigneeChatCreatedReportActionID: - assigneeChatReportOnyxData && assigneeChatReportOnyxData.optimisticChatCreatedReportAction ? assigneeChatReportOnyxData.optimisticChatCreatedReportAction.reportActionID : 0, + assigneeChatReportActionID: assigneeChatReportOnyxData?.optimisticAssigneeAddComment.reportAction.reportActionID ?? 0, + assigneeChatCreatedReportActionID: assigneeChatReportOnyxData?.optimisticChatCreatedReportAction.reportActionID ?? 0, }, {optimisticData, successData, failureData}, ); @@ -305,7 +302,7 @@ function completeTask(taskReport, taskTitle) { * @param {Object} taskReport task report * @param {String} taskTitle Title of the task */ -function reopenTask(taskReport, taskTitle) { +function reopenTask(taskReport: Report, taskTitle: string) { const taskReportID = taskReport.reportID; const message = `reopened task: ${taskTitle}`; const reopenedTaskReportAction = ReportUtils.buildOptimisticTaskReportAction(taskReportID, CONST.REPORT.ACTIONS.TYPE.TASKREOPENED, message); @@ -393,15 +390,15 @@ function reopenTask(taskReport, taskTitle) { * @param {Object} editedTask * @param {Object} assigneeChatReport - The chat report between you and the assignee */ -function editTaskAndNavigate(report, ownerAccountID, {title, description, assignee = '', assigneeAccountID = 0}, assigneeChatReport = null) { +function editTaskAndNavigate(report: Report, ownerAccountID: number, {title, description, assignee = '', assigneeAccountID = 0}: Task, assigneeChatReport: Report | null = null) { // Create the EditedReportAction on the task const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail); // Sometimes title or description is undefined, so we need to check for that, and we provide it to multiple functions - const reportName = (title || report.reportName).trim(); + const reportName = (title ?? report?.reportName).trim(); // Description can be unset, so we default to an empty string if so - const reportDescription = (!_.isUndefined(description) ? description : lodashGet(report, 'description', '')).trim(); + const reportDescription = (description ?? report.description ?? '').trim(); let assigneeChatReportOnyxData; const assigneeChatReportID = assigneeChatReport ? assigneeChatReport.reportID : 0; @@ -418,8 +415,8 @@ function editTaskAndNavigate(report, ownerAccountID, {title, description, assign value: { reportName, description: reportDescription, - managerID: assigneeAccountID || report.managerID, - managerEmail: assignee || report.managerEmail, + managerID: assigneeAccountID ?? report.managerID, + managerEmail: assignee ?? report.managerEmail, pendingFields: { ...(title && {reportName: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), ...(description && {description: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), @@ -487,12 +484,8 @@ function editTaskAndNavigate(report, ownerAccountID, {title, description, assign assigneeAccountID: assigneeAccountID || report.managerID, editedTaskReportActionID: editTaskReportAction.reportActionID, assigneeChatReportID, - assigneeChatReportActionID: - assigneeChatReportOnyxData && assigneeChatReportOnyxData.optimisticAssigneeAddComment - ? assigneeChatReportOnyxData.optimisticAssigneeAddComment.reportAction.reportActionID - : 0, - assigneeChatCreatedReportActionID: - assigneeChatReportOnyxData && assigneeChatReportOnyxData.optimisticChatCreatedReportAction ? assigneeChatReportOnyxData.optimisticChatCreatedReportAction.reportActionID : 0, + assigneeChatReportActionID: assigneeChatReportOnyxData.optimisticAssigneeAddComment.reportAction.reportActionID ?? 0, + assigneeChatCreatedReportActionID: assigneeChatReportOnyxData.optimisticChatCreatedReportAction.reportActionID ?? 0, }, {optimisticData, successData, failureData}, ); @@ -500,10 +493,10 @@ function editTaskAndNavigate(report, ownerAccountID, {title, description, assign Navigation.dismissModal(report.reportID); } -function editTaskAssigneeAndNavigate(report, ownerAccountID, assigneeEmail, assigneeAccountID = 0, assigneeChatReport = null) { +function editTaskAssigneeAndNavigate(report: Report, ownerAccountID: number, assigneeEmail: string, assigneeAccountID = 0, assigneeChatReport: Report | null = null) { // Create the EditedReportAction on the task const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail); - const reportName = report.reportName.trim(); + const reportName = report.reportName?.trim(); let assigneeChatReportOnyxData; const assigneeChatReportID = assigneeChatReport ? assigneeChatReport.reportID : 0; diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index 88caa683305d..2e944c156a64 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -83,6 +83,8 @@ type Report = { participantAccountIDs?: number[]; total?: number; currency?: string; + description?: string; + managerEmail?: string; }; export default Report; From 87998bf588a4fa826f06767b898f022111a5806d Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 27 Sep 2023 13:20:31 +0200 Subject: [PATCH 02/42] ref: move all methods to TS --- src/libs/actions/Task.ts | 155 +++++++++++++-------------------------- src/types/onyx/Report.ts | 1 + 2 files changed, 51 insertions(+), 105 deletions(-) diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index b5c813e14521..adc7c41f4cfe 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -1,6 +1,4 @@ import Onyx from 'react-native-onyx'; -import lodashGet from 'lodash/get'; -import _ from 'underscore'; import ONYXKEYS from '../../ONYXKEYS'; import * as API from '../API'; import * as ReportUtils from '../ReportUtils'; @@ -215,10 +213,8 @@ function createTaskAndNavigate( /** * Complete a task - * @param {Object} taskReport task report - * @param {String} taskTitle Title of the task */ -function completeTask(taskReport, taskTitle) { +function completeTask(taskReport: Report, taskTitle: string) { const taskReportID = taskReport.reportID; const message = `completed task: ${taskTitle}`; const completedTaskReportAction = ReportUtils.buildOptimisticTaskReportAction(taskReportID, CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED, message); @@ -251,6 +247,7 @@ function completeTask(taskReport, taskTitle) { }, }, ]; + const failureData = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -274,7 +271,7 @@ function completeTask(taskReport, taskTitle) { // Multiple report actions can link to the same child. Both share destination (task parent) and assignee report link to the same report action. // We need to find and update the other parent report action (in assignee report). More info https://github.com/Expensify/App/issues/23920#issuecomment-1663092717 const assigneeReportAction = ReportUtils.getTaskParentReportActionIDInAssigneeReport(taskReport); - if (!_.isEmpty(assigneeReportAction)) { + if (Object.keys(assigneeReportAction).length > 0) { const optimisticDataForClonedParentReportAction = ReportUtils.getOptimisticDataForParentReportAction( taskReportID, completedTaskReportAction.created, @@ -282,7 +279,7 @@ function completeTask(taskReport, taskTitle) { assigneeReportAction.reportID, assigneeReportAction.reportActionID, ); - if (!_.isEmpty(optimisticDataForClonedParentReportAction)) { + if (Object.keys(optimisticDataForClonedParentReportAction).length > 0) { optimisticData.push(optimisticDataForClonedParentReportAction); } } @@ -299,8 +296,6 @@ function completeTask(taskReport, taskTitle) { /** * Reopen a closed task - * @param {Object} taskReport task report - * @param {String} taskTitle Title of the task */ function reopenTask(taskReport: Report, taskTitle: string) { const taskReportID = taskReport.reportID; @@ -361,7 +356,7 @@ function reopenTask(taskReport: Report, taskTitle: string) { // Multiple report actions can link to the same child. Both share destination (task parent) and assignee report link to the same report action. // We need to find and update the other parent report action (in assignee report). More info https://github.com/Expensify/App/issues/23920#issuecomment-1663092717 const assigneeReportAction = ReportUtils.getTaskParentReportActionIDInAssigneeReport(taskReport); - if (!_.isEmpty(assigneeReportAction)) { + if (Object.keys(assigneeReportAction).length > 0 && taskReportID) { const optimisticDataForClonedParentReportAction = ReportUtils.getOptimisticDataForParentReportAction( taskReportID, reopenedTaskReportAction.created, @@ -369,7 +364,7 @@ function reopenTask(taskReport: Report, taskTitle: string) { assigneeReportAction.reportID, assigneeReportAction.reportActionID, ); - if (!_.isEmpty(optimisticDataForClonedParentReportAction)) { + if (Object.keys(optimisticDataForClonedParentReportAction).length > 0) { optimisticData.push(optimisticDataForClonedParentReportAction); } } @@ -384,12 +379,6 @@ function reopenTask(taskReport: Report, taskTitle: string) { ); } -/** - * @param {object} report - * @param {Number} ownerAccountID - * @param {Object} editedTask - * @param {Object} assigneeChatReport - The chat report between you and the assignee - */ function editTaskAndNavigate(report: Report, ownerAccountID: number, {title, description, assignee = '', assigneeAccountID = 0}: Task, assigneeChatReport: Report | null = null) { // Create the EditedReportAction on the task const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail); @@ -458,7 +447,7 @@ function editTaskAndNavigate(report: Report, ownerAccountID: number, {title, des // If we make a change to the assignee, we want to add a comment to the assignee's chat // Check if the assignee actually changed - if (assigneeAccountID && assigneeAccountID !== report.managerID && assigneeAccountID !== ownerAccountID && assigneeChatReport) { + if (assigneeAccountID && assigneeAccountID !== report.managerID && assigneeAccountID !== ownerAccountID && assigneeChatReport && report.reportID) { assigneeChatReportOnyxData = ReportUtils.getTaskAssigneeChatOnyxData( currentUserAccountID, assignee, @@ -480,12 +469,12 @@ function editTaskAndNavigate(report: Report, ownerAccountID: number, {title, des taskReportID: report.reportID, title: reportName, description: reportDescription, - assignee: assignee || report.managerEmail, - assigneeAccountID: assigneeAccountID || report.managerID, + assignee: assignee ?? report.managerEmail, + assigneeAccountID: assigneeAccountID ?? report.managerID, editedTaskReportActionID: editTaskReportAction.reportActionID, assigneeChatReportID, - assigneeChatReportActionID: assigneeChatReportOnyxData.optimisticAssigneeAddComment.reportAction.reportActionID ?? 0, - assigneeChatCreatedReportActionID: assigneeChatReportOnyxData.optimisticChatCreatedReportAction.reportActionID ?? 0, + assigneeChatReportActionID: assigneeChatReportOnyxData?.optimisticAssigneeAddComment.reportAction.reportActionID ?? 0, + assigneeChatCreatedReportActionID: assigneeChatReportOnyxData?.optimisticChatCreatedReportAction.reportActionID ?? 0, }, {optimisticData, successData, failureData}, ); @@ -512,8 +501,8 @@ function editTaskAssigneeAndNavigate(report: Report, ownerAccountID: number, ass key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, value: { reportName, - managerID: assigneeAccountID || report.managerID, - managerEmail: assigneeEmail || report.managerEmail, + managerID: assigneeAccountID ?? report.managerID, + managerEmail: assigneeEmail ?? report.managerEmail, }, }, ]; @@ -533,7 +522,7 @@ function editTaskAssigneeAndNavigate(report: Report, ownerAccountID: number, ass // If we make a change to the assignee, we want to add a comment to the assignee's chat // Check if the assignee actually changed - if (assigneeAccountID && assigneeAccountID !== report.managerID && assigneeAccountID !== ownerAccountID && assigneeChatReport) { + if (assigneeAccountID && assigneeAccountID !== report.managerID && assigneeAccountID !== ownerAccountID && assigneeChatReport && report.reportID) { assigneeChatReportOnyxData = ReportUtils.getTaskAssigneeChatOnyxData( currentUserAccountID, assigneeEmail, @@ -553,16 +542,12 @@ function editTaskAssigneeAndNavigate(report: Report, ownerAccountID: number, ass 'EditTaskAssignee', { taskReportID: report.reportID, - assignee: assigneeEmail || report.managerEmail, - assigneeAccountID: assigneeAccountID || report.managerID, + assignee: assigneeEmail ?? report.managerEmail, + assigneeAccountID: assigneeAccountID ?? report.managerID, editedTaskReportActionID: editTaskReportAction.reportActionID, assigneeChatReportID, - assigneeChatReportActionID: - assigneeChatReportOnyxData && assigneeChatReportOnyxData.optimisticAssigneeAddComment - ? assigneeChatReportOnyxData.optimisticAssigneeAddComment.reportAction.reportActionID - : 0, - assigneeChatCreatedReportActionID: - assigneeChatReportOnyxData && assigneeChatReportOnyxData.optimisticChatCreatedReportAction ? assigneeChatReportOnyxData.optimisticChatCreatedReportAction.reportActionID : 0, + assigneeChatReportActionID: assigneeChatReportOnyxData?.optimisticAssigneeAddComment.reportAction.reportActionID ?? 0, + assigneeChatCreatedReportActionID: assigneeChatReportOnyxData?.optimisticChatCreatedReportAction.reportActionID ?? 0, }, {optimisticData, successData, failureData}, ); @@ -575,49 +560,43 @@ function editTaskAssigneeAndNavigate(report: Report, ownerAccountID: number, ass * * @param {Object} report */ -function setTaskReport(report) { +function setTaskReport(report: Report) { Onyx.merge(ONYXKEYS.TASK, {report}); } /** * Sets the title and description values for the task - * @param {string} title - * @param {string} description */ -function setDetailsValue(title, description) { +function setDetailsValue(title: string, description: string) { // This is only needed for creation of a new task and so it should only be stored locally Onyx.merge(ONYXKEYS.TASK, {title: title.trim(), description: description.trim()}); } /** * Sets the title value for the task - * @param {string} title */ -function setTitleValue(title) { +function setTitleValue(title: string) { Onyx.merge(ONYXKEYS.TASK, {title: title.trim()}); } /** * Sets the description value for the task - * @param {string} description */ -function setDescriptionValue(description) { +function setDescriptionValue(description: string) { Onyx.merge(ONYXKEYS.TASK, {description: description.trim()}); } /** * Sets the shareDestination value for the task - * @param {string} shareDestination */ -function setShareDestinationValue(shareDestination) { +function setShareDestinationValue(shareDestination: string) { // This is only needed for creation of a new task and so it should only be stored locally Onyx.merge(ONYXKEYS.TASK, {shareDestination}); } /* Sets the assigneeChatReport details for the task - * @param {Object} chatReport */ -function setAssigneeChatReport(chatReport) { +function setAssigneeChatReport(chatReport: Report) { Onyx.merge(ONYXKEYS.TASK, {assigneeChatReport: chatReport}); } @@ -625,14 +604,9 @@ function setAssigneeChatReport(chatReport) { * Sets the assignee value for the task and checks for an existing chat with the assignee * If there is no existing chat, it creates an optimistic chat report * It also sets the shareDestination as that chat report if a share destination isn't already set - * @param {string} assigneeEmail - * @param {Number} assigneeAccountID - * @param {string} shareDestination - * @param {boolean} isCurrentUser */ - -function setAssigneeValue(assigneeEmail, assigneeAccountID, shareDestination, isCurrentUser = false) { - let chatReport; +function setAssigneeValue(assigneeEmail: string, assigneeAccountID: number, shareDestination: string, isCurrentUser = false) { + let chatReport: Report | undefined; if (!isCurrentUser) { chatReport = ReportUtils.getChatByParticipants([assigneeAccountID]); @@ -644,14 +618,16 @@ function setAssigneeValue(assigneeEmail, assigneeAccountID, shareDestination, is // However, the DM doesn't exist yet - and will be created optimistically once the task is created // We don't want to show the new DM yet, because if you select an assignee and then change the assignee, the previous DM will still be shown // So here, we create it optimistically to share it with the assignee, but we have to hide it until the task is created - chatReport.isHidden = true; + if (chatReport) { + chatReport.isHidden = true; + } Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport); // If this is an optimistic report, we likely don't have their personal details yet so we set it here optimistically as well const optimisticPersonalDetailsListAction = { accountID: assigneeAccountID, - avatar: lodashGet(allPersonalDetails, [assigneeAccountID, 'avatar'], UserUtils.getDefaultAvatarURL(assigneeAccountID)), - displayName: lodashGet(allPersonalDetails, [assigneeAccountID, 'displayName'], assigneeEmail), + avatar: allPersonalDetails?.[assigneeAccountID]?.avatar ?? UserUtils.getDefaultAvatarURL(assigneeAccountID), + displayName: allPersonalDetails?.[assigneeAccountID]?.displayName ?? assigneeEmail, login: assigneeEmail, }; Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {[assigneeAccountID]: optimisticPersonalDetailsListAction}); @@ -662,7 +638,7 @@ function setAssigneeValue(assigneeEmail, assigneeAccountID, shareDestination, is // 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 (!shareDestination) { - setShareDestinationValue(chatReport.reportID); + setShareDestinationValue(chatReport?.reportID ?? ''); } } @@ -677,31 +653,25 @@ function setAssigneeValue(assigneeEmail, assigneeAccountID, shareDestination, is /** * Sets the parentReportID value for the task - * @param {string} parentReportID */ -function setParentReportID(parentReportID) { +function setParentReportID(parentReportID: string) { // This is only needed for creation of a new task and so it should only be stored locally Onyx.merge(ONYXKEYS.TASK, {parentReportID}); } /** * Clears out the task info from the store and navigates to the NewTaskDetails page - * @param {string} reportID */ -function clearOutTaskInfoAndNavigate(reportID) { +function clearOutTaskInfoAndNavigate(reportID: string) { clearOutTaskInfo(); setParentReportID(reportID); - Navigation.navigate(ROUTES.NEW_TASK_DETAILS); + Navigation.navigate(ROUTES.NEW_TASK_DETAILS, ''); } /** * Get the assignee data - * - * @param {Number} assigneeAccountID - * @param {Object} personalDetails - * @returns {Object} */ -function getAssignee(assigneeAccountID, personalDetails) { +function getAssignee(assigneeAccountID: number, personalDetails: Record) { const details = personalDetails[assigneeAccountID]; if (!details) { return { @@ -719,18 +689,15 @@ function getAssignee(assigneeAccountID, personalDetails) { /** * Get the share destination data - * @param {Object} reportID - * @param {Object} reports - * @param {Object} personalDetails - * @returns {Object} * */ -function getShareDestination(reportID, reports, personalDetails) { - const report = lodashGet(reports, `report_${reportID}`, {}); +function getShareDestination(reportID: string, reports: Record, personalDetails: Record) { + const report = reports[`report_${reportID}`] ?? {}; let subtitle = ''; if (ReportUtils.isChatReport(report) && ReportUtils.isDM(report) && ReportUtils.hasSingleParticipant(report)) { - const participantAccountID = lodashGet(report, 'participantAccountIDs[0]'); - const displayName = lodashGet(personalDetails, [participantAccountID, 'displayName']); - const login = lodashGet(personalDetails, [participantAccountID, 'login']); + const participantAccountID = report.participantAccountIDs?.[0]; + + const displayName = personalDetails[participantAccountID ?? 0]?.displayName ?? ''; + const login = personalDetails[participantAccountID ?? 0]?.login ?? ''; subtitle = LocalePhoneNumber.formatPhoneNumber(login || displayName); } else { subtitle = ReportUtils.getChatRoomSubtitle(report); @@ -744,12 +711,8 @@ function getShareDestination(reportID, reports, personalDetails) { /** * Cancels a task by setting the report state to SUBMITTED and status to CLOSED - * @param {string} taskReportID - * @param {string} taskTitle - * @param {number} originalStateNum - * @param {number} originalStatusNum */ -function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum) { +function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: number, originalStatusNum: number) { const message = `deleted task: ${taskTitle}`; const optimisticCancelReportAction = ReportUtils.buildOptimisticTaskReportAction(taskReportID, CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED, message); const optimisticReportActionID = optimisticCancelReportAction.reportActionID; @@ -853,11 +816,8 @@ function dismissModalAndClearOutTaskInfo() { /** * Returns Task assignee accountID - * - * @param {Object} taskReport - * @returns {Number|null} */ -function getTaskAssigneeAccountID(taskReport) { +function getTaskAssigneeAccountID(taskReport: Report): number | null { if (!taskReport) { return null; } @@ -867,26 +827,20 @@ function getTaskAssigneeAccountID(taskReport) { } const reportAction = ReportActionsUtils.getParentReportAction(taskReport); - return lodashGet(reportAction, 'childManagerAccountID'); + return reportAction.childManagerAccountID; } /** * Returns Task owner accountID - * - * @param {Object} taskReport - * @returns {Number|null} */ -function getTaskOwnerAccountID(taskReport) { - return lodashGet(taskReport, 'ownerAccountID', null); +function getTaskOwnerAccountID(taskReport: Report): number | null { + return taskReport.ownerAccountID ?? null; } /** * Check if you're allowed to modify the task - anyone that has write access to the report can modify the task - * @param {Object} taskReport - * @param {Number} sessionAccountID - * @returns {Boolean} */ -function canModifyTask(taskReport, sessionAccountID) { +function canModifyTask(taskReport: Report, sessionAccountID: number): boolean { if (sessionAccountID === getTaskOwnerAccountID(taskReport) || sessionAccountID === getTaskAssigneeAccountID(taskReport)) { return true; } @@ -898,23 +852,14 @@ function canModifyTask(taskReport, sessionAccountID) { return ReportUtils.isAllowedToComment(parentReport); } -/** - * @param {String} reportID - */ -function clearEditTaskErrors(reportID) { +function clearEditTaskErrors(reportID: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, { pendingFields: null, errorFields: null, }); } -/** - * @param {string} actionName - * @param {string} reportID - * @param {boolean} isCreateTaskAction - * @returns {string} - */ -function getTaskReportActionMessage(actionName, reportID, isCreateTaskAction) { +function getTaskReportActionMessage(actionName: string, reportID: string, isCreateTaskAction: boolean): string { const report = ReportUtils.getReport(reportID); if (isCreateTaskAction) { return `Created a task: ${report.reportName}`; diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index 2e944c156a64..ccb33f60531e 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -85,6 +85,7 @@ type Report = { currency?: string; description?: string; managerEmail?: string; + isHidden?: boolean; }; export default Report; From a28efcac58ad7dfd35c24585b3df85187529e786 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Fri, 1 Dec 2023 16:29:28 +0100 Subject: [PATCH 03/42] fix: types in Task lib --- src/libs/ReportActionsUtils.ts | 2 +- src/libs/ReportUtils.ts | 8 +- src/libs/actions/Task.ts | 305 +++++++++++++++++++-------------- src/types/onyx/Task.ts | 3 + 4 files changed, 185 insertions(+), 133 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index bd475a57954e..0138982c6256 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -122,7 +122,7 @@ function isThreadParentMessage(reportAction: OnyxEntry, reportID: * * @deprecated Use Onyx.connect() or withOnyx() instead */ -function getParentReportAction(report: OnyxEntry, allReportActionsParam?: OnyxCollection): ReportAction | Record { +function getParentReportAction(report: OnyxEntry | EmptyObject, allReportActionsParam?: OnyxCollection): ReportAction | Record { if (!report?.parentReportID || !report.parentReportActionID) { return {}; } diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 599963b6a9aa..6b3fcf8a3314 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -187,7 +187,7 @@ type OptimisticClosedReportAction = Pick< type OptimisticCreatedReportAction = Pick< ReportAction, - 'actionName' | 'actorAccountID' | 'automatic' | 'avatar' | 'created' | 'message' | 'person' | 'reportActionID' | 'shouldShow' | 'pendingAction' + 'actionName' | 'actorAccountID' | 'automatic' | 'avatar' | 'created' | 'message' | 'person' | 'reportActionID' | 'shouldShow' | 'pendingAction' | 'originalMessage' >; type OptimisticChatReport = Pick< @@ -270,6 +270,7 @@ type OptimisticTaskReport = Pick< | 'stateNum' | 'statusNum' | 'notificationPreference' + | 'parentReportActionID' >; type TransactionDetails = @@ -841,7 +842,7 @@ function isArchivedRoom(report: OnyxEntry | EmptyObject): boolean { /** * Checks if the current user is allowed to comment on the given report. */ -function isAllowedToComment(report: Report): boolean { +function isAllowedToComment(report: OnyxEntry | EmptyObject): boolean { // Default to allowing all users to post const capability = report?.writeCapability ?? CONST.REPORT.WRITE_CAPABILITIES.ALL; @@ -2150,7 +2151,7 @@ function getModifiedExpenseOriginalMessage(oldTransaction: OnyxEntry): OnyxEntry | EmptyObject { +function getParentReport(report: OnyxEntry | EmptyObject): OnyxEntry | EmptyObject { if (!report?.parentReportID) { return {}; } @@ -3078,6 +3079,7 @@ function buildOptimisticCreatedReportAction(emailCreatingAction: string, created actionName: CONST.REPORT.ACTIONS.TYPE.CREATED, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, actorAccountID: currentUserAccountID, + originalMessage: undefined, message: [ { type: CONST.REPORT.MESSAGE.TYPE.TEXT, diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 03f4b30d56f6..50f6434e4666 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -1,4 +1,4 @@ -import Onyx from 'react-native-onyx'; +import Onyx, {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import * as Expensicons from '@components/Icon/Expensicons'; import * as API from '@libs/API'; import DateUtils from '@libs/DateUtils'; @@ -13,10 +13,16 @@ import * as UserUtils from '@libs/UserUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import {PersonalDetails, Report, Task} from '@src/types/onyx'; +import * as OnyxTypes from '@src/types/onyx'; +import {Icon} from '@src/types/onyx/OnyxCommon'; +import * as Report from './Report'; + +type OptimisticReport = Pick; +type Assignee = {icons: Icon[]; displayName: string; subtitle: string}; + +let currentUserEmail: string | undefined; +let currentUserAccountID: number | undefined; -let currentUserEmail: string; -let currentUserAccountID: number; Onyx.connect({ key: ONYXKEYS.SESSION, callback: (value) => { @@ -25,7 +31,7 @@ Onyx.connect({ }, }); -let allPersonalDetails: Record | null; +let allPersonalDetails: Record | null; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, callback: (value) => (allPersonalDetails = value), @@ -59,22 +65,22 @@ function createTaskAndNavigate( description: string, assigneeEmail: string, assigneeAccountID = 0, - assigneeChatReport: Report | null = null, + assigneeChatReport: OnyxTypes.Report | null = null, policyID = CONST.POLICY.OWNER_EMAIL_FAKE, ) { - const optimisticTaskReport = ReportUtils.buildOptimisticTaskReport(currentUserAccountID, assigneeAccountID, parentReportID, title, description, policyID); + const optimisticTaskReport = ReportUtils.buildOptimisticTaskReport(currentUserAccountID ?? 0, assigneeAccountID, parentReportID, title, description, policyID); - const assigneeChatReportID = assigneeChatReport ? assigneeChatReport.reportID : 0; + const assigneeChatReportID = assigneeChatReport ? assigneeChatReport.reportID : ''; const taskReportID = optimisticTaskReport.reportID; let assigneeChatReportOnyxData; // Parent ReportAction indicating that a task has been created - const optimisticTaskCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(currentUserEmail); + const optimisticTaskCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(currentUserEmail ?? ''); const optimisticAddCommentReport = ReportUtils.buildOptimisticTaskCommentReportAction(taskReportID, title, assigneeAccountID, `task for ${title}`, parentReportID); optimisticTaskReport.parentReportActionID = optimisticAddCommentReport.reportAction.reportActionID; const currentTime = DateUtils.getDBTime(); - const lastCommentText = ReportUtils.formatReportLastMessageText(optimisticAddCommentReport.reportAction.message[0].text); + const lastCommentText = ReportUtils.formatReportLastMessageText(optimisticAddCommentReport?.reportAction?.message?.[0].text ?? ''); const optimisticParentReport = { lastVisibleActionCreated: currentTime, lastMessageText: lastCommentText, @@ -86,7 +92,7 @@ function createTaskAndNavigate( // We're only setting onyx data for the task report here because it's possible for the parent report to not exist yet (if you're assigning a task to someone you haven't chatted with before) // So we don't want to set the parent report data until we've successfully created that chat report // FOR TASK REPORT - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.SET, key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticTaskReport.reportID}`, @@ -104,12 +110,12 @@ function createTaskAndNavigate( { onyxMethod: Onyx.METHOD.SET, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTaskReport.reportID}`, - value: {[optimisticTaskCreatedAction.reportActionID]: optimisticTaskCreatedAction}, + value: {[optimisticTaskCreatedAction.reportActionID ?? '']: optimisticTaskCreatedAction}, }, ]; // FOR TASK REPORT - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticTaskReport.reportID}`, @@ -131,7 +137,7 @@ function createTaskAndNavigate( ]; // FOR TASK REPORT - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticTaskReport.reportID}`, @@ -150,7 +156,7 @@ function createTaskAndNavigate( if (assigneeChatReport) { assigneeChatReportOnyxData = ReportUtils.getTaskAssigneeChatOnyxData( - currentUserAccountID, + currentUserAccountID ?? 0, assigneeAccountID, taskReportID, assigneeChatReportID, @@ -158,6 +164,7 @@ function createTaskAndNavigate( title, assigneeChatReport, ); + optimisticData.push(...assigneeChatReportOnyxData.optimisticData); successData.push(...assigneeChatReportOnyxData.successData); failureData.push(...assigneeChatReportOnyxData.failureData); @@ -174,7 +181,7 @@ function createTaskAndNavigate( { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`, - value: {[optimisticAddCommentReport.reportAction.reportActionID]: optimisticAddCommentReport.reportAction}, + value: {[optimisticAddCommentReport.reportAction.reportActionID ?? '']: optimisticAddCommentReport.reportAction}, }, ); @@ -182,7 +189,7 @@ function createTaskAndNavigate( successData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`, - value: {[optimisticAddCommentReport.reportAction.reportActionID]: {pendingAction: null}}, + value: {[optimisticAddCommentReport.reportAction.reportActionID ?? '']: {pendingAction: null}}, }); // FOR PARENT REPORT (SHARE DESTINATION) @@ -190,7 +197,7 @@ function createTaskAndNavigate( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`, value: { - [optimisticAddCommentReport.reportAction.reportActionID]: { + [optimisticAddCommentReport.reportAction.reportActionID ?? '']: { errors: ErrorUtils.getMicroSecondOnyxError('task.genericCreateTaskFailureMessage'), }, }, @@ -198,23 +205,34 @@ function createTaskAndNavigate( clearOutTaskInfo(); - API.write( - 'CreateTask', - { - parentReportActionID: optimisticAddCommentReport.reportAction.reportActionID, - parentReportID, - taskReportID: optimisticTaskReport.reportID, - createdTaskReportActionID: optimisticTaskCreatedAction.reportActionID, - title: optimisticTaskReport.reportName, - description: optimisticTaskReport.description, - assignee: assigneeEmail, - assigneeAccountID, - assigneeChatReportID, - assigneeChatReportActionID: assigneeChatReportOnyxData?.optimisticAssigneeAddComment.reportAction.reportActionID ?? 0, - assigneeChatCreatedReportActionID: assigneeChatReportOnyxData?.optimisticChatCreatedReportAction.reportActionID ?? 0, - }, - {optimisticData, successData, failureData}, - ); + type CreateTaskParameters = { + parentReportActionID?: string; + parentReportID?: string; + taskReportID?: string; + createdTaskReportActionID?: string; + title?: string; + description?: string; + assignee?: string; + assigneeAccountID?: number; + assigneeChatReportID?: string; + assigneeChatReportActionID?: string; + assigneeChatCreatedReportActionID?: string; + }; + const parameters: CreateTaskParameters = { + parentReportActionID: optimisticAddCommentReport.reportAction.reportActionID, + parentReportID, + taskReportID: optimisticTaskReport.reportID, + createdTaskReportActionID: optimisticTaskCreatedAction.reportActionID, + title: optimisticTaskReport.reportName, + description: optimisticTaskReport.description, + assignee: assigneeEmail, + assigneeAccountID, + assigneeChatReportID, + assigneeChatReportActionID: assigneeChatReportOnyxData?.optimisticAssigneeAddComment?.reportAction.reportActionID ?? '', + assigneeChatCreatedReportActionID: assigneeChatReportOnyxData?.optimisticChatCreatedReportAction?.reportActionID ?? '', + }; + + API.write('CreateTask', parameters, {optimisticData, successData, failureData}); Navigation.dismissModal(parentReportID); } @@ -222,12 +240,12 @@ function createTaskAndNavigate( /** * Complete a task */ -function completeTask(taskReport: Report) { +function completeTask(taskReport: OnyxTypes.Report) { const taskReportID = taskReport.reportID; const message = `marked as complete`; const completedTaskReportAction = ReportUtils.buildOptimisticTaskReportAction(taskReportID, CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED, message); - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, @@ -244,7 +262,7 @@ function completeTask(taskReport: Report) { }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReportID}`, @@ -256,7 +274,7 @@ function completeTask(taskReport: Report) { }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, @@ -276,25 +294,28 @@ function completeTask(taskReport: Report) { }, ]; - API.write( - 'CompleteTask', - { - taskReportID, - completedTaskReportActionID: completedTaskReportAction.reportActionID, - }, - {optimisticData, successData, failureData}, - ); + type CompleteTaskParameters = { + taskReportID?: string; + completedTaskReportActionID?: string; + }; + + const parameters: CompleteTaskParameters = { + taskReportID, + completedTaskReportActionID: completedTaskReportAction.reportActionID, + }; + + API.write('CompleteTask', parameters, {optimisticData, successData, failureData}); } /** * Reopen a closed task */ -function reopenTask(taskReport: Report) { +function reopenTask(taskReport: OnyxTypes.Report) { const taskReportID = taskReport.reportID; const message = `marked as incomplete`; const reopenedTaskReportAction = ReportUtils.buildOptimisticTaskReportAction(taskReportID, CONST.REPORT.ACTIONS.TYPE.TASKREOPENED, message); - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, @@ -314,7 +335,7 @@ function reopenTask(taskReport: Report) { }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReportID}`, @@ -325,7 +346,7 @@ function reopenTask(taskReport: Report) { }, }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, @@ -345,21 +366,20 @@ function reopenTask(taskReport: Report) { }, ]; - API.write( - 'ReopenTask', - { - taskReportID, - reopenedTaskReportActionID: reopenedTaskReportAction.reportActionID, - }, - {optimisticData, successData, failureData}, - ); + type ReopenTaskParameters = { + taskReportID?: string; + reopenedTaskReportActionID?: string; + }; + + const parameters: ReopenTaskParameters = { + taskReportID, + reopenedTaskReportActionID: reopenedTaskReportAction.reportActionID, + }; + + API.write('ReopenTask', parameters, {optimisticData, successData, failureData}); } -/** - * @param {object} report - * @param {Object} editedTask - */ -function editTask(report: Report, {title, description}: Task) { +function editTask(report: OnyxTypes.Report, {title, description}: OnyxTypes.Task) { // Create the EditedReportAction on the task const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail); @@ -369,7 +389,7 @@ function editTask(report: Report, {title, description}: Task) { // Description can be unset, so we default to an empty string if so const reportDescription = (description ?? report.description ?? '').trim(); - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, @@ -388,7 +408,8 @@ function editTask(report: Report, {title, description}: Task) { }, }, ]; - const successData = [ + + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, @@ -400,7 +421,8 @@ function editTask(report: Report, {title, description}: Task) { }, }, ]; - const failureData = [ + + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, @@ -416,37 +438,42 @@ function editTask(report: Report, {title, description}: Task) { }, ]; - API.write( - 'EditTask', - { - taskReportID: report.reportID, - title: reportName, - description: reportDescription, - editedTaskReportActionID: editTaskReportAction.reportActionID, - }, - {optimisticData, successData, failureData}, - ); + type EditTaskParameters = { + taskReportID?: string; + title?: string; + description?: string; + editedTaskReportActionID?: string; + }; + + const parameters: EditTaskParameters = { + taskReportID: report.reportID, + title: reportName, + description: reportDescription, + editedTaskReportActionID: editTaskReportAction.reportActionID, + }; + + API.write('EditTask', parameters, {optimisticData, successData, failureData}); } -function editTaskAssignee(report: Report, ownerAccountID: number, assigneeEmail: string, assigneeAccountID = 0, assigneeChatReport: Report | null = null) { +function editTaskAssignee(report: OnyxTypes.Report, ownerAccountID: number, assigneeEmail: string, assigneeAccountID = 0, assigneeChatReport: OnyxTypes.Report | null = null) { // Create the EditedReportAction on the task - const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail); + const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail ?? string); const reportName = report.reportName?.trim(); let assigneeChatReportOnyxData; - const assigneeChatReportID = assigneeChatReport ? assigneeChatReport.reportID : 0; - const optimisticReport = { + const assigneeChatReportID = assigneeChatReport ? assigneeChatReport.reportID : ''; + const optimisticReport: OptimisticReport = { reportName, managerID: assigneeAccountID || report.managerID, pendingFields: { ...(assigneeAccountID && {managerID: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), }, - notificationPreference: [assigneeAccountID, ownerAccountID].includes(currentUserAccountID) + notificationPreference: [assigneeAccountID, ownerAccountID].includes(currentUserAccountID ?? 0) ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, }; - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, @@ -458,14 +485,16 @@ function editTaskAssignee(report: Report, ownerAccountID: number, assigneeEmail: value: optimisticReport, }, ]; - const successData = [ + + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, value: {pendingFields: {...(assigneeAccountID && {managerID: null})}}, }, ]; - const failureData = [ + + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, @@ -481,45 +510,51 @@ function editTaskAssignee(report: Report, ownerAccountID: number, assigneeEmail: // If we make a change to the assignee, we want to add a comment to the assignee's chat // Check if the assignee actually changed if (assigneeAccountID && assigneeAccountID !== report.managerID && assigneeAccountID !== ownerAccountID && assigneeChatReport) { - const participants = lodashGet(report, 'participantAccountIDs', []); + const participants = report?.participantAccountIDs ?? []; if (!participants.includes(assigneeAccountID)) { optimisticReport.participantAccountIDs = [...participants, assigneeAccountID]; } assigneeChatReportOnyxData = ReportUtils.getTaskAssigneeChatOnyxData( - currentUserAccountID, + currentUserAccountID ?? 0, assigneeAccountID, report.reportID, - assigneeChatReportID, - report.parentReportID, - reportName, + assigneeChatReportID ?? '', + report.parentReportID ?? '', + reportName ?? '', assigneeChatReport, ); + optimisticData.push(...assigneeChatReportOnyxData.optimisticData); successData.push(...assigneeChatReportOnyxData.successData); failureData.push(...assigneeChatReportOnyxData.failureData); } - API.write( - 'EditTaskAssignee', - { - taskReportID: report.reportID, - assignee: assigneeEmail, - editedTaskReportActionID: editTaskReportAction.reportActionID, - assigneeChatReportID, - assigneeChatReportActionID: assigneeChatReportOnyxData?.optimisticAssigneeAddComment.reportAction.reportActionID ?? 0, - assigneeChatCreatedReportActionID: assigneeChatReportOnyxData?.optimisticChatCreatedReportAction.reportActionID ?? 0, - }, - {optimisticData, successData, failureData}, - ); + type EditTaskAssigneeParameters = { + taskReportID?: string; + assignee?: string; + editedTaskReportActionID?: string; + assigneeChatReportID?: string; + assigneeChatReportActionID?: string; + assigneeChatCreatedReportActionID?: string; + }; + + const parameters: EditTaskAssigneeParameters = { + taskReportID: report.reportID, + assignee: assigneeEmail, + editedTaskReportActionID: editTaskReportAction.reportActionID, + assigneeChatReportID, + assigneeChatReportActionID: assigneeChatReportOnyxData?.optimisticAssigneeAddComment?.reportAction.reportActionID ?? '', + assigneeChatCreatedReportActionID: assigneeChatReportOnyxData?.optimisticChatCreatedReportAction?.reportActionID ?? '', + }; + + API.write('EditTaskAssignee', parameters, {optimisticData, successData, failureData}); } /** * Sets the report info for the task being viewed - * - * @param {Object} report */ -function setTaskReport(report: Report) { +function setTaskReport(report: OnyxTypes.Report) { Onyx.merge(ONYXKEYS.TASK, {report}); } @@ -555,7 +590,7 @@ function setShareDestinationValue(shareDestination: string) { /* Sets the assigneeChatReport details for the task */ -function setAssigneeChatReport(chatReport: Report) { +function setAssigneeChatReport(chatReport: OnyxTypes.Report) { Onyx.merge(ONYXKEYS.TASK, {assigneeChatReport: chatReport}); } @@ -564,8 +599,8 @@ function setAssigneeChatReport(chatReport: Report) { * If there is no existing chat, it creates an optimistic chat report * It also sets the shareDestination as that chat report if a share destination isn't already set */ -function setAssigneeValue(assigneeEmail: string, assigneeAccountID: number, shareDestination: string, isCurrentUser = false) { - let chatReport: Report | undefined; +function setAssigneeValue(assigneeEmail: string, assigneeAccountID: number, shareDestination: string, isCurrentUser = false): OnyxEntry | undefined { + let chatReport: OnyxEntry | undefined; if (!isCurrentUser) { chatReport = ReportUtils.getChatByParticipants([assigneeAccountID]); @@ -632,8 +667,9 @@ function clearOutTaskInfoAndNavigate(reportID: string) { /** * Get the assignee data */ -function getAssignee(assigneeAccountID: number, personalDetails: Record) { +function getAssignee(assigneeAccountID: number, personalDetails: Record): Assignee { const details = personalDetails[assigneeAccountID]; + if (!details) { return { icons: [], @@ -641,20 +677,21 @@ function getAssignee(assigneeAccountID: number, personalDetails: Record, personalDetails: Record) { +function getShareDestination(reportID: string, reports: Record, personalDetails: Record) { const report = reports[`report_${reportID}`] ?? {}; - const participantAccountIDs = lodashGet(report, 'participantAccountIDs'); + const participantAccountIDs = report.participantAccountIDs ?? []; const isMultipleParticipant = participantAccountIDs?.length > 1; const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails), isMultipleParticipant); @@ -707,7 +744,7 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n }, }; - const optimisticData = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, @@ -721,10 +758,10 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${parentReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${parentReport?.reportID}`, value: { - lastMessageText: ReportActionsUtils.getLastVisibleMessage(parentReport.reportID, optimisticReportActions).lastMessageText, - lastVisibleActionCreated: lodashGet(ReportActionsUtils.getLastVisibleAction(parentReport.reportID, optimisticReportActions), 'created'), + lastMessageText: ReportActionsUtils.getLastVisibleMessage(parentReport?.reportID, optimisticReportActions).lastMessageText, + lastVisibleActionCreated: ReportActionsUtils.getLastVisibleAction(parentReport?.reportID, optimisticReportActions) ?? 'created', }, }, { @@ -736,12 +773,12 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport?.reportID}`, value: optimisticReportActions, }, ]; - const successData = [ + const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReportID}`, @@ -753,7 +790,7 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport?.reportID}`, value: { [parentReportAction.reportActionID]: { pendingAction: null, @@ -762,7 +799,7 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n }, ]; - const failureData = [ + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, @@ -780,7 +817,7 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport?.reportID}`, value: { [parentReportAction.reportActionID]: { pendingAction: null, @@ -789,7 +826,17 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n }, ]; - API.write('CancelTask', {cancelledTaskReportActionID: optimisticReportActionID, taskReportID}, {optimisticData, successData, failureData}); + type CancelTaskParameters = { + cancelledTaskReportActionID?: string; + taskReportID?: string; + }; + + const parameters: CancelTaskParameters = { + cancelledTaskReportActionID: optimisticReportActionID, + taskReportID, + }; + + API.write('CancelTask', parameters, {optimisticData, successData, failureData}); } /** @@ -803,7 +850,7 @@ function dismissModalAndClearOutTaskInfo() { /** * Returns Task assignee accountID */ -function getTaskAssigneeAccountID(taskReport: Report): number | null { +function getTaskAssigneeAccountID(taskReport: OnyxTypes.Report): number | null | undefined { if (!taskReport) { return null; } @@ -819,14 +866,14 @@ function getTaskAssigneeAccountID(taskReport: Report): number | null { /** * Returns Task owner accountID */ -function getTaskOwnerAccountID(taskReport: Report): number | null { +function getTaskOwnerAccountID(taskReport: OnyxTypes.Report): number | null { return taskReport.ownerAccountID ?? null; } /** * Check if you're allowed to modify the task - anyone that has write access to the report can modify the task */ -function canModifyTask(taskReport: Report, sessionAccountID: number): boolean { +function canModifyTask(taskReport: OnyxTypes.Report, sessionAccountID: number): boolean { if (ReportUtils.isCanceledTaskReport(taskReport)) { return false; } @@ -846,9 +893,9 @@ function clearTaskErrors(reportID: string) { const report = ReportUtils.getReport(reportID); // Delete the task preview in the parent report - if (lodashGet(report, 'pendingFields.createChat') === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { + if (report?.pendingFields?.createChat === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, { - [report.parentReportActionID]: null, + [report.parentReportActionID ?? 0]: null, }); Report.navigateToConciergeChatAndDeleteReport(reportID); @@ -864,7 +911,7 @@ function clearTaskErrors(reportID: string) { function getTaskReportActionMessage(actionName: string, reportID: string, isCreateTaskAction: boolean): string { const report = ReportUtils.getReport(reportID); if (isCreateTaskAction) { - return `task for ${report.reportName}`; + return `task for ${report?.reportName}`; } let taskStatusText = ''; switch (actionName) { diff --git a/src/types/onyx/Task.ts b/src/types/onyx/Task.ts index 9d5c83ee4a40..8a399ee4652f 100644 --- a/src/types/onyx/Task.ts +++ b/src/types/onyx/Task.ts @@ -22,6 +22,9 @@ type Task = { /** Report id only when a task was created from a report */ parentReportID?: string; + + /** Chat report with assignee of task */ + assigneeChatReport?: Report; }; export default Task; From 8a1a642c709947430c2b427b4a34a3c4e47f849a Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 4 Dec 2023 14:37:55 +0100 Subject: [PATCH 04/42] fix: added assertions, fix types --- src/libs/actions/Task.ts | 58 ++++++++++++++++++---------------- src/types/onyx/Report.ts | 1 + src/types/onyx/ReportAction.ts | 46 +++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 28 deletions(-) diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 50f6434e4666..50348fc08573 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -110,7 +110,7 @@ function createTaskAndNavigate( { onyxMethod: Onyx.METHOD.SET, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTaskReport.reportID}`, - value: {[optimisticTaskCreatedAction.reportActionID ?? '']: optimisticTaskCreatedAction}, + value: {[optimisticTaskCreatedAction.reportActionID ?? '']: optimisticTaskCreatedAction as OnyxTypes.ReportAction}, }, ]; @@ -258,7 +258,7 @@ function completeTask(taskReport: OnyxTypes.Report) { { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReportID}`, - value: {[completedTaskReportAction.reportActionID]: completedTaskReportAction}, + value: {[completedTaskReportAction.reportActionID]: completedTaskReportAction as OnyxTypes.ReportAction}, }, ]; @@ -331,7 +331,7 @@ function reopenTask(taskReport: OnyxTypes.Report) { { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReportID}`, - value: {[reopenedTaskReportAction.reportActionID]: reopenedTaskReportAction}, + value: {[reopenedTaskReportAction.reportActionID]: reopenedTaskReportAction as OnyxTypes.ReportAction}, }, ]; @@ -381,7 +381,7 @@ function reopenTask(taskReport: OnyxTypes.Report) { function editTask(report: OnyxTypes.Report, {title, description}: OnyxTypes.Task) { // Create the EditedReportAction on the task - const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail); + const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail ?? ''); // Sometimes title or description is undefined, so we need to check for that, and we provide it to multiple functions const reportName = (title ?? report?.reportName).trim(); @@ -393,7 +393,7 @@ function editTask(report: OnyxTypes.Report, {title, description}: OnyxTypes.Task { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, - value: {[editTaskReportAction.reportActionID]: editTaskReportAction}, + value: {[editTaskReportAction.reportActionID]: editTaskReportAction as OnyxTypes.ReportAction}, }, { onyxMethod: Onyx.METHOD.MERGE, @@ -457,7 +457,7 @@ function editTask(report: OnyxTypes.Report, {title, description}: OnyxTypes.Task function editTaskAssignee(report: OnyxTypes.Report, ownerAccountID: number, assigneeEmail: string, assigneeAccountID = 0, assigneeChatReport: OnyxTypes.Report | null = null) { // Create the EditedReportAction on the task - const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail ?? string); + const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(currentUserEmail ?? ''); const reportName = report.reportName?.trim(); let assigneeChatReportOnyxData; @@ -477,7 +477,7 @@ function editTaskAssignee(report: OnyxTypes.Report, ownerAccountID: number, assi { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, - value: {[editTaskReportAction.reportActionID]: editTaskReportAction}, + value: {[editTaskReportAction.reportActionID]: editTaskReportAction as OnyxTypes.ReportAction}, }, { onyxMethod: Onyx.METHOD.MERGE, @@ -724,24 +724,24 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n const taskReport = ReportUtils.getReport(taskReportID); const parentReportAction = ReportActionsUtils.getParentReportAction(taskReport); const parentReport = ReportUtils.getParentReport(taskReport); - + const optimisticReportAction = { + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + previousMessage: parentReportAction.message, + message: [ + { + translationKey: '', + type: 'COMMENT', + html: '', + text: '', + isEdited: true, + isDeletedParentAction: true, + }, + ], + errors: undefined, + linkMetaData: [], + }; const optimisticReportActions = { - [parentReportAction.reportActionID]: { - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, - previousMessage: parentReportAction.message, - message: [ - { - translationKey: '', - type: 'COMMENT', - html: '', - text: '', - isEdited: true, - isDeletedParentAction: true, - }, - ], - errors: null, - linkMetaData: [], - }, + [parentReportAction.reportActionID]: optimisticReportAction, }; const optimisticData: OnyxUpdate[] = [ @@ -760,15 +760,17 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${parentReport?.reportID}`, value: { - lastMessageText: ReportActionsUtils.getLastVisibleMessage(parentReport?.reportID, optimisticReportActions).lastMessageText, - lastVisibleActionCreated: ReportActionsUtils.getLastVisibleAction(parentReport?.reportID, optimisticReportActions) ?? 'created', + lastMessageText: ReportActionsUtils.getLastVisibleMessage(parentReport?.reportID ?? '', optimisticReportActions as unknown as OnyxTypes.ReportActions).lastMessageText ?? '', + lastVisibleActionCreated: + ReportActionsUtils.getLastVisibleAction(parentReport?.reportID ?? '', optimisticReportActions as unknown as OnyxTypes.ReportActions)?.childLastVisibleActionCreated ?? + 'created', }, }, { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${taskReportID}`, value: { - [optimisticReportActionID]: optimisticCancelReportAction, + [optimisticReportActionID]: optimisticCancelReportAction as OnyxTypes.ReportAction, }, }, { @@ -806,7 +808,7 @@ function cancelTask(taskReportID: string, taskTitle: string, originalStateNum: n value: { stateNum: originalStateNum, statusNum: originalStatusNum, - }, + } as OnyxTypes.Report, }, { onyxMethod: Onyx.METHOD.MERGE, diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index 138b2dc79ba1..0498afe916bc 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -147,6 +147,7 @@ type Report = { participantsList?: Array>; text?: string; privateNotes?: Record; + updateReportInLHN?: boolean; }; export default Report; diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index 64e1eb0b7c88..7bf6090adaf0 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -5,6 +5,48 @@ import * as OnyxCommon from './OnyxCommon'; import OriginalMessage, {Decision, Reaction} from './OriginalMessage'; import {Receipt} from './Transaction'; +type Image = { + /** The height of the image. */ + height?: number; + + /** The width of the image. */ + width?: number; + + /** The URL of the image. */ + url?: string; +}; + +type Logo = { + /** The height of the logo. */ + height?: number; + + /** The width of the logo. */ + width?: number; + + /** The URL of the logo. */ + url?: string; +}; + +type LinkMetaData = { + /** The URL of the link. */ + url?: string; + + /** A description of the link. */ + description?: string; + + /** The title of the link. */ + title?: string; + + /** The publisher of the link. */ + publisher?: string; + + /** The image associated with the link. */ + image: Image; + + /** The provider logo associated with the link. */ + logo: Logo; +}; + type Message = { /** The type of the action item fragment. Used to render a corresponding component */ type: string; @@ -79,6 +121,9 @@ type ReportActionBase = { /** report action message */ message?: Message[]; + /** report action previous message */ + previousMessage?: Message[]; + /** Whether we have received a response back from the server */ isLoading?: boolean; @@ -138,6 +183,7 @@ type ReportActionBase = { isAttachment?: boolean; childRecentReceiptTransactionIDs?: Record; reportID?: string; + linkMetaData?: LinkMetaData[]; }; type ReportAction = ReportActionBase & OriginalMessage; From f34a723a5c345ca95d6cff4f3ed512dac73b94ed Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 14 Dec 2023 20:03:26 +0100 Subject: [PATCH 05/42] fix: linter --- src/types/onyx/ReportAction.ts | 42 ---------------------------------- 1 file changed, 42 deletions(-) diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index 5131e2290d95..8e56aaa67345 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -7,48 +7,6 @@ import OriginalMessage, {Decision, Reaction} from './OriginalMessage'; import {NotificationPreference} from './Report'; import {Receipt} from './Transaction'; -type Image = { - /** The height of the image. */ - height?: number; - - /** The width of the image. */ - width?: number; - - /** The URL of the image. */ - url?: string; -}; - -type Logo = { - /** The height of the logo. */ - height?: number; - - /** The width of the logo. */ - width?: number; - - /** The URL of the logo. */ - url?: string; -}; - -type LinkMetaData = { - /** The URL of the link. */ - url?: string; - - /** A description of the link. */ - description?: string; - - /** The title of the link. */ - title?: string; - - /** The publisher of the link. */ - publisher?: string; - - /** The image associated with the link. */ - image: Image; - - /** The provider logo associated with the link. */ - logo: Logo; -}; - type Message = { /** The type of the action item fragment. Used to render a corresponding component */ type: string; From 9526c1be2cf91f4d37904b07d61e1baca0d79379 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 18 Dec 2023 13:37:54 +0100 Subject: [PATCH 06/42] fix: app crash --- src/libs/actions/Task.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 9f2f01e04623..f4a01fa7cf3c 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -871,7 +871,7 @@ function getTaskAssigneeAccountID(taskReport: OnyxTypes.Report): number | null | * Returns Task owner accountID */ function getTaskOwnerAccountID(taskReport: OnyxTypes.Report): number | null { - return taskReport.ownerAccountID ?? null; + return taskReport?.ownerAccountID ?? null; } /** From 056c4ba11675ca257e9dc1e4b75dfc649d70d4dc Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 19 Dec 2023 14:51:56 +0100 Subject: [PATCH 07/42] fix: type --- src/libs/actions/Task.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 4dcabf6ef25c..dc3b6181c2f5 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -32,7 +32,7 @@ Onyx.connect({ }, }); -let allPersonalDetails: Record | null; +let allPersonalDetails: OnyxEntry; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, callback: (value) => (allPersonalDetails = value), From 69054e2a19b0f102fa4552b72659b594262a5a09 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 19 Dec 2023 15:02:11 +0100 Subject: [PATCH 08/42] fix: added few return types --- src/libs/ReportUtils.ts | 2 +- src/libs/actions/Task.ts | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7480d8163204..29cdc95707af 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4494,4 +4494,4 @@ export { shouldAutoFocusOnKeyPress, }; -export type {OptionData, OptimisticChatReport}; +export type {OptionData, OptimisticChatReport, DisplayNameWithTooltips}; diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index dc3b6181c2f5..ef4eec9271bb 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -20,6 +20,13 @@ import * as Report from './Report'; type OptimisticReport = Pick; type Assignee = {icons: Icon[]; displayName: string; subtitle: string}; +type ShareDestination = { + icons: Icon[]; + displayName: string; + subtitle: string; + displayNamesWithTooltips: ReportUtils.DisplayNameWithTooltips; + shouldUseFullTitleToDisplay: boolean; +}; let currentUserEmail: string | undefined; let currentUserAccountID: number | undefined; @@ -219,6 +226,7 @@ function createTaskAndNavigate( assigneeChatReportActionID?: string; assigneeChatCreatedReportActionID?: string; }; + const parameters: CreateTaskParameters = { parentReportActionID: optimisticAddCommentReport.reportAction.reportActionID, parentReportID, @@ -689,7 +697,7 @@ function getAssignee(assigneeAccountID: number, personalDetails: Record, personalDetails: Record) { +function getShareDestination(reportID: string, reports: Record, personalDetails: Record): ShareDestination { const report = reports[`report_${reportID}`] ?? {}; const participantAccountIDs = report.participantAccountIDs ?? []; From 6557b808f9a4a26ecf9eb314076fecb5929e2eff Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 19 Dec 2023 15:26:35 +0100 Subject: [PATCH 09/42] fix: types --- src/components/TaskHeaderActionButton.tsx | 2 +- src/libs/actions/Task.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/TaskHeaderActionButton.tsx b/src/components/TaskHeaderActionButton.tsx index b1a32b356ae1..1ce17ded4256 100644 --- a/src/components/TaskHeaderActionButton.tsx +++ b/src/components/TaskHeaderActionButton.tsx @@ -31,7 +31,7 @@ function TaskHeaderActionButton({report, session, policy}: TaskHeaderActionButto