diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index 31912c30..42a90364 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -98,12 +98,14 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): "status": self.status, "start_in_seconds": self.start_in_seconds, "end_in_seconds": self.end_in_seconds, + "created_at_in_seconds": self.created_at_in_seconds, + "updated_at_in_seconds": self.updated_at_in_seconds, "process_initiator_id": self.process_initiator_id, "bpmn_xml_file_contents": self.bpmn_xml_file_contents, "bpmn_version_control_identifier": self.bpmn_version_control_identifier, "bpmn_version_control_type": self.bpmn_version_control_type, "spiff_step": self.spiff_step, - "username": self.process_initiator.username, + "process_initiator_username": self.process_initiator.username, } @property diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py index e461def9..5a3aa53d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py @@ -178,20 +178,32 @@ def set_new_access_token_in_cookie( It will also delete the cookies if the user has logged out. """ tld = current_app.config["THREAD_LOCAL_DATA"] - domain_for_frontend_cookie: Optional[str] = re.sub(r"^https?:\/\/", '', current_app.config['SPIFFWORKFLOW_FRONTEND_URL']) - if domain_for_frontend_cookie and domain_for_frontend_cookie.startswith('localhost'): + domain_for_frontend_cookie: Optional[str] = re.sub( + r"^https?:\/\/", "", current_app.config["SPIFFWORKFLOW_FRONTEND_URL"] + ) + if domain_for_frontend_cookie and domain_for_frontend_cookie.startswith( + "localhost" + ): domain_for_frontend_cookie = None if hasattr(tld, "new_access_token") and tld.new_access_token: - response.set_cookie("access_token", tld.new_access_token, domain=domain_for_frontend_cookie) + response.set_cookie( + "access_token", tld.new_access_token, domain=domain_for_frontend_cookie + ) # id_token is required for logging out since this gets passed back to the openid server if hasattr(tld, "new_id_token") and tld.new_id_token: - response.set_cookie("id_token", tld.new_id_token, domain=domain_for_frontend_cookie) + response.set_cookie( + "id_token", tld.new_id_token, domain=domain_for_frontend_cookie + ) if hasattr(tld, "user_has_logged_out") and tld.user_has_logged_out: - response.set_cookie("id_token", "", max_age=0, domain=domain_for_frontend_cookie) - response.set_cookie("access_token", "", max_age=0, domain=domain_for_frontend_cookie) + response.set_cookie( + "id_token", "", max_age=0, domain=domain_for_frontend_cookie + ) + response.set_cookie( + "access_token", "", max_age=0, domain=domain_for_frontend_cookie + ) _clear_auth_tokens_from_thread_local_data() diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py index a4b6a9b1..0b75ea61 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py @@ -338,7 +338,11 @@ class ProcessInstanceReportService: }, {"Header": "Start", "accessor": "start_in_seconds", "filterable": False}, {"Header": "End", "accessor": "end_in_seconds", "filterable": False}, - {"Header": "Username", "accessor": "username", "filterable": False}, + { + "Header": "Started By", + "accessor": "process_initiator_username", + "filterable": False, + }, {"Header": "Status", "accessor": "status", "filterable": False}, ] diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py index 150d033f..83ca22b7 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -232,7 +232,7 @@ class TestProcessApi(BaseTest): "process_model_display_name", "start_in_seconds", "end_in_seconds", - "username", + "process_initiator_username", "status", "summary", "description", @@ -3145,7 +3145,7 @@ class TestProcessApi(BaseTest): assert response.json["pagination"]["pages"] == 1 assert response.json["pagination"]["total"] == 1 - def test_can_get_process_instance_list_with_report_metadata_and_process_initator( + def test_can_get_process_instance_list_with_report_metadata_and_process_initiator( self, app: Flask, client: FlaskClient, @@ -3223,8 +3223,14 @@ class TestProcessApi(BaseTest): assert response.json is not None assert response.status_code == 200 assert len(response.json["results"]) == 2 - assert response.json["results"][0]["username"] == user_one.username - assert response.json["results"][1]["username"] == user_one.username + assert ( + response.json["results"][0]["process_initiator_username"] + == user_one.username + ) + assert ( + response.json["results"][1]["process_initiator_username"] + == user_one.username + ) response = client.get( f"/v1.0/process-instances?report_identifier={process_instance_report_dne.identifier}", @@ -3276,7 +3282,11 @@ class TestProcessApi(BaseTest): }, {"Header": "Start", "accessor": "start_in_seconds", "filterable": False}, {"Header": "End", "accessor": "end_in_seconds", "filterable": False}, - {"Header": "Username", "accessor": "username", "filterable": False}, + { + "Header": "Started By", + "accessor": "process_initiator_username", + "filterable": False, + }, {"Header": "Status", "accessor": "status", "filterable": False}, {"Header": "key1", "accessor": "key1", "filterable": True}, {"Header": "key2", "accessor": "key2", "filterable": True}, diff --git a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx index b161d58d..02a6395f 100644 --- a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx +++ b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx @@ -1171,7 +1171,7 @@ export default function ProcessInstanceListTable({ start_in_seconds: 'Start Time', end_in_seconds: 'End Time', status: 'Status', - username: 'Started By', + process_initiator_username: 'Started By', spiff_step: 'SpiffWorkflow Step', }; const getHeaderLabel = (header: string) => { diff --git a/spiffworkflow-frontend/src/interfaces.ts b/spiffworkflow-frontend/src/interfaces.ts index 97ef763c..5025855b 100644 --- a/spiffworkflow-frontend/src/interfaces.ts +++ b/spiffworkflow-frontend/src/interfaces.ts @@ -73,8 +73,13 @@ export interface ProcessInstance { status: string; start_in_seconds: number | null; end_in_seconds: number | null; + process_initiator_username: string; bpmn_xml_file_contents?: string; spiff_step?: number; + created_at_in_seconds: number; + updated_at_in_seconds: number; + bpmn_version_control_identifier: string; + bpmn_version_control_type: string; } export interface MessageCorrelationProperties { diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx index b32e16fc..a812248a 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx @@ -7,12 +7,12 @@ import { useSearchParams, } from 'react-router-dom'; import { + CaretRight, TrashCan, StopOutline, PauseOutline, PlayOutline, CaretLeft, - CaretRight, InProgress, Checkmark, Warning, @@ -72,6 +72,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { const [eventPayload, setEventPayload] = useState('{}'); const [eventTextEditorEnabled, setEventTextEditorEnabled] = useState(false); + const [displayDetails, setDisplayDetails] = useState(false); const setErrorObject = (useContext as any)(ErrorContext)[1]; @@ -280,6 +281,70 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { }); }; + const detailedViewElement = () => { + if (!processInstance) { + return null; + } + + if (displayDetails) { + return ( + <> + + + + + + 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}) + + + + ); + } + return ( + + + + ); + }; + const getInfoTag = () => { if (!processInstance) { return null; @@ -316,6 +381,14 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { return ( <> + + + Started By:{' '} + + + {processInstance.process_initiator_username} + + Started:{' '} @@ -337,6 +410,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { + {detailedViewElement()}