ProcessInterstitial is now a component, and a page. The component is included into both the Interstitial PAge and the Process Instance Show page.
Fixed routes for interstitial to align with those of the TaskShow page (variants are now accepted and passed through) Removed the View button completely.
This commit is contained in:
parent
3fcc4fd1a6
commit
0ebab2884b
|
@ -10,7 +10,6 @@ import HomePageRoutes from './routes/HomePageRoutes';
|
||||||
import About from './routes/About';
|
import About from './routes/About';
|
||||||
import ErrorBoundary from './components/ErrorBoundary';
|
import ErrorBoundary from './components/ErrorBoundary';
|
||||||
import AdminRoutes from './routes/AdminRoutes';
|
import AdminRoutes from './routes/AdminRoutes';
|
||||||
import ProcessRoutes from './routes/ProcessRoutes';
|
|
||||||
|
|
||||||
import { AbilityContext } from './contexts/Can';
|
import { AbilityContext } from './contexts/Can';
|
||||||
import UserService from './services/UserService';
|
import UserService from './services/UserService';
|
||||||
|
@ -41,7 +40,6 @@ export default function App() {
|
||||||
<Route path="/*" element={<HomePageRoutes />} />
|
<Route path="/*" element={<HomePageRoutes />} />
|
||||||
<Route path="/about" element={<About />} />
|
<Route path="/about" element={<About />} />
|
||||||
<Route path="/tasks/*" element={<HomePageRoutes />} />
|
<Route path="/tasks/*" element={<HomePageRoutes />} />
|
||||||
<Route path="/process/*" element={<ProcessRoutes />} />
|
|
||||||
<Route path="/admin/*" element={<AdminRoutes />} />
|
<Route path="/admin/*" element={<AdminRoutes />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|
|
@ -1590,9 +1590,7 @@ export default function ProcessInstanceListTable({
|
||||||
});
|
});
|
||||||
if (showActionsColumn) {
|
if (showActionsColumn) {
|
||||||
let buttonElement = null;
|
let buttonElement = null;
|
||||||
const interstitialUrl = `/process/${modifyProcessIdentifierForPathParam(
|
const taskShowUrl = `/tasks/${processInstance.id}/${processInstance.task_id}`;
|
||||||
processInstance.process_model_identifier
|
|
||||||
)}/${processInstance.id}/interstitial`;
|
|
||||||
const regex = new RegExp(`\\b(${preferredUsername}|${userEmail})\\b`);
|
const regex = new RegExp(`\\b(${preferredUsername}|${userEmail})\\b`);
|
||||||
let hasAccessToCompleteTask = false;
|
let hasAccessToCompleteTask = false;
|
||||||
if (
|
if (
|
||||||
|
@ -1601,21 +1599,19 @@ export default function ProcessInstanceListTable({
|
||||||
) {
|
) {
|
||||||
hasAccessToCompleteTask = true;
|
hasAccessToCompleteTask = true;
|
||||||
}
|
}
|
||||||
let buttonText = 'View';
|
buttonElement = null;
|
||||||
if (hasAccessToCompleteTask && processInstance.task_id) {
|
if (hasAccessToCompleteTask && processInstance.task_id) {
|
||||||
buttonText = 'Go';
|
buttonElement = (
|
||||||
|
<Button
|
||||||
|
kind="secondary"
|
||||||
|
href={taskShowUrl}
|
||||||
|
style={{ width: '60px' }}
|
||||||
|
>
|
||||||
|
Go
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonElement = (
|
|
||||||
<Button
|
|
||||||
kind="secondary"
|
|
||||||
href={interstitialUrl}
|
|
||||||
style={{ width: '60px' }}
|
|
||||||
>
|
|
||||||
{buttonText}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
processInstance.status === 'not_started' ||
|
processInstance.status === 'not_started' ||
|
||||||
processInstance.status === 'user_input_required' ||
|
processInstance.status === 'user_input_required' ||
|
||||||
|
|
|
@ -96,7 +96,7 @@ export default function ProcessInstanceRun({
|
||||||
const onProcessInstanceRun = (processInstance: any) => {
|
const onProcessInstanceRun = (processInstance: any) => {
|
||||||
const processInstanceId = (processInstance as any).id;
|
const processInstanceId = (processInstance as any).id;
|
||||||
navigate(
|
navigate(
|
||||||
`/process/${modifyProcessIdentifierForPathParam(
|
`/admin/process-instances/${modifyProcessIdentifierForPathParam(
|
||||||
processModel.id
|
processModel.id
|
||||||
)}/${processInstanceId}/interstitial`
|
)}/${processInstanceId}/interstitial`
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,33 +2,32 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { fetchEventSource } from '@microsoft/fetch-event-source';
|
import { fetchEventSource } from '@microsoft/fetch-event-source';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { Loading, Button } from '@carbon/react';
|
import { Loading } from '@carbon/react';
|
||||||
import { BACKEND_BASE_URL } from '../config';
|
import { BACKEND_BASE_URL } from '../config';
|
||||||
import { getBasicHeaders } from '../services/HttpService';
|
import { getBasicHeaders } from '../services/HttpService';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import InstructionsForEndUser from './InstructionsForEndUser';
|
import InstructionsForEndUser from './InstructionsForEndUser';
|
||||||
import ProcessBreadcrumb from './ProcessBreadcrumb';
|
|
||||||
import { ProcessInstance, ProcessInstanceTask } from '../interfaces';
|
import { ProcessInstance, ProcessInstanceTask } from '../interfaces';
|
||||||
import useAPIError from '../hooks/UseApiError';
|
import useAPIError from '../hooks/UseApiError';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
processInstanceId: number;
|
processInstanceId: number;
|
||||||
modifiedProcessModelIdentifier: string;
|
processInstanceShowPageUrl: string;
|
||||||
allowRedirect: boolean;
|
allowRedirect: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ProcessInterstitial({
|
export default function ProcessInterstitial({
|
||||||
processInstanceId,
|
processInstanceId,
|
||||||
modifiedProcessModelIdentifier,
|
|
||||||
allowRedirect,
|
allowRedirect,
|
||||||
|
processInstanceShowPageUrl,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const [data, setData] = useState<any[]>([]);
|
const [data, setData] = useState<any[]>([]);
|
||||||
const [lastTask, setLastTask] = useState<any>(null);
|
const [lastTask, setLastTask] = useState<any>(null);
|
||||||
const [state, setState] = useState<string>('RUNNING');
|
const [state, setState] = useState<string>('RUNNING');
|
||||||
const [processInstance, setProcessInstance] =
|
const [processInstance, setProcessInstance] =
|
||||||
useState<ProcessInstance | null>(null);
|
useState<ProcessInstance | null>(null);
|
||||||
const processInstanceShowPageBaseUrl = `/admin/process-instances/for-me/${modifiedProcessModelIdentifier}`;
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const userTasks = useMemo(() => {
|
const userTasks = useMemo(() => {
|
||||||
return ['User Task', 'Manual Task'];
|
return ['User Task', 'Manual Task'];
|
||||||
|
@ -50,13 +49,14 @@ export default function ProcessInterstitial({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onclose() {
|
onclose() {
|
||||||
|
console.log('The state is closed.');
|
||||||
setState('CLOSED');
|
setState('CLOSED');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []); // it is critical to only run this once.
|
}, []); // it is critical to only run this once.
|
||||||
|
|
||||||
const shouldRedirect = useCallback(
|
const shouldRedirectToTask = useCallback(
|
||||||
(myTask: ProcessInstanceTask): boolean => {
|
(myTask: ProcessInstanceTask): boolean => {
|
||||||
return (
|
return (
|
||||||
allowRedirect &&
|
allowRedirect &&
|
||||||
|
@ -66,21 +66,38 @@ export default function ProcessInterstitial({
|
||||||
userTasks.includes(myTask.type)
|
userTasks.includes(myTask.type)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[userTasks, processInstance]
|
[allowRedirect, processInstance, userTasks]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const shouldRedirectToProcessInstance = useCallback((): boolean => {
|
||||||
|
return allowRedirect && state === 'CLOSED';
|
||||||
|
}, [allowRedirect, state]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Added this seperate use effect so that the timer interval will be cleared if
|
// Added this seperate use effect so that the timer interval will be cleared if
|
||||||
// we end up redirecting back to the TaskShow page.
|
// we end up redirecting back to the TaskShow page.
|
||||||
if (shouldRedirect(lastTask)) {
|
if (shouldRedirectToTask(lastTask)) {
|
||||||
lastTask.properties.instructionsForEndUser = '';
|
lastTask.properties.instructionsForEndUser = '';
|
||||||
const timerId = setInterval(() => {
|
const timerId = setInterval(() => {
|
||||||
navigate(`/tasks/${lastTask.process_instance_id}/${lastTask.id}`);
|
navigate(`/tasks/${lastTask.process_instance_id}/${lastTask.id}`);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
return () => clearInterval(timerId);
|
return () => clearInterval(timerId);
|
||||||
}
|
}
|
||||||
|
if (shouldRedirectToProcessInstance()) {
|
||||||
|
// Navigate without pause as we will be showing the same information.
|
||||||
|
navigate(processInstanceShowPageUrl);
|
||||||
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}, [lastTask, navigate, userTasks, shouldRedirect]);
|
}, [
|
||||||
|
lastTask,
|
||||||
|
navigate,
|
||||||
|
userTasks,
|
||||||
|
shouldRedirectToTask,
|
||||||
|
processInstanceId,
|
||||||
|
processInstanceShowPageUrl,
|
||||||
|
state,
|
||||||
|
shouldRedirectToProcessInstance,
|
||||||
|
]);
|
||||||
|
|
||||||
const getStatus = (): string => {
|
const getStatus = (): string => {
|
||||||
if (processInstance) {
|
if (processInstance) {
|
||||||
|
@ -101,35 +118,13 @@ export default function ProcessInterstitial({
|
||||||
<Loading
|
<Loading
|
||||||
description="Active loading indicator"
|
description="Active loading indicator"
|
||||||
withOverlay={false}
|
withOverlay={false}
|
||||||
style={{ margin: 'auto' }}
|
style={{ margin: '50px 0 50px 50px' }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getReturnHomeButton = (index: number) => {
|
|
||||||
if (
|
|
||||||
index === 0 &&
|
|
||||||
!shouldRedirect(lastTask) &&
|
|
||||||
['WAITING', 'ERROR', 'LOCKED', 'COMPLETED', 'READY'].includes(getStatus())
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<div style={{ padding: '10px 0 0 0' }}>
|
|
||||||
<Button
|
|
||||||
kind="secondary"
|
|
||||||
data-qa="return-to-home-button"
|
|
||||||
onClick={() => navigate(`/tasks`)}
|
|
||||||
style={{ marginBottom: 30 }}
|
|
||||||
>
|
|
||||||
Return to Home
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
};
|
|
||||||
|
|
||||||
const userMessage = (myTask: ProcessInstanceTask) => {
|
const userMessage = (myTask: ProcessInstanceTask) => {
|
||||||
if (!processInstance || processInstance.status === 'completed') {
|
if (!processInstance || processInstance.status === 'completed') {
|
||||||
if (!myTask.can_complete && userTasks.includes(myTask.type)) {
|
if (!myTask.can_complete && userTasks.includes(myTask.type)) {
|
||||||
|
@ -140,7 +135,7 @@ export default function ProcessInterstitial({
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (shouldRedirect(myTask)) {
|
if (shouldRedirectToTask(myTask)) {
|
||||||
return <div>Redirecting you to the next task now ...</div>;
|
return <div>Redirecting you to the next task now ...</div>;
|
||||||
}
|
}
|
||||||
if (myTask && myTask.can_complete && userTasks.includes(myTask.type)) {
|
if (myTask && myTask.can_complete && userTasks.includes(myTask.type)) {
|
||||||
|
@ -170,40 +165,24 @@ export default function ProcessInterstitial({
|
||||||
navigate(`/tasks`);
|
navigate(`/tasks`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let displayableData = data;
|
||||||
|
if (state === 'CLOSED') {
|
||||||
|
displayableData = [data[0]];
|
||||||
|
}
|
||||||
|
|
||||||
if (lastTask) {
|
if (lastTask) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ProcessBreadcrumb
|
|
||||||
hotCrumbs={[
|
|
||||||
['Process Groups', '/admin'],
|
|
||||||
{
|
|
||||||
entityToExplode: lastTask.process_model_identifier,
|
|
||||||
entityType: 'process-model-id',
|
|
||||||
linkLastItem: true,
|
|
||||||
},
|
|
||||||
[
|
|
||||||
`Process Instance: ${processInstanceId}`,
|
|
||||||
`${processInstanceShowPageBaseUrl}/${processInstanceId}`,
|
|
||||||
],
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
{getLoadingIcon()}
|
{getLoadingIcon()}
|
||||||
<div style={{ maxWidth: 800, margin: 'auto', padding: 50 }}>
|
{displayableData.map((d, index) => (
|
||||||
{data.map((d, index) => (
|
<div
|
||||||
<>
|
className={
|
||||||
<div
|
index < 4 ? `user_instructions_${index}` : `user_instructions_4`
|
||||||
className={
|
}
|
||||||
index < 4
|
>
|
||||||
? `user_instructions_${index}`
|
{userMessage(d)}
|
||||||
: `user_instructions_4`
|
</div>
|
||||||
}
|
))}
|
||||||
>
|
|
||||||
{userMessage(d)}
|
|
||||||
</div>
|
|
||||||
{getReturnHomeButton(index)}
|
|
||||||
</>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import Configuration from './Configuration';
|
||||||
import JsonSchemaFormBuilder from './JsonSchemaFormBuilder';
|
import JsonSchemaFormBuilder from './JsonSchemaFormBuilder';
|
||||||
import ProcessModelNewExperimental from './ProcessModelNewExperimental';
|
import ProcessModelNewExperimental from './ProcessModelNewExperimental';
|
||||||
import ProcessInstanceFindById from './ProcessInstanceFindById';
|
import ProcessInstanceFindById from './ProcessInstanceFindById';
|
||||||
|
import ProcessInterstitialPage from "./ProcessInterstitialPage";
|
||||||
|
|
||||||
export default function AdminRoutes() {
|
export default function AdminRoutes() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
@ -75,6 +76,14 @@ export default function AdminRoutes() {
|
||||||
path="process-instances/for-me/:process_model_id/:process_instance_id/:to_task_guid"
|
path="process-instances/for-me/:process_model_id/:process_instance_id/:to_task_guid"
|
||||||
element={<ProcessInstanceShow variant="for-me" />}
|
element={<ProcessInstanceShow variant="for-me" />}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="process-instances/for-me/:process_model_id/:process_instance_id/interstitial"
|
||||||
|
element={<ProcessInterstitialPage variant="for-me" />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="process-instances/:process_model_id/:process_instance_id/interstitial"
|
||||||
|
element={<ProcessInterstitialPage variant="all" />}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="process-instances/:process_model_id/:process_instance_id"
|
path="process-instances/:process_model_id/:process_instance_id"
|
||||||
element={<ProcessInstanceShow variant="all" />}
|
element={<ProcessInstanceShow variant="all" />}
|
||||||
|
|
|
@ -53,7 +53,7 @@ import { usePermissionFetcher } from '../hooks/PermissionService';
|
||||||
import ProcessInstanceClass from '../classes/ProcessInstanceClass';
|
import ProcessInstanceClass from '../classes/ProcessInstanceClass';
|
||||||
import TaskListTable from '../components/TaskListTable';
|
import TaskListTable from '../components/TaskListTable';
|
||||||
import useAPIError from '../hooks/UseApiError';
|
import useAPIError from '../hooks/UseApiError';
|
||||||
import ProcessInterstitial from "../components/ProcessInterstitial";
|
import ProcessInterstitial from '../components/ProcessInterstitial';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
variant: string;
|
variant: string;
|
||||||
|
@ -1093,9 +1093,28 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ProcessInterstitial processInstanceId={processInstance.id} modifiedProcessModelIdentifier={String(modifiedProcessModelId)} allowRedirect={false}/>
|
<ProcessBreadcrumb
|
||||||
{buttonIcons()}
|
hotCrumbs={[
|
||||||
<br />
|
['Process Groups', '/admin'],
|
||||||
|
{
|
||||||
|
entityToExplode: processModelId,
|
||||||
|
entityType: 'process-model-id',
|
||||||
|
linkLastItem: true,
|
||||||
|
},
|
||||||
|
[`Process Instance Id: ${processInstance.id}`],
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Stack orientation="horizontal" gap={1}>
|
||||||
|
<h1 className="with-icons">
|
||||||
|
Process Instance Id: {processInstance.id}
|
||||||
|
</h1>
|
||||||
|
{buttonIcons()}
|
||||||
|
</Stack>
|
||||||
|
<ProcessInterstitial
|
||||||
|
processInstanceId={processInstance.id}
|
||||||
|
processInstanceShowPageUrl={processInstanceShowPageBaseUrl}
|
||||||
|
allowRedirect={false}
|
||||||
|
/>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<Grid condensed fullWidth>
|
<Grid condensed fullWidth>
|
||||||
|
|
|
@ -2,17 +2,42 @@ import React from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import ProcessInterstitial from '../components/ProcessInterstitial';
|
import ProcessInterstitial from '../components/ProcessInterstitial';
|
||||||
|
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||||
|
|
||||||
export default function ProcessInterstitialPage() {
|
type OwnProps = {
|
||||||
|
variant: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ProcessInterstitialPage({ variant }: OwnProps) {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
let processInstanceShowPageUrl = `/admin/process-instances/for-me/${params.process_model_id}/${params.process_instance_id}`;
|
||||||
|
if (variant === 'all') {
|
||||||
|
processInstanceShowPageUrl = `/admin/process-instances/${params.process_model_id}/${params.process_instance_id}`;
|
||||||
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
console.log('params', params, processInstanceShowPageUrl);
|
||||||
return (
|
return (
|
||||||
<ProcessInterstitial
|
<>
|
||||||
processInstanceId={Number(params.process_instance_id)}
|
<ProcessBreadcrumb
|
||||||
modifiedProcessModelIdentifier={String(
|
hotCrumbs={[
|
||||||
params.modified_process_model_identifier
|
['Process Groups', '/admin'],
|
||||||
)}
|
{
|
||||||
allowRedirect
|
entityToExplode: String(params.process_model_id),
|
||||||
/>
|
entityType: 'process-model-id',
|
||||||
|
linkLastItem: true,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
`Process Instance: ${params.process_instance_id}`,
|
||||||
|
`${processInstanceShowPageUrl}`,
|
||||||
|
],
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<ProcessInterstitial
|
||||||
|
processInstanceId={Number(params.process_instance_id)}
|
||||||
|
processInstanceShowPageUrl={processInstanceShowPageUrl}
|
||||||
|
allowRedirect
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { Route, Routes } from 'react-router-dom';
|
|
||||||
// @ts-ignore
|
|
||||||
import ProcessInterstitialPage from './ProcessInterstitialPage';
|
|
||||||
|
|
||||||
export default function ProcessRoutes() {
|
|
||||||
return (
|
|
||||||
<Routes>
|
|
||||||
<Route
|
|
||||||
path=":modified_process_model_identifier/:process_instance_id/interstitial"
|
|
||||||
element={<ProcessInterstitialPage />}
|
|
||||||
/>
|
|
||||||
</Routes>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -102,7 +102,7 @@ export default function TaskShow() {
|
||||||
|
|
||||||
const navigateToInterstitial = (myTask: Task) => {
|
const navigateToInterstitial = (myTask: Task) => {
|
||||||
navigate(
|
navigate(
|
||||||
`/process/${modifyProcessIdentifierForPathParam(
|
`/admin/process-instances/${modifyProcessIdentifierForPathParam(
|
||||||
myTask.process_model_identifier
|
myTask.process_model_identifier
|
||||||
)}/${myTask.process_instance_id}/interstitial`
|
)}/${myTask.process_instance_id}/interstitial`
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue