diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index 9e075600..3e9f54eb 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -75,6 +75,10 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): ) # type: ignore message_instances = relationship("MessageInstanceModel", cascade="delete") # type: ignore message_correlations = relationship("MessageCorrelationModel", cascade="delete") # type: ignore + process_metadata = relationship( + "ProcessInstanceMetadataModel", + cascade="delete", + ) # type: ignore bpmn_json: str | None = deferred(db.Column(db.JSON)) # type: ignore start_in_seconds: int | None = db.Column(db.Integer) @@ -111,6 +115,11 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): "process_initiator_username": self.process_initiator.username, } + def serialized_with_metadata(self) -> dict[str, Any]: + process_instance_attributes = self.serialized + process_instance_attributes["process_metadata"] = self.process_metadata + return process_instance_attributes + @property def serialized_flat(self) -> dict: """Return object in serializeable format with data merged together with top-level attributes. diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py index 1271f929..f4601a0a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py @@ -682,7 +682,8 @@ def _get_process_instance( ) process_instance.bpmn_xml_file_contents = bpmn_xml_file_contents - return make_response(jsonify(process_instance), 200) + process_instance_as_dict = process_instance.serialized_with_metadata() + return make_response(jsonify(process_instance_as_dict), 200) def _find_process_instance_for_me_or_raise( diff --git a/spiffworkflow-frontend/src/interfaces.ts b/spiffworkflow-frontend/src/interfaces.ts index f2d2d0a6..990d3bbd 100644 --- a/spiffworkflow-frontend/src/interfaces.ts +++ b/spiffworkflow-frontend/src/interfaces.ts @@ -66,6 +66,12 @@ export interface ProcessFile { file_contents?: string; } +export interface ProcessInstanceMetadata { + id: number; + key: string; + value: string; +} + export interface ProcessInstance { id: number; process_model_identifier: string; @@ -80,6 +86,7 @@ export interface ProcessInstance { updated_at_in_seconds: number; bpmn_version_control_identifier: string; bpmn_version_control_type: string; + process_metadata?: ProcessInstanceMetadata[]; } export interface MessageCorrelationProperties { diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx index 279322a6..9b6f1492 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx @@ -1,4 +1,9 @@ -import { useContext, useEffect, useState } from 'react'; +import React, { + ReactComponentElement, + useContext, + useEffect, + useState, +} from 'react'; import Editor from '@monaco-editor/react'; import { useParams, @@ -44,6 +49,7 @@ import { PermissionsToCheck, ProcessData, ProcessInstance, + ProcessInstanceMetadata, ProcessInstanceTask, } from '../interfaces'; import { usePermissionFetcher } from '../hooks/PermissionService'; @@ -161,6 +167,11 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { variant, ]); + // useEffect(() => { + // setTimeout(() => setDisplayDetails(!displayDetails), 1 * 2000); + // // setTimeout(() => setDisplayDetails(false), 1 * 6000); + // }, [displayDetails]); + const deleteProcessInstance = () => { HttpService.makeCallToBackend({ path: targetUris.processInstanceActionPath, @@ -284,6 +295,38 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { }); }; + const processMetadataDisplayArea = () => { + if ( + !processInstance || + (processInstance.process_metadata && + processInstance.process_metadata.length < 1) + ) { + return null; + } + const metadataComponents: any[] = []; + (processInstance.process_metadata || []).forEach( + (processInstanceMetadata: ProcessInstanceMetadata) => { + metadataComponents.push( + + + {processInstanceMetadata.key} + + + {processInstanceMetadata.value} + + + ); + } + ); + return ( + <> +
+ {metadataComponents} + + ); + // return metadataComponents; + }; + const detailedViewElement = () => { if (!processInstance) { return null; @@ -331,6 +374,15 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { {processInstance.bpmn_version_control_type}) + + + Process model revision:{' '} + + + {processInstance.bpmn_version_control_identifier} ( + {processInstance.bpmn_version_control_type}) + + ); } @@ -348,6 +400,68 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { ); }; + let deets: any = null; + if (processInstance) { + if (displayDetails) { + deets = ( + <> + + + + + + Updated At:{' '} + + + {convertSecondsToFormattedDateTime( + processInstance.updated_at_in_seconds + )} + + + + + Created At:{' '} + + + {convertSecondsToFormattedDateTime( + processInstance.created_at_in_seconds + )} + + + + + Process model revision:{' '} + + + {processInstance.bpmn_version_control_identifier} ( + {processInstance.bpmn_version_control_type}) + + + + ); + } else { + deets = ( + + + + ); + } + } + const getInfoTag = () => { if (!processInstance) { return null; @@ -382,8 +496,11 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { statusIcon = ; } + const details = detailedViewElement(); + return ( <> + {/* Started By:{' '} @@ -403,6 +520,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { {currentEndDateTag} + */} Status:{' '} @@ -413,8 +531,11 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { - {detailedViewElement()} + {/* detailedViewElement() */} + {deets} + {/*
+ */} @@ -1002,6 +1123,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { [`Process Instance Id: ${processInstance.id}`], ]} /> + {/*

Process Instance Id: {processInstance.id} @@ -1030,12 +1152,8 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { /> + */} {getInfoTag()} -
- {taskUpdateDisplayArea()} - {processDataDisplayArea()} - {stepsElement()} -
+ {/*
*/} + {/* {stepsElement()} */} + {/*
*/} + {taskUpdateDisplayArea()} + {processDataDisplayArea()}
);