From 46446030ffabe4dffcfd10dfb25dc860d294b17c Mon Sep 17 00:00:00 2001 From: jbirddog <100367399+jbirddog@users.noreply.github.com> Date: Thu, 27 Oct 2022 10:58:22 -0400 Subject: [PATCH] Front end changes to allow editing task data (#4) Co-authored-by: mike cullerton --- .../src/routes/ProcessInstanceShow.tsx | 140 ++++++++++++++++-- 1 file changed, 127 insertions(+), 13 deletions(-) diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx index 72a43899..f5336df8 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx @@ -1,4 +1,5 @@ -import { useEffect, useState } from 'react'; +import { useContext, useEffect, useState } from 'react'; +import Editor from '@monaco-editor/react'; import { useParams, useNavigate, Link } from 'react-router-dom'; import { Button, Modal, Stack } from 'react-bootstrap'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; @@ -6,6 +7,7 @@ import HttpService from '../services/HttpService'; import ReactDiagramEditor from '../components/ReactDiagramEditor'; import { convertSecondsToFormattedDate } from '../helpers'; import ButtonWithConfirmation from '../components/ButtonWithConfirmation'; +import ErrorContext from '../contexts/ErrorContext'; export default function ProcessInstanceShow() { const navigate = useNavigate(); @@ -14,6 +16,10 @@ export default function ProcessInstanceShow() { const [processInstance, setProcessInstance] = useState(null); const [tasks, setTasks] = useState | null>(null); const [taskToDisplay, setTaskToDisplay] = useState(null); + const [taskDataToDisplay, setTaskDataToDisplay] = useState(''); + const [editingTaskData, setEditingTaskData] = useState(false); + + const setErrorMessage = (useContext as any)(ErrorContext)[1]; const navigateToProcessInstances = (_result: any) => { navigate( @@ -168,19 +174,29 @@ export default function ProcessInstanceShow() { return
; }; + const initializeTaskDataToDisplay = (task: any) => { + if (task == null) { + setTaskDataToDisplay(''); + } else { + setTaskDataToDisplay(JSON.stringify(task.data, null, 2)); + } + }; + const handleClickedDiagramTask = (shapeElement: any) => { if (tasks) { - const matchingTask = tasks.find( + const matchingTask: any = tasks.find( (task: any) => task.name === shapeElement.id ); if (matchingTask) { setTaskToDisplay(matchingTask); + initializeTaskDataToDisplay(matchingTask); } } }; const handleTaskDataDisplayClose = () => { setTaskToDisplay(null); + initializeTaskDataToDisplay(null); }; const getTaskById = (taskId: string) => { @@ -211,29 +227,127 @@ export default function ProcessInstanceShow() { } }; - const taskDataDisplayArea = () => { - const taskToUse: any = taskToDisplay; - if (taskToDisplay) { - let createScriptUnitTestElement = null; - if (taskToUse.type === 'Script Task') { - createScriptUnitTestElement = ( + const canEditTaskData = (task: any) => { + return task.state === 'READY'; + }; + + const cancelEditingTaskData = () => { + setEditingTaskData(false); + initializeTaskDataToDisplay(taskToDisplay); + setErrorMessage(null); + }; + + const taskDataStringToObject = (dataString: string) => { + return JSON.parse(dataString); + }; + + const saveTaskDataResult = (_: any) => { + setEditingTaskData(false); + const dataObject = taskDataStringToObject(taskDataToDisplay); + const taskToDisplayCopy = { ...taskToDisplay, data: dataObject }; // spread operator + setTaskToDisplay(taskToDisplayCopy); + refreshPage(); + }; + + const saveTaskDataFailure = (result: any) => { + setErrorMessage({ message: result.toString() }); + }; + + const saveTaskData = () => { + if (!taskToDisplay) { + return; + } + + setErrorMessage(null); + + // taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute + const taskToUse: any = { ...taskToDisplay, data: taskDataToDisplay }; + HttpService.makeCallToBackend({ + path: `/process-instances/${params.process_instance_id}/task/${taskToUse.id}/update`, + httpMethod: 'POST', + successCallback: saveTaskDataResult, + failureCallback: saveTaskDataFailure, + postBody: { + new_task_data: taskToUse.data, + }, + }); + }; + + const taskDataButtons = (task: any) => { + const buttons = []; + + if (task.type === 'Script Task') { + buttons.push( + + ); + } + + if (canEditTaskData(task)) { + if (editingTaskData) { + buttons.push( + ); + buttons.push( + + ); + } else { + buttons.push( + ); } + } + + return buttons; + }; + + const taskDataContainer = () => { + return editingTaskData ? ( + setTaskDataToDisplay(value || '')} + /> + ) : ( +
{taskDataToDisplay}
+ ); + }; + + const taskDataDisplayArea = () => { + const taskToUse: any = { ...taskToDisplay, data: taskDataToDisplay }; + if (taskToDisplay) { return ( - {taskToUse.name} ({taskToUse.type}): {taskToUse.state} - {createScriptUnitTestElement} + + {taskToUse.name} ({taskToUse.type}): {taskToUse.state} + {taskDataButtons(taskToUse)} + -
{JSON.stringify(taskToUse.data, null, 2)}
+ {taskDataContainer()}
); }