From abffccedbd17f09d49a048f4003bf0f35408d6e5 Mon Sep 17 00:00:00 2001 From: jasquat Date: Wed, 30 Nov 2022 15:08:04 -0500 Subject: [PATCH] added correlations to message list table w/ burnettk --- spiffworkflow-backend/migrations/env.py | 2 - spiffworkflow-backend/poetry.lock | 19 +--- .../routes/process_api_blueprint.py | 7 +- .../process_instance_report_service.py | 1 + .../integration/test_process_api.py | 17 +++- .../src/components/MiniComponents.tsx | 22 +++++ .../components/ProcessInstanceListTable.tsx | 19 +--- spiffworkflow-frontend/src/index.css | 14 +++ spiffworkflow-frontend/src/interfaces.ts | 22 +++++ .../src/routes/MessageInstanceList.tsx | 92 ++++++++++++------- 10 files changed, 145 insertions(+), 70 deletions(-) create mode 100644 spiffworkflow-frontend/src/components/MiniComponents.tsx diff --git a/spiffworkflow-backend/migrations/env.py b/spiffworkflow-backend/migrations/env.py index 68feded2..630e381a 100644 --- a/spiffworkflow-backend/migrations/env.py +++ b/spiffworkflow-backend/migrations/env.py @@ -1,5 +1,3 @@ -from __future__ import with_statement - import logging from logging.config import fileConfig diff --git a/spiffworkflow-backend/poetry.lock b/spiffworkflow-backend/poetry.lock index 8484cdb4..ac024241 100644 --- a/spiffworkflow-backend/poetry.lock +++ b/spiffworkflow-backend/poetry.lock @@ -1851,7 +1851,7 @@ lxml = "*" type = "git" url = "https://github.com/sartography/SpiffWorkflow" reference = "main" -resolved_reference = "46f410a2852baeedc8f9ac5165347ce6d4470594" +resolved_reference = "bba7ddf5478af579b891ca63c50babbfccf6b7a4" [[package]] name = "SQLAlchemy" @@ -2563,7 +2563,6 @@ greenlet = [ {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000"}, {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2"}, - {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9"}, {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1"}, {file = "greenlet-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1"}, {file = "greenlet-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23"}, @@ -2572,7 +2571,6 @@ greenlet = [ {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48"}, {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764"}, - {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0"}, {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9"}, {file = "greenlet-2.0.1-cp38-cp38-win32.whl", hash = "sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608"}, {file = "greenlet-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6"}, @@ -2581,7 +2579,6 @@ greenlet = [ {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7"}, {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d"}, - {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726"}, {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e"}, {file = "greenlet-2.0.1-cp39-cp39-win32.whl", hash = "sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a"}, {file = "greenlet-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6"}, @@ -2880,7 +2877,10 @@ orjson = [ {file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b68a42a31f8429728183c21fb440c21de1b62e5378d0d73f280e2d894ef8942e"}, {file = "orjson-3.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ff13410ddbdda5d4197a4a4c09969cb78c722a67550f0a63c02c07aadc624833"}, {file = "orjson-3.8.0-cp310-none-win_amd64.whl", hash = "sha256:2d81e6e56bbea44be0222fb53f7b255b4e7426290516771592738ca01dbd053b"}, + {file = "orjson-3.8.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:200eae21c33f1f8b02a11f5d88d76950cd6fd986d88f1afe497a8ae2627c49aa"}, + {file = "orjson-3.8.0-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9529990f3eab54b976d327360aa1ff244a4b12cb5e4c5b3712fcdd96e8fe56d4"}, {file = "orjson-3.8.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e2defd9527651ad39ec20ae03c812adf47ef7662bdd6bc07dabb10888d70dc62"}, + {file = "orjson-3.8.0-cp311-none-win_amd64.whl", hash = "sha256:b21c7af0ff6228ca7105f54f0800636eb49201133e15ddb80ac20c1ce973ef07"}, {file = "orjson-3.8.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9e6ac22cec72d5b39035b566e4b86c74b84866f12b5b0b6541506a080fb67d6d"}, {file = "orjson-3.8.0-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e2f4a5542f50e3d336a18cb224fc757245ca66b1fd0b70b5dd4471b8ff5f2b0e"}, {file = "orjson-3.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1418feeb8b698b9224b1f024555895169d481604d5d884498c1838d7412794c"}, @@ -2989,18 +2989,7 @@ psycopg2 = [ {file = "psycopg2-2.9.4.tar.gz", hash = "sha256:d529926254e093a1b669f692a3aa50069bc71faf5b0ecd91686a78f62767d52f"}, ] pyasn1 = [ - {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"}, - {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"}, - {file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"}, - {file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"}, {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, - {file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"}, - {file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"}, - {file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"}, - {file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"}, - {file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"}, - {file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"}, - {file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"}, {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, ] pycodestyle = [ diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py index b96cc262..46067031 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -647,6 +647,7 @@ def message_instance_list( .add_columns( MessageModel.identifier.label("message_identifier"), ProcessInstanceModel.process_model_identifier, + ProcessInstanceModel.process_model_display_name, ) .paginate(page=page, per_page=per_page, error_out=False) ) @@ -978,10 +979,12 @@ def process_instance_list( def process_instance_report_column_list() -> flask.wrappers.Response: - + """Process_instance_report_column_list.""" table_columns = ProcessInstanceReportService.builtin_column_options() columns_for_metadata = db.session.query(ProcessInstanceMetadataModel.key).distinct().all() # type: ignore - columns_for_metadata_strings = [{ 'Header': i[0], 'accessor': i[0]} for i in columns_for_metadata] + columns_for_metadata_strings = [ + {"Header": i[0], "accessor": i[0]} for i in columns_for_metadata + ] # columns = sorted(table_columns + columns_for_metadata_strings) return make_response(jsonify(table_columns + columns_for_metadata_strings), 200) 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 da70f0c0..bd3a2e08 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 @@ -271,6 +271,7 @@ class ProcessInstanceReportService: @classmethod def builtin_column_options(cls) -> list[dict]: + """Builtin_column_options.""" return [ {"Header": "id", "accessor": "id"}, { 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 beef3b74..215e44d4 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -2630,11 +2630,22 @@ class TestProcessApi(BaseTest): assert len(process_instance_metadata) == 2 response = client.get( - f"/v1.0/process-instances/reports/columns", + "/v1.0/process-instances/reports/columns", headers=self.logged_in_headers(with_super_admin_user), ) assert response.json is not None assert response.status_code == 200 - assert response.json == [{'Header': 'id', 'accessor': 'id'}, {'Header': 'process_model_display_name', 'accessor': 'process_model_display_name'}, {'Header': 'start_in_seconds', 'accessor': 'start_in_seconds'}, {'Header': 'end_in_seconds', 'accessor': 'end_in_seconds'}, {'Header': 'username', 'accessor': 'username'}, {'Header': 'status', 'accessor': 'status'}, {'Header': 'key1', 'accessor': 'key1'}, {'Header': 'key2', 'accessor': 'key2'}] - + assert response.json == [ + {"Header": "id", "accessor": "id"}, + { + "Header": "process_model_display_name", + "accessor": "process_model_display_name", + }, + {"Header": "start_in_seconds", "accessor": "start_in_seconds"}, + {"Header": "end_in_seconds", "accessor": "end_in_seconds"}, + {"Header": "username", "accessor": "username"}, + {"Header": "status", "accessor": "status"}, + {"Header": "key1", "accessor": "key1"}, + {"Header": "key2", "accessor": "key2"}, + ] diff --git a/spiffworkflow-frontend/src/components/MiniComponents.tsx b/spiffworkflow-frontend/src/components/MiniComponents.tsx new file mode 100644 index 00000000..6f0a1293 --- /dev/null +++ b/spiffworkflow-frontend/src/components/MiniComponents.tsx @@ -0,0 +1,22 @@ +import { Link } from 'react-router-dom'; +import { modifyProcessIdentifierForPathParam } from '../helpers'; +import { MessageInstance, ProcessInstance } from '../interfaces'; + +export function FormatProcessModelDisplayName( + instanceObject: ProcessInstance | MessageInstance +) { + const { + process_model_identifier: processModelIdentifier, + process_model_display_name: processModelDisplayName, + } = instanceObject; + return ( + + {processModelDisplayName} + + ); +} diff --git a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx index 9b239502..50b69c0b 100644 --- a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx +++ b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx @@ -53,6 +53,7 @@ import { import ProcessModelSearch from './ProcessModelSearch'; import ProcessInstanceReportSearch from './ProcessInstanceReportSearch'; import ProcessInstanceListSaveAsReport from './ProcessInstanceListSaveAsReport'; +import { FormatProcessModelDisplayName } from './MiniComponents'; const REFRESH_INTERVAL = 5; const REFRESH_TIMEOUT = 600; @@ -693,22 +694,6 @@ export default function ProcessInstanceListTable({ ); }; - const formatProcessModelDisplayName = ( - row: ProcessInstance, - displayName: string - ) => { - return ( - - {displayName} - - ); - }; - const formatSecondsForDisplay = (_row: any, seconds: any) => { return convertSecondsToFormattedDateTime(seconds) || '-'; }; @@ -719,7 +704,7 @@ export default function ProcessInstanceListTable({ const columnFormatters: Record = { id: formatProcessInstanceId, process_model_identifier: formatProcessModelIdentifier, - process_model_display_name: formatProcessModelDisplayName, + process_model_display_name: FormatProcessModelDisplayName, start_in_seconds: formatSecondsForDisplay, end_in_seconds: formatSecondsForDisplay, }; diff --git a/spiffworkflow-frontend/src/index.css b/spiffworkflow-frontend/src/index.css index 4723e557..53e04b78 100644 --- a/spiffworkflow-frontend/src/index.css +++ b/spiffworkflow-frontend/src/index.css @@ -69,6 +69,20 @@ h2 { color: black; } +/* match normal link colors */ +.cds--btn--ghost.button-link { + color: #0062fe; +} +.cds--btn--ghost.button-link:visited { + color: #0062fe; +} +.cds--btn--ghost.button-link:hover { + color: #0062fe; +} +.cds--btn--ghost.button-link:visited:hover { + color: #0062fe; +} + .cds--header__global .cds--btn--primary { background-color: #161616 } diff --git a/spiffworkflow-frontend/src/interfaces.ts b/spiffworkflow-frontend/src/interfaces.ts index 42ba5335..66759dfe 100644 --- a/spiffworkflow-frontend/src/interfaces.ts +++ b/spiffworkflow-frontend/src/interfaces.ts @@ -39,6 +39,28 @@ export interface ProcessFile { export interface ProcessInstance { id: number; process_model_identifier: string; + process_model_display_name: string; +} + +export interface MessageCorrelationProperties { + [key: string]: string; +} + +export interface MessageCorrelations { + [key: string]: MessageCorrelationProperties; +} + +export interface MessageInstance { + id: number; + process_model_identifier: string; + process_model_display_name: string; + process_instance_id: number; + message_identifier: string; + message_type: string; + failure_cause: string; + status: string; + created_at_in_seconds: number; + message_correlations?: MessageCorrelations; } export interface ProcessInstanceReport { diff --git a/spiffworkflow-frontend/src/routes/MessageInstanceList.tsx b/spiffworkflow-frontend/src/routes/MessageInstanceList.tsx index f1478058..5a2d4e1a 100644 --- a/spiffworkflow-frontend/src/routes/MessageInstanceList.tsx +++ b/spiffworkflow-frontend/src/routes/MessageInstanceList.tsx @@ -1,15 +1,17 @@ import { useEffect, useState } from 'react'; // @ts-ignore -import { Table } from '@carbon/react'; +import { Table, Modal, Button } from '@carbon/react'; import { Link, useParams, useSearchParams } from 'react-router-dom'; import PaginationForTable from '../components/PaginationForTable'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import { - convertSecondsToFormattedDateString, + convertSecondsToFormattedDateTime, getPageInfoFromSearchParams, modifyProcessIdentifierForPathParam, } from '../helpers'; import HttpService from '../services/HttpService'; +import { FormatProcessModelDisplayName } from '../components/MiniComponents'; +import { MessageInstance } from '../interfaces'; export default function MessageInstanceList() { const params = useParams(); @@ -17,6 +19,9 @@ export default function MessageInstanceList() { const [messageIntances, setMessageInstances] = useState([]); const [pagination, setPagination] = useState(null); + const [messageInstanceForModal, setMessageInstanceForModal] = + useState(null); + useEffect(() => { const setMessageInstanceListFromResult = (result: any) => { setMessageInstances(result.results); @@ -35,41 +40,64 @@ export default function MessageInstanceList() { }); }, [searchParams, params]); - const buildTable = () => { - // return null; - const rows = messageIntances.map((row) => { - const rowToUse = row as any; + const handleCorrelationDisplayClose = () => { + setMessageInstanceForModal(null); + }; + + const correlationsDisplayModal = () => { + if (messageInstanceForModal) { return ( - - {rowToUse.id} - - - {rowToUse.process_model_identifier} - - + +
+            {JSON.stringify(
+              messageInstanceForModal.message_correlations,
+              null,
+              2
+            )}
+          
+
+ ); + } + return null; + }; + + const buildTable = () => { + const rows = messageIntances.map((row: MessageInstance) => { + return ( + + {row.id} + {FormatProcessModelDisplayName(row)} - {rowToUse.process_instance_id} + {row.process_instance_id} - {rowToUse.message_identifier} - {rowToUse.message_type} - {rowToUse.failure_cause || '-'} - {rowToUse.status} + {row.message_identifier} + {row.message_type} + {row.failure_cause || '-'} - {convertSecondsToFormattedDateString( - rowToUse.created_at_in_seconds - )} + + + {row.status} + + {convertSecondsToFormattedDateTime(row.created_at_in_seconds)} ); @@ -78,12 +106,13 @@ export default function MessageInstanceList() { - - + + - + + @@ -121,6 +150,7 @@ export default function MessageInstanceList() { <> {breadcrumbElement}

Messages

+ {correlationsDisplayModal()}
Instance IdProcess ModelIdProcess Process InstanceMessage ModelName Type Failure CauseCorrelations Status Created At