import { useContext, useEffect, useState } from 'react'; import Editor from '@monaco-editor/react'; import { useParams, useNavigate, Link, useSearchParams, } from 'react-router-dom'; import { TrashCan, StopOutline, PauseOutline, PlayOutline, CaretLeft, CaretRight, InProgress, Checkmark, Warning, // @ts-ignore } from '@carbon/icons-react'; import { Grid, Column, Button, ButtonSet, Tag, Modal, Stack, // @ts-ignore } from '@carbon/react'; import { Can } from '@casl/react'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import HttpService from '../services/HttpService'; import ReactDiagramEditor from '../components/ReactDiagramEditor'; import { convertSecondsToFormattedDateTime, unModifyProcessIdentifierForPathParam, } from '../helpers'; import ButtonWithConfirmation from '../components/ButtonWithConfirmation'; import ErrorContext from '../contexts/ErrorContext'; import { useUriListForPermissions } from '../hooks/UriListForPermissions'; import { PermissionsToCheck, ProcessInstance, ProcessInstanceTask, } from '../interfaces'; import { usePermissionFetcher } from '../hooks/PermissionService'; import ProcessInstanceClass from '../classes/ProcessInstanceClass'; type OwnProps = { variant: string; }; export default function ProcessInstanceShow({ variant }: OwnProps) { const navigate = useNavigate(); const params = useParams(); const [searchParams] = useSearchParams(); const [processInstance, setProcessInstance] = useState(null); const [tasks, setTasks] = useState(null); const [tasksCallHadError, setTasksCallHadError] = useState(false); const [taskToDisplay, setTaskToDisplay] = useState(null); const [taskDataToDisplay, setTaskDataToDisplay] = useState(''); const [editingTaskData, setEditingTaskData] = useState(false); const setErrorMessage = (useContext as any)(ErrorContext)[1]; const unModifiedProcessModelId = unModifyProcessIdentifierForPathParam( `${params.process_model_id}` ); const modifiedProcessModelId = params.process_model_id; const { targetUris } = useUriListForPermissions(); const permissionRequestData: PermissionsToCheck = { [targetUris.messageInstanceListPath]: ['GET'], [targetUris.processInstanceTaskListPath]: ['GET'], [targetUris.processInstanceTaskListDataPath]: ['GET', 'PUT'], [targetUris.processInstanceActionPath]: ['DELETE'], [targetUris.processInstanceLogListPath]: ['GET'], [targetUris.processModelShowPath]: ['PUT'], [`${targetUris.processInstanceResumePath}`]: ['POST'], [`${targetUris.processInstanceSuspendPath}`]: ['POST'], [`${targetUris.processInstanceTerminatePath}`]: ['POST'], }; const { ability, permissionsLoaded } = usePermissionFetcher( permissionRequestData ); const navigateToProcessInstances = (_result: any) => { navigate( `/admin/process-instances?process_model_identifier=${unModifiedProcessModelId}` ); }; useEffect(() => { if (permissionsLoaded) { const processTaskFailure = () => { setTasksCallHadError(true); }; let queryParams = ''; const processIdentifier = searchParams.get('process_identifier'); if (processIdentifier) { queryParams = `?process_identifier=${processIdentifier}`; } let apiPath = '/process-instances/for-me'; if (variant === 'all') { apiPath = '/process-instances'; } HttpService.makeCallToBackend({ path: `${apiPath}/${modifiedProcessModelId}/${params.process_instance_id}${queryParams}`, successCallback: setProcessInstance, }); let taskParams = '?all_tasks=true'; if (typeof params.spiff_step !== 'undefined') { taskParams = `${taskParams}&spiff_step=${params.spiff_step}`; } let taskPath = ''; if (ability.can('GET', targetUris.processInstanceTaskListDataPath)) { taskPath = `${targetUris.processInstanceTaskListDataPath}${taskParams}`; } else if (ability.can('GET', targetUris.processInstanceTaskListPath)) { taskPath = `${targetUris.processInstanceTaskListPath}${taskParams}`; } if (taskPath) { HttpService.makeCallToBackend({ path: taskPath, successCallback: setTasks, failureCallback: processTaskFailure, }); } else { setTasksCallHadError(true); } } }, [ params, modifiedProcessModelId, permissionsLoaded, ability, targetUris, searchParams, ]); const deleteProcessInstance = () => { HttpService.makeCallToBackend({ path: targetUris.processInstanceActionPath, successCallback: navigateToProcessInstances, httpMethod: 'DELETE', }); }; // to force update the diagram since it could have changed const refreshPage = () => { window.location.reload(); }; const terminateProcessInstance = () => { HttpService.makeCallToBackend({ path: `${targetUris.processInstanceTerminatePath}`, successCallback: refreshPage, httpMethod: 'POST', }); }; const suspendProcessInstance = () => { HttpService.makeCallToBackend({ path: `${targetUris.processInstanceSuspendPath}`, successCallback: refreshPage, httpMethod: 'POST', }); }; const resumeProcessInstance = () => { HttpService.makeCallToBackend({ path: `${targetUris.processInstanceResumePath}`, successCallback: refreshPage, httpMethod: 'POST', }); }; const getTaskIds = () => { const taskIds = { completed: [], readyOrWaiting: [] }; if (tasks) { tasks.forEach(function getUserTasksElement(task: ProcessInstanceTask) { if (task.state === 'COMPLETED') { (taskIds.completed as any).push(task); } if (task.state === 'READY' || task.state === 'WAITING') { (taskIds.readyOrWaiting as any).push(task); } }); } return taskIds; }; const currentSpiffStep = () => { if (processInstance && typeof params.spiff_step === 'undefined') { return processInstance.spiff_step || 0; } return Number(params.spiff_step); }; const showingFirstSpiffStep = () => { return currentSpiffStep() === 1; }; const showingLastSpiffStep = () => { return processInstance && currentSpiffStep() === processInstance.spiff_step; }; const spiffStepLink = (label: any, distance: number) => { const processIdentifier = searchParams.get('process_identifier'); let queryParams = ''; if (processIdentifier) { queryParams = `?process_identifier=${processIdentifier}`; } return ( {label} ); }; const previousStepLink = () => { if (showingFirstSpiffStep()) { return null; } return spiffStepLink(, -1); }; const nextStepLink = () => { if (showingLastSpiffStep()) { return null; } return spiffStepLink(, 1); }; const getInfoTag = () => { if (!processInstance) { return null; } const currentEndDate = convertSecondsToFormattedDateTime( processInstance.end_in_seconds || 0 ); let currentEndDateTag; if (currentEndDate) { currentEndDateTag = ( Completed:{' '} {convertSecondsToFormattedDateTime( processInstance.end_in_seconds || 0 ) || 'N/A'} ); } let statusIcon = ; if (processInstance.status === 'suspended') { statusIcon = ; } else if (processInstance.status === 'complete') { statusIcon = ; } else if (processInstance.status === 'terminated') { statusIcon = ; } else if (processInstance.status === 'error') { statusIcon = ; } return ( <> Started:{' '} {convertSecondsToFormattedDateTime( processInstance.start_in_seconds || 0 )} {currentEndDateTag} Status:{' '} {processInstance.status} {statusIcon}
); }; const terminateButton = () => { if ( processInstance && !ProcessInstanceClass.terminalStatuses().includes(processInstance.status) ) { return ( ); } return
; }; const suspendButton = () => { if ( processInstance && !ProcessInstanceClass.terminalStatuses() .concat(['suspended']) .includes(processInstance.status) ) { return ( ); } if (task.type === 'Call Activity') { buttons.push( View Call Activity Diagram ); } 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} {taskDataButtons(taskToUse)} {taskDataContainer()} ); } return null; }; const stepsElement = () => { if (!processInstance) { return null; } return ( {previousStepLink()} Step {currentSpiffStep()} of {processInstance.spiff_step} {nextStepLink()} ); }; const buttonIcons = () => { if (!processInstance) { return null; } const elements = []; if (ability.can('POST', `${targetUris.processInstanceTerminatePath}`)) { elements.push(terminateButton()); } if (ability.can('POST', `${targetUris.processInstanceSuspendPath}`)) { elements.push(suspendButton()); } if (ability.can('POST', `${targetUris.processInstanceResumePath}`)) { elements.push(resumeButton()); } if ( ability.can('DELETE', targetUris.processInstanceActionPath) && ProcessInstanceClass.terminalStatuses().includes(processInstance.status) ) { elements.push( ); } return elements; }; if (processInstance && (tasks || tasksCallHadError)) { const taskIds = getTaskIds(); const processModelId = unModifyProcessIdentifierForPathParam( params.process_model_id ? params.process_model_id : '' ); return ( <>

Process Instance Id: {processInstance.id}

{buttonIcons()}


{getInfoTag()}
{taskDataDisplayArea()} {stepsElement()}
); } return null; }