From 2c99e17381756849ab6bdcedd7a7b01b55aaa302 Mon Sep 17 00:00:00 2001 From: jbirddog <100367399+jbirddog@users.noreply.github.com> Date: Fri, 23 Jun 2023 02:15:23 -0400 Subject: [PATCH] Show callers for non primary files (#334) * WIP - working with multiple process ids, need to return a file's process ids * Send bpmn process ids back with bpmn files * Getting ./bin/pyl to pass * Fix up unit test * Wire up the front end * Pre pr cleanup --- .../src/spiffworkflow_backend/api.yml | 13 ++++++++----- .../src/spiffworkflow_backend/models/file.py | 1 + .../routes/process_api_blueprint.py | 4 ++-- .../routes/process_models_controller.py | 5 +++++ .../services/process_caller_service.py | 6 +++--- .../services/spec_file_service.py | 6 ++++++ .../integration/test_process_api.py | 2 +- .../unit/test_process_caller_service.py | 10 +++++----- spiffworkflow-frontend/src/interfaces.ts | 1 + .../src/routes/ProcessModelEditDiagram.tsx | 5 +++-- 10 files changed, 35 insertions(+), 18 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index 90429e8d..ab945726 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -633,14 +633,17 @@ paths: schema: type: string - /processes/callers: + /processes/callers/{bpmn_process_identifiers}: parameters: - - name: bpmn_process_identifier - in: query + - name: bpmn_process_identifiers + in: path required: true - description: the bpmn process identifier/id (not the name with spaces and not the process model identifier) + description: the bpmn process identifiers/ids (not the names with spaces and not the process model identifiers) schema: - type: string + type: array + items: + type: string + minItems: 1 get: operationId: spiffworkflow_backend.routes.process_api_blueprint.process_caller_list summary: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py index 15fb717a..40db8502 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py @@ -70,6 +70,7 @@ class File: references: list[SpecReference] | None = None file_contents: bytes | None = None process_model_id: str | None = None + bpmn_process_ids: list[str] | None = None file_contents_hash: str | None = None def __post_init__(self) -> None: 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 51fbb8fc..ec1eef35 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -68,8 +68,8 @@ def process_list() -> Any: return SpecReferenceSchema(many=True).dump(references) -def process_caller_list(bpmn_process_identifier: str) -> Any: - callers = ProcessCallerService.callers(bpmn_process_identifier) +def process_caller_list(bpmn_process_identifiers: list[str]) -> Any: + callers = ProcessCallerService.callers(bpmn_process_identifiers) references = ( SpecReferenceCache.query.filter_by(type="process").filter(SpecReferenceCache.identifier.in_(callers)).all() ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py index 8c86dae9..3693c608 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_models_controller.py @@ -16,6 +16,7 @@ from werkzeug.datastructures import FileStorage from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.interfaces import IdToProcessGroupMapping +from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_instance_report import ProcessInstanceReportModel from spiffworkflow_backend.models.process_model import ProcessModelInfo @@ -290,6 +291,10 @@ def process_model_file_show(modified_process_model_identifier: str, file_name: s file_contents_hash = sha256(file_contents).hexdigest() file.file_contents_hash = file_contents_hash file.process_model_id = process_model.id + + if file.type == FileType.bpmn.value: + file.bpmn_process_ids = SpecFileService.get_bpmn_process_ids_for_file_contents(file_contents) + return make_response(jsonify(file), 200) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_caller_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_caller_service.py index 31b96030..bdbbb06b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_caller_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_caller_service.py @@ -30,10 +30,10 @@ class ProcessCallerService: db.session.commit() @staticmethod - def callers(process_id: str) -> list[str]: + def callers(process_ids: list[str]) -> list[str]: records = ( db.session.query(ProcessCallerCacheModel) - .filter(ProcessCallerCacheModel.process_identifier == process_id) + .filter(ProcessCallerCacheModel.process_identifier.in_(process_ids)) .all() ) - return list({r.calling_process_identifier for r in records}) + return sorted({r.calling_process_identifier for r in records}) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py index 8f9720fc..1cc4cbb0 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py @@ -77,6 +77,12 @@ class SpecFileService(FileSystemService): etree_xml_parser = etree.XMLParser(resolve_entities=False) return etree.fromstring(binary_data, parser=etree_xml_parser) # noqa: S320 + @classmethod + def get_bpmn_process_ids_for_file_contents(cls, binary_data: bytes) -> list[str]: + parser = MyCustomParser() + parser.add_bpmn_xml(cls.get_etree_from_xml_bytes(binary_data)) + return list(parser.process_parsers.keys()) + @classmethod def get_references_for_file_contents( cls, process_model_info: ProcessModelInfo, file_name: str, binary_data: bytes 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 e60e2a59..18b313bc 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -565,7 +565,7 @@ class TestProcessApi(BaseTest): # get the results response = client.get( - "/v1.0/processes/callers?bpmn_process_identifier=Level2", + "/v1.0/processes/callers/Level2", headers=self.logged_in_headers(with_super_admin_user), ) assert response.json is not None diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_caller_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_caller_service.py index e5853de5..3afa6455 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_caller_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_caller_service.py @@ -110,19 +110,19 @@ class TestProcessCallerService(BaseTest): assert ProcessCallerService.count() == 2 def test_can_return_no_callers_when_no_records(self, with_no_process_callers: None) -> None: - assert ProcessCallerService.callers("bob") == [] + assert ProcessCallerService.callers(["bob"]) == [] def test_can_return_no_callers_when_process_id_is_unknown(self, with_multiple_process_callers: None) -> None: - assert ProcessCallerService.callers("bob") == [] + assert ProcessCallerService.callers(["bob"]) == [] def test_can_return_single_caller(self, with_single_process_caller: None) -> None: - assert ProcessCallerService.callers("called_once") == ["one_caller"] + assert ProcessCallerService.callers(["called_once"]) == ["one_caller"] def test_can_return_mulitple_callers(self, with_multiple_process_callers: None) -> None: - callers = sorted(ProcessCallerService.callers("called_many")) + callers = sorted(ProcessCallerService.callers(["called_many"])) assert callers == ["one_caller", "three_caller", "two_caller"] def test_can_return_single_caller_when_there_are_other_process_ids( self, with_single_process_caller: None, with_multiple_process_callers: None ) -> None: - assert ProcessCallerService.callers("called_once") == ["one_caller"] + assert ProcessCallerService.callers(["called_once"]) == ["one_caller"] diff --git a/spiffworkflow-frontend/src/interfaces.ts b/spiffworkflow-frontend/src/interfaces.ts index 139a0107..09aafbb2 100644 --- a/spiffworkflow-frontend/src/interfaces.ts +++ b/spiffworkflow-frontend/src/interfaces.ts @@ -124,6 +124,7 @@ export interface ProcessFile { type: string; file_contents?: string; file_contents_hash?: string; + bpmn_process_ids?: string[]; } export interface ProcessInstanceMetadata { diff --git a/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx b/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx index 76412163..fdd5dd4a 100644 --- a/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx @@ -171,9 +171,10 @@ export default function ProcessModelEditDiagram() { }, [processModelPath, params]); useEffect(() => { - if (processModel !== null) { + const bpmn_process_ids = processModelFile?.bpmn_process_ids; + if (processModel !== null && bpmn_process_ids) { HttpService.makeCallToBackend({ - path: `/processes/callers?bpmn_process_identifier=${processModel.primary_process_id}`, + path: `/processes/callers/${bpmn_process_ids.join(',')}`, successCallback: setCallers, }); }