From c4ab065272e876739d51aab96467eb697196ad85 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 11 Nov 2022 09:27:32 -0500 Subject: [PATCH 1/5] noop, testing pre-commit hook. --- spiffworkflow-backend/README.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/spiffworkflow-backend/README.rst b/spiffworkflow-backend/README.rst index 4f769d64f..e9d3a68de 100644 --- a/spiffworkflow-backend/README.rst +++ b/spiffworkflow-backend/README.rst @@ -90,5 +90,3 @@ This project was generated from `@cjolowicz`_'s `Hypermodern Python Cookiecutter .. github-only .. _Contributor Guide: CONTRIBUTING.rst .. _Usage: https://spiffworkflow-backend.readthedocs.io/en/latest/usage.html - -(test) From f5db186866b1814647d5d12164eee293c299a5cf Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 11 Nov 2022 11:02:29 -0500 Subject: [PATCH 2/5] add a search button to the call activity to allow finding a process id through some sort of admin interface. --- bpmn-js-spiffworkflow/README.md | 4 +- .../CallActivityPropertiesProvider.js | 31 +++++++++++++- .../SpiffExtensionLaunchButton.js | 2 +- .../test/spec/CallActivitySpec.js | 42 +++++++++++++++---- spiffworkflow-backend/README.rst | 5 +-- 5 files changed, 69 insertions(+), 15 deletions(-) diff --git a/bpmn-js-spiffworkflow/README.md b/bpmn-js-spiffworkflow/README.md index c3de64f98..43c3eb8e5 100644 --- a/bpmn-js-spiffworkflow/README.md +++ b/bpmn-js-spiffworkflow/README.md @@ -72,7 +72,7 @@ this in the app.js file. Below is a table of all the events that are sent and accepted: | Event Name | Description | Fired or Acceped | Parameters | Description | -| ------------------------------ | ---------------------------------------------------------------------------- | ---------------- |----------------------| ------------------------------------------------------------------------ | +|--------------------------------|------------------------------------------------------------------------------| ---------------- |----------------------|--------------------------------------------------------------------------| | spiff.service\_tasks.requested | Request a list of available services that can be called from a service task. | Fired | \- | | | spiff.service\_tasks.returned | Provides a list of services. | Recieved | serviceTaskOperators | ex: \[{id:'Chuck Facts', parameters\[{id:'category', type:'string'}\]}\] | | spiff.script.edit | Request to edit a python script in some sort of facy editor. | Fired | scriptType | one of: script, preScript, postScript | @@ -87,6 +87,8 @@ Below is a table of all the events that are sent and accepted: | spiff.markdown.update | Update Markdown content for a paticular elements 'instructions'. | Recieved | element | The element that needs updating | | | | | value | Tne updated Markdown content | | spiff.callactivity.edit | Requst to edit a call activity by process id. | Fired | processId | The Process the users wants to edit | +| spiff.callactivity.search | Requst to search for a call activity | Fired | | | +| spiff.callactivity.update | Update the process id from a call activity (based on search) | Fired | processId | The Process the users wants to edit | | spiff.file.edit | request to edit a file, but file name. | Fired | value | The file name the user wants to edit | | spiff.dmn.edit | request to edit a dmn by process id. | Fired | value | The DMN id the user wants to edit | | spiff.json\_files.requested | request a list of local json files. | Fired | optionType | The type of options required ('json' or 'dmn') | diff --git a/bpmn-js-spiffworkflow/app/spiffworkflow/callActivity/propertiesPanel/CallActivityPropertiesProvider.js b/bpmn-js-spiffworkflow/app/spiffworkflow/callActivity/propertiesPanel/CallActivityPropertiesProvider.js index 24bb56f41..c5d20851a 100644 --- a/bpmn-js-spiffworkflow/app/spiffworkflow/callActivity/propertiesPanel/CallActivityPropertiesProvider.js +++ b/bpmn-js-spiffworkflow/app/spiffworkflow/callActivity/propertiesPanel/CallActivityPropertiesProvider.js @@ -46,7 +46,6 @@ function createCalledElementGroup(element, translate, moddle, commandStack) { translate, }, /* Commented out until such time as we can effectively calculate the list of available processes by process id */ - /* { id: `called_element_launch_button`, element, @@ -55,7 +54,14 @@ function createCalledElementGroup(element, translate, moddle, commandStack) { commandStack, translate, }, - */ + { + id: `called_element_find_button`, + element, + component: FindProcessButton, + moddle, + commandStack, + translate, + }, ], }; } @@ -91,6 +97,27 @@ function CalledElementTextField(props) { }); } +function FindProcessButton(props) { + const { element } = props; + const eventBus = useService('eventBus'); + return HeaderButton({ + id: 'spiffworkflow-search-call-activity-button', + class: 'spiffworkflow-properties-panel-button', + onClick: () => { + const processId = getCalledElementValue(element); + eventBus.fire('spiff.callactivity.search', { + element, + processId, + }); + // Listen for a response, to update the script. + eventBus.once('spiff.callactivity.update', (response) => { + element.businessObject.calledElement = response.value; + }); + }, + children: 'Search', + }); +} + function LaunchEditorButton(props) { const { element } = props; const eventBus = useService('eventBus'); diff --git a/bpmn-js-spiffworkflow/app/spiffworkflow/extensions/propertiesPanel/SpiffExtensionLaunchButton.js b/bpmn-js-spiffworkflow/app/spiffworkflow/extensions/propertiesPanel/SpiffExtensionLaunchButton.js index 332c9084a..233646db6 100644 --- a/bpmn-js-spiffworkflow/app/spiffworkflow/extensions/propertiesPanel/SpiffExtensionLaunchButton.js +++ b/bpmn-js-spiffworkflow/app/spiffworkflow/extensions/propertiesPanel/SpiffExtensionLaunchButton.js @@ -21,7 +21,7 @@ export function SpiffExtensionLaunchButton(props) { listenEvent, }); - // Listen for a respose if the listenEvent is provided, and + // Listen for a response if the listenEvent is provided, and // set the value to the response // Optional additional arguments if we should listen for a reponse. if (listenEvent) { diff --git a/bpmn-js-spiffworkflow/test/spec/CallActivitySpec.js b/bpmn-js-spiffworkflow/test/spec/CallActivitySpec.js index f4749884d..b2110bb03 100644 --- a/bpmn-js-spiffworkflow/test/spec/CallActivitySpec.js +++ b/bpmn-js-spiffworkflow/test/spec/CallActivitySpec.js @@ -9,13 +9,14 @@ import { inject } from 'bpmn-js/test/helper'; import { bootstrapPropertiesPanel, changeInput, - expectSelected, findButton, - findGroupEntry, pressButton, + expectSelected, + findButton, + findGroupEntry, + pressButton, } from './helpers'; import spiffModdleExtension from '../../app/spiffworkflow/moddle/spiffworkflow.json'; import callActivity from '../../app/spiffworkflow/callActivity'; - describe('Call Activities should work', function () { const xml = require('./bpmn/call_activity.bpmn').default; let container; @@ -60,9 +61,9 @@ describe('Call Activities should work', function () { expect(businessObject.get('calledElement')).to.equal('newProcessId'); }); - /** fixme: Reenable this when we add this button back in. - it('should issue an event to the event bus if user clicks the edit button', inject( - async function(eventBus) { + it('should issue an event to the event bus if user clicks the edit button', inject(async function ( + eventBus + ) { const shapeElement = await expectSelected('the_call_activity'); expect(shapeElement, "Can't find Call Activity").to.exist; const businessObject = getBusinessObject(shapeElement); @@ -79,5 +80,32 @@ describe('Call Activities should work', function () { await pressButton(button); expect(launchEvent.processId).to.exist; })); - */ + + it('should issue an event to the event bus if user clicks the search button', inject(async function ( + eventBus + ) { + const shapeElement = await expectSelected('the_call_activity'); + expect(shapeElement, "Can't find Call Activity").to.exist; + const businessObject = getBusinessObject(shapeElement); + expect(businessObject.get('calledElement')).to.equal('ProcessIdTBD1'); + + const entry = findGroupEntry('called_element', container); + const button = findButton( + 'spiffworkflow-search-call-activity-button', + entry + ); + expect(button).to.exist; + + let launchEvent; + eventBus.on('spiff.callactivity.search', function (event) { + launchEvent = event; + }); + await pressButton(button); + expect(launchEvent.processId).to.exist; + + eventBus.fire('spiff.callactivity.update', {value: 'searchedProcessId'}); + const textInput = domQuery('input', entry); + expect(businessObject.get('calledElement')).to.equal('searchedProcessId'); + + })); }); diff --git a/spiffworkflow-backend/README.rst b/spiffworkflow-backend/README.rst index e9d3a68de..404ed5205 100644 --- a/spiffworkflow-backend/README.rst +++ b/spiffworkflow-backend/README.rst @@ -1,9 +1,6 @@ Spiffworkflow Backend ========== - -|Tests| |Codecov| - -|pre-commit| |Black| +|Tests| |Codecov| |pre-commit| |Black| .. |Tests| image:: https://github.com/sartography/spiffworkflow-backend/workflows/Tests/badge.svg :target: https://github.com/sartography/spiffworkflow-backend/actions?workflow=Tests From 7c35b20446fe8a83589ff503b83836136af4698d Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 11 Nov 2022 11:24:35 -0500 Subject: [PATCH 3/5] Squashed 'spiffworkflow-backend/' changes from e78e32dcf..46a590749 46a590749 pulled in subtrees and resolved conflicts w/ burnettk 1dcad7262 Report URL fixes (#29) 131dbeb3c oops c50c85eda mypy fixes 3735b71e0 removed duplicate code ba08826c6 modify process_groups_list so it can process any group path, not just the root process_groups_list now takes an optional group path 1e09c9552 renamed and reordered some methods in base_test.py dfa79360c Merge branch 'main' into feature/nested-groups-2 450a8d075 Delete groups now checks for running instances in nested models also, pyl c814e991a use error as a status instead of faulted w/ burnettk 3211e7a49 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: 46a590749dc147d0fe7250dcb65d764e87fb2200 --- bin/import_tickets_for_command_line.py | 1 - bin/start_blocking_appscheduler.py | 1 - conftest.py | 5 +- migrations/env.py | 25 +- migrations/versions/fd00c59e1f60_.py | 769 ++++++++++++------ poetry.lock | 2 +- src/spiffworkflow_backend/__init__.py | 5 +- src/spiffworkflow_backend/api.yml | 68 +- src/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 +- src/spiffworkflow_backend/models/principal.py | 5 +- .../models/process_group.py | 1 - .../models/process_instance.py | 12 +- .../models/process_instance_report.py | 11 +- .../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 | 20 +- src/spiffworkflow_backend/routes/user.py | 7 +- .../routes/user_blueprint.py | 3 +- .../scripts/get_current_user.py | 1 - .../scripts/get_frontend_url.py | 1 - .../scripts/get_localtime.py | 1 - src/spiffworkflow_backend/scripts/script.py | 1 - .../services/acceptance_test_fixtures.py | 5 +- .../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 | 3 +- .../services/file_system_service.py | 3 +- .../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 | 3 +- .../services/process_model_service.py | 38 +- .../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.bpmn | 63 ++ tests/data/simple_form/simple_form.json | 24 + tests/data/simple_form/simple_form_ui.json | 13 + .../helpers/base_test.py | 162 ++-- .../helpers/example_data.py | 1 - .../helpers/test_data.py | 3 +- .../integration/test_authentication.py | 3 +- .../integration/test_logging_service.py | 5 +- .../integration/test_nested_groups.py | 115 ++- .../integration/test_process_api.py | 103 ++- .../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 | 5 +- .../unit/test_dot_notation.py | 7 +- .../unit/test_environment_var_script.py | 3 +- .../unit/test_message_instance.py | 5 +- .../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 | 13 +- .../unit/test_spiff_logging.py | 3 +- .../unit/test_various_bpmn_constructs.py | 5 +- tests/test_main.py | 1 - 86 files changed, 999 insertions(+), 666 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/bin/import_tickets_for_command_line.py b/bin/import_tickets_for_command_line.py index 8b145dc4a..5818d438d 100644 --- a/bin/import_tickets_for_command_line.py +++ b/bin/import_tickets_for_command_line.py @@ -2,7 +2,6 @@ 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/bin/start_blocking_appscheduler.py b/bin/start_blocking_appscheduler.py index 4af99e411..61b753f26 100755 --- a/bin/start_blocking_appscheduler.py +++ b/bin/start_blocking_appscheduler.py @@ -2,7 +2,6 @@ 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/conftest.py b/conftest.py index d73693c23..012f3c776 100644 --- a/conftest.py +++ b/conftest.py @@ -7,8 +7,6 @@ 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 @@ -19,6 +17,7 @@ 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 @@ -77,7 +76,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/__init__.py b/src/spiffworkflow_backend/__init__.py index 6ca51aef2..9f1a74e70 100644 --- a/src/spiffworkflow_backend/__init__.py +++ b/src/spiffworkflow_backend/__init__.py @@ -5,6 +5,7 @@ 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 @@ -14,9 +15,6 @@ 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 @@ -26,6 +24,7 @@ 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/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/config/__init__.py b/src/spiffworkflow_backend/config/__init__.py index b56683ca3..082195798 100644 --- a/src/spiffworkflow_backend/config/__init__.py +++ b/src/spiffworkflow_backend/config/__init__.py @@ -3,9 +3,8 @@ import os import threading from flask.app import Flask -from werkzeug.utils import ImportStringError - from spiffworkflow_backend.services.logging_service import setup_logger +from werkzeug.utils import ImportStringError class ConfigurationError(Exception): diff --git a/src/spiffworkflow_backend/models/active_task.py b/src/spiffworkflow_backend/models/active_task.py index ea9e10552..50bd8c75b 100644 --- a/src/spiffworkflow_backend/models/active_task.py +++ b/src/spiffworkflow_backend/models/active_task.py @@ -6,14 +6,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 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/src/spiffworkflow_backend/models/active_task_user.py b/src/spiffworkflow_backend/models/active_task_user.py index f194c38e4..002759b1b 100644 --- a/src/spiffworkflow_backend/models/active_task_user.py +++ b/src/spiffworkflow_backend/models/active_task_user.py @@ -5,10 +5,9 @@ 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/src/spiffworkflow_backend/models/file.py b/src/spiffworkflow_backend/models/file.py index 02ad5fc10..9260e1844 100644 --- a/src/spiffworkflow_backend/models/file.py +++ b/src/spiffworkflow_backend/models/file.py @@ -7,7 +7,6 @@ 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/src/spiffworkflow_backend/models/message_correlation.py b/src/spiffworkflow_backend/models/message_correlation.py index baec8270a..c3338f0b1 100644 --- a/src/spiffworkflow_backend/models/message_correlation.py +++ b/src/spiffworkflow_backend/models/message_correlation.py @@ -4,13 +4,12 @@ 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/src/spiffworkflow_backend/models/message_correlation_message_instance.py b/src/spiffworkflow_backend/models/message_correlation_message_instance.py index 320dfba3e..f056aec6f 100644 --- a/src/spiffworkflow_backend/models/message_correlation_message_instance.py +++ b/src/spiffworkflow_backend/models/message_correlation_message_instance.py @@ -3,10 +3,9 @@ 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/src/spiffworkflow_backend/models/message_correlation_property.py b/src/spiffworkflow_backend/models/message_correlation_property.py index b84b7140c..04acaa940 100644 --- a/src/spiffworkflow_backend/models/message_correlation_property.py +++ b/src/spiffworkflow_backend/models/message_correlation_property.py @@ -1,9 +1,8 @@ """Message_correlation_property.""" from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey - from spiffworkflow_backend.models.message_model import MessageModel +from sqlalchemy import ForeignKey class MessageCorrelationPropertyModel(SpiffworkflowBaseDBModel): diff --git a/src/spiffworkflow_backend/models/message_instance.py b/src/spiffworkflow_backend/models/message_instance.py index 61dd12b24..2bc9c2673 100644 --- a/src/spiffworkflow_backend/models/message_instance.py +++ b/src/spiffworkflow_backend/models/message_instance.py @@ -7,15 +7,14 @@ 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/src/spiffworkflow_backend/models/message_triggerable_process_model.py b/src/spiffworkflow_backend/models/message_triggerable_process_model.py index 97d54aa7d..b82580d7e 100644 --- a/src/spiffworkflow_backend/models/message_triggerable_process_model.py +++ b/src/spiffworkflow_backend/models/message_triggerable_process_model.py @@ -1,9 +1,8 @@ """Message_correlation_property.""" from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey - from spiffworkflow_backend.models.message_model import MessageModel +from sqlalchemy import ForeignKey class MessageTriggerableProcessModel(SpiffworkflowBaseDBModel): diff --git a/src/spiffworkflow_backend/models/permission_assignment.py b/src/spiffworkflow_backend/models/permission_assignment.py index 63295f74e..194341929 100644 --- a/src/spiffworkflow_backend/models/permission_assignment.py +++ b/src/spiffworkflow_backend/models/permission_assignment.py @@ -4,11 +4,10 @@ from typing import Any from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel -from sqlalchemy import ForeignKey -from sqlalchemy.orm import validates - from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.principal import PrincipalModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import validates class PermitDeny(enum.Enum): diff --git a/src/spiffworkflow_backend/models/principal.py b/src/spiffworkflow_backend/models/principal.py index c7efa8609..d43be35a4 100644 --- a/src/spiffworkflow_backend/models/principal.py +++ b/src/spiffworkflow_backend/models/principal.py @@ -3,13 +3,12 @@ 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/src/spiffworkflow_backend/models/process_group.py b/src/spiffworkflow_backend/models/process_group.py index 9efc8cf5e..4a93c417b 100644 --- a/src/spiffworkflow_backend/models/process_group.py +++ b/src/spiffworkflow_backend/models/process_group.py @@ -9,7 +9,6 @@ from typing import Any import marshmallow from marshmallow import post_load from marshmallow import Schema - from spiffworkflow_backend.models.process_model import ProcessModelInfo diff --git a/src/spiffworkflow_backend/models/process_instance.py b/src/spiffworkflow_backend/models/process_instance.py index 37b651575..cc53623ee 100644 --- a/src/spiffworkflow_backend/models/process_instance.py +++ b/src/spiffworkflow_backend/models/process_instance.py @@ -12,16 +12,15 @@ 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): @@ -61,10 +60,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..c4fcbad27 100644 --- a/src/spiffworkflow_backend/models/process_instance_report.py +++ b/src/spiffworkflow_backend/models/process_instance_report.py @@ -9,10 +9,6 @@ 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, ) @@ -21,6 +17,9 @@ 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] @@ -83,10 +82,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/models/process_model.py b/src/spiffworkflow_backend/models/process_model.py index d63197be2..1c82bd405 100644 --- a/src/spiffworkflow_backend/models/process_model.py +++ b/src/spiffworkflow_backend/models/process_model.py @@ -9,7 +9,6 @@ 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/src/spiffworkflow_backend/models/secret_model.py b/src/spiffworkflow_backend/models/secret_model.py index 92fd470a3..9cc338ed2 100644 --- a/src/spiffworkflow_backend/models/secret_model.py +++ b/src/spiffworkflow_backend/models/secret_model.py @@ -4,9 +4,8 @@ from dataclasses import dataclass from flask_bpmn.models.db import db from flask_bpmn.models.db import SpiffworkflowBaseDBModel from marshmallow import Schema -from sqlalchemy import ForeignKey - from spiffworkflow_backend.models.user import UserModel +from sqlalchemy import ForeignKey @dataclass() diff --git a/src/spiffworkflow_backend/models/user.py b/src/spiffworkflow_backend/models/user.py index c33a72e7a..0df4c9c21 100644 --- a/src/spiffworkflow_backend/models/user.py +++ b/src/spiffworkflow_backend/models/user.py @@ -10,13 +10,12 @@ 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/src/spiffworkflow_backend/models/user_group_assignment.py b/src/spiffworkflow_backend/models/user_group_assignment.py index fa5b620c8..8cccf1d8c 100644 --- a/src/spiffworkflow_backend/models/user_group_assignment.py +++ b/src/spiffworkflow_backend/models/user_group_assignment.py @@ -1,11 +1,10 @@ """UserGroupAssignment.""" 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.group import GroupModel from spiffworkflow_backend.models.user import UserModel +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship class UserGroupAssignmentModel(SpiffworkflowBaseDBModel): diff --git a/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py b/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py index 2e480f2a4..f13e4e073 100644 --- a/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py +++ b/src/spiffworkflow_backend/routes/admin_blueprint/admin_blueprint.py @@ -7,8 +7,6 @@ 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, ) @@ -18,6 +16,7 @@ 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/src/spiffworkflow_backend/routes/process_api_blueprint.py b/src/spiffworkflow_backend/routes/process_api_blueprint.py index e37f2d0bd..260da3788 100644 --- a/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -28,9 +28,6 @@ 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, ) @@ -78,6 +75,8 @@ 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): @@ -162,7 +161,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 +178,12 @@ 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 +234,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..45d7c2ae5 100644 --- a/src/spiffworkflow_backend/routes/user.py +++ b/src/spiffworkflow_backend/routes/user.py @@ -12,14 +12,13 @@ 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 @@ -125,7 +124,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/routes/user_blueprint.py b/src/spiffworkflow_backend/routes/user_blueprint.py index 29bbddcd1..9520dfc85 100644 --- a/src/spiffworkflow_backend/routes/user_blueprint.py +++ b/src/spiffworkflow_backend/routes/user_blueprint.py @@ -9,11 +9,10 @@ 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/src/spiffworkflow_backend/scripts/get_current_user.py b/src/spiffworkflow_backend/scripts/get_current_user.py index a1a1b47e9..4cdcdc37c 100644 --- a/src/spiffworkflow_backend/scripts/get_current_user.py +++ b/src/spiffworkflow_backend/scripts/get_current_user.py @@ -2,7 +2,6 @@ from typing import Any from flask import g - from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/src/spiffworkflow_backend/scripts/get_frontend_url.py b/src/spiffworkflow_backend/scripts/get_frontend_url.py index 9490df95a..6930c57e0 100644 --- a/src/spiffworkflow_backend/scripts/get_frontend_url.py +++ b/src/spiffworkflow_backend/scripts/get_frontend_url.py @@ -2,7 +2,6 @@ from typing import Any from flask import current_app - from spiffworkflow_backend.models.script_attributes_context import ( ScriptAttributesContext, ) diff --git a/src/spiffworkflow_backend/scripts/get_localtime.py b/src/spiffworkflow_backend/scripts/get_localtime.py index 689b86d8c..16b9bf577 100644 --- a/src/spiffworkflow_backend/scripts/get_localtime.py +++ b/src/spiffworkflow_backend/scripts/get_localtime.py @@ -4,7 +4,6 @@ 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/src/spiffworkflow_backend/scripts/script.py b/src/spiffworkflow_backend/scripts/script.py index b744694a2..7ed745d6e 100644 --- a/src/spiffworkflow_backend/scripts/script.py +++ b/src/spiffworkflow_backend/scripts/script.py @@ -9,7 +9,6 @@ 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/src/spiffworkflow_backend/services/acceptance_test_fixtures.py b/src/spiffworkflow_backend/services/acceptance_test_fixtures.py index c6c1b578a..c71e6069e 100644 --- a/src/spiffworkflow_backend/services/acceptance_test_fixtures.py +++ b/src/spiffworkflow_backend/services/acceptance_test_fixtures.py @@ -4,10 +4,9 @@ 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]: @@ -24,7 +23,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/authentication_service.py b/src/spiffworkflow_backend/services/authentication_service.py index 18f08d0f3..1ec35ae15 100644 --- a/src/spiffworkflow_backend/services/authentication_service.py +++ b/src/spiffworkflow_backend/services/authentication_service.py @@ -11,9 +11,8 @@ 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 werkzeug.wrappers import Response - from spiffworkflow_backend.models.refresh_token import RefreshTokenModel +from werkzeug.wrappers import Response class AuthenticationProviderTypes(enum.Enum): diff --git a/src/spiffworkflow_backend/services/authorization_service.py b/src/spiffworkflow_backend/services/authorization_service.py index 75c17ab86..7c654609c 100644 --- a/src/spiffworkflow_backend/services/authorization_service.py +++ b/src/spiffworkflow_backend/services/authorization_service.py @@ -11,8 +11,6 @@ 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 @@ -27,6 +25,7 @@ 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/src/spiffworkflow_backend/services/background_processing_service.py b/src/spiffworkflow_backend/services/background_processing_service.py index 08a2b02df..8c4fee6e7 100644 --- a/src/spiffworkflow_backend/services/background_processing_service.py +++ b/src/spiffworkflow_backend/services/background_processing_service.py @@ -1,6 +1,5 @@ """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/src/spiffworkflow_backend/services/data_setup_service.py b/src/spiffworkflow_backend/services/data_setup_service.py index 23df25f34..226003c46 100644 --- a/src/spiffworkflow_backend/services/data_setup_service.py +++ b/src/spiffworkflow_backend/services/data_setup_service.py @@ -1,6 +1,5 @@ """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/src/spiffworkflow_backend/services/error_handling_service.py b/src/spiffworkflow_backend/services/error_handling_service.py index 3f1622a47..8bf377bdc 100644 --- a/src/spiffworkflow_backend/services/error_handling_service.py +++ b/src/spiffworkflow_backend/services/error_handling_service.py @@ -5,7 +5,6 @@ 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 @@ -46,7 +45,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..f6091de09 100644 --- a/src/spiffworkflow_backend/services/file_system_service.py +++ b/src/spiffworkflow_backend/services/file_system_service.py @@ -7,7 +7,6 @@ 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 @@ -34,7 +33,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/git_service.py b/src/spiffworkflow_backend/services/git_service.py index 815e4cadc..08f45386d 100644 --- a/src/spiffworkflow_backend/services/git_service.py +++ b/src/spiffworkflow_backend/services/git_service.py @@ -2,7 +2,6 @@ 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/src/spiffworkflow_backend/services/group_service.py b/src/spiffworkflow_backend/services/group_service.py index aa560009e..a2e54460a 100644 --- a/src/spiffworkflow_backend/services/group_service.py +++ b/src/spiffworkflow_backend/services/group_service.py @@ -2,7 +2,6 @@ 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/src/spiffworkflow_backend/services/logging_service.py b/src/spiffworkflow_backend/services/logging_service.py index c4e8c8ae9..201a7e5c2 100644 --- a/src/spiffworkflow_backend/services/logging_service.py +++ b/src/spiffworkflow_backend/services/logging_service.py @@ -8,7 +8,6 @@ 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/src/spiffworkflow_backend/services/message_service.py b/src/spiffworkflow_backend/services/message_service.py index 216a66a58..190eaaa41 100644 --- a/src/spiffworkflow_backend/services/message_service.py +++ b/src/spiffworkflow_backend/services/message_service.py @@ -3,10 +3,6 @@ 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, @@ -23,6 +19,9 @@ 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/src/spiffworkflow_backend/services/process_instance_processor.py b/src/spiffworkflow_backend/services/process_instance_processor.py index a9f7ac661..fb59960be 100644 --- a/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/src/spiffworkflow_backend/services/process_instance_processor.py @@ -65,7 +65,6 @@ 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/src/spiffworkflow_backend/services/process_instance_service.py b/src/spiffworkflow_backend/services/process_instance_service.py index 7854537e3..f5c5128cc 100644 --- a/src/spiffworkflow_backend/services/process_instance_service.py +++ b/src/spiffworkflow_backend/services/process_instance_service.py @@ -7,7 +7,6 @@ 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 @@ -64,7 +63,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..d8fe12033 100644 --- a/src/spiffworkflow_backend/services/process_model_service.py +++ b/src/spiffworkflow_backend/services/process_model_service.py @@ -8,7 +8,6 @@ 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, ) @@ -161,9 +160,9 @@ 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 +212,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 +254,16 @@ 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] == ".": diff --git a/src/spiffworkflow_backend/services/script_unit_test_runner.py b/src/spiffworkflow_backend/services/script_unit_test_runner.py index 9112e20f0..b9ec129ec 100644 --- a/src/spiffworkflow_backend/services/script_unit_test_runner.py +++ b/src/spiffworkflow_backend/services/script_unit_test_runner.py @@ -8,7 +8,6 @@ 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/src/spiffworkflow_backend/services/secret_service.py b/src/spiffworkflow_backend/services/secret_service.py index 42f401c18..332644995 100644 --- a/src/spiffworkflow_backend/services/secret_service.py +++ b/src/spiffworkflow_backend/services/secret_service.py @@ -3,7 +3,6 @@ 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/src/spiffworkflow_backend/services/service_task_service.py b/src/spiffworkflow_backend/services/service_task_service.py index 97ce1495a..fb2961f56 100644 --- a/src/spiffworkflow_backend/services/service_task_service.py +++ b/src/spiffworkflow_backend/services/service_task_service.py @@ -5,7 +5,6 @@ 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/src/spiffworkflow_backend/services/spec_file_service.py b/src/spiffworkflow_backend/services/spec_file_service.py index 92e905bf3..757a259d6 100644 --- a/src/spiffworkflow_backend/services/spec_file_service.py +++ b/src/spiffworkflow_backend/services/spec_file_service.py @@ -12,7 +12,6 @@ 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/src/spiffworkflow_backend/services/user_service.py b/src/spiffworkflow_backend/services/user_service.py index 0e8e65c2c..c65c48873 100644 --- a/src/spiffworkflow_backend/services/user_service.py +++ b/src/spiffworkflow_backend/services/user_service.py @@ -6,7 +6,6 @@ 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/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..ded388eb2 --- /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" + ] + } + } +} \ No newline at end of file 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..e6788536e --- /dev/null +++ b/tests/data/simple_form/simple_form_ui.json @@ -0,0 +1,13 @@ +{ + "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..0d30df0a2 100644 --- a/tests/spiffworkflow_backend/helpers/base_test.py +++ b/tests/spiffworkflow_backend/helpers/base_test.py @@ -12,9 +12,6 @@ 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 @@ -28,6 +25,8 @@ 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 @@ -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/helpers/example_data.py b/tests/spiffworkflow_backend/helpers/example_data.py index 251ba19c8..c5e5c9bce 100644 --- a/tests/spiffworkflow_backend/helpers/example_data.py +++ b/tests/spiffworkflow_backend/helpers/example_data.py @@ -4,7 +4,6 @@ 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/tests/spiffworkflow_backend/helpers/test_data.py b/tests/spiffworkflow_backend/helpers/test_data.py index d6b4f730c..0ce535d1e 100644 --- a/tests/spiffworkflow_backend/helpers/test_data.py +++ b/tests/spiffworkflow_backend/helpers/test_data.py @@ -1,14 +1,13 @@ """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/tests/spiffworkflow_backend/integration/test_authentication.py b/tests/spiffworkflow_backend/integration/test_authentication.py index 34e4d71bc..537943480 100644 --- a/tests/spiffworkflow_backend/integration/test_authentication.py +++ b/tests/spiffworkflow_backend/integration/test_authentication.py @@ -2,11 +2,10 @@ 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/tests/spiffworkflow_backend/integration/test_logging_service.py b/tests/spiffworkflow_backend/integration/test_logging_service.py index 02d8ade17..a5e3e36dc 100644 --- a/tests/spiffworkflow_backend/integration/test_logging_service.py +++ b/tests/spiffworkflow_backend/integration/test_logging_service.py @@ -1,9 +1,8 @@ """Test_logging_service.""" 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 tests.spiffworkflow_backend.helpers.base_test import BaseTest class TestLoggingService(BaseTest): @@ -45,7 +44,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..c5d38b4fa 100644 --- a/tests/spiffworkflow_backend/integration/test_nested_groups.py +++ b/tests/spiffworkflow_backend/integration/test_nested_groups.py @@ -3,18 +3,129 @@ 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 from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema 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): """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..a860eaab8 100644 --- a/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/tests/spiffworkflow_backend/integration/test_process_api.py @@ -9,9 +9,6 @@ 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, ) @@ -35,6 +32,8 @@ 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 @@ -286,7 +285,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 +622,7 @@ 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 +646,7 @@ 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 +722,7 @@ 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 +748,7 @@ 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 +769,7 @@ 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 +796,7 @@ 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 +816,7 @@ 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 +851,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 +871,7 @@ 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 +892,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 +937,7 @@ 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 +955,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 +965,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 +997,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 +1005,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 +1040,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 +1088,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 +1105,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 +1156,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 +1165,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 +1205,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 +1215,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 +1244,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 +1254,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 +1296,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 +1305,7 @@ 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 +1341,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 +1350,11 @@ 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 +1390,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 +1503,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 +1543,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 +1657,7 @@ 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 +1675,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 +1715,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 +1729,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 +1783,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 +1826,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 +1842,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 +1875,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 +1967,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 +1982,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 +2170,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 +2191,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 +2238,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/integration/test_secret_service.py b/tests/spiffworkflow_backend/integration/test_secret_service.py index 071ef6ccd..ea1a486e5 100644 --- a/tests/spiffworkflow_backend/integration/test_secret_service.py +++ b/tests/spiffworkflow_backend/integration/test_secret_service.py @@ -6,15 +6,14 @@ 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/tests/spiffworkflow_backend/scripts/test_get_group_members.py b/tests/spiffworkflow_backend/scripts/test_get_group_members.py index 8a6046b5b..b38296be2 100644 --- a/tests/spiffworkflow_backend/scripts/test_get_group_members.py +++ b/tests/spiffworkflow_backend/scripts/test_get_group_members.py @@ -2,15 +2,14 @@ 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/tests/spiffworkflow_backend/scripts/test_get_localtime.py b/tests/spiffworkflow_backend/scripts/test_get_localtime.py index 9e65b9707..b04e93f5f 100644 --- a/tests/spiffworkflow_backend/scripts/test_get_localtime.py +++ b/tests/spiffworkflow_backend/scripts/test_get_localtime.py @@ -4,9 +4,6 @@ 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, ) @@ -17,6 +14,8 @@ 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/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py b/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py index 1d5157123..a9305a04c 100644 --- a/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py +++ b/tests/spiffworkflow_backend/unit/test_acceptance_test_fixtures.py @@ -1,6 +1,5 @@ """Test_acceptance_test_fixtures.""" from flask.app import Flask - from spiffworkflow_backend.services.acceptance_test_fixtures import ( load_acceptance_test_fixtures, ) diff --git a/tests/spiffworkflow_backend/unit/test_authorization_service.py b/tests/spiffworkflow_backend/unit/test_authorization_service.py index 5d0a10be1..25bce349c 100644 --- a/tests/spiffworkflow_backend/unit/test_authorization_service.py +++ b/tests/spiffworkflow_backend/unit/test_authorization_service.py @@ -2,8 +2,6 @@ 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 @@ -14,6 +12,7 @@ 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): @@ -104,7 +103,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..2e3f432f2 100644 --- a/tests/spiffworkflow_backend/unit/test_dot_notation.py +++ b/tests/spiffworkflow_backend/unit/test_dot_notation.py @@ -1,8 +1,6 @@ """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, @@ -10,6 +8,7 @@ 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): @@ -27,7 +26,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 +36,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_environment_var_script.py b/tests/spiffworkflow_backend/unit/test_environment_var_script.py index ac96e7e4d..e00fb7708 100644 --- a/tests/spiffworkflow_backend/unit/test_environment_var_script.py +++ b/tests/spiffworkflow_backend/unit/test_environment_var_script.py @@ -1,10 +1,9 @@ """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/tests/spiffworkflow_backend/unit/test_message_instance.py b/tests/spiffworkflow_backend/unit/test_message_instance.py index 39b37f2c2..f91290e55 100644 --- a/tests/spiffworkflow_backend/unit/test_message_instance.py +++ b/tests/spiffworkflow_backend/unit/test_message_instance.py @@ -3,12 +3,11 @@ 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): @@ -20,7 +19,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_message_service.py b/tests/spiffworkflow_backend/unit/test_message_service.py index aa1f28053..46b98c4af 100644 --- a/tests/spiffworkflow_backend/unit/test_message_service.py +++ b/tests/spiffworkflow_backend/unit/test_message_service.py @@ -1,9 +1,6 @@ """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, @@ -18,6 +15,8 @@ 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/tests/spiffworkflow_backend/unit/test_permission_target.py b/tests/spiffworkflow_backend/unit/test_permission_target.py index 567681428..a6fefd682 100644 --- a/tests/spiffworkflow_backend/unit/test_permission_target.py +++ b/tests/spiffworkflow_backend/unit/test_permission_target.py @@ -2,12 +2,11 @@ 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/tests/spiffworkflow_backend/unit/test_permissions.py b/tests/spiffworkflow_backend/unit/test_permissions.py index 117fd0af5..0973bb4cb 100644 --- a/tests/spiffworkflow_backend/unit/test_permissions.py +++ b/tests/spiffworkflow_backend/unit/test_permissions.py @@ -2,15 +2,14 @@ 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/tests/spiffworkflow_backend/unit/test_process_group.py b/tests/spiffworkflow_backend/unit/test_process_group.py index 6c3ad0ade..b2cf3c444 100644 --- a/tests/spiffworkflow_backend/unit/test_process_group.py +++ b/tests/spiffworkflow_backend/unit/test_process_group.py @@ -1,6 +1,5 @@ """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/tests/spiffworkflow_backend/unit/test_process_instance_processor.py b/tests/spiffworkflow_backend/unit/test_process_instance_processor.py index ad7aefe34..20b47b0cc 100644 --- a/tests/spiffworkflow_backend/unit/test_process_instance_processor.py +++ b/tests/spiffworkflow_backend/unit/test_process_instance_processor.py @@ -3,9 +3,6 @@ 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 @@ -19,6 +16,8 @@ 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/tests/spiffworkflow_backend/unit/test_process_instance_report.py b/tests/spiffworkflow_backend/unit/test_process_instance_report.py index 482395076..ccfb088f6 100644 --- a/tests/spiffworkflow_backend/unit/test_process_instance_report.py +++ b/tests/spiffworkflow_backend/unit/test_process_instance_report.py @@ -2,12 +2,11 @@ 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/tests/spiffworkflow_backend/unit/test_process_model.py b/tests/spiffworkflow_backend/unit/test_process_model.py index 5b5b9f256..4154be5df 100644 --- a/tests/spiffworkflow_backend/unit/test_process_model.py +++ b/tests/spiffworkflow_backend/unit/test_process_model.py @@ -2,15 +2,14 @@ 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/tests/spiffworkflow_backend/unit/test_process_model_service.py b/tests/spiffworkflow_backend/unit/test_process_model_service.py index 438ef89d9..bd981e1c5 100644 --- a/tests/spiffworkflow_backend/unit/test_process_model_service.py +++ b/tests/spiffworkflow_backend/unit/test_process_model_service.py @@ -1,11 +1,10 @@ """Test_process_model_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.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 class TestProcessModelService(BaseTest): diff --git a/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py b/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py index d31ea424f..46f88e749 100644 --- a/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py +++ b/tests/spiffworkflow_backend/unit/test_restricted_script_engine.py @@ -3,13 +3,12 @@ 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/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py b/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py index 9ece043a5..38a03c116 100644 --- a/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py +++ b/tests/spiffworkflow_backend/unit/test_script_unit_test_runner.py @@ -1,15 +1,14 @@ """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/tests/spiffworkflow_backend/unit/test_service_task_delegate.py b/tests/spiffworkflow_backend/unit/test_service_task_delegate.py index 95b557560..647db1759 100644 --- a/tests/spiffworkflow_backend/unit/test_service_task_delegate.py +++ b/tests/spiffworkflow_backend/unit/test_service_task_delegate.py @@ -1,9 +1,8 @@ """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/tests/spiffworkflow_backend/unit/test_spec_file_service.py b/tests/spiffworkflow_backend/unit/test_spec_file_service.py index d74acb47b..630ae5951 100644 --- a/tests/spiffworkflow_backend/unit/test_spec_file_service.py +++ b/tests/spiffworkflow_backend/unit/test_spec_file_service.py @@ -7,13 +7,12 @@ 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): @@ -35,7 +34,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 +59,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 +103,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 +143,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_spiff_logging.py b/tests/spiffworkflow_backend/unit/test_spiff_logging.py index d8680b719..fe5c8afef 100644 --- a/tests/spiffworkflow_backend/unit/test_spiff_logging.py +++ b/tests/spiffworkflow_backend/unit/test_spiff_logging.py @@ -3,11 +3,10 @@ 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/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py b/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py index c655d3ffd..9ff299074 100644 --- a/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py +++ b/tests/spiffworkflow_backend/unit/test_various_bpmn_constructs.py @@ -1,13 +1,12 @@ """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): @@ -21,7 +20,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", diff --git a/tests/test_main.py b/tests/test_main.py index 7917a970d..001dbcc6d 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,7 +1,6 @@ """Test cases for the __main__ module.""" import pytest from click.testing import CliRunner - from spiffworkflow_backend import __main__ From 997146e18fafd175423d7b3cedb6440c39b226d7 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 11 Nov 2022 11:24:41 -0500 Subject: [PATCH 4/5] Squashed 'spiffworkflow-frontend/' changes from ab6cf2817..c096ca3f9 c096ca3f9 Report URL fixes (#29) ca49db4d7 get pagination for groups 2bff2d4b2 Merge branch 'main' into feature/nested-groups-2 8a443ebe2 use error as a status instead of faulted w/ burnettk 2e32ed4d4 favor h1 tags over h2 w/ burnettk 0a4ac2d53 fixed up the process instance show page and moved contents of scss to css file and load that last w/ burnettk 670cbabb0 fix lint d21a94467 Assure we are using the latest bpmn-js-spiffworkflow library. a5339a3cb Use the modify method 3983a6eda Minor fixes for the launch buttons. c63161699 moved usage of ProcessBreadcrumb to use hotCrumbs except for report pages d06a3b6b7 cleaned up breadcrumbs some more and cleaned up console.log statements 614080e39 support process-groups in breadcrumb component fe8f79017 add breadcrumb to instances page sometimes 2206972c5 fix recent process models, at least after they visit process model show page ff0721362 make Files half-width and add link to file f08538225 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