Skip to content

Commit

Permalink
Merge pull request #18672 from infinitered/dan-editTaskFrontend
Browse files Browse the repository at this point in the history
  • Loading branch information
thienlnam authored May 14, 2023
2 parents dbcad5a + daf9ae1 commit 2e73562
Show file tree
Hide file tree
Showing 15 changed files with 415 additions and 84 deletions.
1 change: 1 addition & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ const CONST = {
ADDCOMMENT: 'ADDCOMMENT',
CLOSED: 'CLOSED',
CREATED: 'CREATED',
TASKEDITED: 'TASKEDITED',
IOU: 'IOU',
RENAMED: 'RENAMED',
CHRONOSOOOLIST: 'CHRONOSOOOLIST',
Expand Down
2 changes: 2 additions & 0 deletions src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ export default {
NEW_TASK_WITH_REPORT_ID: `${NEW_TASK}/:reportID?`,
TASK_TITLE: 'r/:reportID/title',
TASK_DESCRIPTION: 'r/:reportID/description',
TASK_ASSIGNEE: 'r/:reportID/assignee',
getTaskReportTitleRoute: (reportID) => `r/${reportID}/title`,
getTaskReportDescriptionRoute: (reportID) => `r/${reportID}/description`,
getTaskReportAssigneeRoute: (reportID) => `r/${reportID}/assignee`,
NEW_TASK_ASSIGNEE: `${NEW_TASK}/assignee`,
NEW_TASK_SHARE_DESTINATION: `${NEW_TASK}/share-destination`,
NEW_TASK_DETAILS: `${NEW_TASK}/details`,
Expand Down
9 changes: 6 additions & 3 deletions src/components/TaskSelectorLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ const propTypes = {
/** Whether the Touchable should be disabled */
disabled: PropTypes.bool,

/** Whether we're creating a new task or editing */
isNewTask: PropTypes.bool,

...withLocalizePropTypes,
};

Expand All @@ -45,16 +48,16 @@ const defaultProps = {
alternateText: '',
isShareDestination: false,
disabled: false,
isNewTask: true,
};

const TaskSelectorLink = (props) => {
const shortenedText = props.text.length > 35 ? `${props.text.substring(0, 35)}...` : props.text;
const displayNameStyle = StyleUtils.combineStyles(styles.optionDisplayName, styles.pre);
const alternateTextStyle = StyleUtils.combineStyles(styles.sidebarLinkText, styles.optionAlternateText, styles.textLabelSupporting, styles.pre);
const linkBottomMargin = props.icons.length !== 0 ? styles.mb6 : styles.mb2;
return (
<TouchableOpacity
style={[styles.flexRow, styles.taskSelectorLink, linkBottomMargin]}
style={[styles.flexRow, styles.taskSelectorLink, styles.mb1]}
onPress={props.onPress}
disabled={props.disabled}
>
Expand Down Expand Up @@ -93,7 +96,7 @@ const TaskSelectorLink = (props) => {
) : (
<Text style={[styles.textWhite, styles.textNormal]}>{props.translate(props.label)}</Text>
)}
{props.disabled ? null : (
{props.disabled || !props.isNewTask ? null : (
<Icon
src={Expensicons.ArrowRight}
fill={themeColors.textLight}
Expand Down
7 changes: 7 additions & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ const TaskModalStackNavigator = createModalStackNavigator([
},
name: 'Task_Description',
},
{
getComponent: () => {
const TaskAssigneeSelectorPage = require('../../../pages/tasks/TaskAssigneeSelectorModal').default;
return TaskAssigneeSelectorPage;
},
name: 'Task_Assignee',
},
]);

const ReportSettingsModalStackNavigator = createModalStackNavigator([
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ export default {
screens: {
Task_Title: ROUTES.TASK_TITLE,
Task_Description: ROUTES.TASK_DESCRIPTION,
Task_Assignee: ROUTES.TASK_ASSIGNEE,
},
},
AddPersonalBankAccount: {
Expand Down
4 changes: 3 additions & 1 deletion src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,9 @@ function getNewChatOptions(reports, personalDetails, betas = [], searchValue = '
*/

function getShareDestinationOptions(reports, personalDetails, betas = [], searchValue = '', selectedOptions = [], excludeLogins = [], includeOwnedWorkspaceChats = true) {
return getOptions(reports, personalDetails, {
// We want to filter out any IOUs or expense reports
const filteredReports = _.filter(reports, (report) => !ReportUtils.isMoneyRequestReport(report));
return getOptions(filteredReports, personalDetails, {
betas,
searchInputValue: searchValue.trim(),
selectedOptions,
Expand Down
4 changes: 4 additions & 0 deletions src/libs/ReportActionsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ function shouldReportActionBeVisible(reportAction, key) {
return false;
}

if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.TASKEDITED) {
return false;
}

// Filter out any unsupported reportAction types
if (!_.has(CONST.REPORT.ACTIONS.TYPE, reportAction.actionName) && !_.contains(_.values(CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG), reportAction.actionName)) {
return false;
Expand Down
42 changes: 42 additions & 0 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,7 @@ function buildOptimisticCreatedReportAction(ownerEmail) {
actionName: CONST.REPORT.ACTIONS.TYPE.CREATED,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
actorAccountID: currentUserAccountID,
actorEmail: currentUserEmail,
message: [
{
type: CONST.REPORT.MESSAGE.TYPE.TEXT,
Expand All @@ -1455,6 +1456,46 @@ function buildOptimisticCreatedReportAction(ownerEmail) {
};
}

/**
* Returns the necessary reportAction onyx data to indicate that a task report has been edited
*
* @param {String} ownerEmail
* @returns {Object}
*/

function buildOptimisticEditedTaskReportAction(ownerEmail) {
return {
reportActionID: NumberUtils.rand64(),
actionName: CONST.REPORT.ACTIONS.TYPE.TASKEDITED,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
actorAccountID: currentUserAccountID,
actorEmail: currentUserEmail,
message: [
{
type: CONST.REPORT.MESSAGE.TYPE.TEXT,
style: 'strong',
text: ownerEmail === currentUserEmail ? 'You' : ownerEmail,
},
{
type: CONST.REPORT.MESSAGE.TYPE.TEXT,
style: 'normal',
text: ' edited this task',
},
],
person: [
{
type: CONST.REPORT.MESSAGE.TYPE.TEXT,
style: 'strong',
text: lodashGet(allPersonalDetails, [currentUserEmail, 'displayName'], currentUserEmail),
},
],
automatic: false,
avatar: lodashGet(allPersonalDetails, [currentUserEmail, 'avatar'], getDefaultAvatar(currentUserEmail)),
created: DateUtils.getDBTime(),
shouldShow: false,
};
}

/**
* Returns the necessary reportAction onyx data to indicate that a chat has been archived
*
Expand Down Expand Up @@ -2068,6 +2109,7 @@ export {
buildOptimisticChatReport,
buildOptimisticClosedReportAction,
buildOptimisticCreatedReportAction,
buildOptimisticEditedTaskReportAction,
buildOptimisticIOUReport,
buildOptimisticExpenseReport,
buildOptimisticIOUReportAction,
Expand Down
167 changes: 165 additions & 2 deletions src/libs/actions/Task.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,122 @@ function createTaskAndNavigate(currentUserEmail, parentReportID, title, descript
Navigation.navigate(ROUTES.getReportRoute(optimisticTaskReport.reportID));
}

/**
* @function editTask
* @param {object} report
* @param {string} ownerEmail
* @param {string} title
* @param {string} description
* @param {string} assignee
* @returns {object} action
*
*/

function editTaskAndNavigate(report, ownerEmail, title, description, assignee) {
// Create the EditedReportAction on the task
const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskReportAction(ownerEmail);

// Sometimes title is undefined, so we need to check for that, and we provide it to multiple functions
const reportName = title || report.reportName;

// If we make a change to the assignee, we want to add a comment to the assignee's chat
let optimisticAssigneeAddComment;
let assigneeChatReportID;
if (assignee && assignee !== report.assignee) {
assigneeChatReportID = ReportUtils.getChatByParticipants([assignee]).reportID;
optimisticAssigneeAddComment = ReportUtils.buildOptimisticTaskCommentReportAction(report.reportID, reportName, assignee, `Assigned a task to you: ${reportName}`);
}

const optimisticData = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`,
value: {[editTaskReportAction.reportActionID]: editTaskReportAction},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`,
value: {
reportName,
description: description || report.description,
assignee: assignee || report.assignee,
},
},
];
const successData = [];
const failureData = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`,
value: {[editTaskReportAction.reportActionID]: {pendingAction: null}},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`,
value: {reportName: report.reportName, description: report.description, assignee: report.assignee},
},
];

if (optimisticAssigneeAddComment) {
const currentTime = DateUtils.getDBTime();
const lastAssigneeCommentText = ReportUtils.formatReportLastMessageText(optimisticAssigneeAddComment.reportAction.message[0].text);

const optimisticAssigneeReport = {
lastVisibleActionCreated: currentTime,
lastMessageText: Str.htmlDecode(lastAssigneeCommentText),
lastActorEmail: ownerEmail,
lastReadTime: currentTime,
};

optimisticData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${assigneeChatReportID}`,
value: {[optimisticAssigneeAddComment.reportAction.reportActionID]: optimisticAssigneeAddComment.reportAction},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${assigneeChatReportID}`,
value: optimisticAssigneeReport,
},
);

failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${assigneeChatReportID}`,
value: {[optimisticAssigneeAddComment.reportAction.reportActionID]: {pendingAction: null}},
});
}

API.write(
'EditTask',
{
taskReportID: report.reportID,
title: reportName,
description: description || report.description,
assignee: assignee || report.assignee,
editedTaskReportActionID: editTaskReportAction.reportActionID,
assigneeChatReportActionID: optimisticAssigneeAddComment ? optimisticAssigneeAddComment.reportAction.reportActionID : 0,
},
{optimisticData, successData, failureData},
);

Navigation.navigate(ROUTES.getReportRoute(report.reportID));
}

/**
* Sets the report info for the task being viewed
*
* @param {Object} report
*/
function setTaskReport(report) {
Onyx.merge(ONYXKEYS.TASK, {report});
}

/**
* Sets the title and description values for the task
* @param {string} title
@param {string} description
* @param {string} description
*/

function setDetailsValue(title, description) {
Expand Down Expand Up @@ -233,4 +345,55 @@ function clearOutTaskInfoAndNavigate(reportID) {
Navigation.navigate(ROUTES.NEW_TASK_DETAILS);
}

export {createTaskAndNavigate, setTitleValue, setDescriptionValue, setDetailsValue, setAssigneeValue, setShareDestinationValue, clearOutTaskInfo, clearOutTaskInfoAndNavigate};
/**
* Get the assignee data
*
* @param {Object} details
* @returns {Object}
*/
function getAssignee(details) {
if (!details) {
return {
icons: [],
displayName: '',
subtitle: '',
};
}
const source = ReportUtils.getAvatar(lodashGet(details, 'avatar', ''), lodashGet(details, 'login', ''));
return {
icons: [{source, type: 'avatar', name: details.login}],
displayName: details.displayName,
subtitle: details.login,
};
}

/**
* 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}`, {});
return {
icons: ReportUtils.getIcons(report, personalDetails),
displayName: ReportUtils.getReportName(report),
subtitle: ReportUtils.getChatRoomSubtitle(report),
};
}

export {
createTaskAndNavigate,
editTaskAndNavigate,
setTitleValue,
setDescriptionValue,
setTaskReport,
setDetailsValue,
setAssigneeValue,
setShareDestinationValue,
clearOutTaskInfo,
clearOutTaskInfoAndNavigate,
getAssignee,
getShareDestination,
};
Loading

0 comments on commit 2e73562

Please sign in to comment.