diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py index c836456a9..4e1de9a59 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py @@ -396,9 +396,6 @@ def _interstitial_stream(process_instance_id: int) -> Generator[str, str, None]: process_instance = _find_process_instance_by_id_or_raise(process_instance_id) processor = ProcessInstanceProcessor(process_instance) reported_ids = [] # bit of an issue with end tasks showing as getting completed twice. - - # return Response(get_data(), mimetype='text/event-stream') - spiff_task = processor.next_task() last_task = None while last_task != spiff_task: @@ -413,7 +410,11 @@ def _interstitial_stream(process_instance_id: int) -> Generator[str, str, None]: spiff_task = processor.next_task() # Note, this has to be done in case someone leaves the page, # which can otherwise cancel this function and leave completed tasks un-registered. - processor.save() # Fixme - maybe find a way not to do this on every method? + processor.save() # Fixme - maybe find a way not to do this on every loop? + if len(reported_ids) == 0: + # Always provide some response, in the event no instructions were provided. + task = ProcessInstanceService.spiff_task_to_api_task(processor, processor.next_task()) + yield f"data: {current_app.json.dumps(task)} \n\n" def interstitial(process_instance_id: int) -> Response: diff --git a/spiffworkflow-frontend/public/interstitial/checkmark.png b/spiffworkflow-frontend/public/interstitial/checkmark.png deleted file mode 100644 index 6467b220c..000000000 Binary files a/spiffworkflow-frontend/public/interstitial/checkmark.png and /dev/null differ diff --git a/spiffworkflow-frontend/public/interstitial/clock.png b/spiffworkflow-frontend/public/interstitial/clock.png deleted file mode 100644 index 3e4e5119a..000000000 Binary files a/spiffworkflow-frontend/public/interstitial/clock.png and /dev/null differ diff --git a/spiffworkflow-frontend/public/interstitial/completed.png b/spiffworkflow-frontend/public/interstitial/completed.png new file mode 100644 index 000000000..e5cf35100 Binary files /dev/null and b/spiffworkflow-frontend/public/interstitial/completed.png differ diff --git a/spiffworkflow-frontend/public/interstitial/lock.png b/spiffworkflow-frontend/public/interstitial/lock.png deleted file mode 100644 index 98f537d43..000000000 Binary files a/spiffworkflow-frontend/public/interstitial/lock.png and /dev/null differ diff --git a/spiffworkflow-frontend/public/interstitial/locked.png b/spiffworkflow-frontend/public/interstitial/locked.png new file mode 100644 index 000000000..fd39fb0d1 Binary files /dev/null and b/spiffworkflow-frontend/public/interstitial/locked.png differ diff --git a/spiffworkflow-frontend/public/interstitial/redirect.png b/spiffworkflow-frontend/public/interstitial/redirect.png new file mode 100644 index 000000000..b9de365bc Binary files /dev/null and b/spiffworkflow-frontend/public/interstitial/redirect.png differ diff --git a/spiffworkflow-frontend/public/interstitial/waiting.png b/spiffworkflow-frontend/public/interstitial/waiting.png new file mode 100644 index 000000000..e646611d4 Binary files /dev/null and b/spiffworkflow-frontend/public/interstitial/waiting.png differ diff --git a/spiffworkflow-frontend/src/components/InstructionsForEndUser.tsx b/spiffworkflow-frontend/src/components/InstructionsForEndUser.tsx index c779e9520..2a6cecdb9 100644 --- a/spiffworkflow-frontend/src/components/InstructionsForEndUser.tsx +++ b/spiffworkflow-frontend/src/components/InstructionsForEndUser.tsx @@ -6,8 +6,7 @@ export default function InstructionsForEndUser({ task }: any) { if (!task) { return null; } - let instructions = ''; - console.log('I was passed a task: ', task); + let instructions = 'There is no additional instructions or information for this task.'; const { properties } = task; const { instructionsForEndUser } = properties; if (instructionsForEndUser) { diff --git a/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx b/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx index 47042e910..f0f9705e9 100644 --- a/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx +++ b/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx @@ -10,6 +10,7 @@ export default function MyCompletedInstances() { perPageOptions={[2, 5, 25]} reportIdentifier="system_report_completed_instances_initiated_by_me" showReports={false} + showActionsColumn /> ); } diff --git a/spiffworkflow-frontend/src/routes/CompletedInstances.tsx b/spiffworkflow-frontend/src/routes/CompletedInstances.tsx index 78f73e92f..6d43020df 100644 --- a/spiffworkflow-frontend/src/routes/CompletedInstances.tsx +++ b/spiffworkflow-frontend/src/routes/CompletedInstances.tsx @@ -33,6 +33,7 @@ export default function CompletedInstances() { showReports={false} textToShowIfEmpty="This group has no completed instances at this time." additionalParams={`user_group_identifier=${userGroup}`} + showActionsColumn /> ); @@ -61,6 +62,7 @@ export default function CompletedInstances() { textToShowIfEmpty="You have no completed instances at this time." paginationClassName="with-large-bottom-margin" autoReload + showActionsColumn />

{groupTableComponents()} diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx index ca69eb7d3..d46778434 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx @@ -51,7 +51,7 @@ export default function ProcessInstanceList({ variant }: OwnProps) {
{processInstanceBreadcrumbElement()} {processInstanceTitleElement()} - + ); } diff --git a/spiffworkflow-frontend/src/routes/ProcessInterstitial.tsx b/spiffworkflow-frontend/src/routes/ProcessInterstitial.tsx index 0e6b3c637..8d5fb0e82 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInterstitial.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInterstitial.tsx @@ -14,7 +14,7 @@ import { ProcessInstanceTask } from '../interfaces'; export default function ProcessInterstitial() { const [data, setData] = useState([]); const [lastTask, setLastTask] = useState(null); - const [status, setStatus] = useState('running'); + const [state, setState] = useState('RUNNING'); const params = useParams(); const navigate = useNavigate(); const userTasks = ['User Task', 'Manual Task']; @@ -31,62 +31,74 @@ export default function ProcessInterstitial() { setLastTask(task); }, onclose() { - setStatus('closed'); - console.log('Connection Closed by the Server'); + setState('CLOSED'); }, } ); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // it is critical to only run this once. + const shouldRedirect = (myTask: ProcessInstanceTask): boolean => { + return myTask && myTask.can_complete && userTasks.includes(myTask.type); + }; + useEffect(() => { // Added this seperate use effect so that the timer interval will be cleared if // we end up redirecting back to the TaskShow page. - if ( - lastTask && - lastTask.can_complete && - userTasks.includes(lastTask.type) - ) { + if (shouldRedirect(lastTask)) { + setState('REDIRECTING'); + lastTask.properties.instructionsForEndUser = ''; const timerId = setInterval(() => { navigate(`/tasks/${lastTask.process_instance_id}/${lastTask.id}`); - }, 1000); + }, 2000); return () => clearInterval(timerId); } return undefined; }, [lastTask, navigate, userTasks]); - const processStatusImage = () => { - if (status !== 'running') { - setStatus(lastTask.state); - } + const getStatus = (): string => { if (!lastTask.can_complete && userTasks.includes(lastTask.type)) { - setStatus('LOCKED'); + return 'LOCKED'; } - switch (status) { - case 'running': + if (state === 'CLOSED') { + return lastTask.state; + } + console.log('The State is: ', state); + return state; + }; + + const getStatusImage = () => { + switch (getStatus()) { + case 'RUNNING': return ( ); - case 'WAITING': - return Waiting ....; - case 'COMPLETED': - return Completed; case 'LOCKED': - return ( - Locked, Waiting on someone else. - ); - default: - return null; + return Locked; + case 'REDIRECTING': + return Redirecting ....; + case 'WAITING': + return Waiting ....; + case 'COMPLETED': + return Completed; } }; + function capitalize(str: string): string { + console.log('Capitalizing: ', str); + if (str && str.length > 0) { + return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); + } + return ''; + } + const userMessage = (myTask: ProcessInstanceTask) => { if (!myTask.can_complete && userTasks.includes(myTask.type)) { return
This next task must be completed by a different person.
; } + if (shouldRedirect(myTask)) { + return
Redirecting you to the next task now ...
; + } return (
@@ -96,7 +108,7 @@ export default function ProcessInterstitial() { /** In the event there is no task information and the connection closed, * redirect to the home page. */ - if (status === 'closed' && lastTask === null) { + if (state === 'closed' && lastTask === null) { navigate(`/tasks`); } if (lastTask) { @@ -113,26 +125,28 @@ export default function ProcessInterstitial() { [`Process Instance Id: ${lastTask.process_instance_id}`], ]} /> -

- {processStatusImage()} - {lastTask.process_model_display_name}: {lastTask.process_instance_id} -

- - - - {data && - data.map((d) => ( -
-
- Task: {d.title} -
-
{userMessage(d)}
-
- ))} -
-
+
+ {getStatusImage()} +
+

+ {lastTask.process_model_display_name}:{' '} + {lastTask.process_instance_id} +

+
Status: {capitalize(getStatus())}
+
+
+
+
+ {data.map((d) => ( + + + Task: {d.title} + + + {userMessage(d)} + + + ))} ); }