From 92b97a57b8a04056e2ed81a462e0d6e3f40bc9d5 Mon Sep 17 00:00:00 2001 From: jasquat Date: Fri, 11 Nov 2022 11:25:20 -0500 Subject: [PATCH 01/17] attempt to run pre-commit in own action w/ burnettk jbirddog --- .github/workflows/backend_tests.yml | 76 ++++++++++++++++++++--------- bin/run_pre_commit_in_ci | 10 ++++ 2 files changed, 62 insertions(+), 24 deletions(-) create mode 100755 bin/run_pre_commit_in_ci diff --git a/.github/workflows/backend_tests.yml b/.github/workflows/backend_tests.yml index 156db1eba..816667a03 100644 --- a/.github/workflows/backend_tests.yml +++ b/.github/workflows/backend_tests.yml @@ -16,7 +16,6 @@ jobs: fail-fast: false matrix: include: - - { python: "3.11", os: "ubuntu-latest", session: "pre-commit" } - { python: "3.11", os: "ubuntu-latest", session: "safety" } - { python: "3.11", os: "ubuntu-latest", session: "mypy" } - { @@ -97,29 +96,29 @@ jobs: pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry nox --version - - name: Compute pre-commit cache key - if: matrix.session == 'pre-commit' - id: pre-commit-cache - shell: python - run: | - import hashlib - import sys - - python = "py{}.{}".format(*sys.version_info[:2]) - payload = sys.version.encode() + sys.executable.encode() - digest = hashlib.sha256(payload).hexdigest() - result = "${{ runner.os }}-{}-{}-pre-commit".format(python, digest[:8]) - - print("::set-output name=result::{}".format(result)) - - - name: Restore pre-commit cache - uses: actions/cache@v3.0.11 - if: matrix.session == 'pre-commit' - with: - path: ~/.cache/pre-commit - key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }} - restore-keys: | - ${{ steps.pre-commit-cache.outputs.result }}- + # - name: Compute pre-commit cache key + # if: matrix.session == 'pre-commit' + # id: pre-commit-cache + # shell: python + # run: | + # import hashlib + # import sys + # + # python = "py{}.{}".format(*sys.version_info[:2]) + # payload = sys.version.encode() + sys.executable.encode() + # digest = hashlib.sha256(payload).hexdigest() + # result = "${{ runner.os }}-{}-{}-pre-commit".format(python, digest[:8]) + # + # print("::set-output name=result::{}".format(result)) + # + # - name: Restore pre-commit cache + # uses: actions/cache@v3.0.11 + # if: matrix.session == 'pre-commit' + # with: + # path: ~/.cache/pre-commit + # key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }} + # restore-keys: | + # ${{ steps.pre-commit-cache.outputs.result }}- - name: Setup Mysql uses: mirromutth/mysql-action@v1.1 with: @@ -160,6 +159,35 @@ jobs: name: logs-${{matrix.python}}-${{matrix.os}}-${{matrix.database}} path: "./log/*.log" + run_pre_commit_checks: + runs-on: ubuntu-latest + steps: + - name: Check out the repository + uses: actions/checkout@v3.0.2 + with: + # Disabling shallow clone is recommended for improving relevancy of reporting in sonarcloud + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v4.2.0 + with: + python-version: "3.11" + - name: Upgrade pip + working-directory: . + run: | + pip install --constraint=.github/workflows/constraints.txt pip + pip --version + - name: Install Poetry + working-directory: . + run: | + pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry + poetry --version + - name: Poetry Install + run: poetry install + working-directory: . + - name: run_pre_commit + run: ./bin/run_pre_commit_in_ci + working-directory: . + check_docker_start_script: runs-on: ubuntu-latest steps: diff --git a/bin/run_pre_commit_in_ci b/bin/run_pre_commit_in_ci new file mode 100755 index 000000000..b30b7e17b --- /dev/null +++ b/bin/run_pre_commit_in_ci @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +function error_handler() { + >&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}." + exit "$2" +} +trap 'error_handler ${LINENO} $?' ERR +set -o errtrace -o errexit -o nounset -o pipefail + +poetry run pre-commit run --verbose --all-files From f579ce0b0440d6e890533106d994a931efaf1652 Mon Sep 17 00:00:00 2001 From: jasquat Date: Fri, 11 Nov 2022 11:26:55 -0500 Subject: [PATCH 02/17] do not update pip for pre commit w/ burnettk jbirddog --- .github/workflows/backend_tests.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/backend_tests.yml b/.github/workflows/backend_tests.yml index 816667a03..8b1c3cf2a 100644 --- a/.github/workflows/backend_tests.yml +++ b/.github/workflows/backend_tests.yml @@ -171,15 +171,10 @@ jobs: uses: actions/setup-python@v4.2.0 with: python-version: "3.11" - - name: Upgrade pip - working-directory: . - run: | - pip install --constraint=.github/workflows/constraints.txt pip - pip --version - name: Install Poetry working-directory: . run: | - pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry + pipx install poetry --version - name: Poetry Install run: poetry install From a7f0051bb6d8c7a7df69e66afc539648ce266daa Mon Sep 17 00:00:00 2001 From: jasquat Date: Fri, 11 Nov 2022 11:28:03 -0500 Subject: [PATCH 03/17] actually install poetry w/ burnettk jbirddog --- .github/workflows/backend_tests.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/backend_tests.yml b/.github/workflows/backend_tests.yml index 8b1c3cf2a..185d91c86 100644 --- a/.github/workflows/backend_tests.yml +++ b/.github/workflows/backend_tests.yml @@ -160,7 +160,9 @@ jobs: path: "./log/*.log" run_pre_commit_checks: - runs-on: ubuntu-latest + defaults: + run: + working-directory: . steps: - name: Check out the repository uses: actions/checkout@v3.0.2 @@ -172,16 +174,13 @@ jobs: with: python-version: "3.11" - name: Install Poetry - working-directory: . run: | - pipx install + pipx install poetry poetry --version - name: Poetry Install run: poetry install - working-directory: . - name: run_pre_commit run: ./bin/run_pre_commit_in_ci - working-directory: . check_docker_start_script: runs-on: ubuntu-latest From b6424cd955214274d431b8e8894b2d6b4549c444 Mon Sep 17 00:00:00 2001 From: jasquat Date: Fri, 11 Nov 2022 11:31:19 -0500 Subject: [PATCH 04/17] added runs on to pre commit w/ burnettk jbirddog --- .github/workflows/backend_tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/backend_tests.yml b/.github/workflows/backend_tests.yml index 185d91c86..715b1c4a2 100644 --- a/.github/workflows/backend_tests.yml +++ b/.github/workflows/backend_tests.yml @@ -160,6 +160,7 @@ jobs: path: "./log/*.log" run_pre_commit_checks: + runs-on: ubuntu-latest defaults: run: working-directory: . From d25c37153a704b8d34c637f6b11fd0fd2e71ed4f Mon Sep 17 00:00:00 2001 From: burnettk Date: Fri, 11 Nov 2022 11:39:15 -0500 Subject: [PATCH 05/17] pyl --- .../bin/import_tickets_for_command_line.py | 1 + .../bin/start_blocking_appscheduler.py | 1 + spiffworkflow-backend/conftest.py | 3 +- .../src/spiffworkflow_backend/__init__.py | 5 +- .../spiffworkflow_backend/config/__init__.py | 3 +- .../models/active_task.py | 7 +- .../models/active_task_user.py | 3 +- .../src/spiffworkflow_backend/models/file.py | 1 + .../models/message_correlation.py | 5 +- .../message_correlation_message_instance.py | 3 +- .../models/message_correlation_property.py | 3 +- .../models/message_instance.py | 5 +- .../message_triggerable_process_model.py | 3 +- .../models/permission_assignment.py | 5 +- .../spiffworkflow_backend/models/principal.py | 5 +- .../models/process_group.py | 5 +- .../models/process_instance.py | 9 +-- .../models/process_instance_report.py | 7 +- .../models/process_model.py | 1 + .../models/secret_model.py | 3 +- .../src/spiffworkflow_backend/models/user.py | 5 +- .../models/user_group_assignment.py | 5 +- .../routes/admin_blueprint/admin_blueprint.py | 3 +- .../routes/process_api_blueprint.py | 13 ++-- .../src/spiffworkflow_backend/routes/user.py | 3 +- .../routes/user_blueprint.py | 3 +- .../scripts/get_current_user.py | 1 + .../scripts/get_frontend_url.py | 1 + .../scripts/get_localtime.py | 1 + .../spiffworkflow_backend/scripts/script.py | 1 + .../services/acceptance_test_fixtures.py | 3 +- .../services/authentication_service.py | 3 +- .../services/authorization_service.py | 3 +- .../services/background_processing_service.py | 1 + .../services/data_setup_service.py | 1 + .../services/error_handling_service.py | 1 + .../services/file_system_service.py | 1 + .../services/git_service.py | 1 + .../services/group_service.py | 1 + .../services/logging_service.py | 1 + .../services/message_service.py | 7 +- .../services/process_instance_processor.py | 1 + .../services/process_instance_service.py | 1 + .../services/process_model_service.py | 13 ++-- .../services/script_unit_test_runner.py | 1 + .../services/secret_service.py | 1 + .../services/service_task_service.py | 1 + .../services/spec_file_service.py | 1 + .../services/user_service.py | 1 + .../tests/data/simple_form/simple_form.json | 2 +- .../data/simple_form/simple_form_ui.json | 2 - .../helpers/base_test.py | 6 +- .../helpers/example_data.py | 1 + .../helpers/test_data.py | 3 +- .../integration/test_authentication.py | 3 +- .../integration/test_logging_service.py | 3 +- .../integration/test_nested_groups.py | 3 +- .../integration/test_process_api.py | 69 ++++++++++++++----- .../integration/test_secret_service.py | 5 +- .../scripts/test_get_group_members.py | 5 +- .../scripts/test_get_localtime.py | 5 +- .../unit/test_acceptance_test_fixtures.py | 1 + .../unit/test_authorization_service.py | 3 +- .../unit/test_dot_notation.py | 3 +- .../unit/test_environment_var_script.py | 3 +- .../unit/test_message_instance.py | 3 +- .../unit/test_message_service.py | 5 +- .../unit/test_permission_target.py | 3 +- .../unit/test_permissions.py | 5 +- .../unit/test_process_group.py | 1 + .../unit/test_process_instance_processor.py | 5 +- .../unit/test_process_instance_report.py | 3 +- .../unit/test_process_model.py | 5 +- .../unit/test_process_model_service.py | 5 +- .../unit/test_restricted_script_engine.py | 5 +- .../unit/test_script_unit_test_runner.py | 5 +- .../unit/test_service_task_delegate.py | 3 +- .../unit/test_spec_file_service.py | 5 +- .../unit/test_spiff_logging.py | 3 +- .../unit/test_various_bpmn_constructs.py | 3 +- spiffworkflow-backend/tests/test_main.py | 1 + 81 files changed, 223 insertions(+), 111 deletions(-) diff --git a/spiffworkflow-backend/bin/import_tickets_for_command_line.py b/spiffworkflow-backend/bin/import_tickets_for_command_line.py index 5818d438d..8b145dc4a 100644 --- a/spiffworkflow-backend/bin/import_tickets_for_command_line.py +++ b/spiffworkflow-backend/bin/import_tickets_for_command_line.py @@ -2,6 +2,7 @@ import csv from flask_bpmn.models.db import db + from spiffworkflow_backend import get_hacked_up_app_for_script from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel diff --git a/spiffworkflow-backend/bin/start_blocking_appscheduler.py b/spiffworkflow-backend/bin/start_blocking_appscheduler.py index 61b753f26..4af99e411 100755 --- a/spiffworkflow-backend/bin/start_blocking_appscheduler.py +++ b/spiffworkflow-backend/bin/start_blocking_appscheduler.py @@ -2,6 +2,7 @@ import time from apscheduler.schedulers.background import BlockingScheduler # type: ignore + from spiffworkflow_backend import create_app from spiffworkflow_backend import start_scheduler from spiffworkflow_backend.helpers.db_helper import try_to_connect diff --git a/spiffworkflow-backend/conftest.py b/spiffworkflow-backend/conftest.py index 012f3c776..4751b8588 100644 --- a/spiffworkflow-backend/conftest.py +++ b/spiffworkflow-backend/conftest.py @@ -7,6 +7,8 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.user import UserModel @@ -17,7 +19,6 @@ from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) from spiffworkflow_backend.services.process_model_service import ProcessModelService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest # from tests.spiffworkflow_backend.helpers.test_data import load_test_spec diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py b/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py index 9f1a74e70..6ca51aef2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/__init__.py @@ -5,7 +5,6 @@ from typing import Any import connexion # type: ignore import flask.app import flask.json -import spiffworkflow_backend.load_database_models # noqa: F401 import sqlalchemy from apscheduler.schedulers.background import BackgroundScheduler # type: ignore from apscheduler.schedulers.base import BaseScheduler # type: ignore @@ -15,6 +14,9 @@ from flask_bpmn.models.db import db from flask_bpmn.models.db import migrate from flask_cors import CORS # type: ignore from flask_mail import Mail # type: ignore +from werkzeug.exceptions import NotFound + +import spiffworkflow_backend.load_database_models # noqa: F401 from spiffworkflow_backend.config import setup_config from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint from spiffworkflow_backend.routes.process_api_blueprint import process_api_blueprint @@ -24,7 +26,6 @@ from spiffworkflow_backend.services.authorization_service import AuthorizationSe from spiffworkflow_backend.services.background_processing_service import ( BackgroundProcessingService, ) -from werkzeug.exceptions import NotFound class MyJSONEncoder(DefaultJSONProvider): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py b/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py index 082195798..b56683ca3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py @@ -3,9 +3,10 @@ import os import threading from flask.app import Flask -from spiffworkflow_backend.services.logging_service import setup_logger from werkzeug.utils import ImportStringError +from spiffworkflow_backend.services.logging_service import setup_logger + class ConfigurationError(Exception): """ConfigurationError.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task.py index 50bd8c75b..ea9e10552 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task.py @@ -6,13 +6,14 @@ from typing import TYPE_CHECKING from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship +from sqlalchemy.orm import RelationshipProperty + from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.user import UserModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import relationship -from sqlalchemy.orm import RelationshipProperty if TYPE_CHECKING: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task_user.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task_user.py index 002759b1b..f194c38e4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task_user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task_user.py @@ -5,9 +5,10 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from sqlalchemy import ForeignKey + from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.user import UserModel -from sqlalchemy import ForeignKey @dataclass diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py index 9260e1844..02ad5fc10 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/file.py @@ -7,6 +7,7 @@ from typing import Optional import marshmallow from marshmallow import INCLUDE from marshmallow import Schema + from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py index c3338f0b1..baec8270a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation.py @@ -4,12 +4,13 @@ from typing import TYPE_CHECKING from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship + from spiffworkflow_backend.models.message_correlation_property import ( MessageCorrelationPropertyModel, ) from spiffworkflow_backend.models.process_instance import ProcessInstanceModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import relationship if TYPE_CHECKING: from spiffworkflow_backend.models.message_correlation_message_instance import ( # noqa: F401 diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py index f056aec6f..320dfba3e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_message_instance.py @@ -3,9 +3,10 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from sqlalchemy import ForeignKey + from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_instance import MessageInstanceModel -from sqlalchemy import ForeignKey @dataclass diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py index 04acaa940..b84b7140c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_correlation_property.py @@ -1,9 +1,10 @@ """Message_correlation_property.""" from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from spiffworkflow_backend.models.message_model import MessageModel from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.message_model import MessageModel + class MessageCorrelationPropertyModel(SpiffworkflowBaseDBModel): """MessageCorrelationPropertyModel.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py index 2bc9c2673..61dd12b24 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_instance.py @@ -7,14 +7,15 @@ from typing import TYPE_CHECKING from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from spiffworkflow_backend.models.message_model import MessageModel -from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from sqlalchemy import ForeignKey from sqlalchemy.event import listens_for from sqlalchemy.orm import relationship from sqlalchemy.orm import Session from sqlalchemy.orm import validates +from spiffworkflow_backend.models.message_model import MessageModel +from spiffworkflow_backend.models.process_instance import ProcessInstanceModel + if TYPE_CHECKING: from spiffworkflow_backend.models.message_correlation_message_instance import ( # noqa: F401 MessageCorrelationMessageInstanceModel, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py index b82580d7e..97d54aa7d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/message_triggerable_process_model.py @@ -1,9 +1,10 @@ """Message_correlation_property.""" from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from spiffworkflow_backend.models.message_model import MessageModel from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.message_model import MessageModel + class MessageTriggerableProcessModel(SpiffworkflowBaseDBModel): """MessageTriggerableProcessModel.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py index 194341929..63295f74e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/permission_assignment.py @@ -4,11 +4,12 @@ from typing import Any from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from spiffworkflow_backend.models.permission_target import PermissionTargetModel -from spiffworkflow_backend.models.principal import PrincipalModel from sqlalchemy import ForeignKey from sqlalchemy.orm import validates +from spiffworkflow_backend.models.permission_target import PermissionTargetModel +from spiffworkflow_backend.models.principal import PrincipalModel + class PermitDeny(enum.Enum): """PermitDeny.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py index d43be35a4..c7efa8609 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/principal.py @@ -3,12 +3,13 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from spiffworkflow_backend.models.group import GroupModel -from spiffworkflow_backend.models.user import UserModel from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.schema import CheckConstraint +from spiffworkflow_backend.models.group import GroupModel +from spiffworkflow_backend.models.user import UserModel + class DataValidityError(Exception): """DataValidityError.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_group.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_group.py index 4a93c417b..6edb19e53 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_group.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_group.py @@ -9,6 +9,7 @@ from typing import Any import marshmallow from marshmallow import post_load from marshmallow import Schema + from spiffworkflow_backend.models.process_model import ProcessModelInfo @@ -26,9 +27,7 @@ class ProcessGroup: process_models: list[ProcessModelInfo] = field( default_factory=list[ProcessModelInfo] ) - process_groups: list[ProcessGroup] = field( - default_factory=list['ProcessGroup'] - ) + process_groups: list[ProcessGroup] = field(default_factory=list["ProcessGroup"]) def __post_init__(self) -> None: """__post_init__.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index cc53623ee..cfa892528 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -12,15 +12,16 @@ from marshmallow import INCLUDE from marshmallow import Schema from marshmallow_enum import EnumField # type: ignore from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore +from sqlalchemy import ForeignKey +from sqlalchemy.orm import deferred +from sqlalchemy.orm import relationship +from sqlalchemy.orm import validates + from spiffworkflow_backend.helpers.spiff_enum import SpiffEnum from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.task import TaskSchema from spiffworkflow_backend.models.user import UserModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import deferred -from sqlalchemy.orm import relationship -from sqlalchemy.orm import validates class NavigationItemSchema(Schema): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py index c4fcbad27..1425d69f5 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_report.py @@ -9,6 +9,10 @@ from typing import TypedDict from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import deferred +from sqlalchemy.orm import relationship + from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -17,9 +21,6 @@ from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) -from sqlalchemy import ForeignKey -from sqlalchemy.orm import deferred -from sqlalchemy.orm import relationship ReportMetadata = dict[str, Any] diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py index 1c82bd405..d63197be2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_model.py @@ -9,6 +9,7 @@ from typing import Any import marshmallow from marshmallow import Schema from marshmallow.decorators import post_load + from spiffworkflow_backend.models.file import File diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py index 9cc338ed2..92fd470a3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/secret_model.py @@ -4,9 +4,10 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel from marshmallow import Schema -from spiffworkflow_backend.models.user import UserModel from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.user import UserModel + @dataclass() class SecretModel(SpiffworkflowBaseDBModel): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py index 0df4c9c21..c33a72e7a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py @@ -10,12 +10,13 @@ from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel from marshmallow import Schema +from sqlalchemy.orm import relationship +from sqlalchemy.orm import validates + from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.services.authentication_service import ( AuthenticationProviderTypes, ) -from sqlalchemy.orm import relationship -from sqlalchemy.orm import validates class UserNotFoundError(Exception): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py index 8cccf1d8c..fa5b620c8 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user_group_assignment.py @@ -1,11 +1,12 @@ """UserGroupAssignment.""" from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from spiffworkflow_backend.models.group import GroupModel -from spiffworkflow_backend.models.user import UserModel from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship +from spiffworkflow_backend.models.group import GroupModel +from spiffworkflow_backend.models.user import UserModel + class UserGroupAssignmentModel(SpiffworkflowBaseDBModel): """UserGroupAssignmentModel.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py index f13e4e073..2e480f2a4 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py @@ -7,6 +7,8 @@ from flask import redirect from flask import render_template from flask import request from flask import url_for +from werkzeug.wrappers import Response + from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) @@ -16,7 +18,6 @@ from spiffworkflow_backend.services.process_instance_service import ( from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService from spiffworkflow_backend.services.user_service import UserService -from werkzeug.wrappers import Response admin_blueprint = Blueprint( "admin", __name__, template_folder="templates", static_folder="static" 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 260da3788..17b64d4cc 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -28,6 +28,9 @@ from lxml import etree # type: ignore from lxml.builder import ElementMaker # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState +from sqlalchemy import asc +from sqlalchemy import desc + from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -75,8 +78,6 @@ from spiffworkflow_backend.services.secret_service import SecretService from spiffworkflow_backend.services.service_task_service import ServiceTaskService from spiffworkflow_backend.services.spec_file_service import SpecFileService from spiffworkflow_backend.services.user_service import UserService -from sqlalchemy import asc -from sqlalchemy import desc class TaskDataSelectOption(TypedDict): @@ -178,10 +179,14 @@ def process_group_update( return make_response(jsonify(process_group), 200) -def process_groups_list(process_group_identifier: Optional[str] = None, page: int = 1, per_page: int = 100) -> flask.wrappers.Response: +def process_groups_list( + process_group_identifier: Optional[str] = None, page: int = 1, per_page: int = 100 +) -> flask.wrappers.Response: """Process_groups_list.""" if process_group_identifier is not None: - process_groups = ProcessModelService().get_process_groups(process_group_identifier) + process_groups = ProcessModelService().get_process_groups( + process_group_identifier + ) else: process_groups = ProcessModelService().get_process_groups() batch = ProcessModelService().get_batch( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py index 45d7c2ae5..5fe10e0af 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user.py @@ -12,13 +12,14 @@ from flask import g from flask import redirect from flask import request from flask_bpmn.api.api_error import ApiError +from werkzeug.wrappers import Response + from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.authentication_service import ( AuthenticationService, ) from spiffworkflow_backend.services.authorization_service import AuthorizationService from spiffworkflow_backend.services.user_service import UserService -from werkzeug.wrappers import Response """ .. module:: crc.api.user diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py index 9520dfc85..29bbddcd1 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/user_blueprint.py @@ -9,10 +9,11 @@ from flask import request from flask import Response from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db +from sqlalchemy.exc import IntegrityError + from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel -from sqlalchemy.exc import IntegrityError APPLICATION_JSON: Final = "application/json" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_current_user.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_current_user.py index 4cdcdc37c..a1a1b47e9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_current_user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_current_user.py @@ -2,6 +2,7 @@ from typing import Any from flask import g + from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_frontend_url.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_frontend_url.py index 6930c57e0..9490df95a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_frontend_url.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_frontend_url.py @@ -2,6 +2,7 @@ from typing import Any from flask import current_app + from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py index 16b9bf577..689b86d8c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/get_localtime.py @@ -4,6 +4,7 @@ from typing import Any import pytz from flask_bpmn.api.api_error import ApiError + from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py index 7ed745d6e..b744694a2 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/scripts/script.py @@ -9,6 +9,7 @@ from typing import Any from typing import Callable from flask_bpmn.api.api_error import ApiError + from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py index c71e6069e..cfea3148b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/acceptance_test_fixtures.py @@ -4,9 +4,10 @@ import time from flask import current_app from flask_bpmn.models.db import db +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus -from tests.spiffworkflow_backend.helpers.base_test import BaseTest def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py index 1ec35ae15..18f08d0f3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authentication_service.py @@ -11,9 +11,10 @@ from flask import current_app from flask import redirect from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db -from spiffworkflow_backend.models.refresh_token import RefreshTokenModel from werkzeug.wrappers import Response +from spiffworkflow_backend.models.refresh_token import RefreshTokenModel + class AuthenticationProviderTypes(enum.Enum): """AuthenticationServiceProviders.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py index 7c654609c..75c17ab86 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/authorization_service.py @@ -11,6 +11,8 @@ from flask import request from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db from SpiffWorkflow.task import Task as SpiffTask # type: ignore +from sqlalchemy import text + from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel @@ -25,7 +27,6 @@ from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) from spiffworkflow_backend.services.user_service import UserService -from sqlalchemy import text class PermissionsFileNotSetError(Exception): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py index 8c4fee6e7..08a2b02df 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/background_processing_service.py @@ -1,5 +1,6 @@ """Background_processing_service.""" import flask + from spiffworkflow_backend.services.message_service import MessageService from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py index 226003c46..23df25f34 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/data_setup_service.py @@ -1,5 +1,6 @@ """Data_setup_service.""" from flask import current_app + from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py index 8bf377bdc..99e4fbe8c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/error_handling_service.py @@ -5,6 +5,7 @@ from typing import Union from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db + from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.services.email_service import EmailService diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py index f6091de09..15327400b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/file_system_service.py @@ -7,6 +7,7 @@ from typing import Optional import pytz from flask import current_app from flask_bpmn.api.api_error import ApiError + from spiffworkflow_backend.models.file import CONTENT_TYPES from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import FileType diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/git_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/git_service.py index 08f45386d..815e4cadc 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/git_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/git_service.py @@ -2,6 +2,7 @@ import os from flask import current_app + from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.services.file_system_service import FileSystemService diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py index a2e54460a..aa560009e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/group_service.py @@ -2,6 +2,7 @@ from typing import Optional from flask_bpmn.models.db import db + from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.services.user_service import UserService diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py index 201a7e5c2..c4e8c8ae9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/logging_service.py @@ -8,6 +8,7 @@ from typing import Optional from flask import g from flask.app import Flask from flask_bpmn.models.db import db + from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py index 190eaaa41..216a66a58 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/message_service.py @@ -3,6 +3,10 @@ from typing import Any from typing import Optional from flask_bpmn.models.db import db +from sqlalchemy import and_ +from sqlalchemy import or_ +from sqlalchemy import select + from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_correlation_message_instance import ( MessageCorrelationMessageInstanceModel, @@ -19,9 +23,6 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) -from sqlalchemy import and_ -from sqlalchemy import or_ -from sqlalchemy import select class MessageServiceError(Exception): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py index fb59960be..a9f7ac661 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -65,6 +65,7 @@ from SpiffWorkflow.spiff.serializer.task_spec_converters import UserTaskConverte from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore + from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py index f5c5128cc..ca9f66aa7 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py @@ -7,6 +7,7 @@ from flask import current_app from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db from SpiffWorkflow.task import Task as SpiffTask # type: ignore + from spiffworkflow_backend.models.process_instance import ProcessInstanceApi from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py index d8fe12033..f473a4ca0 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_model_service.py @@ -8,6 +8,7 @@ from typing import Optional from typing import TypeVar from flask_bpmn.api.api_error import ApiError + from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -160,7 +161,9 @@ class ProcessModelService(FileSystemService): process_models.sort() return process_models - def get_process_groups(self, process_group_id: Optional[str] = None) -> list[ProcessGroup]: + def get_process_groups( + self, process_group_id: Optional[str] = None + ) -> list[ProcessGroup]: """Returns the process_groups as a list in display order.""" process_groups = self.__scan_process_groups(process_group_id) process_groups.sort() @@ -254,7 +257,9 @@ class ProcessModelService(FileSystemService): index += 1 return process_groups - def __scan_process_groups(self, process_group_id: Optional[str] = None) -> list[ProcessGroup]: + def __scan_process_groups( + self, process_group_id: Optional[str] = None + ) -> list[ProcessGroup]: """__scan_process_groups.""" if not os.path.exists(FileSystemService.root_path()): return [] # Nothing to scan yet. There are no files. @@ -303,9 +308,7 @@ class ProcessModelService(FileSystemService): if self.is_group(nested_item.path): # This is a nested group process_group.process_groups.append( - self.__scan_process_group( - nested_item.path - ) + self.__scan_process_group(nested_item.path) ) elif self.is_model(nested_item.path): process_group.process_models.append( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/script_unit_test_runner.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/script_unit_test_runner.py index b9ec129ec..9112e20f0 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/script_unit_test_runner.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/script_unit_test_runner.py @@ -8,6 +8,7 @@ from typing import Optional from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore + from spiffworkflow_backend.services.process_instance_processor import ( CustomBpmnScriptEngine, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py index 332644995..42f401c18 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/secret_service.py @@ -3,6 +3,7 @@ from typing import Optional from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db + from spiffworkflow_backend.models.secret_model import SecretModel # from cryptography.fernet import Fernet diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/service_task_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/service_task_service.py index fb2961f56..97ce1495a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/service_task_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/service_task_service.py @@ -5,6 +5,7 @@ from typing import Any import requests from flask import current_app from flask import g + from spiffworkflow_backend.services.file_system_service import FileSystemService from spiffworkflow_backend.services.secret_service import SecretService 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 757a259d6..92e905bf3 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/spec_file_service.py @@ -12,6 +12,7 @@ from lxml import etree # type: ignore from lxml.etree import _Element # type: ignore from lxml.etree import Element as EtreeElement from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException # type: ignore + from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import FileReference diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py index c65c48873..0e8e65c2c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/user_service.py @@ -6,6 +6,7 @@ from flask import current_app from flask import g from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db + from spiffworkflow_backend.models.active_task import ActiveTaskModel from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel from spiffworkflow_backend.models.group import GroupModel diff --git a/spiffworkflow-backend/tests/data/simple_form/simple_form.json b/spiffworkflow-backend/tests/data/simple_form/simple_form.json index ded388eb2..68a9e4de7 100644 --- a/spiffworkflow-backend/tests/data/simple_form/simple_form.json +++ b/spiffworkflow-backend/tests/data/simple_form/simple_form.json @@ -21,4 +21,4 @@ ] } } -} \ No newline at end of file +} diff --git a/spiffworkflow-backend/tests/data/simple_form/simple_form_ui.json b/spiffworkflow-backend/tests/data/simple_form/simple_form_ui.json index e6788536e..9ceddac03 100644 --- a/spiffworkflow-backend/tests/data/simple_form/simple_form_ui.json +++ b/spiffworkflow-backend/tests/data/simple_form/simple_form_ui.json @@ -9,5 +9,3 @@ }, "ui:order": ["name", "department"] } - - diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py index 0d30df0a2..e3660ad44 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/base_test.py @@ -8,10 +8,12 @@ from typing import Dict from typing import Optional from flask import current_app -from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from werkzeug.test import TestResponse # type: ignore + from spiffworkflow_backend.models.permission_assignment import Permission from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.process_group import ProcessGroup @@ -25,8 +27,6 @@ from spiffworkflow_backend.services.authorization_service import AuthorizationSe from spiffworkflow_backend.services.file_system_service import FileSystemService from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.user_service import UserService -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec -from werkzeug.test import TestResponse # type: ignore # from tests.spiffworkflow_backend.helpers.test_data import logged_in_headers diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py index c5e5c9bce..251ba19c8 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/example_data.py @@ -4,6 +4,7 @@ import os from typing import Optional from flask import current_app + from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py index 0ce535d1e..d6b4f730c 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/helpers/test_data.py @@ -1,13 +1,14 @@ """User.""" from typing import Optional +from tests.spiffworkflow_backend.helpers.example_data import ExampleDataLoader + from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.services.process_model_service import ProcessModelService -from tests.spiffworkflow_backend.helpers.example_data import ExampleDataLoader def assure_process_group_exists(process_group_id: Optional[str] = None) -> ProcessGroup: diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_authentication.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_authentication.py index 537943480..34e4d71bc 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_authentication.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_authentication.py @@ -2,10 +2,11 @@ import ast import base64 +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.services.authentication_service import ( AuthenticationService, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestAuthentication(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py index a5e3e36dc..97dafaf3f 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_logging_service.py @@ -1,9 +1,10 @@ """Test_logging_service.""" from flask.app import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.models.user import UserModel from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from spiffworkflow_backend.models.user import UserModel + class TestLoggingService(BaseTest): """Test logging service.""" diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py index c5d38b4fa..9a48ebf18 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_nested_groups.py @@ -3,6 +3,8 @@ import json from flask.app import Flask from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_group import ProcessGroupSchema from spiffworkflow_backend.models.process_model import ProcessModelInfo @@ -11,7 +13,6 @@ from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestNestedGroups(BaseTest): 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 a860eaab8..a45336841 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -9,6 +9,9 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -32,8 +35,6 @@ from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) from spiffworkflow_backend.services.process_model_service import ProcessModelService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec # from spiffworkflow_backend.services.git_service import GitService @@ -622,7 +623,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_id = process_model_identifier.replace("/", ":") data = {"key1": "THIS DATA"} @@ -646,7 +649,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_id = process_model_identifier.replace("/", ":") data = {"file": (io.BytesIO(b""), "random_fact.svg")} @@ -722,7 +727,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) # self.create_spec_file(client, user=with_super_admin_user) # process_model = load_test_spec("random_fact") @@ -748,7 +755,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.delete( @@ -769,7 +778,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.delete( @@ -796,7 +807,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_file.""" - process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.get( @@ -816,7 +829,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_workflow_from_workflow_spec.""" - process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.post( @@ -871,7 +886,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_group_when_found.""" - process_model_identifier = self.create_group_and_model_with_bpmn(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) process_group_id, process_model_id = os.path.split(process_model_identifier) response = client.get( @@ -937,7 +954,9 @@ class TestProcessApi(BaseTest): """Test_process_instance_create.""" test_process_model_id = "runs_without_input/sample" headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance_from_process_model_id(client, test_process_model_id, headers) + response = self.create_process_instance_from_process_model_id( + client, test_process_model_id, headers + ) assert response.json is not None assert response.json["updated_at_in_seconds"] is not None assert response.json["status"] == "not_started" @@ -1305,7 +1324,9 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) response = client.get( "/v1.0/process-instances", @@ -1350,11 +1371,21 @@ class TestProcessApi(BaseTest): bpmn_file_location=bpmn_file_location, ) headers = self.logged_in_headers(with_super_admin_user) - self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) - self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) - self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) - self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) - self.create_process_instance_from_process_model_id(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) response = client.get( "/v1.0/process-instances?per_page=2&page=3", @@ -1657,7 +1688,9 @@ class TestProcessApi(BaseTest): ) -> Any: """Setup_testing_instance.""" headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance_from_process_model_id(client, process_model_id, headers) + response = self.create_process_instance_from_process_model_id( + client, process_model_id, headers + ) process_instance = response.json assert isinstance(process_instance, dict) process_instance_id = process_instance["id"] diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py index ea1a486e5..071ef6ccd 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_secret_service.py @@ -6,14 +6,15 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from werkzeug.test import TestResponse # type: ignore + from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.secret_model import SecretModel from spiffworkflow_backend.models.secret_model import SecretModelSchema from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.secret_service import SecretService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from werkzeug.test import TestResponse # type: ignore class SecretServiceTestHelpers(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py index b38296be2..8a6046b5b 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_group_members.py @@ -2,14 +2,15 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) from spiffworkflow_backend.services.user_service import UserService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestGetGroupMembers(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py index b04e93f5f..9e65b9707 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py @@ -4,6 +4,9 @@ import datetime import pytz from flask.app import Flask from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) @@ -14,8 +17,6 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestGetLocaltime(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py index a9305a04c..1d5157123 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py @@ -1,5 +1,6 @@ """Test_acceptance_test_fixtures.""" from flask.app import Flask + from spiffworkflow_backend.services.acceptance_test_fixtures import ( load_acceptance_test_fixtures, ) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py index 25bce349c..916347b35 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py @@ -2,6 +2,8 @@ import pytest from flask import Flask from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserNotFoundError from spiffworkflow_backend.services.authorization_service import AuthorizationService @@ -12,7 +14,6 @@ from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) from spiffworkflow_backend.services.process_model_service import ProcessModelService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestAuthorizationService(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py index 2e3f432f2..6bd1cca6d 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py @@ -1,6 +1,8 @@ """Test_various_bpmn_constructs.""" from flask.app import Flask from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, @@ -8,7 +10,6 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestDotNotation(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_environment_var_script.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_environment_var_script.py index e00fb7708..ac96e7e4d 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_environment_var_script.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_environment_var_script.py @@ -1,9 +1,10 @@ """Test_environment_var_script.""" from flask import Flask +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestEnvironmentVarScript(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py index f91290e55..0292032ee 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_instance.py @@ -3,11 +3,12 @@ import pytest from flask import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.message_instance import MessageInstanceModel from spiffworkflow_backend.models.message_model import MessageModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestMessageInstance(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py index 46b98c4af..aa1f28053 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_message_service.py @@ -1,6 +1,9 @@ """Test_message_service.""" from flask import Flask from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.message_correlation import MessageCorrelationModel from spiffworkflow_backend.models.message_correlation_message_instance import ( MessageCorrelationMessageInstanceModel, @@ -15,8 +18,6 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestMessageService(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py index a6fefd682..567681428 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permission_target.py @@ -2,11 +2,12 @@ import pytest from flask.app import Flask from flask_bpmn.models.db import db +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.permission_target import ( InvalidPermissionTargetUriError, ) from spiffworkflow_backend.models.permission_target import PermissionTargetModel -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestPermissionTarget(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py index 0973bb4cb..117fd0af5 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_permissions.py @@ -2,14 +2,15 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.user_service import UserService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec # we think we can get the list of roles for a user. diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_group.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_group.py index b2cf3c444..6c3ad0ade 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_group.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_group.py @@ -1,5 +1,6 @@ """Process Model.""" from flask.app import Flask + from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.services.process_model_service import ProcessModelService diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py index 20b47b0cc..ad7aefe34 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py @@ -3,6 +3,9 @@ import pytest from flask import g from flask.app import Flask from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.group import GroupModel from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.models.user import UserModel @@ -16,8 +19,6 @@ from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_service import ( ProcessInstanceService, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestProcessInstanceProcessor(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report.py index ccfb088f6..482395076 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_report.py @@ -2,11 +2,12 @@ from typing import Optional from flask.app import Flask +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance_report import ( ProcessInstanceReportModel, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest # from tests.spiffworkflow_backend.helpers.test_data import find_or_create_process_group # from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py index 4154be5df..5b5b9f256 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model.py @@ -2,14 +2,15 @@ from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.models.db import db +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestProcessModel(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py index bd981e1c5..438ef89d9 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_model_service.py @@ -1,11 +1,12 @@ """Test_process_model_service.""" from flask import Flask from flask.testing import FlaskClient -from spiffworkflow_backend.models.user import UserModel -from spiffworkflow_backend.services.process_model_service import ProcessModelService from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.models.user import UserModel +from spiffworkflow_backend.services.process_model_service import ProcessModelService + class TestProcessModelService(BaseTest): """TestProcessModelService.""" diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py index 46f88e749..d31ea424f 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py @@ -3,12 +3,13 @@ import pytest from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestOpenFile(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py index 38a03c116..9ece043a5 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py @@ -1,14 +1,15 @@ """Test Permissions.""" from flask.app import Flask from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) from spiffworkflow_backend.services.script_unit_test_runner import PythonScriptContext from spiffworkflow_backend.services.script_unit_test_runner import ScriptUnitTestRunner -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestScriptUnitTestRunner(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_service_task_delegate.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_service_task_delegate.py index 647db1759..95b557560 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_service_task_delegate.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_service_task_delegate.py @@ -1,8 +1,9 @@ """Test_various_bpmn_constructs.""" from flask.app import Flask +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.services.secret_service import SecretService from spiffworkflow_backend.services.service_task_service import ServiceTaskDelegate -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestServiceTaskDelegate(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py index 630ae5951..76195449d 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spec_file_service.py @@ -7,12 +7,13 @@ from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser # type: ignore +from tests.spiffworkflow_backend.helpers.base_test import BaseTest +from tests.spiffworkflow_backend.helpers.test_data import load_test_spec + from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_model_service import ProcessModelService from spiffworkflow_backend.services.spec_file_service import SpecFileService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest -from tests.spiffworkflow_backend.helpers.test_data import load_test_spec class TestSpecFileService(BaseTest): diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py index fe5c8afef..d8680b719 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_spiff_logging.py @@ -3,10 +3,11 @@ from decimal import Decimal from flask.app import Flask from flask_bpmn.models.db import db -from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from tests.spiffworkflow_backend.helpers.base_test import BaseTest from tests.spiffworkflow_backend.helpers.test_data import load_test_spec +from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel + class TestSpiffLogging(BaseTest): """TestSpiffLogging.""" diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py index 9ff299074..aa91fcfd3 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py @@ -1,12 +1,13 @@ """Test_various_bpmn_constructs.""" from flask.app import Flask from flask.testing import FlaskClient +from tests.spiffworkflow_backend.helpers.base_test import BaseTest + from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, ) from spiffworkflow_backend.services.process_model_service import ProcessModelService -from tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestVariousBpmnConstructs(BaseTest): diff --git a/spiffworkflow-backend/tests/test_main.py b/spiffworkflow-backend/tests/test_main.py index 001dbcc6d..7917a970d 100644 --- a/spiffworkflow-backend/tests/test_main.py +++ b/spiffworkflow-backend/tests/test_main.py @@ -1,6 +1,7 @@ """Test cases for the __main__ module.""" import pytest from click.testing import CliRunner + from spiffworkflow_backend import __main__ From a1d7c2b6cb1ec759aaa31dedccc798905bd55710 Mon Sep 17 00:00:00 2001 From: burnettk Date: Fri, 11 Nov 2022 11:40:59 -0500 Subject: [PATCH 06/17] Squashed 'spiffworkflow-backend/' changes from e78e32dcf9..2cb3fb27e2 2cb3fb27e2 pyl 46a590749d pulled in subtrees and resolved conflicts w/ burnettk 1dcad72629 Report URL fixes (#29) 131dbeb3cf oops c50c85edaf mypy fixes 3735b71e06 removed duplicate code ba08826c65 modify process_groups_list so it can process any group path, not just the root process_groups_list now takes an optional group path 1e09c95520 renamed and reordered some methods in base_test.py dfa79360c4 Merge branch 'main' into feature/nested-groups-2 450a8d0757 Delete groups now checks for running instances in nested models also, pyl c814e991a0 use error as a status instead of faulted w/ burnettk 3211e7a49e fixed up the process instance show page and moved contents of scss to css file and load that last w/ burnettk git-subtree-dir: spiffworkflow-backend git-subtree-split: 2cb3fb27e200e211965175914c01f7fd7290aa75 --- conftest.py | 2 +- migrations/env.py | 25 +- migrations/versions/fd00c59e1f60_.py | 769 ++++++++++++------ poetry.lock | 2 +- src/spiffworkflow_backend/api.yml | 68 +- .../models/process_group.py | 4 +- .../models/process_instance.py | 3 +- .../models/process_instance_report.py | 4 - .../routes/process_api_blueprint.py | 19 +- src/spiffworkflow_backend/routes/user.py | 4 +- .../services/acceptance_test_fixtures.py | 2 +- .../services/error_handling_service.py | 2 +- .../services/file_system_service.py | 2 +- .../services/process_instance_service.py | 2 +- .../services/process_model_service.py | 45 +- tests/data/simple_form/simple_form.bpmn | 63 ++ tests/data/simple_form/simple_form.json | 24 + tests/data/simple_form/simple_form_ui.json | 11 + .../helpers/base_test.py | 158 ++-- .../integration/test_logging_service.py | 2 +- .../integration/test_nested_groups.py | 112 +++ .../integration/test_process_api.py | 130 +-- .../unit/test_authorization_service.py | 2 +- .../unit/test_dot_notation.py | 4 +- .../unit/test_message_instance.py | 2 +- .../unit/test_spec_file_service.py | 8 +- .../unit/test_various_bpmn_constructs.py | 2 +- 27 files changed, 958 insertions(+), 513 deletions(-) create mode 100644 tests/data/simple_form/simple_form.bpmn create mode 100644 tests/data/simple_form/simple_form.json create mode 100644 tests/data/simple_form/simple_form_ui.json diff --git a/conftest.py b/conftest.py index d73693c23..4751b8588 100644 --- a/conftest.py +++ b/conftest.py @@ -77,7 +77,7 @@ def setup_process_instances_for_reports( process_model_id = "sample" # bpmn_file_name = "sample.bpmn" bpmn_file_location = "sample" - process_model_identifier = BaseTest().basic_test_setup( + process_model_identifier = BaseTest().create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, diff --git a/migrations/env.py b/migrations/env.py index 630e381ad..4bd0316c2 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -1,9 +1,8 @@ import logging from logging.config import fileConfig -from flask import current_app - from alembic import context +from flask import current_app # this is the Alembic Config object, which provides # access to the values within the .ini file in use. @@ -12,17 +11,17 @@ config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') +logger = logging.getLogger("alembic.env") # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option( - 'sqlalchemy.url', - str(current_app.extensions['migrate'].db.get_engine().url).replace( - '%', '%%')) -target_metadata = current_app.extensions['migrate'].db.metadata + "sqlalchemy.url", + str(current_app.extensions["migrate"].db.get_engine().url).replace("%", "%%"), +) +target_metadata = current_app.extensions["migrate"].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -43,9 +42,7 @@ def run_migrations_offline(): """ url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, target_metadata=target_metadata, literal_binds=True - ) + context.configure(url=url, target_metadata=target_metadata, literal_binds=True) with context.begin_transaction(): context.run_migrations() @@ -63,20 +60,20 @@ def run_migrations_online(): # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): + if getattr(config.cmd_opts, "autogenerate", False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] - logger.info('No changes in schema detected.') + logger.info("No changes in schema detected.") - connectable = current_app.extensions['migrate'].db.get_engine() + connectable = current_app.extensions["migrate"].db.get_engine() with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args + **current_app.extensions["migrate"].configure_args ) with context.begin_transaction(): diff --git a/migrations/versions/fd00c59e1f60_.py b/migrations/versions/fd00c59e1f60_.py index f240843ae..ed8bbeb8d 100644 --- a/migrations/versions/fd00c59e1f60_.py +++ b/migrations/versions/fd00c59e1f60_.py @@ -1,16 +1,16 @@ """empty message Revision ID: fd00c59e1f60 -Revises: +Revises: Create Date: 2022-11-09 14:04:14.169379 """ -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. -revision = 'fd00c59e1f60' +revision = "fd00c59e1f60" down_revision = None branch_labels = None depends_on = None @@ -18,291 +18,532 @@ depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('bpmn_process_id_lookup', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('bpmn_process_identifier', sa.String(length=255), nullable=True), - sa.Column('bpmn_file_relative_path', sa.String(length=255), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_table( + "bpmn_process_id_lookup", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("bpmn_process_identifier", sa.String(length=255), nullable=True), + sa.Column("bpmn_file_relative_path", sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_bpmn_process_id_lookup_bpmn_process_identifier'), 'bpmn_process_id_lookup', ['bpmn_process_identifier'], unique=True) - op.create_table('group', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=255), nullable=True), - sa.Column('identifier', sa.String(length=255), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_index( + op.f("ix_bpmn_process_id_lookup_bpmn_process_identifier"), + "bpmn_process_id_lookup", + ["bpmn_process_identifier"], + unique=True, ) - op.create_table('message_model', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('identifier', sa.String(length=50), nullable=True), - sa.Column('name', sa.String(length=50), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_table( + "group", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=255), nullable=True), + sa.Column("identifier", sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_message_model_identifier'), 'message_model', ['identifier'], unique=True) - op.create_index(op.f('ix_message_model_name'), 'message_model', ['name'], unique=True) - op.create_table('permission_target', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('uri', sa.String(length=255), nullable=False), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('uri') + op.create_table( + "message_model", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("identifier", sa.String(length=50), nullable=True), + sa.Column("name", sa.String(length=50), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('spiff_logging', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('bpmn_process_identifier', sa.String(length=255), nullable=False), - sa.Column('bpmn_task_identifier', sa.String(length=255), nullable=False), - sa.Column('bpmn_task_name', sa.String(length=255), nullable=True), - sa.Column('bpmn_task_type', sa.String(length=255), nullable=True), - sa.Column('spiff_task_guid', sa.String(length=50), nullable=False), - sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False), - sa.Column('message', sa.String(length=255), nullable=True), - sa.Column('current_user_id', sa.Integer(), nullable=True), - sa.Column('spiff_step', sa.Integer(), nullable=False), - sa.PrimaryKeyConstraint('id') + op.create_index( + op.f("ix_message_model_identifier"), + "message_model", + ["identifier"], + unique=True, ) - op.create_table('spiff_step_details', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('spiff_step', sa.Integer(), nullable=False), - sa.Column('task_json', sa.JSON(), nullable=False), - sa.Column('timestamp', sa.DECIMAL(precision=17, scale=6), nullable=False), - sa.Column('completed_by_user_id', sa.Integer(), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_index( + op.f("ix_message_model_name"), "message_model", ["name"], unique=True ) - op.create_table('user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('username', sa.String(length=255), nullable=False), - sa.Column('uid', sa.String(length=50), nullable=True), - sa.Column('service', sa.String(length=50), nullable=False), - sa.Column('service_id', sa.String(length=255), nullable=False), - sa.Column('name', sa.String(length=255), nullable=True), - sa.Column('email', sa.String(length=255), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('service', 'service_id', name='service_key'), - sa.UniqueConstraint('uid'), - sa.UniqueConstraint('username') + op.create_table( + "permission_target", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("uri", sa.String(length=255), nullable=False), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("uri"), ) - op.create_table('message_correlation_property', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('identifier', sa.String(length=50), nullable=True), - sa.Column('message_model_id', sa.Integer(), nullable=False), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['message_model_id'], ['message_model.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('identifier', 'message_model_id', name='message_correlation_property_unique') + op.create_table( + "spiff_logging", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("bpmn_process_identifier", sa.String(length=255), nullable=False), + sa.Column("bpmn_task_identifier", sa.String(length=255), nullable=False), + sa.Column("bpmn_task_name", sa.String(length=255), nullable=True), + sa.Column("bpmn_task_type", sa.String(length=255), nullable=True), + sa.Column("spiff_task_guid", sa.String(length=50), nullable=False), + sa.Column("timestamp", sa.DECIMAL(precision=17, scale=6), nullable=False), + sa.Column("message", sa.String(length=255), nullable=True), + sa.Column("current_user_id", sa.Integer(), nullable=True), + sa.Column("spiff_step", sa.Integer(), nullable=False), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_message_correlation_property_identifier'), 'message_correlation_property', ['identifier'], unique=False) - op.create_table('message_triggerable_process_model', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('message_model_id', sa.Integer(), nullable=False), - sa.Column('process_model_identifier', sa.String(length=50), nullable=False), - sa.Column('process_group_identifier', sa.String(length=50), nullable=False), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['message_model_id'], ['message_model.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('message_model_id') + op.create_table( + "spiff_step_details", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("spiff_step", sa.Integer(), nullable=False), + sa.Column("task_json", sa.JSON(), nullable=False), + sa.Column("timestamp", sa.DECIMAL(precision=17, scale=6), nullable=False), + sa.Column("completed_by_user_id", sa.Integer(), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_message_triggerable_process_model_process_group_identifier'), 'message_triggerable_process_model', ['process_group_identifier'], unique=False) - op.create_index(op.f('ix_message_triggerable_process_model_process_model_identifier'), 'message_triggerable_process_model', ['process_model_identifier'], unique=False) - op.create_table('principal', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('group_id', sa.Integer(), nullable=True), - sa.CheckConstraint('NOT(user_id IS NULL AND group_id IS NULL)'), - sa.ForeignKeyConstraint(['group_id'], ['group.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('group_id'), - sa.UniqueConstraint('user_id') + op.create_table( + "user", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("username", sa.String(length=255), nullable=False), + sa.Column("uid", sa.String(length=50), nullable=True), + sa.Column("service", sa.String(length=50), nullable=False), + sa.Column("service_id", sa.String(length=255), nullable=False), + sa.Column("name", sa.String(length=255), nullable=True), + sa.Column("email", sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("service", "service_id", name="service_key"), + sa.UniqueConstraint("uid"), + sa.UniqueConstraint("username"), ) - op.create_table('process_instance', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_model_identifier', sa.String(length=255), nullable=False), - sa.Column('process_group_identifier', sa.String(length=50), nullable=False), - sa.Column('process_initiator_id', sa.Integer(), nullable=False), - sa.Column('bpmn_json', sa.JSON(), nullable=True), - sa.Column('start_in_seconds', sa.Integer(), nullable=True), - sa.Column('end_in_seconds', sa.Integer(), nullable=True), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('status', sa.String(length=50), nullable=True), - sa.Column('bpmn_version_control_type', sa.String(length=50), nullable=True), - sa.Column('bpmn_version_control_identifier', sa.String(length=255), nullable=True), - sa.Column('spiff_step', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['process_initiator_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "message_correlation_property", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("identifier", sa.String(length=50), nullable=True), + sa.Column("message_model_id", sa.Integer(), nullable=False), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["message_model_id"], + ["message_model.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "identifier", "message_model_id", name="message_correlation_property_unique" + ), ) - op.create_index(op.f('ix_process_instance_process_group_identifier'), 'process_instance', ['process_group_identifier'], unique=False) - op.create_index(op.f('ix_process_instance_process_model_identifier'), 'process_instance', ['process_model_identifier'], unique=False) - op.create_table('process_instance_report', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('identifier', sa.String(length=50), nullable=False), - sa.Column('report_metadata', sa.JSON(), nullable=True), - sa.Column('created_by_id', sa.Integer(), nullable=False), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('created_by_id', 'identifier', name='process_instance_report_unique') + op.create_index( + op.f("ix_message_correlation_property_identifier"), + "message_correlation_property", + ["identifier"], + unique=False, ) - op.create_index(op.f('ix_process_instance_report_created_by_id'), 'process_instance_report', ['created_by_id'], unique=False) - op.create_index(op.f('ix_process_instance_report_identifier'), 'process_instance_report', ['identifier'], unique=False) - op.create_table('refresh_token', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('token', sa.String(length=1024), nullable=False), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('user_id') + op.create_table( + "message_triggerable_process_model", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("message_model_id", sa.Integer(), nullable=False), + sa.Column("process_model_identifier", sa.String(length=50), nullable=False), + sa.Column("process_group_identifier", sa.String(length=50), nullable=False), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["message_model_id"], + ["message_model.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("message_model_id"), ) - op.create_table('secret', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('key', sa.String(length=50), nullable=False), - sa.Column('value', sa.Text(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('key') + op.create_index( + op.f("ix_message_triggerable_process_model_process_group_identifier"), + "message_triggerable_process_model", + ["process_group_identifier"], + unique=False, ) - op.create_table('user_group_assignment', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('group_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['group_id'], ['group.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('user_id', 'group_id', name='user_group_assignment_unique') + op.create_index( + op.f("ix_message_triggerable_process_model_process_model_identifier"), + "message_triggerable_process_model", + ["process_model_identifier"], + unique=False, ) - op.create_table('active_task', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('actual_owner_id', sa.Integer(), nullable=True), - sa.Column('lane_assignment_id', sa.Integer(), nullable=True), - sa.Column('form_file_name', sa.String(length=50), nullable=True), - sa.Column('ui_form_file_name', sa.String(length=50), nullable=True), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('task_id', sa.String(length=50), nullable=True), - sa.Column('task_name', sa.String(length=50), nullable=True), - sa.Column('task_title', sa.String(length=50), nullable=True), - sa.Column('task_type', sa.String(length=50), nullable=True), - sa.Column('task_status', sa.String(length=50), nullable=True), - sa.Column('process_model_display_name', sa.String(length=255), nullable=True), - sa.ForeignKeyConstraint(['actual_owner_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['lane_assignment_id'], ['group.id'], ), - sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('task_id', 'process_instance_id', name='active_task_unique') + op.create_table( + "principal", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("group_id", sa.Integer(), nullable=True), + sa.CheckConstraint("NOT(user_id IS NULL AND group_id IS NULL)"), + sa.ForeignKeyConstraint( + ["group_id"], + ["group.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("group_id"), + sa.UniqueConstraint("user_id"), ) - op.create_table('message_correlation', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('message_correlation_property_id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('value', sa.String(length=255), nullable=False), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['message_correlation_property_id'], ['message_correlation_property.id'], ), - sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('process_instance_id', 'message_correlation_property_id', 'name', name='message_instance_id_name_unique') + op.create_table( + "process_instance", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_model_identifier", sa.String(length=255), nullable=False), + sa.Column("process_group_identifier", sa.String(length=50), nullable=False), + sa.Column("process_initiator_id", sa.Integer(), nullable=False), + sa.Column("bpmn_json", sa.JSON(), nullable=True), + sa.Column("start_in_seconds", sa.Integer(), nullable=True), + sa.Column("end_in_seconds", sa.Integer(), nullable=True), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("status", sa.String(length=50), nullable=True), + sa.Column("bpmn_version_control_type", sa.String(length=50), nullable=True), + sa.Column( + "bpmn_version_control_identifier", sa.String(length=255), nullable=True + ), + sa.Column("spiff_step", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["process_initiator_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_index(op.f('ix_message_correlation_message_correlation_property_id'), 'message_correlation', ['message_correlation_property_id'], unique=False) - op.create_index(op.f('ix_message_correlation_name'), 'message_correlation', ['name'], unique=False) - op.create_index(op.f('ix_message_correlation_process_instance_id'), 'message_correlation', ['process_instance_id'], unique=False) - op.create_index(op.f('ix_message_correlation_value'), 'message_correlation', ['value'], unique=False) - op.create_table('message_instance', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('process_instance_id', sa.Integer(), nullable=False), - sa.Column('message_model_id', sa.Integer(), nullable=False), - sa.Column('message_type', sa.String(length=20), nullable=False), - sa.Column('payload', sa.JSON(), nullable=True), - sa.Column('status', sa.String(length=20), nullable=False), - sa.Column('failure_cause', sa.Text(), nullable=True), - sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), - sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['message_model_id'], ['message_model.id'], ), - sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_index( + op.f("ix_process_instance_process_group_identifier"), + "process_instance", + ["process_group_identifier"], + unique=False, ) - op.create_table('permission_assignment', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('principal_id', sa.Integer(), nullable=False), - sa.Column('permission_target_id', sa.Integer(), nullable=False), - sa.Column('grant_type', sa.String(length=50), nullable=False), - sa.Column('permission', sa.String(length=50), nullable=False), - sa.ForeignKeyConstraint(['permission_target_id'], ['permission_target.id'], ), - sa.ForeignKeyConstraint(['principal_id'], ['principal.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('principal_id', 'permission_target_id', 'permission', name='permission_assignment_uniq') + op.create_index( + op.f("ix_process_instance_process_model_identifier"), + "process_instance", + ["process_model_identifier"], + unique=False, ) - op.create_table('active_task_user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('active_task_id', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['active_task_id'], ['active_task.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('active_task_id', 'user_id', name='active_task_user_unique') + op.create_table( + "process_instance_report", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("identifier", sa.String(length=50), nullable=False), + sa.Column("report_metadata", sa.JSON(), nullable=True), + sa.Column("created_by_id", sa.Integer(), nullable=False), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["created_by_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "created_by_id", "identifier", name="process_instance_report_unique" + ), ) - op.create_index(op.f('ix_active_task_user_active_task_id'), 'active_task_user', ['active_task_id'], unique=False) - op.create_index(op.f('ix_active_task_user_user_id'), 'active_task_user', ['user_id'], unique=False) - op.create_table('message_correlation_message_instance', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('message_instance_id', sa.Integer(), nullable=False), - sa.Column('message_correlation_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['message_correlation_id'], ['message_correlation.id'], ), - sa.ForeignKeyConstraint(['message_instance_id'], ['message_instance.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('message_instance_id', 'message_correlation_id', name='message_correlation_message_instance_unique') + op.create_index( + op.f("ix_process_instance_report_created_by_id"), + "process_instance_report", + ["created_by_id"], + unique=False, + ) + op.create_index( + op.f("ix_process_instance_report_identifier"), + "process_instance_report", + ["identifier"], + unique=False, + ) + op.create_table( + "refresh_token", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("token", sa.String(length=1024), nullable=False), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("user_id"), + ) + op.create_table( + "secret", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("key", sa.String(length=50), nullable=False), + sa.Column("value", sa.Text(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("key"), + ) + op.create_table( + "user_group_assignment", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("group_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["group_id"], + ["group.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("user_id", "group_id", name="user_group_assignment_unique"), + ) + op.create_table( + "active_task", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("actual_owner_id", sa.Integer(), nullable=True), + sa.Column("lane_assignment_id", sa.Integer(), nullable=True), + sa.Column("form_file_name", sa.String(length=50), nullable=True), + sa.Column("ui_form_file_name", sa.String(length=50), nullable=True), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("task_id", sa.String(length=50), nullable=True), + sa.Column("task_name", sa.String(length=50), nullable=True), + sa.Column("task_title", sa.String(length=50), nullable=True), + sa.Column("task_type", sa.String(length=50), nullable=True), + sa.Column("task_status", sa.String(length=50), nullable=True), + sa.Column("process_model_display_name", sa.String(length=255), nullable=True), + sa.ForeignKeyConstraint( + ["actual_owner_id"], + ["user.id"], + ), + sa.ForeignKeyConstraint( + ["lane_assignment_id"], + ["group.id"], + ), + sa.ForeignKeyConstraint( + ["process_instance_id"], + ["process_instance.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "task_id", "process_instance_id", name="active_task_unique" + ), + ) + op.create_table( + "message_correlation", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("message_correlation_property_id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=255), nullable=False), + sa.Column("value", sa.String(length=255), nullable=False), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["message_correlation_property_id"], + ["message_correlation_property.id"], + ), + sa.ForeignKeyConstraint( + ["process_instance_id"], + ["process_instance.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "process_instance_id", + "message_correlation_property_id", + "name", + name="message_instance_id_name_unique", + ), + ) + op.create_index( + op.f("ix_message_correlation_message_correlation_property_id"), + "message_correlation", + ["message_correlation_property_id"], + unique=False, + ) + op.create_index( + op.f("ix_message_correlation_name"), + "message_correlation", + ["name"], + unique=False, + ) + op.create_index( + op.f("ix_message_correlation_process_instance_id"), + "message_correlation", + ["process_instance_id"], + unique=False, + ) + op.create_index( + op.f("ix_message_correlation_value"), + "message_correlation", + ["value"], + unique=False, + ) + op.create_table( + "message_instance", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("process_instance_id", sa.Integer(), nullable=False), + sa.Column("message_model_id", sa.Integer(), nullable=False), + sa.Column("message_type", sa.String(length=20), nullable=False), + sa.Column("payload", sa.JSON(), nullable=True), + sa.Column("status", sa.String(length=20), nullable=False), + sa.Column("failure_cause", sa.Text(), nullable=True), + sa.Column("updated_at_in_seconds", sa.Integer(), nullable=True), + sa.Column("created_at_in_seconds", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["message_model_id"], + ["message_model.id"], + ), + sa.ForeignKeyConstraint( + ["process_instance_id"], + ["process_instance.id"], + ), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "permission_assignment", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("principal_id", sa.Integer(), nullable=False), + sa.Column("permission_target_id", sa.Integer(), nullable=False), + sa.Column("grant_type", sa.String(length=50), nullable=False), + sa.Column("permission", sa.String(length=50), nullable=False), + sa.ForeignKeyConstraint( + ["permission_target_id"], + ["permission_target.id"], + ), + sa.ForeignKeyConstraint( + ["principal_id"], + ["principal.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "principal_id", + "permission_target_id", + "permission", + name="permission_assignment_uniq", + ), + ) + op.create_table( + "active_task_user", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("active_task_id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["active_task_id"], + ["active_task.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "active_task_id", "user_id", name="active_task_user_unique" + ), + ) + op.create_index( + op.f("ix_active_task_user_active_task_id"), + "active_task_user", + ["active_task_id"], + unique=False, + ) + op.create_index( + op.f("ix_active_task_user_user_id"), + "active_task_user", + ["user_id"], + unique=False, + ) + op.create_table( + "message_correlation_message_instance", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("message_instance_id", sa.Integer(), nullable=False), + sa.Column("message_correlation_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["message_correlation_id"], + ["message_correlation.id"], + ), + sa.ForeignKeyConstraint( + ["message_instance_id"], + ["message_instance.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint( + "message_instance_id", + "message_correlation_id", + name="message_correlation_message_instance_unique", + ), + ) + op.create_index( + op.f("ix_message_correlation_message_instance_message_correlation_id"), + "message_correlation_message_instance", + ["message_correlation_id"], + unique=False, + ) + op.create_index( + op.f("ix_message_correlation_message_instance_message_instance_id"), + "message_correlation_message_instance", + ["message_instance_id"], + unique=False, ) - op.create_index(op.f('ix_message_correlation_message_instance_message_correlation_id'), 'message_correlation_message_instance', ['message_correlation_id'], unique=False) - op.create_index(op.f('ix_message_correlation_message_instance_message_instance_id'), 'message_correlation_message_instance', ['message_instance_id'], unique=False) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_index(op.f('ix_message_correlation_message_instance_message_instance_id'), table_name='message_correlation_message_instance') - op.drop_index(op.f('ix_message_correlation_message_instance_message_correlation_id'), table_name='message_correlation_message_instance') - op.drop_table('message_correlation_message_instance') - op.drop_index(op.f('ix_active_task_user_user_id'), table_name='active_task_user') - op.drop_index(op.f('ix_active_task_user_active_task_id'), table_name='active_task_user') - op.drop_table('active_task_user') - op.drop_table('permission_assignment') - op.drop_table('message_instance') - op.drop_index(op.f('ix_message_correlation_value'), table_name='message_correlation') - op.drop_index(op.f('ix_message_correlation_process_instance_id'), table_name='message_correlation') - op.drop_index(op.f('ix_message_correlation_name'), table_name='message_correlation') - op.drop_index(op.f('ix_message_correlation_message_correlation_property_id'), table_name='message_correlation') - op.drop_table('message_correlation') - op.drop_table('active_task') - op.drop_table('user_group_assignment') - op.drop_table('secret') - op.drop_table('refresh_token') - op.drop_index(op.f('ix_process_instance_report_identifier'), table_name='process_instance_report') - op.drop_index(op.f('ix_process_instance_report_created_by_id'), table_name='process_instance_report') - op.drop_table('process_instance_report') - op.drop_index(op.f('ix_process_instance_process_model_identifier'), table_name='process_instance') - op.drop_index(op.f('ix_process_instance_process_group_identifier'), table_name='process_instance') - op.drop_table('process_instance') - op.drop_table('principal') - op.drop_index(op.f('ix_message_triggerable_process_model_process_model_identifier'), table_name='message_triggerable_process_model') - op.drop_index(op.f('ix_message_triggerable_process_model_process_group_identifier'), table_name='message_triggerable_process_model') - op.drop_table('message_triggerable_process_model') - op.drop_index(op.f('ix_message_correlation_property_identifier'), table_name='message_correlation_property') - op.drop_table('message_correlation_property') - op.drop_table('user') - op.drop_table('spiff_step_details') - op.drop_table('spiff_logging') - op.drop_table('permission_target') - op.drop_index(op.f('ix_message_model_name'), table_name='message_model') - op.drop_index(op.f('ix_message_model_identifier'), table_name='message_model') - op.drop_table('message_model') - op.drop_table('group') - op.drop_index(op.f('ix_bpmn_process_id_lookup_bpmn_process_identifier'), table_name='bpmn_process_id_lookup') - op.drop_table('bpmn_process_id_lookup') + op.drop_index( + op.f("ix_message_correlation_message_instance_message_instance_id"), + table_name="message_correlation_message_instance", + ) + op.drop_index( + op.f("ix_message_correlation_message_instance_message_correlation_id"), + table_name="message_correlation_message_instance", + ) + op.drop_table("message_correlation_message_instance") + op.drop_index(op.f("ix_active_task_user_user_id"), table_name="active_task_user") + op.drop_index( + op.f("ix_active_task_user_active_task_id"), table_name="active_task_user" + ) + op.drop_table("active_task_user") + op.drop_table("permission_assignment") + op.drop_table("message_instance") + op.drop_index( + op.f("ix_message_correlation_value"), table_name="message_correlation" + ) + op.drop_index( + op.f("ix_message_correlation_process_instance_id"), + table_name="message_correlation", + ) + op.drop_index(op.f("ix_message_correlation_name"), table_name="message_correlation") + op.drop_index( + op.f("ix_message_correlation_message_correlation_property_id"), + table_name="message_correlation", + ) + op.drop_table("message_correlation") + op.drop_table("active_task") + op.drop_table("user_group_assignment") + op.drop_table("secret") + op.drop_table("refresh_token") + op.drop_index( + op.f("ix_process_instance_report_identifier"), + table_name="process_instance_report", + ) + op.drop_index( + op.f("ix_process_instance_report_created_by_id"), + table_name="process_instance_report", + ) + op.drop_table("process_instance_report") + op.drop_index( + op.f("ix_process_instance_process_model_identifier"), + table_name="process_instance", + ) + op.drop_index( + op.f("ix_process_instance_process_group_identifier"), + table_name="process_instance", + ) + op.drop_table("process_instance") + op.drop_table("principal") + op.drop_index( + op.f("ix_message_triggerable_process_model_process_model_identifier"), + table_name="message_triggerable_process_model", + ) + op.drop_index( + op.f("ix_message_triggerable_process_model_process_group_identifier"), + table_name="message_triggerable_process_model", + ) + op.drop_table("message_triggerable_process_model") + op.drop_index( + op.f("ix_message_correlation_property_identifier"), + table_name="message_correlation_property", + ) + op.drop_table("message_correlation_property") + op.drop_table("user") + op.drop_table("spiff_step_details") + op.drop_table("spiff_logging") + op.drop_table("permission_target") + op.drop_index(op.f("ix_message_model_name"), table_name="message_model") + op.drop_index(op.f("ix_message_model_identifier"), table_name="message_model") + op.drop_table("message_model") + op.drop_table("group") + op.drop_index( + op.f("ix_bpmn_process_id_lookup_bpmn_process_identifier"), + table_name="bpmn_process_id_lookup", + ) + op.drop_table("bpmn_process_id_lookup") # ### end Alembic commands ### diff --git a/poetry.lock b/poetry.lock index 285f19e78..8baf76e90 100644 --- a/poetry.lock +++ b/poetry.lock @@ -643,7 +643,7 @@ werkzeug = "*" type = "git" url = "https://github.com/sartography/flask-bpmn" reference = "main" -resolved_reference = "b9d4077955e0d45406946ef07440176fb9fd12e5" +resolved_reference = "df9ab9a12078e4f908c87778371725e0af414a11" [[package]] name = "Flask-Cors" diff --git a/src/spiffworkflow_backend/api.yml b/src/spiffworkflow_backend/api.yml index 2bfa117ea..14a0e52f6 100755 --- a/src/spiffworkflow_backend/api.yml +++ b/src/spiffworkflow_backend/api.yml @@ -141,6 +141,12 @@ paths: /process-groups: parameters: + - name: process_group_identifier + in: query + required: false + description: Optional parameter to filter by a single group + schema: + type: string - name: page in: query required: false @@ -413,7 +419,7 @@ paths: - name: process_status in: query required: false - description: For filtering - not_started, user_input_required, waiting, complete, faulted, or suspended + description: For filtering - not_started, user_input_required, waiting, complete, error, or suspended schema: type: string # process_instance_list @@ -702,33 +708,6 @@ paths: type: array items: $ref: "#/components/schemas/Workflow" - - /process-models/{process_group_id}/{process_model_id}/process-instances/reports: - parameters: - - name: process_group_id - in: path - required: true - description: The unique id of an existing process group - schema: - type: string - - name: process_model_id - in: path - required: true - description: The unique id of an existing process model. - schema: - type: string - - name: page - in: query - required: false - description: The page number to return. Defaults to page 1. - schema: - type: integer - - name: per_page - in: query - required: false - description: The page number to return. Defaults to page 1. - schema: - type: integer post: operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_create summary: Returns all process instance reports for process model @@ -776,39 +755,6 @@ paths: type: array items: $ref: "#/components/schemas/Workflow" - - /process-models/{process_group_id}/{process_model_id}/process-instances/reports/{report_identifier}: - parameters: - - name: process_group_id - in: path - required: true - description: The unique id of an existing process group - schema: - type: string - - name: process_model_id - in: path - required: true - description: The unique id of an existing process model. - schema: - type: string - - name: report_identifier - in: path - required: true - description: The unique id of an existing report - schema: - type: string - - name: page - in: query - required: false - description: The page number to return. Defaults to page 1. - schema: - type: integer - - name: per_page - in: query - required: false - description: The page number to return. Defaults to page 1. - schema: - type: integer put: operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_update summary: Updates a process instance report diff --git a/src/spiffworkflow_backend/models/process_group.py b/src/spiffworkflow_backend/models/process_group.py index 9efc8cf5e..6edb19e53 100644 --- a/src/spiffworkflow_backend/models/process_group.py +++ b/src/spiffworkflow_backend/models/process_group.py @@ -27,9 +27,7 @@ class ProcessGroup: process_models: list[ProcessModelInfo] = field( default_factory=list[ProcessModelInfo] ) - process_groups: list[ProcessGroup] = field( - default_factory=list['ProcessGroup'] - ) + process_groups: list[ProcessGroup] = field(default_factory=list["ProcessGroup"]) def __post_init__(self) -> None: """__post_init__.""" diff --git a/src/spiffworkflow_backend/models/process_instance.py b/src/spiffworkflow_backend/models/process_instance.py index 37b651575..cfa892528 100644 --- a/src/spiffworkflow_backend/models/process_instance.py +++ b/src/spiffworkflow_backend/models/process_instance.py @@ -61,10 +61,9 @@ class ProcessInstanceStatus(SpiffEnum): user_input_required = "user_input_required" waiting = "waiting" complete = "complete" - faulted = "faulted" + error = "error" suspended = "suspended" terminated = "terminated" - erroring = "erroring" class ProcessInstanceModel(SpiffworkflowBaseDBModel): diff --git a/src/spiffworkflow_backend/models/process_instance_report.py b/src/spiffworkflow_backend/models/process_instance_report.py index b6f16288f..1425d69f5 100644 --- a/src/spiffworkflow_backend/models/process_instance_report.py +++ b/src/spiffworkflow_backend/models/process_instance_report.py @@ -83,10 +83,6 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel): report_metadata = { "columns": [ {"Header": "id", "accessor": "id"}, - { - "Header": "process_group_identifier", - "accessor": "process_group_identifier", - }, { "Header": "process_model_identifier", "accessor": "process_model_identifier", diff --git a/src/spiffworkflow_backend/routes/process_api_blueprint.py b/src/spiffworkflow_backend/routes/process_api_blueprint.py index e37f2d0bd..17b64d4cc 100644 --- a/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -162,7 +162,9 @@ def process_group_delete(modified_process_group_id: str) -> flask.wrappers.Respo return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") -def process_group_update(modified_process_group_id: str, body: dict) -> flask.wrappers.Response: +def process_group_update( + modified_process_group_id: str, body: dict +) -> flask.wrappers.Response: """Process Group Update.""" body_include_list = ["display_name", "description"] body_filtered = { @@ -177,9 +179,16 @@ def process_group_update(modified_process_group_id: str, body: dict) -> flask.wr return make_response(jsonify(process_group), 200) -def process_groups_list(page: int = 1, per_page: int = 100) -> flask.wrappers.Response: +def process_groups_list( + process_group_identifier: Optional[str] = None, page: int = 1, per_page: int = 100 +) -> flask.wrappers.Response: """Process_groups_list.""" - process_groups = ProcessModelService().get_process_groups() + if process_group_identifier is not None: + process_groups = ProcessModelService().get_process_groups( + process_group_identifier + ) + else: + process_groups = ProcessModelService().get_process_groups() batch = ProcessModelService().get_batch( items=process_groups, page=page, per_page=per_page ) @@ -230,7 +239,9 @@ def process_model_add( ) modified_process_model_id = process_model_info.id - unmodified_process_model_id = un_modify_modified_process_model_id(modified_process_model_id) + unmodified_process_model_id = un_modify_modified_process_model_id( + modified_process_model_id + ) process_model_info.id = unmodified_process_model_id process_group_id, _ = os.path.split(process_model_info.id) process_model_service = ProcessModelService() diff --git a/src/spiffworkflow_backend/routes/user.py b/src/spiffworkflow_backend/routes/user.py index ed5961418..5fe10e0af 100644 --- a/src/spiffworkflow_backend/routes/user.py +++ b/src/spiffworkflow_backend/routes/user.py @@ -125,7 +125,9 @@ def verify_token( # no user_info else: raise ApiError( - error_code="no_user_info", message="Cannot retrieve user info", status_code=401 + error_code="no_user_info", + message="Cannot retrieve user info", + status_code=401, ) else: diff --git a/src/spiffworkflow_backend/services/acceptance_test_fixtures.py b/src/spiffworkflow_backend/services/acceptance_test_fixtures.py index c6c1b578a..cfea3148b 100644 --- a/src/spiffworkflow_backend/services/acceptance_test_fixtures.py +++ b/src/spiffworkflow_backend/services/acceptance_test_fixtures.py @@ -24,7 +24,7 @@ def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]: # user_input_required - 2 hours ago # waiting - 3 hourse ago # complete - 4 hours ago - # faulted - 5 hours ago + # error - 5 hours ago # suspended - 6 hours ago process_instances = [] for i in range(len(statuses)): diff --git a/src/spiffworkflow_backend/services/error_handling_service.py b/src/spiffworkflow_backend/services/error_handling_service.py index 3f1622a47..99e4fbe8c 100644 --- a/src/spiffworkflow_backend/services/error_handling_service.py +++ b/src/spiffworkflow_backend/services/error_handling_service.py @@ -46,7 +46,7 @@ class ErrorHandlingService: # fault is the default self.set_instance_status( _processor.process_instance_model.id, - ProcessInstanceStatus.faulted.value, + ProcessInstanceStatus.error.value, ) if len(process_model.exception_notification_addresses) > 0: diff --git a/src/spiffworkflow_backend/services/file_system_service.py b/src/spiffworkflow_backend/services/file_system_service.py index a4a01b836..15327400b 100644 --- a/src/spiffworkflow_backend/services/file_system_service.py +++ b/src/spiffworkflow_backend/services/file_system_service.py @@ -34,7 +34,7 @@ class FileSystemService: @staticmethod def process_group_path(name: str) -> str: """Category_path.""" - return os.path.join(FileSystemService.root_path(), name) + return os.path.abspath(os.path.join(FileSystemService.root_path(), name)) @staticmethod def full_path_from_relative_path(relative_path: str) -> str: diff --git a/src/spiffworkflow_backend/services/process_instance_service.py b/src/spiffworkflow_backend/services/process_instance_service.py index 7854537e3..ca9f66aa7 100644 --- a/src/spiffworkflow_backend/services/process_instance_service.py +++ b/src/spiffworkflow_backend/services/process_instance_service.py @@ -64,7 +64,7 @@ class ProcessInstanceService: processor.do_engine_steps(save=True) except Exception as e: db.session.rollback() # in case the above left the database with a bad transaction - process_instance.status = ProcessInstanceStatus.erroring.value + process_instance.status = ProcessInstanceStatus.error.value db.session.add(process_instance) db.session.commit() error_message = ( diff --git a/src/spiffworkflow_backend/services/process_model_service.py b/src/spiffworkflow_backend/services/process_model_service.py index d64596cb8..f473a4ca0 100644 --- a/src/spiffworkflow_backend/services/process_model_service.py +++ b/src/spiffworkflow_backend/services/process_model_service.py @@ -161,9 +161,11 @@ class ProcessModelService(FileSystemService): process_models.sort() return process_models - def get_process_groups(self) -> list[ProcessGroup]: + def get_process_groups( + self, process_group_id: Optional[str] = None + ) -> list[ProcessGroup]: """Returns the process_groups as a list in display order.""" - process_groups = self.__scan_process_groups() + process_groups = self.__scan_process_groups(process_group_id) process_groups.sort() return process_groups @@ -213,10 +215,35 @@ class ProcessModelService(FileSystemService): ) return process_group + def __get_all_nested_models(self, group_path: str) -> list: + """__get_all_nested_models.""" + all_nested_models = [] + for root, dirs, files in os.walk(group_path): + for dir in dirs: + model_dir = os.path.join(group_path, dir) + if ProcessModelService().is_model(model_dir): + process_model = self.get_process_model(model_dir) + all_nested_models.append(process_model) + return all_nested_models + def process_group_delete(self, process_group_id: str) -> None: """Delete_process_group.""" + problem_models = [] path = self.process_group_path(process_group_id) if os.path.exists(path): + nested_models = self.__get_all_nested_models(path) + for process_model in nested_models: + instances = ProcessInstanceModel.query.filter( + ProcessInstanceModel.process_model_identifier == process_model.id + ).all() + if len(instances) > 0: + problem_models.append(process_model) + if len(problem_models) > 0: + raise ApiError( + error_code="existing_instances", + message=f"We cannot delete the group `{process_group_id}`, " + f"there are models with existing instances inside the group. {problem_models}", + ) shutil.rmtree(path) self.cleanup_process_group_display_order() @@ -230,12 +257,18 @@ class ProcessModelService(FileSystemService): index += 1 return process_groups - def __scan_process_groups(self) -> list[ProcessGroup]: + def __scan_process_groups( + self, process_group_id: Optional[str] = None + ) -> list[ProcessGroup]: """__scan_process_groups.""" if not os.path.exists(FileSystemService.root_path()): return [] # Nothing to scan yet. There are no files. + if process_group_id is not None: + scan_path = os.path.join(FileSystemService.root_path(), process_group_id) + else: + scan_path = FileSystemService.root_path() - with os.scandir(FileSystemService.root_path()) as directory_items: + with os.scandir(scan_path) as directory_items: process_groups = [] for item in directory_items: # if item.is_dir() and not item.name[0] == ".": @@ -275,9 +308,7 @@ class ProcessModelService(FileSystemService): if self.is_group(nested_item.path): # This is a nested group process_group.process_groups.append( - self.__scan_process_group( - nested_item.path - ) + self.__scan_process_group(nested_item.path) ) elif self.is_model(nested_item.path): process_group.process_models.append( diff --git a/tests/data/simple_form/simple_form.bpmn b/tests/data/simple_form/simple_form.bpmn new file mode 100644 index 000000000..410561738 --- /dev/null +++ b/tests/data/simple_form/simple_form.bpmn @@ -0,0 +1,63 @@ + + + + + Flow_0smvjir + + + + Flow_1boyhcj + + + + + Hello {{ name }} +Department: {{ department }} + + + Flow_1ly1khd + Flow_1boyhcj + + + + + + + + + + Flow_0smvjir + Flow_1ly1khd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/data/simple_form/simple_form.json b/tests/data/simple_form/simple_form.json new file mode 100644 index 000000000..68a9e4de7 --- /dev/null +++ b/tests/data/simple_form/simple_form.json @@ -0,0 +1,24 @@ +{ + "title": "Simple form", + "description": "A simple form example.", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "title": "Name", + "default": "World" + }, + "department": { + "type": "string", + "title": "Department", + "enum": [ + "Finance", + "HR", + "IT" + ] + } + } +} diff --git a/tests/data/simple_form/simple_form_ui.json b/tests/data/simple_form/simple_form_ui.json new file mode 100644 index 000000000..9ceddac03 --- /dev/null +++ b/tests/data/simple_form/simple_form_ui.json @@ -0,0 +1,11 @@ +{ + "name": { + "ui:title": "Name", + "ui:description": "(Your name)" + }, + "department": { + "ui:title": "Department", + "ui:description": "(Your department)" + }, + "ui:order": ["name", "department"] +} diff --git a/tests/spiffworkflow_backend/helpers/base_test.py b/tests/spiffworkflow_backend/helpers/base_test.py index 794e1cea6..e3660ad44 100644 --- a/tests/spiffworkflow_backend/helpers/base_test.py +++ b/tests/spiffworkflow_backend/helpers/base_test.py @@ -8,7 +8,6 @@ from typing import Dict from typing import Optional from flask import current_app -from flask.app import Flask from flask.testing import FlaskClient from flask_bpmn.api.api_error import ApiError from flask_bpmn.models.db import db @@ -35,7 +34,30 @@ from spiffworkflow_backend.services.user_service import UserService class BaseTest: """BaseTest.""" - def basic_test_setup( + @staticmethod + def find_or_create_user(username: str = "test_user_1") -> UserModel: + """Find_or_create_user.""" + user = UserModel.query.filter_by(username=username).first() + if isinstance(user, UserModel): + return user + + user = UserService.create_user("internal", username, username=username) + if isinstance(user, UserModel): + return user + + raise ApiError( + error_code="create_user_error", + message=f"Cannot find or create user: {username}", + ) + + @staticmethod + def logged_in_headers( + user: UserModel, _redirect_url: str = "http://some/frontend/url" + ) -> Dict[str, str]: + """Logged_in_headers.""" + return dict(Authorization="Bearer " + user.encode_auth_token()) + + def create_group_and_model_with_bpmn( self, client: FlaskClient, user: UserModel, @@ -75,56 +97,27 @@ class BaseTest: return process_model_identifier - @staticmethod - def find_or_create_user(username: str = "test_user_1") -> UserModel: - """Find_or_create_user.""" - user = UserModel.query.filter_by(username=username).first() - if isinstance(user, UserModel): - return user - - user = UserService.create_user("internal", username, username=username) - if isinstance(user, UserModel): - return user - - raise ApiError( - error_code="create_user_error", - message=f"Cannot find or create user: {username}", - ) - - @staticmethod - def get_open_id_constants(app: Flask) -> tuple: - """Get_open_id_constants.""" - open_id_server_url = app.config["OPEN_ID_SERVER_URL"] - open_id_client_id = app.config["OPEN_ID_CLIENT_ID"] - open_id_realm_name = app.config["OPEN_ID_REALM_NAME"] - open_id_client_secret_key = app.config[ - "OPEN_ID_CLIENT_SECRET_KEY" - ] # noqa: S105 - - return ( - open_id_server_url, - open_id_client_id, - open_id_realm_name, - open_id_client_secret_key, - ) - - @staticmethod - def create_process_instance( + def create_process_group( + self, client: FlaskClient, - test_process_model_id: str, - headers: Dict[str, str], - ) -> TestResponse: - """Create_process_instance. - - There must be an existing process model to instantiate. - """ - modified_process_model_id = test_process_model_id.replace("/", ":") + user: Any, + process_group_id: str, + display_name: str = "", + ) -> str: + """Create_process_group.""" + process_group = ProcessGroup( + id=process_group_id, display_name=display_name, display_order=0, admin=False + ) response = client.post( - f"/v1.0/process-models/{modified_process_model_id}/process-instances", - headers=headers, + "/v1.0/process-groups", + headers=self.logged_in_headers(user), + content_type="application/json", + data=json.dumps(ProcessGroupSchema().dump(process_group)), ) assert response.status_code == 201 - return response + assert response.json is not None + assert response.json["id"] == process_group_id + return process_group_id def create_process_model_with_api( self, @@ -178,6 +171,22 @@ class BaseTest: "You must include the process_model_id, which must be a path to the model" ) + def get_test_data_file_contents( + self, file_name: str, process_model_test_data_dir: str + ) -> bytes: + """Get_test_data_file_contents.""" + file_full_path = os.path.join( + current_app.instance_path, + "..", + "..", + "tests", + "data", + process_model_test_data_dir, + file_name, + ) + with open(file_full_path, "rb") as file: + return file.read() + def create_spec_file( self, client: FlaskClient, @@ -230,27 +239,23 @@ class BaseTest: assert file["file_contents"] == file2["file_contents"] return file - def create_process_group( - self, + @staticmethod + def create_process_instance_from_process_model_id( client: FlaskClient, - user: Any, - process_group_id: str, - display_name: str = "", - ) -> str: - """Create_process_group.""" - process_group = ProcessGroup( - id=process_group_id, display_name=display_name, display_order=0, admin=False - ) + test_process_model_id: str, + headers: Dict[str, str], + ) -> TestResponse: + """Create_process_instance. + + There must be an existing process model to instantiate. + """ + modified_process_model_id = test_process_model_id.replace("/", ":") response = client.post( - "/v1.0/process-groups", - headers=self.logged_in_headers(user), - content_type="application/json", - data=json.dumps(ProcessGroupSchema().dump(process_group)), + f"/v1.0/process-models/{modified_process_model_id}/process-instances", + headers=headers, ) assert response.status_code == 201 - assert response.json is not None - assert response.json["id"] == process_group_id - return process_group_id + return response # @staticmethod # def get_public_access_token(username: str, password: str) -> dict: @@ -324,29 +329,6 @@ class BaseTest: ) return user - @staticmethod - def logged_in_headers( - user: UserModel, _redirect_url: str = "http://some/frontend/url" - ) -> Dict[str, str]: - """Logged_in_headers.""" - return dict(Authorization="Bearer " + user.encode_auth_token()) - - def get_test_data_file_contents( - self, file_name: str, process_model_test_data_dir: str - ) -> bytes: - """Get_test_data_file_contents.""" - file_full_path = os.path.join( - current_app.instance_path, - "..", - "..", - "tests", - "data", - process_model_test_data_dir, - file_name, - ) - with open(file_full_path, "rb") as file: - return file.read() - def assert_user_has_permission( self, user: UserModel, diff --git a/tests/spiffworkflow_backend/integration/test_logging_service.py b/tests/spiffworkflow_backend/integration/test_logging_service.py index 02d8ade17..97dafaf3f 100644 --- a/tests/spiffworkflow_backend/integration/test_logging_service.py +++ b/tests/spiffworkflow_backend/integration/test_logging_service.py @@ -45,7 +45,7 @@ class TestLoggingService(BaseTest): user=with_super_admin_user, ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None diff --git a/tests/spiffworkflow_backend/integration/test_nested_groups.py b/tests/spiffworkflow_backend/integration/test_nested_groups.py index ef89a561a..9a48ebf18 100644 --- a/tests/spiffworkflow_backend/integration/test_nested_groups.py +++ b/tests/spiffworkflow_backend/integration/test_nested_groups.py @@ -10,11 +10,123 @@ from spiffworkflow_backend.models.process_group import ProcessGroupSchema from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema from spiffworkflow_backend.models.user import UserModel +from spiffworkflow_backend.services.process_instance_service import ( + ProcessInstanceService, +) class TestNestedGroups(BaseTest): """TestNestedGroups.""" + def test_delete_group_with_running_instance( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + """Test_delete_group_with_running_instance.""" + process_group_id = "test_group" + process_model_id = "manual_task" + bpmn_file_name = "manual_task.bpmn" + bpmn_file_location = "manual_task" + process_model_identifier = self.create_group_and_model_with_bpmn( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location, + ) + response = self.create_process_instance_from_process_model_id( + client, + process_model_identifier, + self.logged_in_headers(with_super_admin_user), + ) + process_instance_id = response.json["id"] + + client.post( + f"/v1.0/process-instances/{process_instance_id}/run", + headers=self.logged_in_headers(with_super_admin_user), + ) + process_instance = ProcessInstanceService().get_process_instance( + process_instance_id + ) + assert process_instance + modified_process_group_id = process_group_id.replace("/", ":") + response = client.delete( + f"/v1.0/process-groups/{modified_process_group_id}", + headers=self.logged_in_headers(with_super_admin_user), + ) + assert response.status_code == 400 + assert response.json["error_code"] == "existing_instances" + assert "We cannot delete the group" in response.json["message"] + assert ( + "there are models with existing instances inside the group" + in response.json["message"] + ) + + def test_delete_group_with_running_instance_in_nested_group( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + """Test_delete_group_with_running_instance_in_nested_group.""" + process_group_a = ProcessGroup( + id="group_a", + display_name="Group A", + display_order=0, + admin=False, + ) + response_a = client.post( # noqa: F841 + "/v1.0/process-groups", + headers=self.logged_in_headers(with_super_admin_user), + content_type="application/json", + data=json.dumps(ProcessGroupSchema().dump(process_group_a)), + ) + + process_group_id = "group_a/test_group" + process_model_id = "manual_task" + bpmn_file_name = "manual_task.bpmn" + bpmn_file_location = "manual_task" + process_model_identifier = self.create_group_and_model_with_bpmn( + client, + with_super_admin_user, + process_group_id=process_group_id, + process_model_id=process_model_id, + bpmn_file_name=bpmn_file_name, + bpmn_file_location=bpmn_file_location, + ) + response = self.create_process_instance_from_process_model_id( + client, + process_model_identifier, + self.logged_in_headers(with_super_admin_user), + ) + process_instance_id = response.json["id"] + + client.post( + f"/v1.0/process-instances/{process_instance_id}/run", + headers=self.logged_in_headers(with_super_admin_user), + ) + process_instance = ProcessInstanceService().get_process_instance( + process_instance_id + ) + assert process_instance + modified_process_group_id = process_group_id.replace("/", ":") + response = client.delete( + f"/v1.0/process-groups/{modified_process_group_id}", + headers=self.logged_in_headers(with_super_admin_user), + ) + assert response.status_code == 400 + assert response.json["error_code"] == "existing_instances" + assert "We cannot delete the group" in response.json["message"] + assert ( + "there are models with existing instances inside the group" + in response.json["message"] + ) + def test_nested_groups( self, app: Flask, diff --git a/tests/spiffworkflow_backend/integration/test_process_api.py b/tests/spiffworkflow_backend/integration/test_process_api.py index 91355e0e0..a45336841 100644 --- a/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/tests/spiffworkflow_backend/integration/test_process_api.py @@ -286,7 +286,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) # create an instance from a model - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) @@ -623,7 +623,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_id = process_model_identifier.replace("/", ":") data = {"key1": "THIS DATA"} @@ -647,7 +649,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_id = process_model_identifier.replace("/", ":") data = {"file": (io.BytesIO(b""), "random_fact.svg")} @@ -723,7 +727,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) # self.create_spec_file(client, user=with_super_admin_user) # process_model = load_test_spec("random_fact") @@ -749,7 +755,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.delete( @@ -770,7 +778,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_process_model_file_update.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.delete( @@ -797,7 +807,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_file.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.get( @@ -817,7 +829,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_workflow_from_workflow_spec.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) modified_process_model_identifier = process_model_identifier.replace("/", ":") response = client.post( @@ -852,7 +866,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_groups_when_there_are_some.""" - self.basic_test_setup(client, with_super_admin_user) + self.create_group_and_model_with_bpmn(client, with_super_admin_user) response = client.get( "/v1.0/process-groups", headers=self.logged_in_headers(with_super_admin_user), @@ -872,7 +886,9 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_group_when_found.""" - process_model_identifier = self.basic_test_setup(client, with_super_admin_user) + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) process_group_id, process_model_id = os.path.split(process_model_identifier) response = client.get( @@ -893,7 +909,7 @@ class TestProcessApi(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_get_process_model_when_found.""" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, bpmn_file_name="random_fact.bpmn" ) modified_process_model_identifier = process_model_identifier.replace("/", ":") @@ -938,7 +954,9 @@ class TestProcessApi(BaseTest): """Test_process_instance_create.""" test_process_model_id = "runs_without_input/sample" headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance(client, test_process_model_id, headers) + response = self.create_process_instance_from_process_model_id( + client, test_process_model_id, headers + ) assert response.json is not None assert response.json["updated_at_in_seconds"] is not None assert response.json["status"] == "not_started" @@ -956,7 +974,7 @@ class TestProcessApi(BaseTest): ) -> None: """Test_process_instance_run.""" # process_model_id = "runs_without_input/sample" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id="runs_without_input", @@ -966,7 +984,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None @@ -998,7 +1016,7 @@ class TestProcessApi(BaseTest): """Test_process_instance_show.""" process_group_id = "simple_script" process_model_id = "simple_script" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1006,7 +1024,7 @@ class TestProcessApi(BaseTest): ) modified_process_model_identifier = process_model_identifier.replace("/", ":") headers = self.logged_in_headers(with_super_admin_user) - create_response = self.create_process_instance( + create_response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert create_response.json is not None @@ -1041,7 +1059,7 @@ class TestProcessApi(BaseTest): process_model_id = "message_receiver" bpmn_file_name = "message_receiver.bpmn" bpmn_file_location = "message_send_one_conversation" - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1089,7 +1107,7 @@ class TestProcessApi(BaseTest): process_model_id = "message_sender" bpmn_file_name = "message_sender.bpmn" bpmn_file_location = "message_send_one_conversation" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1106,7 +1124,7 @@ class TestProcessApi(BaseTest): "andThis": "another_item_non_key", } } - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, self.logged_in_headers(with_super_admin_user), @@ -1157,7 +1175,7 @@ class TestProcessApi(BaseTest): process_model_id = "message_sender" bpmn_file_name = "message_sender.bpmn" bpmn_file_location = "message_send_one_conversation" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1166,7 +1184,7 @@ class TestProcessApi(BaseTest): bpmn_file_location=bpmn_file_location, ) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, self.logged_in_headers(with_super_admin_user), @@ -1206,7 +1224,7 @@ class TestProcessApi(BaseTest): process_model_id = "user_task" bpmn_file_name = "user_task.bpmn" bpmn_file_location = "user_task" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1216,7 +1234,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None @@ -1245,7 +1263,7 @@ class TestProcessApi(BaseTest): process_group_id = "my_process_group" process_model_id = "dynamic_enum_select_fields" bpmn_file_location = "dynamic_enum_select_fields" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1255,7 +1273,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None @@ -1297,7 +1315,7 @@ class TestProcessApi(BaseTest): process_group_id = "runs_without_input" process_model_id = "sample" bpmn_file_location = "sample" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1306,7 +1324,9 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - self.create_process_instance(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) response = client.get( "/v1.0/process-instances", @@ -1342,7 +1362,7 @@ class TestProcessApi(BaseTest): process_model_id = "sample" bpmn_file_name = "sample.bpmn" bpmn_file_location = "sample" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1351,11 +1371,21 @@ class TestProcessApi(BaseTest): bpmn_file_location=bpmn_file_location, ) headers = self.logged_in_headers(with_super_admin_user) - self.create_process_instance(client, process_model_identifier, headers) - self.create_process_instance(client, process_model_identifier, headers) - self.create_process_instance(client, process_model_identifier, headers) - self.create_process_instance(client, process_model_identifier, headers) - self.create_process_instance(client, process_model_identifier, headers) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) + self.create_process_instance_from_process_model_id( + client, process_model_identifier, headers + ) response = client.get( "/v1.0/process-instances?per_page=2&page=3", @@ -1391,7 +1421,7 @@ class TestProcessApi(BaseTest): process_model_id = "sample" bpmn_file_name = "sample.bpmn" bpmn_file_location = "sample" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1504,7 +1534,7 @@ class TestProcessApi(BaseTest): process_model_id = "sample" bpmn_file_name = "sample.bpmn" bpmn_file_location = "sample" - process_model_identifier = self.basic_test_setup( # noqa: F841 + process_model_identifier = self.create_group_and_model_with_bpmn( # noqa: F841 client, with_super_admin_user, process_group_id=process_group_id, @@ -1544,7 +1574,7 @@ class TestProcessApi(BaseTest): process_model_id = "sample" # bpmn_file_name = "sample.bpmn" # bpmn_file_location = "sample" - # process_model_identifier = self.basic_test_setup( + # process_model_identifier = self.create_group_and_model_with_bpmn( # client, # with_super_admin_user, # process_group_id=process_group_id, @@ -1658,7 +1688,9 @@ class TestProcessApi(BaseTest): ) -> Any: """Setup_testing_instance.""" headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance(client, process_model_id, headers) + response = self.create_process_instance_from_process_model_id( + client, process_model_id, headers + ) process_instance = response.json assert isinstance(process_instance, dict) process_instance_id = process_instance["id"] @@ -1676,7 +1708,7 @@ class TestProcessApi(BaseTest): process_model_id = "error" bpmn_file_name = "error.bpmn" bpmn_file_location = "error" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1716,7 +1748,7 @@ class TestProcessApi(BaseTest): .first() ) assert process is not None - assert process.status == "faulted" + assert process.status == "error" def test_error_handler_suspend( self, @@ -1730,7 +1762,7 @@ class TestProcessApi(BaseTest): process_model_id = "error" bpmn_file_name = "error.bpmn" bpmn_file_location = "error" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1784,7 +1816,7 @@ class TestProcessApi(BaseTest): process_model_id = "error" bpmn_file_name = "error.bpmn" bpmn_file_location = "error" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1827,7 +1859,7 @@ class TestProcessApi(BaseTest): .first() ) assert process is not None - assert process.status == "faulted" + assert process.status == "error" def test_process_model_file_create( self, @@ -1843,7 +1875,7 @@ class TestProcessApi(BaseTest): file_data = b"abc123" bpmn_file_name = "hello_world.bpmn" bpmn_file_location = "hello_world" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1876,7 +1908,7 @@ class TestProcessApi(BaseTest): process_model_id = "message_receiver" bpmn_file_name = "message_receiver.bpmn" bpmn_file_location = "message_send_one_conversation" - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1968,7 +2000,7 @@ class TestProcessApi(BaseTest): process_model_id = "model_with_lanes" bpmn_file_name = "lanes.bpmn" bpmn_file_location = "model_with_lanes" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -1983,7 +2015,7 @@ class TestProcessApi(BaseTest): # process_group_id="finance", # ) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, # process_model.process_group_id, process_model_identifier, @@ -2171,7 +2203,7 @@ class TestProcessApi(BaseTest): """Test_process_instance_suspend.""" bpmn_file_name = "manual_task.bpmn" bpmn_file_location = "manual_task" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_model_id="manual_task", @@ -2192,7 +2224,7 @@ class TestProcessApi(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) assert response.json is not None @@ -2239,7 +2271,7 @@ class TestProcessApi(BaseTest): process_model_id = "simple_script" bpmn_file_name = "simple_script.bpmn" bpmn_file_location = "simple_script" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=process_group_id, diff --git a/tests/spiffworkflow_backend/unit/test_authorization_service.py b/tests/spiffworkflow_backend/unit/test_authorization_service.py index 5d0a10be1..916347b35 100644 --- a/tests/spiffworkflow_backend/unit/test_authorization_service.py +++ b/tests/spiffworkflow_backend/unit/test_authorization_service.py @@ -104,7 +104,7 @@ class TestAuthorizationService(BaseTest): self.find_or_create_user("testuser1") AuthorizationService.import_permissions_from_yaml_file() - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id="test_group", diff --git a/tests/spiffworkflow_backend/unit/test_dot_notation.py b/tests/spiffworkflow_backend/unit/test_dot_notation.py index ff37c3b5f..6bd1cca6d 100644 --- a/tests/spiffworkflow_backend/unit/test_dot_notation.py +++ b/tests/spiffworkflow_backend/unit/test_dot_notation.py @@ -27,7 +27,7 @@ class TestDotNotation(BaseTest): process_model_id = "test_dot_notation" bpmn_file_name = "diagram.bpmn" bpmn_file_location = "dot_notation" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, @@ -37,7 +37,7 @@ class TestDotNotation(BaseTest): ) headers = self.logged_in_headers(with_super_admin_user) - response = self.create_process_instance( + response = self.create_process_instance_from_process_model_id( client, process_model_identifier, headers ) process_instance_id = response.json["id"] diff --git a/tests/spiffworkflow_backend/unit/test_message_instance.py b/tests/spiffworkflow_backend/unit/test_message_instance.py index 39b37f2c2..0292032ee 100644 --- a/tests/spiffworkflow_backend/unit/test_message_instance.py +++ b/tests/spiffworkflow_backend/unit/test_message_instance.py @@ -20,7 +20,7 @@ class TestMessageInstance(BaseTest): process_model_id = "hello_world" bpmn_file_name = "hello_world.bpmn" bpmn_file_location = "hello_world" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, user, process_group_id=process_group_id, diff --git a/tests/spiffworkflow_backend/unit/test_spec_file_service.py b/tests/spiffworkflow_backend/unit/test_spec_file_service.py index d74acb47b..76195449d 100644 --- a/tests/spiffworkflow_backend/unit/test_spec_file_service.py +++ b/tests/spiffworkflow_backend/unit/test_spec_file_service.py @@ -35,7 +35,7 @@ class TestSpecFileService(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_can_store_process_ids_for_lookup.""" - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=self.process_group_id, @@ -60,7 +60,7 @@ class TestSpecFileService(BaseTest): ) -> None: """Test_fails_to_save_duplicate_process_id.""" bpmn_process_identifier = "Level1" - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=self.process_group_id, @@ -104,7 +104,7 @@ class TestSpecFileService(BaseTest): db.session.add(process_id_lookup) db.session.commit() - self.basic_test_setup( + self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=self.process_group_id, @@ -144,7 +144,7 @@ class TestSpecFileService(BaseTest): """ process_group_id = "test_group" process_model_id = "call_activity_nested" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client=client, user=with_super_admin_user, process_group_id=process_group_id, diff --git a/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py b/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py index c655d3ffd..aa91fcfd3 100644 --- a/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py +++ b/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py @@ -21,7 +21,7 @@ class TestVariousBpmnConstructs(BaseTest): with_super_admin_user: UserModel, ) -> None: """Test_running_process_with_timer_intermediate_catch_event.""" - process_model_identifier = self.basic_test_setup( + process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, "test_group", From e10bc47851566a4812b9dbec81d0b15b245388e9 Mon Sep 17 00:00:00 2001 From: burnettk Date: Fri, 11 Nov 2022 11:41:01 -0500 Subject: [PATCH 07/17] Squashed 'spiffworkflow-frontend/' changes from ab6cf28172..c096ca3f9c c096ca3f9c Report URL fixes (#29) ca49db4d76 get pagination for groups 2bff2d4b28 Merge branch 'main' into feature/nested-groups-2 8a443ebe2c use error as a status instead of faulted w/ burnettk 2e32ed4d4d favor h1 tags over h2 w/ burnettk 0a4ac2d53e fixed up the process instance show page and moved contents of scss to css file and load that last w/ burnettk 670cbabb04 fix lint d21a944674 Assure we are using the latest bpmn-js-spiffworkflow library. a5339a3cbd Use the modify method 3983a6eda0 Minor fixes for the launch buttons. c631616991 moved usage of ProcessBreadcrumb to use hotCrumbs except for report pages d06a3b6b75 cleaned up breadcrumbs some more and cleaned up console.log statements 614080e39d support process-groups in breadcrumb component fe8f790176 add breadcrumb to instances page sometimes 2206972c56 fix recent process models, at least after they visit process model show page ff0721362e make Files half-width and add link to file f085382253 lint git-subtree-dir: spiffworkflow-frontend git-subtree-split: c096ca3f9c99df2812191b2a02702c1916c239bd --- package-lock.json | 9 +- src/components/NavigationBar.tsx | 10 + src/components/ProcessBreadcrumb.test.tsx | 33 --- src/components/ProcessBreadcrumb.tsx | 12 +- src/components/ProcessGroupForm.tsx | 5 +- src/components/ReactDiagramEditor.tsx | 7 +- src/components/SubNavigation.tsx | 7 + src/config.tsx | 3 +- src/helpers.tsx | 10 +- src/index.css | 110 ++++++++-- src/index.scss | 82 ------- src/index.tsx | 2 +- src/interfaces.ts | 2 +- src/routes/AdminRoutes.tsx | 8 +- src/routes/HomePage.tsx | 13 +- src/routes/MessageInstanceList.tsx | 40 ++-- src/routes/ProcessGroupEdit.tsx | 12 +- src/routes/ProcessGroupNew.tsx | 13 +- src/routes/ProcessGroupShow.tsx | 56 +++-- src/routes/ProcessInstanceList.tsx | 31 +-- src/routes/ProcessInstanceLogList.tsx | 23 +- src/routes/ProcessInstanceReportEdit.tsx | 12 +- src/routes/ProcessInstanceReportList.tsx | 18 +- src/routes/ProcessInstanceReportNew.tsx | 9 +- src/routes/ProcessInstanceReportShow.tsx | 4 +- src/routes/ProcessInstanceShow.tsx | 252 +++++++++++++++------- src/routes/ProcessModelEdit.tsx | 15 +- src/routes/ProcessModelEditDiagram.tsx | 70 +++--- src/routes/ProcessModelNew.tsx | 12 +- src/routes/ProcessModelShow.tsx | 189 ++++++++-------- src/routes/ReactFormEditor.tsx | 7 +- src/routes/SecretList.tsx | 2 +- src/routes/SecretNew.tsx | 2 +- src/routes/SecretShow.tsx | 2 +- 34 files changed, 610 insertions(+), 472 deletions(-) diff --git a/package-lock.json b/package-lock.json index 42c0fad8a..258b3e586 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7485,7 +7485,7 @@ }, "node_modules/bpmn-js-spiffworkflow": { "version": "0.0.8", - "resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#24c2cc36067adf8fed75990c6bf4a1a67bc9122b", + "resolved": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#09fa713bb0bb1b9d4f97684afc46bc3711e11770", "license": "MIT", "dependencies": { "inherits": "^2.0.4", @@ -35755,7 +35755,7 @@ } }, "bpmn-js-spiffworkflow": { - "version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#24c2cc36067adf8fed75990c6bf4a1a67bc9122b", + "version": "git+ssh://git@github.com/sartography/bpmn-js-spiffworkflow.git#09fa713bb0bb1b9d4f97684afc46bc3711e11770", "from": "bpmn-js-spiffworkflow@sartography/bpmn-js-spiffworkflow#main", "requires": { "inherits": "^2.0.4", @@ -46545,7 +46545,7 @@ "@csstools/postcss-text-decoration-shorthand": "^1.0.0", "@csstools/postcss-trigonometric-functions": "^1.0.2", "@csstools/postcss-unset-value": "^1.0.2", - "autoprefixer": "10.4.5", + "autoprefixer": "10.4.8", "browserslist": "^4.21.3", "css-blank-pseudo": "^3.0.3", "css-has-pseudo": "^3.0.4", @@ -46583,8 +46583,7 @@ }, "dependencies": { "autoprefixer": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.5.tgz", + "version": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.5.tgz", "integrity": "sha512-Fvd8yCoA7lNX/OUllvS+aS1I7WRBclGXsepbvT8ZaPgrH24rgXpZzF0/6Hh3ZEkwg+0AES/Osd196VZmYoEFtw==", "requires": { "browserslist": "^4.20.2", diff --git a/src/components/NavigationBar.tsx b/src/components/NavigationBar.tsx index 7ecd7c475..25ff3582f 100644 --- a/src/components/NavigationBar.tsx +++ b/src/components/NavigationBar.tsx @@ -38,6 +38,10 @@ export default function NavigationBar() { let newActiveKey = '/admin/process-groups'; if (location.pathname.match(/^\/admin\/messages\b/)) { newActiveKey = '/admin/messages'; + } else if ( + location.pathname.match(/^\/admin\/process-instances\/reports\b/) + ) { + newActiveKey = '/admin/process-instances/reports'; } else if (location.pathname.match(/^\/admin\/process-instances\b/)) { newActiveKey = '/admin/process-instances'; } else if (location.pathname.match(/^\/admin\/secrets\b/)) { @@ -119,6 +123,12 @@ export default function NavigationBar() { > Authentications + + Reports + ); }; diff --git a/src/components/ProcessBreadcrumb.test.tsx b/src/components/ProcessBreadcrumb.test.tsx index c581f30db..49400e8e3 100644 --- a/src/components/ProcessBreadcrumb.test.tsx +++ b/src/components/ProcessBreadcrumb.test.tsx @@ -25,36 +25,3 @@ test('renders hotCrumbs', () => { const nextElement = screen.getByText(/Process Group: hey/); expect(nextElement).toBeInTheDocument(); }); - -// FIXME: update to use hotcrumbs -// test('renders process group when given processGroupId', async () => { -// render( -// -// -// -// ); -// const processGroupElement = screen.getByText(/group-a/); -// expect(processGroupElement).toBeInTheDocument(); -// const processGroupBreadcrumbs = await screen.findAllByText( -// /Process Group: group-a/ -// ); -// expect(processGroupBreadcrumbs[0]).toHaveClass('breadcrumb-item active'); -// }); -// -// test('renders process model when given processModelId', async () => { -// render( -// -// -// -// ); -// const processGroupElement = screen.getByText(/group-b/); -// expect(processGroupElement).toBeInTheDocument(); -// const processModelBreadcrumbs = await screen.findAllByText( -// /Process Model: model-c/ -// ); -// expect(processModelBreadcrumbs[0]).toHaveClass('breadcrumb-item active'); -// const processGroupBreadcrumbs = await screen.findAllByText( -// /Process Group: group-b/ -// ); -// expect(processGroupBreadcrumbs[0]).toBeInTheDocument(); -// }); diff --git a/src/components/ProcessBreadcrumb.tsx b/src/components/ProcessBreadcrumb.tsx index 3b2a9af98..23d2558ea 100644 --- a/src/components/ProcessBreadcrumb.tsx +++ b/src/components/ProcessBreadcrumb.tsx @@ -13,7 +13,7 @@ type OwnProps = { const explodeCrumb = (crumb: HotCrumbItem) => { const url: string = crumb[1] || ''; // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [_unused, processModelId, link] = url.split(':'); + const [endingUrlType, processModelId, link] = url.split(':'); const processModelIdSegments = splitProcessModelId(processModelId); const paths: string[] = []; const lastPathItem = processModelIdSegments.pop(); @@ -29,7 +29,13 @@ const explodeCrumb = (crumb: HotCrumbItem) => { } ); if (link === 'link') { - const lastUrl = `/admin/process-models/${paths.join(':')}:${lastPathItem}`; + if (lastPathItem !== undefined) { + paths.push(lastPathItem); + } + // process_model to process-models + const lastUrl = `/admin/${endingUrlType + .replace('_', '-') + .replace(/s*$/, 's')}/${paths.join(':')}`; breadcrumbItems.push( {lastPathItem} @@ -64,7 +70,7 @@ export default function ProcessBreadcrumb({ ); } - if (url && url.startsWith('process_model:')) { + if (url && url.match(/^process[_-](model|group)s?:/)) { return explodeCrumb(crumb); } return ( diff --git a/src/components/ProcessGroupForm.tsx b/src/components/ProcessGroupForm.tsx index 09f2ceccd..3d51adeb9 100644 --- a/src/components/ProcessGroupForm.tsx +++ b/src/components/ProcessGroupForm.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; // @ts-ignore import { Button, ButtonSet, Form, Stack, TextInput } from '@carbon/react'; -import {modifyProcessModelPath, slugifyString} from '../helpers'; +import { modifyProcessModelPath, slugifyString } from '../helpers'; import HttpService from '../services/HttpService'; import { ProcessGroup } from '../interfaces'; import ButtonWithConfirmation from './ButtonWithConfirmation'; @@ -79,12 +79,9 @@ export default function ProcessGroupForm({ description: processGroup.description, }; if (mode === 'new') { - console.log(`parentGroupId: ${parentGroupId}`); - console.log(`processGroup.id: ${processGroup.id}`); if (parentGroupId) { newProcessGroupId = `${parentGroupId}/${processGroup.id}`; } - console.log(`newProcessGroupId: ${newProcessGroupId}`); Object.assign(postBody, { id: parentGroupId ? `${parentGroupId}/${processGroup.id}` diff --git a/src/components/ReactDiagramEditor.tsx b/src/components/ReactDiagramEditor.tsx index e9ddb4452..37a947e43 100644 --- a/src/components/ReactDiagramEditor.tsx +++ b/src/components/ReactDiagramEditor.tsx @@ -229,7 +229,7 @@ export default function ReactDiagramEditor({ diagramModeler.on('spiff.script.edit', (event: any) => { const { error, element, scriptType, script, eventBus } = event; if (error) { - console.log(error); + console.error(error); } handleLaunchScriptEditor(element, script, scriptType, eventBus); }); @@ -237,7 +237,7 @@ export default function ReactDiagramEditor({ diagramModeler.on('spiff.markdown.edit', (event: any) => { const { error, element, value, eventBus } = event; if (error) { - console.log(error); + console.error(error); } handleLaunchMarkdownEditor(element, value, eventBus); }); @@ -318,7 +318,7 @@ export default function ReactDiagramEditor({ } function handleError(err: any) { - console.log('ERROR:', err); + console.error('ERROR:', err); } function checkTaskCanBeHighlighted(taskBpmnId: string) { @@ -406,7 +406,6 @@ export default function ReactDiagramEditor({ } function fetchDiagramFromURL(urlToUse: any) { - console.log(`urlToUse: ${urlToUse}`); fetch(urlToUse) .then((response) => response.text()) .then((text) => { diff --git a/src/components/SubNavigation.tsx b/src/components/SubNavigation.tsx index 6c5369aa7..be3097f72 100644 --- a/src/components/SubNavigation.tsx +++ b/src/components/SubNavigation.tsx @@ -10,6 +10,10 @@ export default function SubNavigation() { let newActiveKey = '/admin/process-groups'; if (location.pathname.match(/^\/admin\/messages\b/)) { newActiveKey = '/admin/messages'; + } else if ( + location.pathname.match(/^\/admin\/process-instances\/reports\b/) + ) { + newActiveKey = '/admin/process-instances/reports'; } else if (location.pathname.match(/^\/admin\/process-instances\b/)) { newActiveKey = '/admin/process-instances'; } else if (location.pathname.match(/^\/admin\/secrets\b/)) { @@ -45,6 +49,9 @@ export default function SubNavigation() { Authentications + + Reports + ); } diff --git a/src/config.tsx b/src/config.tsx index c9e94eb06..47ff5025a 100644 --- a/src/config.tsx +++ b/src/config.tsx @@ -12,10 +12,11 @@ export const PROCESS_STATUSES = [ 'user_input_required', 'waiting', 'complete', - 'faulted', + 'error', 'suspended', ]; // with time: yyyy-MM-dd HH:mm:ss +export const DATE_TIME_FORMAT = 'yyyy-MM-dd HH:mm:ss'; export const DATE_FORMAT = 'yyyy-MM-dd'; export const DATE_FORMAT_CARBON = 'Y-m-d'; diff --git a/src/helpers.tsx b/src/helpers.tsx index 564c99f1b..383c3e0a5 100644 --- a/src/helpers.tsx +++ b/src/helpers.tsx @@ -1,5 +1,5 @@ import { format } from 'date-fns'; -import { DATE_FORMAT } from './config'; +import { DATE_TIME_FORMAT, DATE_FORMAT } from './config'; import { DEFAULT_PER_PAGE, DEFAULT_PAGE, @@ -51,6 +51,14 @@ export const convertStringToDate = (dateString: string) => { return null; }; +export const convertSecondsToFormattedDateTime = (seconds: number) => { + if (seconds) { + const dateObject = new Date(seconds * 1000); + return format(dateObject, DATE_TIME_FORMAT); + } + return null; +}; + export const convertSecondsToFormattedDate = (seconds: number) => { if (seconds) { const dateObject = new Date(seconds * 1000); diff --git a/src/index.css b/src/index.css index b1eedf700..c2e2e8028 100644 --- a/src/index.css +++ b/src/index.css @@ -1,24 +1,79 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +/* site is mainly using white theme. */ +/* header is mainly using g100 */ +/* mockup wanted white, not grey, text */ +.cds--header, a.cds--header__menu-item { + color: white; } +h1{ + height: 36px; + font-family: 'IBM Plex Sans'; + font-style: normal; + font-weight: 400; + font-size: 28px; + line-height: 36px; + color: #161616; + flex: none; + order: 0; + align-self: stretch; + flex-grow: 0; + margin-bottom: 1em +} + +.span-tag { + color: black; +} + +.cds--btn.button-white-background { + color: #393939; + background: #FFFFFF; + background-blend-mode: multiply; + border: 1px solid #393939; +} +.cds--btn.button-white-background:hover { + background: #525252; +} + +.cds--breadcrumb-item a.cds--link:hover { + color: #525252; +} +.cds--breadcrumb-item a.cds--link:visited { + color: #525252; +} +.cds--breadcrumb-item a.cds--link:visited:hover { + color: #525252; +} +.cds--breadcrumb-item a.cds--link { + color: #525252; +} + +.cds--btn--ghost { + color: black; +} +.cds--btn--ghost:visited { + color: black; +} +.cds--btn--ghost:hover { + color: black; +} +.cds--btn--ghost:visited:hover { + color: black; +} + +.cds--header__global .cds--btn--primary { + background-color: #161616 +} +.cds--btn--primary { + background-color: #393939; +} +.cds--btn--primary:hover { + background-color: #474747; +} code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } -span.bjs-crumb { - color: #0000ff; -} -.bjs-breadcrumbs li:last-of-type span.bjs-crumb a { - color: black; -} - .app-logo { height: 85%; width: 85%; @@ -52,6 +107,26 @@ span.bjs-crumb { margin-bottom: 2em; } +h1.with-icons { + margin-top: 5px; +} + +.grid-list-title { + font-weight: 600; + font-size: 14px; + line-height: 18px; + color: #161616; +} +.grid-date { + font-size: 14px; + line-height: 18px; + letter-spacing: 0.16px; + color: #525252; +} +.smaller-text { + font-size: 14px; +} + .diagram-editor-canvas { border:1px solid #000000; height:70vh; @@ -59,13 +134,6 @@ span.bjs-crumb { margin:auto; } -.cds--btn.button-white-background { - color: #393939; - background: #FFFFFF; - background-blend-mode: multiply; - border: 1px solid #393939; -} - .with-bottom-margin { margin-bottom: 1em; } diff --git a/src/index.scss b/src/index.scss index 37766c21f..86b769987 100644 --- a/src/index.scss +++ b/src/index.scss @@ -15,85 +15,3 @@ @use '@carbon/colors'; // @use '@carbon/react/scss/colors'; @use '@carbon/react/scss/themes'; - -// var(--cds-link-text-color, var(--cds-link-primary, #0f62fe)) - -// site is mainly using white theme. -// header is mainly using g100 -// mockup wanted white, not grey, text -.cds--header, a.cds--header__menu-item { - // background-color: colors.$gray-100; - color: white; -} -h1{ - height: 36px; - font-family: 'IBM Plex Sans'; - font-style: normal; - font-weight: 400; - font-size: 28px; - line-height: 36px; - color: #161616; - flex: none; - order: 0; - align-self: stretch; - flex-grow: 0; - margin-bottom: 1em -} - - -.cds--breadcrumb-item a.cds--link:hover { - color: #525252; -} -.cds--breadcrumb-item a.cds--link:visited { - color: #525252; -} -.cds--breadcrumb-item a.cds--link:visited:hover { - color: #525252; -} -.cds--breadcrumb-item a.cds--link { - color: #525252; -} - -.cds--btn--ghost { - color: black; -} -.cds--btn--ghost:visited { - color: black; -} -.cds--btn--ghost:hover { - color: black; -} -.cds--btn--ghost:visited:hover { - color: black; -} - -$slightly-lighter-gray: #474747; -$spiff-header-background-color: #161616; - -.cds--header__global .cds--btn--primary { - background-color: $spiff-header-background-color; -} -.cds--btn--primary { - background-color: #393939; -} -.cds--btn--primary:hover { - background-color: $slightly-lighter-gray; -} -// .cds--btn--ghost:visited { -// color: black; -// } -// .cds--btn--ghost:hover { -// color: black; -// } -// .cds--btn--ghost:visited:hover { -// color: black; -// } - - -// :root { -// --cds-link-primary: #525252; -// } -// .card { -// background: var(--orange); -// --orange: hsl(255, 72%, var(--lightness)); -// } diff --git a/src/index.tsx b/src/index.tsx index a2fab5c0b..7a602be60 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,8 +3,8 @@ import * as ReactDOMClient from 'react-dom/client'; import App from './App'; import 'bootstrap/dist/css/bootstrap.css'; -import './index.css'; import './index.scss'; +import './index.css'; import reportWebVitals from './reportWebVitals'; import UserService from './services/UserService'; diff --git a/src/interfaces.ts b/src/interfaces.ts index 1417a3a90..7c9cb0365 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -6,7 +6,7 @@ export interface Secret { } export interface RecentProcessModel { - processGroupIdentifier: string; + processGroupIdentifier?: string; processModelIdentifier: string; processModelDisplayName: string; } diff --git a/src/routes/AdminRoutes.tsx b/src/routes/AdminRoutes.tsx index 96293ee71..84609d663 100644 --- a/src/routes/AdminRoutes.tsx +++ b/src/routes/AdminRoutes.tsx @@ -81,19 +81,19 @@ export default function AdminRoutes() { element={} /> } /> } /> } /> } /> -

Processes I can start

+

Processes I can start

@@ -145,7 +145,7 @@ export default function HomePage() { ); return ( <> -

Tasks waiting for me

+

Tasks waiting for me

0 && buildRecentProcessModelSection(); + (recentProcessModels.length > 0 && buildRecentProcessModelSection()) || + null; if (pagination) { + if (tasksWaitingForMe === null && relevantProcessModelSection === null) { + return

No tasks are waiting for you.

; + } return ( <> - {tasksWaitingForMeComponent()} + {tasksWaitingForMe} {relevantProcessModelSection} ); diff --git a/src/routes/MessageInstanceList.tsx b/src/routes/MessageInstanceList.tsx index 6bc0a57d4..89bd6ac97 100644 --- a/src/routes/MessageInstanceList.tsx +++ b/src/routes/MessageInstanceList.tsx @@ -7,6 +7,8 @@ import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import { convertSecondsToFormattedDate, getPageInfoFromSearchParams, + modifyProcessModelPath, + unModifyProcessModelPath, } from '../helpers'; import HttpService from '../services/HttpService'; @@ -44,15 +46,9 @@ export default function MessageInstanceList() {
- - @@ -107,16 +104,29 @@ export default function MessageInstanceList() { )}&process_instance_id=${searchParams.get('process_instance_id')}`; breadcrumbElement = ( ); } return ( <> {breadcrumbElement} -

Messages

+

Messages

- -

Edit Process Group: {(processGroup as any).id}

+ +

Edit Process Group: {(processGroup as any).id}

({ id: '', display_name: '', description: '', }); + const hotCrumbs: HotCrumbItem[] = [['Process Groups', '/admin']]; + if (parentGroupId) { + hotCrumbs.push(['', `process_group:${parentGroupId}:link`]); + } + return ( <> - -

Add Process Group

+ +

Add Process Group

(null); const [processModels, setProcessModels] = useState([]); const [processGroups, setProcessGroups] = useState([]); - const [pagination, setPagination] = useState(null); + const [modelPagination, setModelPagination] = useState(null); + const [groupPagination, setGroupPagination] = useState(null); useEffect(() => { const { page, perPage } = getPageInfoFromSearchParams(searchParams); const setProcessModelFromResult = (result: any) => { setProcessModels(result.results); - setPagination(result.pagination); + setModelPagination(result.pagination); + }; + const setProcessGroupFromResult = (result: any) => { + setProcessGroups(result.results); + setGroupPagination(result.pagination); }; const processResult = (result: any) => { setProcessGroup(result); @@ -33,7 +42,10 @@ export default function ProcessGroupShow() { path: `/process-models?process_group_identifier=${unmodifiedProcessGroupId}&per_page=${perPage}&page=${page}`, successCallback: setProcessModelFromResult, }); - setProcessGroups(result.process_groups); + HttpService.makeCallToBackend({ + path: `/process-groups?process_group_identifier=${unmodifiedProcessGroupId}&per_page=${perPage}&page=${page}`, + successCallback: setProcessGroupFromResult, + }); }; HttpService.makeCallToBackend({ path: `/process-groups/${params.process_group_id}`, @@ -45,19 +57,19 @@ export default function ProcessGroupShow() { if (processGroup === null) { return null; } - const rows = processModels.map((row) => { - const modifiedProcessModelId: String = (row as any).id.replace('/', ':'); + const rows = processModels.map((row: ProcessModel) => { + const modifiedProcessModelId: String = modifyProcessModelPath((row as any).id); return ( -
+ - + ); }); @@ -81,19 +93,19 @@ export default function ProcessGroupShow() { if (processGroup === null) { return null; } - const rows = processGroups.map((row) => { - const modifiedProcessGroupId: String = modifyProcessModelPath((row as any).id); + const rows = processGroups.map((row: ProcessGroup) => { + const modifiedProcessGroupId: String = modifyProcessModelPath(row.id); return ( - + - + ); }); @@ -113,15 +125,15 @@ export default function ProcessGroupShow() { ); }; - if (processGroup && pagination) { + if (processGroup && groupPagination && modelPagination) { const { page, perPage } = getPageInfoFromSearchParams(searchParams); - const modifiedProcessGroupId = modifyProcessModelPath((processGroup as any).id); + const modifiedProcessGroupId = modifyProcessModelPath(processGroup.id); return ( <>
    @@ -149,18 +161,18 @@ export default function ProcessGroupShow() {

diff --git a/src/routes/ProcessInstanceList.tsx b/src/routes/ProcessInstanceList.tsx index 04fcfd875..b7c057344 100644 --- a/src/routes/ProcessInstanceList.tsx +++ b/src/routes/ProcessInstanceList.tsx @@ -41,6 +41,7 @@ import 'react-bootstrap-typeahead/css/Typeahead.css'; import 'react-bootstrap-typeahead/css/Typeahead.bs5.css'; import { PaginationObject, ProcessModel } from '../interfaces'; import ProcessModelSearch from '../components/ProcessModelSearch'; +import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; export default function ProcessInstanceList() { const params = useParams(); @@ -471,26 +472,31 @@ export default function ProcessInstanceList() { ); }; - const processInstanceTitleElement = () => { + const processInstanceBreadcrumbElement = () => { const processModelFullIdentifier = getProcessModelFullIdentifierFromSearchParams(searchParams); if (processModelFullIdentifier === null) { - return

Process Instances

; + return null; } + return ( -

- Process Instances for:{' '} - - {processModelFullIdentifier} - -

+ ); }; + const processInstanceTitleElement = () => { + return

Process Instances

; + }; + const toggleShowFilterOptions = () => { setShowFilterOptions(!showFilterOptions); }; @@ -499,6 +505,7 @@ export default function ProcessInstanceList() { const { page, perPage } = getPageInfoFromSearchParams(searchParams); return ( <> + {processInstanceBreadcrumbElement()} {processInstanceTitleElement()} { - // return null; const rows = processInstanceLogs.map((row) => { const rowToUse = row as any; - console.log(`rowToUse: ${rowToUse}`); return (
@@ -57,7 +56,7 @@ export default function ProcessInstanceLogList() { ); }); return ( -
- {rowToUse.process_group_identifier} - - - {rowToUse.process_model_identifier} @@ -60,7 +56,9 @@ export default function MessageInstanceList() { {rowToUse.process_instance_id} @@ -80,7 +78,6 @@ export default function MessageInstanceList() {
Instance IdProcess Group Process Model Process Instance Message Model
- {(row as any).id} + {row.id} {(row as any).display_name}{row.display_name}
- {(row as any).id} + {row.id} {(row as any).display_name}{row.display_name}
{rowToUse.bpmn_process_identifier}
+
@@ -75,13 +74,25 @@ export default function ProcessInstanceLogList() { }; if (pagination) { + console.log('params.process_model_id', params.process_model_id); const { page, perPage } = getPageInfoFromSearchParams(searchParams); return (
{ - navigate( - `/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${params.report_identifier}` - ); + navigate(`/admin/process-instances/reports/${params.report_identifier}`); }; const navigateToProcessInstanceReports = (_result: any) => { - navigate( - `/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports` - ); + navigate(`/admin/process-instances/reports`); }; useEffect(() => { @@ -111,8 +106,7 @@ export default function ProcessInstanceReportEdit() { return ( <> - -

Edit Process Instance Report: {params.report_identifier}

+

Edit Process Instance Report: {params.report_identifier}

{ HttpService.makeCallToBackend({ @@ -27,7 +22,7 @@ export default function ProcessInstanceReportList() {
Bpmn Process Identifier
{rowToUse.identifier} @@ -49,15 +44,8 @@ export default function ProcessInstanceReportList() { const headerStuff = ( <> - -

Reports for Process Model: {params.process_model_id}

- diff --git a/src/routes/ProcessInstanceReportNew.tsx b/src/routes/ProcessInstanceReportNew.tsx index 16d575fd6..124be4daf 100644 --- a/src/routes/ProcessInstanceReportNew.tsx +++ b/src/routes/ProcessInstanceReportNew.tsx @@ -1,10 +1,9 @@ import { useState } from 'react'; -import { useNavigate, useParams } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import HttpService from '../services/HttpService'; export default function ProcessInstanceReportNew() { - const params = useParams(); const navigate = useNavigate(); const [identifier, setIdentifier] = useState(''); @@ -13,9 +12,7 @@ export default function ProcessInstanceReportNew() { const [filterBy, setFilterBy] = useState(''); const navigateToNewProcessInstance = (_result: any) => { - navigate( - `/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${identifier}` - ); + navigate(`/admin/process-instances/reports/${identifier}`); }; const addProcessInstanceReport = (event: any) => { @@ -59,7 +56,7 @@ export default function ProcessInstanceReportNew() { return ( <> -

Add Process Model

+

Add Process Model