From 919150b73b1035c76f0231e4226c75eefdb12ce1 Mon Sep 17 00:00:00 2001 From: jasquat Date: Fri, 18 Nov 2022 16:40:49 -0500 Subject: [PATCH] added create new instance page and moved model run to a component w/ burnettk cullerton --- .../src/components/ProcessGroupListTiles.tsx | 4 +- .../src/components/ProcessInstanceRun.tsx | 64 +++++++++++ .../src/components/ProcessModelForm.tsx | 2 +- .../src/components/ProcessModelListTiles.tsx | 105 ++++++++++++++++++ spiffworkflow-frontend/src/index.css | 13 ++- spiffworkflow-frontend/src/interfaces.ts | 5 + .../src/routes/CreateNewInstance.tsx | 9 ++ .../src/routes/HomePageRoutes.tsx | 7 ++ .../src/routes/ProcessModelShow.tsx | 42 ++----- 9 files changed, 216 insertions(+), 35 deletions(-) create mode 100644 spiffworkflow-frontend/src/components/ProcessInstanceRun.tsx create mode 100644 spiffworkflow-frontend/src/components/ProcessModelListTiles.tsx create mode 100644 spiffworkflow-frontend/src/routes/CreateNewInstance.tsx diff --git a/spiffworkflow-frontend/src/components/ProcessGroupListTiles.tsx b/spiffworkflow-frontend/src/components/ProcessGroupListTiles.tsx index 839f2149..4c964bec 100644 --- a/spiffworkflow-frontend/src/components/ProcessGroupListTiles.tsx +++ b/spiffworkflow-frontend/src/components/ProcessGroupListTiles.tsx @@ -60,10 +60,10 @@ export default function ProcessGroupListTiles({
{row.display_name}
-

+

{truncateString(row.description || '', 25)}

-

+

Total Sub Items: {processGroupDirectChildrenCount(row)}

diff --git a/spiffworkflow-frontend/src/components/ProcessInstanceRun.tsx b/spiffworkflow-frontend/src/components/ProcessInstanceRun.tsx new file mode 100644 index 00000000..c4f288c0 --- /dev/null +++ b/spiffworkflow-frontend/src/components/ProcessInstanceRun.tsx @@ -0,0 +1,64 @@ +import { useContext } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + Button, + // @ts-ignore +} from '@carbon/react'; +import { ProcessModel } from '../interfaces'; +import HttpService from '../services/HttpService'; +import ErrorContext from '../contexts/ErrorContext'; +import { modifyProcessModelPath } from '../helpers'; + +type OwnProps = { + processModel: ProcessModel; + onSuccessCallback: Function; + className?: string; +}; + +export default function ProcessInstanceRun({ + processModel, + onSuccessCallback, + className, +}: OwnProps) { + const navigate = useNavigate(); + const setErrorMessage = (useContext as any)(ErrorContext)[1]; + const modifiedProcessModelId = modifyProcessModelPath(processModel.id); + + const onProcessInstanceRun = (processInstance: any) => { + // FIXME: ensure that the task is actually for the current user as well + const processInstanceId = (processInstance as any).id; + const nextTask = (processInstance as any).next_task; + if (nextTask && nextTask.state === 'READY') { + navigate(`/tasks/${processInstanceId}/${nextTask.id}`); + } + onSuccessCallback(processInstance); + }; + + const processModelRun = (processInstance: any) => { + setErrorMessage(null); + HttpService.makeCallToBackend({ + path: `/process-instances/${processInstance.id}/run`, + successCallback: onProcessInstanceRun, + failureCallback: setErrorMessage, + httpMethod: 'POST', + }); + }; + + const processInstanceCreateAndRun = () => { + HttpService.makeCallToBackend({ + path: `/process-models/${modifiedProcessModelId}/process-instances`, + successCallback: processModelRun, + httpMethod: 'POST', + }); + }; + + return ( + + ); +} diff --git a/spiffworkflow-frontend/src/components/ProcessModelForm.tsx b/spiffworkflow-frontend/src/components/ProcessModelForm.tsx index 10f4ffd3..532e3927 100644 --- a/spiffworkflow-frontend/src/components/ProcessModelForm.tsx +++ b/spiffworkflow-frontend/src/components/ProcessModelForm.tsx @@ -42,7 +42,7 @@ export default function ProcessModelForm({ const handleFormSubmission = (event: any) => { event.preventDefault(); let hasErrors = false; - if (!hasValidIdentifier(processModel.id)) { + if (mode === 'new' && !hasValidIdentifier(processModel.id)) { setIdentifierInvalid(true); hasErrors = true; } diff --git a/spiffworkflow-frontend/src/components/ProcessModelListTiles.tsx b/spiffworkflow-frontend/src/components/ProcessModelListTiles.tsx new file mode 100644 index 00000000..a10fd754 --- /dev/null +++ b/spiffworkflow-frontend/src/components/ProcessModelListTiles.tsx @@ -0,0 +1,105 @@ +import { ReactElement, useEffect, useState } from 'react'; +import { Link, useSearchParams } from 'react-router-dom'; +import { + Tile, + // @ts-ignore +} from '@carbon/react'; +import HttpService from '../services/HttpService'; +import { ProcessModel, ProcessInstance } from '../interfaces'; +import { modifyProcessModelPath, truncateString } from '../helpers'; +import ProcessInstanceRun from './ProcessInstanceRun'; + +type OwnProps = { + headerElement?: ReactElement; +}; + +export default function ProcessModelListTiles({ headerElement }: OwnProps) { + const [searchParams] = useSearchParams(); + const [processModels, setProcessModels] = useState( + null + ); + const [processInstance, setProcessInstance] = + useState(null); + + useEffect(() => { + const setProcessModelsFromResult = (result: any) => { + setProcessModels(result.results); + }; + // only allow 10 for now until we get the backend only returnin certain models for user execution + const queryParams = '?per_page=10'; + HttpService.makeCallToBackend({ + path: `/process-models${queryParams}`, + successCallback: setProcessModelsFromResult, + }); + }, [searchParams]); + + const processInstanceRunResultTag = () => { + if (processInstance) { + return ( +
+

+ Process Instance {processInstance.id} kicked off ( + + view + + ). +

+
+ ); + } + return null; + }; + + const processModelsDisplayArea = () => { + let displayText = null; + if (processModels && processModels.length > 0) { + displayText = (processModels || []).map((row: ProcessModel) => { + return ( + +
+
{row.display_name}
+

+ {truncateString(row.description || '', 25)} +

+ +
+
+ ); + }); + } else { + displayText =

No Models To Display

; + } + return displayText; + }; + + const processModelArea = () => { + if (processModels && processModels.length > 0) { + return ( + <> + {headerElement} + {processInstanceRunResultTag()} + {processModelsDisplayArea()} + + ); + } + return null; + }; + + if (processModels) { + return <>{processModelArea()}; + } + return null; +} diff --git a/spiffworkflow-frontend/src/index.css b/spiffworkflow-frontend/src/index.css index 3b803517..0d267086 100644 --- a/spiffworkflow-frontend/src/index.css +++ b/spiffworkflow-frontend/src/index.css @@ -215,7 +215,15 @@ in on this with the react-jsonschema-form repo. This is just a patch fix to allo order: 0; } -.tile-process-group-description { +.tile-title-top { + margin-bottom: 2em; + font-size: 20px; + line-height: 28px; + color: #161616; + order: 0; +} + +.tile-description { font-size: 14px; line-height: 20px; letter-spacing: 0.16px; @@ -229,6 +237,9 @@ in on this with the react-jsonschema-form repo. This is just a patch fix to allo letter-spacing: 0.16px; color: #161616; order: 1; +} + +.tile-pin-bottom { position: absolute; bottom: 1em; } diff --git a/spiffworkflow-frontend/src/interfaces.ts b/spiffworkflow-frontend/src/interfaces.ts index a9ac1ec0..aceca049 100644 --- a/spiffworkflow-frontend/src/interfaces.ts +++ b/spiffworkflow-frontend/src/interfaces.ts @@ -36,6 +36,11 @@ export interface ProcessFile { file_contents?: string; } +export interface ProcessInstance { + id: number; + process_model_identifier: string; +} + export interface ProcessModel { id: string; description: string; diff --git a/spiffworkflow-frontend/src/routes/CreateNewInstance.tsx b/spiffworkflow-frontend/src/routes/CreateNewInstance.tsx new file mode 100644 index 00000000..fbb3f844 --- /dev/null +++ b/spiffworkflow-frontend/src/routes/CreateNewInstance.tsx @@ -0,0 +1,9 @@ +import ProcessModelListTiles from '../components/ProcessModelListTiles'; + +export default function CreateNewInstance() { + return ( + Process models available to you} + /> + ); +} diff --git a/spiffworkflow-frontend/src/routes/HomePageRoutes.tsx b/spiffworkflow-frontend/src/routes/HomePageRoutes.tsx index 9f4bc698..99e535e5 100644 --- a/spiffworkflow-frontend/src/routes/HomePageRoutes.tsx +++ b/spiffworkflow-frontend/src/routes/HomePageRoutes.tsx @@ -7,6 +7,7 @@ import ErrorContext from '../contexts/ErrorContext'; import MyTasks from './MyTasks'; import GroupedTasks from './GroupedTasks'; import CompletedInstances from './CompletedInstances'; +import CreateNewInstance from './CreateNewInstance'; export default function HomePageRoutes() { const location = useLocation(); @@ -21,6 +22,8 @@ export default function HomePageRoutes() { newSelectedTabIndex = 1; } else if (location.pathname.match(/^\/tasks\/completed-instances\b/)) { newSelectedTabIndex = 2; + } else if (location.pathname.match(/^\/tasks\/create-new-instance\b/)) { + newSelectedTabIndex = 3; } setSelectedTabIndex(newSelectedTabIndex); }, [location, setErrorMessage]); @@ -34,6 +37,9 @@ export default function HomePageRoutes() { navigate('/tasks/completed-instances')}> Completed Instances + navigate('/tasks/create-new-instance')}> + Create New Instance + +
@@ -43,6 +49,7 @@ export default function HomePageRoutes() { } /> } /> } /> + } /> ); diff --git a/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx b/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx index 957a37e7..d154075a 100644 --- a/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx @@ -38,6 +38,7 @@ import { import { PermissionsToCheck, ProcessFile, + ProcessInstance, ProcessModel, RecentProcessModel, } from '../interfaces'; @@ -45,6 +46,7 @@ import ButtonWithConfirmation from '../components/ButtonWithConfirmation'; import ProcessInstanceListTable from '../components/ProcessInstanceListTable'; import { usePermissionFetcher } from '../hooks/PermissionService'; import { useUriListForPermissions } from '../hooks/UriListForPermissions'; +import ProcessInstanceRun from '../components/ProcessInstanceRun'; const storeRecentProcessModelInLocalStorage = ( processModelForStorage: ProcessModel @@ -100,7 +102,8 @@ export default function ProcessModelShow() { const setErrorMessage = (useContext as any)(ErrorContext)[1]; const [processModel, setProcessModel] = useState(null); - const [processInstanceResult, setProcessInstanceResult] = useState(null); + const [processInstance, setProcessInstance] = + useState(null); const [reloadModel, setReloadModel] = useState(false); const [filesToUpload, setFilesToUpload] = useState(null); const [showFileUploadModal, setShowFileUploadModal] = @@ -132,38 +135,14 @@ export default function ProcessModelShow() { }); }, [reloadModel, modifiedProcessModelId]); - const processModelRun = (processInstance: any) => { - setErrorMessage(null); - HttpService.makeCallToBackend({ - path: `/process-instances/${processInstance.id}/run`, - successCallback: setProcessInstanceResult, - failureCallback: setErrorMessage, - httpMethod: 'POST', - }); - }; - - const processInstanceCreateAndRun = () => { - HttpService.makeCallToBackend({ - path: `/process-models/${modifiedProcessModelId}/process-instances`, - successCallback: processModelRun, - httpMethod: 'POST', - }); - }; - const processInstanceRunResultTag = () => { - if (processModel && processInstanceResult) { - // FIXME: ensure that the task is actually for the current user as well - const processInstanceId = (processInstanceResult as any).id; - const nextTask = (processInstanceResult as any).next_task; - if (nextTask && nextTask.state === 'READY') { - navigate(`/tasks/${processInstanceId}/${nextTask.id}`); - } + if (processInstance) { return (

- Process Instance {processInstanceId} kicked off ( + Process Instance {processInstance.id} kicked off ( view @@ -572,9 +551,10 @@ export default function ProcessModelShow() { a={targetUris.processInstanceActionPath} ability={ability} > - +