Merge branch 'main' into move-group-or-model

This commit is contained in:
mike cullerton 2022-11-21 15:56:44 -05:00
commit e36bf1b548
29 changed files with 805 additions and 715 deletions

View File

@ -16,7 +16,10 @@ jobs:
fail-fast: false
matrix:
include:
- { python: "3.11", os: "ubuntu-latest", session: "safety" }
# FIXME: https://github.com/mysql/mysql-connector-python/pull/86
# put back when poetry update protobuf mysql-connector-python updates protobuf
# right now mysql is forcing protobuf to version 3
# - { python: "3.11", os: "ubuntu-latest", session: "safety" }
- { python: "3.11", os: "ubuntu-latest", session: "mypy" }
- { python: "3.10", os: "ubuntu-latest", session: "mypy" }
- { python: "3.9", os: "ubuntu-latest", session: "mypy" }

View File

@ -1,9 +1,10 @@
import logging
from logging.config import fileConfig
from alembic import context
from flask import current_app
from alembic import context
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
@ -11,17 +12,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:
@ -42,7 +43,9 @@ 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()
@ -60,20 +63,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():

View File

@ -0,0 +1,322 @@
"""empty message
Revision ID: 70223f5c7b98
Revises:
Create Date: 2022-11-20 19:54:45.061376
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '70223f5c7b98'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
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_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_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('spec_reference_cache',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('identifier', sa.String(length=255), nullable=True),
sa.Column('display_name', sa.String(length=255), nullable=True),
sa.Column('process_model_id', sa.String(length=255), nullable=True),
sa.Column('type', sa.String(length=255), nullable=True),
sa.Column('file_name', sa.String(length=255), nullable=True),
sa.Column('relative_path', sa.String(length=255), nullable=True),
sa.Column('has_lanes', sa.Boolean(), nullable=True),
sa.Column('is_executable', sa.Boolean(), nullable=True),
sa.Column('is_primary', sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('identifier', 'type', name='_identifier_type_unique')
)
op.create_index(op.f('ix_spec_reference_cache_display_name'), 'spec_reference_cache', ['display_name'], unique=False)
op.create_index(op.f('ix_spec_reference_cache_identifier'), 'spec_reference_cache', ['identifier'], unique=False)
op.create_index(op.f('ix_spec_reference_cache_type'), 'spec_reference_cache', ['type'], unique=False)
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_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('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_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_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('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_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_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('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.Column('lane_assignment_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['lane_assignment_id'], ['group.id'], ),
sa.PrimaryKeyConstraint('id')
)
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)
# ### 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('spiff_step_details')
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_logging')
op.drop_index(op.f('ix_spec_reference_cache_type'), table_name='spec_reference_cache')
op.drop_index(op.f('ix_spec_reference_cache_identifier'), table_name='spec_reference_cache')
op.drop_index(op.f('ix_spec_reference_cache_display_name'), table_name='spec_reference_cache')
op.drop_table('spec_reference_cache')
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')
# ### end Alembic commands ###

View File

@ -1,579 +0,0 @@
"""empty message
Revision ID: b7790c9c8174
Revises:
Create Date: 2022-11-15 14:11:47.309399
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = "b7790c9c8174"
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
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_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_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(
"spec_reference_cache",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("identifier", sa.String(length=255), nullable=True),
sa.Column("display_name", sa.String(length=255), nullable=True),
sa.Column("process_model_id", sa.String(length=255), nullable=True),
sa.Column("type", sa.String(length=255), nullable=True),
sa.Column("file_name", sa.String(length=255), nullable=True),
sa.Column("relative_path", sa.String(length=255), nullable=True),
sa.Column("has_lanes", sa.Boolean(), nullable=True),
sa.Column("is_executable", sa.Boolean(), nullable=True),
sa.Column("is_primary", sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("identifier", "type", name="_identifier_type_unique"),
)
op.create_index(
op.f("ix_spec_reference_cache_display_name"),
"spec_reference_cache",
["display_name"],
unique=False,
)
op.create_index(
op.f("ix_spec_reference_cache_identifier"),
"spec_reference_cache",
["identifier"],
unique=False,
)
op.create_index(
op.f("ix_spec_reference_cache_type"),
"spec_reference_cache",
["type"],
unique=False,
)
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_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(
"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_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_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(
"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_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_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(
"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.Column("lane_assignment_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["lane_assignment_id"],
["group.id"],
),
sa.PrimaryKeyConstraint("id"),
)
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,
)
# ### 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("spiff_step_details")
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_logging")
op.drop_index(
op.f("ix_spec_reference_cache_type"), table_name="spec_reference_cache"
)
op.drop_index(
op.f("ix_spec_reference_cache_identifier"), table_name="spec_reference_cache"
)
op.drop_index(
op.f("ix_spec_reference_cache_display_name"), table_name="spec_reference_cache"
)
op.drop_table("spec_reference_cache")
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")
# ### end Alembic commands ###

View File

@ -477,6 +477,17 @@ six = ">=1.9.0"
gmpy = ["gmpy"]
gmpy2 = ["gmpy2"]
[[package]]
name = "exceptiongroup"
version = "1.0.4"
description = "Backport of PEP 654 (exception groups)"
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
test = ["pytest (>=6)"]
[[package]]
name = "filelock"
version = "3.8.0"
@ -1240,14 +1251,6 @@ category = "main"
optional = false
python-versions = ">=3.6"
[[package]]
name = "py"
version = "1.11.0"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "pyasn1"
version = "0.4.8"
@ -1332,7 +1335,7 @@ python-versions = ">=3.7"
[[package]]
name = "pytest"
version = "7.1.3"
version = "7.2.0"
description = "pytest: simple powerful testing with Python"
category = "main"
optional = false
@ -1341,11 +1344,11 @@ python-versions = ">=3.7"
[package.dependencies]
attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<2.0"
py = ">=1.8.2"
tomli = ">=1.0.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
@ -1876,7 +1879,7 @@ lxml = "*"
type = "git"
url = "https://github.com/sartography/SpiffWorkflow"
reference = "main"
resolved_reference = "eea53c912984d21a064330c3b3334ac219cb8e18"
resolved_reference = "46f410a2852baeedc8f9ac5165347ce6d4470594"
[[package]]
name = "SQLAlchemy"
@ -2259,7 +2262,7 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
[metadata]
lock-version = "1.1"
python-versions = ">=3.9,<3.12"
content-hash = "a6d3882a3ab142b82201b83ee8a0552fd16112c4540e2a1dbcb5c38599b917c1"
content-hash = "e171edf387c3a4569b52e14acff436a3448f93ffe0977d3491d77822e168bd8d"
[metadata.files]
alabaster = [
@ -2484,6 +2487,10 @@ ecdsa = [
{file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"},
{file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"},
]
exceptiongroup = [
{file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"},
{file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"},
]
filelock = [
{file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"},
{file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"},
@ -3051,10 +3058,6 @@ psycopg2 = [
{file = "psycopg2-2.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:849bd868ae3369932127f0771c08d1109b254f08d48dc42493c3d1b87cb2d308"},
{file = "psycopg2-2.9.4.tar.gz", hash = "sha256:d529926254e093a1b669f692a3aa50069bc71faf5b0ecd91686a78f62767d52f"},
]
py = [
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
]
pyasn1 = [
{file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"},
{file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"},
@ -3118,8 +3121,8 @@ pyrsistent = [
{file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"},
]
pytest = [
{file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"},
{file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"},
{file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"},
{file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"},
]
pytest-flask = [
{file = "pytest-flask-1.2.0.tar.gz", hash = "sha256:46fde652f77777bf02dc91205aec4ce20cdf2acbbbd66a918ab91f5c14693d3d"},

View File

@ -33,7 +33,7 @@ sentry-sdk = "^1.10"
sphinx-autoapi = "^2.0"
flask-bpmn = {git = "https://github.com/sartography/flask-bpmn", rev = "main"}
# flask-bpmn = {develop = true, path = "../flask-bpmn"}
mysql-connector-python = "^8.0.29"
mysql-connector-python = "*"
pytest-flask = "^1.2.0"
pytest-flask-sqlalchemy = "^1.1.0"
psycopg2 = "^2.9.3"
@ -75,7 +75,7 @@ types-dateparser = "^1.1.4.1"
[tool.poetry.dev-dependencies]
pytest = "^7.1.2"
pytest = "*"
coverage = {extras = ["toml"], version = "^6.1"}
safety = "^2.3.1"
mypy = ">=0.961"
@ -103,7 +103,6 @@ sphinx-click = "^4.3.0"
Pygments = "^2.10.0"
pyupgrade = "^3.1.0"
furo = ">=2021.11.12"
MonkeyType = "^22.2.0"
[tool.poetry.scripts]
spiffworkflow-backend = "spiffworkflow_backend.__main__:main"

View File

@ -67,9 +67,9 @@ def start_scheduler(
seconds=10,
)
scheduler.add_job(
BackgroundProcessingService(app).run,
BackgroundProcessingService(app).process_waiting_process_instances,
"interval",
seconds=30,
seconds=10,
)
scheduler.start()

View File

@ -1,5 +1,4 @@
"""Acceptance_test_fixtures."""
import json
import time
from flask import current_app
@ -8,13 +7,15 @@ 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 spiffworkflow_backend.services.process_instance_service import (
ProcessInstanceService,
)
def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]:
"""Load_fixtures."""
current_app.logger.debug("load_acceptance_test_fixtures() start")
test_process_group_id = ""
test_process_model_id = "acceptance-tests-group-one/acceptance-tests-model-1"
test_process_model_id = "misc/acceptance-tests-group-one/acceptance-tests-model-1"
user = BaseTest.find_or_create_user()
statuses = ProcessInstanceStatus.list()
current_time = round(time.time())
@ -28,16 +29,13 @@ def load_acceptance_test_fixtures() -> list[ProcessInstanceModel]:
# suspended - 6 hours ago
process_instances = []
for i in range(len(statuses)):
process_instance = ProcessInstanceModel(
status=statuses[i],
process_initiator=user,
process_model_identifier=test_process_model_id,
process_group_identifier=test_process_group_id,
updated_at_in_seconds=round(time.time()),
start_in_seconds=current_time - (3600 * i),
end_in_seconds=current_time - (3600 * i - 20),
bpmn_json=json.dumps({"i": i}),
process_instance = ProcessInstanceService.create_process_instance(
test_process_model_id, user
)
process_instance.status = statuses[i]
process_instance.start_in_seconds = current_time - (3600 * i)
process_instance.end_in_seconds = current_time - (3600 * i - 20)
db.session.add(process_instance)
process_instances.append(process_instance)

View File

@ -14,7 +14,7 @@ class BackgroundProcessingService:
"""__init__."""
self.app = app
def run(self) -> None:
def process_waiting_process_instances(self) -> None:
"""Since this runs in a scheduler, we need to specify the app context as well."""
with self.app.app_context():
ProcessInstanceService.do_waiting()

View File

@ -359,21 +359,8 @@ class ProcessInstanceProcessor:
subprocesses=subprocesses,
)
self.bpmn_process_instance.script_engine = self._script_engine
self.add_user_info_to_process_instance(self.bpmn_process_instance)
if self.PROCESS_INSTANCE_ID_KEY not in self.bpmn_process_instance.data:
if not process_instance_model.id:
db.session.add(process_instance_model)
# If the model is new, and has no id, save it, write it into the process_instance model
# and save it again. In this way, the workflow process is always aware of the
# database model to which it is associated, and scripts running within the model
# can then load data as needed.
self.bpmn_process_instance.data[
ProcessInstanceProcessor.PROCESS_INSTANCE_ID_KEY
] = process_instance_model.id
self.save()
except MissingSpecError as ke:
raise ApiError(
error_code="unexpected_process_instance_structure",

View File

@ -323,14 +323,9 @@ class ProcessInstanceService:
"""Serialize_flat_with_task_data."""
results = {}
try:
original_status = process_instance.status
processor = ProcessInstanceProcessor(process_instance)
process_instance.data = processor.get_current_data()
results = process_instance.serialized_flat
# this process seems to mutate the status of the process_instance which
# can result in different results than expected from process_instance_list,
# so set the status back to the expected value
results["status"] = original_status
except ApiError:
results = process_instance.serialized
return results

View File

@ -2,6 +2,7 @@
import json
import os
import shutil
from glob import glob
from typing import Any
from typing import List
from typing import Optional
@ -181,17 +182,20 @@ class ProcessModelService(FileSystemService):
self, process_group_id: Optional[str] = None
) -> List[ProcessModelInfo]:
"""Get process models."""
process_groups = []
if process_group_id is None:
process_groups = self.get_process_groups()
else:
process_group = self.get_process_group(process_group_id)
if process_group is not None:
process_groups.append(process_group)
process_models = []
for process_group in process_groups:
process_models.extend(process_group.process_models)
root_path = FileSystemService.root_path()
if process_group_id:
awesome_id = process_group_id.replace("/", os.sep)
root_path = os.path.join(root_path, awesome_id)
process_model_glob = os.path.join(root_path, "**", "process_model.json")
for file in glob(process_model_glob, recursive=True):
process_model_relative_path = os.path.relpath(
file, start=FileSystemService.root_path()
)
process_model = self.get_process_model_from_relative_path(
os.path.dirname(process_model_relative_path)
)
process_models.append(process_model)
process_models.sort()
return process_models

View File

@ -355,6 +355,41 @@ class TestProcessApi(BaseTest):
assert response.json["primary_process_id"] == "superduper"
assert response.json["is_review"] is False
def test_process_model_list_all(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_process_model_list_all."""
group_id = "test_group/test_sub_group"
self.create_process_group(client, with_super_admin_user, group_id)
# add 5 models to the group
for i in range(5):
process_model_identifier = f"{group_id}/test_model_{i}"
model_display_name = f"Test Model {i}"
model_description = f"Test Model {i} Description"
self.create_process_model_with_api(
client,
process_model_id=process_model_identifier,
process_model_display_name=model_display_name,
process_model_description=model_description,
user=with_super_admin_user,
)
# get all models
response = client.get(
"/v1.0/process-models?per_page=1000",
headers=self.logged_in_headers(with_super_admin_user),
)
assert response.json is not None
assert len(response.json["results"]) == 5
assert response.json["pagination"]["count"] == 5
assert response.json["pagination"]["total"] == 5
assert response.json["pagination"]["pages"] == 1
def test_process_model_list(
self,
app: Flask,

View File

@ -37,7 +37,8 @@ describe('process-groups', () => {
cy.contains(groupId).should('not.exist');
});
it('can paginate items', () => {
cy.basicPaginationTest();
});
// process groups no longer has pagination post-tiles
// it('can paginate items', () => {
// cy.basicPaginationTest();
// });
});

View File

@ -3,9 +3,9 @@ import { DATE_FORMAT, PROCESS_STATUSES } from '../../src/config';
const filterByDate = (fromDate) => {
cy.get('#date-picker-start-from').clear().type(format(fromDate, DATE_FORMAT));
cy.contains('Start date from').click();
cy.contains('Start date to').click();
cy.get('#date-picker-end-from').clear().type(format(fromDate, DATE_FORMAT));
cy.contains('End date from').click();
cy.contains('End date to').click();
cy.getBySel('filter-button').click();
};
@ -53,9 +53,9 @@ const updateBpmnPythonScriptWithMonaco = (
cy.get('.monaco-editor textarea:first')
.click()
.focused() // change subject to currently focused element
// .type('{ctrl}a') // had been doing it this way, but it turns out to be flaky relative to clear()
.clear()
.type(pythonScript, { delay: 30 });
// long delay to ensure cypress isn't competing with monaco auto complete stuff
.type(pythonScript, { delay: 120 });
cy.contains('Close').click();
// wait for a little bit for the xml to get set before saving
@ -119,28 +119,28 @@ describe('process-instances', () => {
cy.runPrimaryBpmnFile();
});
it('can create a new instance and can modify with monaco text editor', () => {
// leave off the ending double quote since manco adds it
const originalPythonScript = 'person = "Kevin';
const newPythonScript = 'person = "Mike';
const bpmnFile = 'process_model_one.bpmn';
// Change bpmn
cy.getBySel('files-accordion').click();
cy.getBySel(`edit-file-${bpmnFile.replace('.', '-')}`).click();
cy.contains(`Process Model File: ${bpmnFile}`);
updateBpmnPythonScriptWithMonaco(newPythonScript);
cy.contains('acceptance-tests-model-1').click();
cy.runPrimaryBpmnFile();
cy.getBySel('files-accordion').click();
cy.getBySel(`edit-file-${bpmnFile.replace('.', '-')}`).click();
cy.contains(`Process Model File: ${bpmnFile}`);
updateBpmnPythonScriptWithMonaco(originalPythonScript);
cy.contains('acceptance-tests-model-1').click();
cy.runPrimaryBpmnFile();
});
// it('can create a new instance and can modify with monaco text editor', () => {
// // leave off the ending double quote since manco adds it
// const originalPythonScript = 'person = "Kevin';
// const newPythonScript = 'person = "Mike';
//
// const bpmnFile = 'process_model_one.bpmn';
//
// // Change bpmn
// cy.getBySel('files-accordion').click();
// cy.getBySel(`edit-file-${bpmnFile.replace('.', '-')}`).click();
// cy.contains(`Process Model File: ${bpmnFile}`);
// updateBpmnPythonScriptWithMonaco(newPythonScript);
// cy.contains('acceptance-tests-model-1').click();
// cy.runPrimaryBpmnFile();
//
// cy.getBySel('files-accordion').click();
// cy.getBySel(`edit-file-${bpmnFile.replace('.', '-')}`).click();
// cy.contains(`Process Model File: ${bpmnFile}`);
// updateBpmnPythonScriptWithMonaco(originalPythonScript);
// cy.contains('acceptance-tests-model-1').click();
// cy.runPrimaryBpmnFile();
// });
it('can paginate items', () => {
// make sure we have some process instances
@ -174,13 +174,12 @@ describe('process-instances', () => {
if (!['all', 'waiting'].includes(processStatus)) {
cy.get(statusSelect).click();
cy.get(statusSelect).contains(processStatus).click();
// close the dropdown again
cy.get(statusSelect).click();
cy.getBySel('filter-button').click();
// FIXME: wait a little bit for the useEffects to be able to fully set processInstanceFilters
cy.wait(1000);
cy.url().should('include', `status=${processStatus}`);
cy.assertAtLeastOneItemInPaginatedResults();
cy.getBySel(`process-instance-status-${processStatus}`).contains(
processStatus
);
cy.getBySel(`process-instance-status-${processStatus}`);
// there should really only be one, but in CI there are sometimes more
cy.get('div[aria-label="Clear all selected items"]:first').click();
}

View File

@ -29,17 +29,20 @@ describe('process-models', () => {
newModelDisplayName
);
cy.contains('Delete').click();
// go back to process model show by clicking on the breadcrumb
cy.contains(modelId).click();
cy.getBySel('delete-process-model-button').click();
cy.contains('Are you sure');
cy.getBySel('modal-confirmation-dialog').find('.cds--btn--danger').click();
cy.url().should('include', `process-groups/${groupId}`);
cy.contains(modelId).should('not.exist');
});
it('can create new bpmn, dmn, and json files', () => {
it.only('can create new bpmn, dmn, and json files', () => {
const uuid = () => Cypress._.random(0, 1e6);
const id = uuid();
const groupId = 'acceptance-tests-group-one';
const groupId = 'misc/acceptance-tests-group-one';
const groupDisplayName = 'Acceptance Tests Group One';
const modelDisplayName = `Test Model 2 ${id}`;
const modelId = `test-model-2-${id}`;
@ -48,13 +51,13 @@ describe('process-models', () => {
const dmnFileName = `dmn_test_file_${id}`;
const jsonFileName = `json_test_file_${id}`;
cy.contains('Misc').click();
cy.contains(groupDisplayName).click();
cy.createModel(groupId, modelId, modelDisplayName);
cy.contains(groupId).click();
cy.contains(modelId).click();
cy.url().should('include', `process-models/${groupId}:${modelId}`);
cy.contains(`Process Model: ${modelDisplayName}`);
cy.getBySel('files-accordion').click();
cy.contains(`${bpmnFileName}.bpmn`).should('not.exist');
cy.contains(`${dmnFileName}.dmn`).should('not.exist');
cy.contains(`${jsonFileName}.json`).should('not.exist');
@ -73,7 +76,7 @@ describe('process-models', () => {
cy.contains(`Process Model File: ${bpmnFileName}`);
cy.contains(modelId).click();
cy.contains(`Process Model: ${modelDisplayName}`);
cy.getBySel('files-accordion').click();
// cy.getBySel('files-accordion').click();
cy.contains(`${bpmnFileName}.bpmn`).should('exist');
// add new dmn file
@ -81,13 +84,17 @@ describe('process-models', () => {
cy.contains(/^Process Model File$/);
cy.get('g[data-element-id=decision_1]').click().should('exist');
cy.contains('General').click();
cy.get('#bio-properties-panel-id')
.clear()
.type('decision_acceptance_test_1');
cy.contains('General').click();
cy.contains('Save').click();
cy.get('input[name=file_name]').type(dmnFileName);
cy.contains('Save Changes').click();
cy.contains(`Process Model File: ${dmnFileName}`);
cy.contains(modelId).click();
cy.contains(`Process Model: ${modelDisplayName}`);
cy.getBySel('files-accordion').click();
// cy.getBySel('files-accordion').click();
cy.contains(`${dmnFileName}.dmn`).should('exist');
// add new json file
@ -103,11 +110,10 @@ describe('process-models', () => {
cy.wait(500);
cy.contains(modelId).click();
cy.contains(`Process Model: ${modelDisplayName}`);
cy.getBySel('files-accordion').click();
// cy.getBySel('files-accordion').click();
cy.contains(`${jsonFileName}.json`).should('exist');
cy.contains('Edit process model').click();
cy.contains('Delete').click();
cy.getBySel('delete-process-model-button').click();
cy.contains('Are you sure');
cy.getBySel('modal-confirmation-dialog').find('.cds--btn--danger').click();
cy.url().should('include', `process-groups/${groupId}`);
@ -131,7 +137,6 @@ describe('process-models', () => {
cy.url().should('include', `process-models/${groupId}:${modelId}`);
cy.contains(`Process Model: ${modelDisplayName}`);
cy.getBySel('files-accordion').click();
cy.getBySel('upload-file-button').click();
cy.contains('Add file').selectFile(
'cypress/fixtures/test_bpmn_file_upload.bpmn'
@ -142,7 +147,7 @@ describe('process-models', () => {
.click();
cy.runPrimaryBpmnFile();
cy.getBySel('process-instance-list-link').click();
// cy.getBySel('process-instance-list-link').click();
cy.getBySel('process-instance-show-link').click();
cy.getBySel('process-instance-delete').click();
cy.contains('Are you sure');
@ -151,8 +156,7 @@ describe('process-models', () => {
// in breadcrumb
cy.contains(modelId).click();
cy.contains('Edit process model').click();
cy.contains('Delete').click();
cy.getBySel('delete-process-model-button').click();
cy.contains('Are you sure');
cy.getBySel('modal-confirmation-dialog').find('.cds--btn--danger').click();
cy.url().should('include', `process-groups/${groupId}`);

View File

@ -76,7 +76,10 @@ Cypress.Commands.add('createModel', (groupId, modelId, modelDisplayName) => {
cy.get('input[name=id]').should('have.value', modelId);
cy.contains('Submit').click();
cy.url().should('include', `process-models/${groupId}:${modelId}`);
cy.url().should(
'include',
`process-models/${cy.modifyProcessModelPath(groupId)}:${modelId}`
);
cy.contains(`Process Model: ${modelDisplayName}`);
});
@ -93,6 +96,8 @@ Cypress.Commands.add(
'navigateToProcessModel',
(groupDisplayName, modelDisplayName, modelIdentifier) => {
cy.navigateToAdmin();
cy.contains('Misc').click();
cy.contains(`Process Group: Misc`);
cy.contains(groupDisplayName).click();
cy.contains(`Process Group: ${groupDisplayName}`);
// https://stackoverflow.com/q/51254946/6090676

View File

@ -164,7 +164,7 @@ export default function NavigationBar() {
href="/admin/process-instances/reports"
isCurrentPage={isActivePage('/admin/process-instances/reports')}
>
Reports
Perspectives
</HeaderMenuItem>
</>
);

View File

@ -24,7 +24,6 @@ export default function ProcessModelForm({
useState<boolean>(false);
const [displayNameInvalid, setDisplayNameInvalid] = useState<boolean>(false);
const navigate = useNavigate();
const modifiedProcessModelPath = modifyProcessModelPath(processModel.id);
const navigateToProcessModel = (result: ProcessModel) => {
if ('id' in result) {
@ -53,7 +52,9 @@ export default function ProcessModelForm({
if (hasErrors) {
return;
}
const path = `/process-models/${modifiedProcessModelPath}`;
const path = `/process-models/${modifyProcessModelPath(
processGroupId || ''
)}`;
let httpMethod = 'POST';
if (mode === 'edit') {
httpMethod = 'PUT';
@ -64,7 +65,7 @@ export default function ProcessModelForm({
};
if (mode === 'new') {
Object.assign(postBody, {
id: `${processGroupId}:${processModel.id}`,
id: `${processGroupId}/${processModel.id}`,
});
}

View File

@ -102,3 +102,11 @@ export interface PermissionCheckResult {
export interface PermissionCheckResponseBody {
results: PermissionCheckResult;
}
export interface FormField {
id: string;
title: string;
required: boolean;
type: string;
enum: string[];
}

View File

@ -21,6 +21,7 @@ import ErrorContext from '../contexts/ErrorContext';
import ProcessInstanceLogList from './ProcessInstanceLogList';
import MessageInstanceList from './MessageInstanceList';
import Configuration from './Configuration';
import JsonSchemaFormBuilder from './JsonSchemaFormBuilder';
export default function AdminRoutes() {
const location = useLocation();
@ -108,6 +109,10 @@ export default function AdminRoutes() {
<Route path="process-instances" element={<ProcessInstanceList />} />
<Route path="messages" element={<MessageInstanceList />} />
<Route path="configuration/*" element={<Configuration />} />
<Route
path="process-models/:process_model_id/form-builder"
element={<JsonSchemaFormBuilder />}
/>
</Routes>
);
}

View File

@ -0,0 +1,250 @@
import { useEffect, useState } from 'react';
// @ts-ignore
import { Button, Select, SelectItem, TextInput } from '@carbon/react';
import { useParams } from 'react-router-dom';
import { FormField } from '../interfaces';
import { modifyProcessModelPath, slugifyString } from '../helpers';
import HttpService from '../services/HttpService';
export default function JsonSchemaFormBuilder() {
const params = useParams();
const formFieldTypes = ['textbox', 'checkbox', 'select'];
const [formTitle, setFormTitle] = useState<string>('');
const [formDescription, setFormDescription] = useState<string>('');
const [formId, setFormId] = useState<string>('');
const [formFields, setFormFields] = useState<FormField[]>([]);
const [showNewFormField, setShowNewFormField] = useState<boolean>(false);
const [formFieldSelectOptions, setFormFieldSelectOptions] =
useState<string>('');
const [formIdHasBeenUpdatedByUser, setFormIdHasBeenUpdatedByUser] =
useState<boolean>(false);
const [formFieldIdHasBeenUpdatedByUser, setFormFieldIdHasBeenUpdatedByUser] =
useState<boolean>(false);
const [showFormFieldSelectTextField, setShowFormFieldSelectTextField] =
useState<boolean>(false);
const [formFieldId, setFormFieldId] = useState<string>('');
const [formFieldTitle, setFormFieldTitle] = useState<string>('');
const [formFieldType, setFormFieldType] = useState<string>('');
const modifiedProcessModelId = modifyProcessModelPath(
`${params.process_model_id}`
);
useEffect(() => {}, []);
const renderFormJson = () => {
const formJson = {
title: formTitle,
description: formDescription,
properties: {},
required: [],
};
formFields.forEach((formField: FormField) => {
let jsonSchemaFieldType = 'string';
if (formField.type === 'checkbox') {
jsonSchemaFieldType = 'boolean';
}
const formJsonObject: any = {
type: jsonSchemaFieldType,
title: formField.title,
};
if (formField.type === 'select') {
formJsonObject.enum = formField.enum;
}
(formJson.properties as any)[formField.id] = formJsonObject;
});
return JSON.stringify(formJson, null, 2);
};
const renderFormUiJson = () => {
const uiOrder = formFields.map((formField: FormField) => {
return formField.id;
});
return JSON.stringify({ 'ui:order': uiOrder }, null, 2);
};
const onFormFieldTitleChange = (newFormFieldTitle: string) => {
console.log('newFormFieldTitle', newFormFieldTitle);
console.log(
'setFormFieldIdHasBeenUpdatedByUser',
formFieldIdHasBeenUpdatedByUser
);
if (!formFieldIdHasBeenUpdatedByUser) {
setFormFieldId(slugifyString(newFormFieldTitle));
}
setFormFieldTitle(newFormFieldTitle);
};
const onFormTitleChange = (newFormTitle: string) => {
if (!formIdHasBeenUpdatedByUser) {
setFormId(slugifyString(newFormTitle));
}
setFormTitle(newFormTitle);
};
const addFormField = () => {
const newFormField: FormField = {
id: formFieldId,
title: formFieldTitle,
required: false,
type: formFieldType,
enum: formFieldSelectOptions.split(','),
};
setFormFieldIdHasBeenUpdatedByUser(false);
setShowNewFormField(false);
setFormFields([...formFields, newFormField]);
};
const handleFormFieldTypeChange = (event: any) => {
setFormFieldType(event.srcElement.value);
if (event.srcElement.value === 'select') {
setShowFormFieldSelectTextField(true);
} else {
setShowFormFieldSelectTextField(false);
}
};
const newFormFieldComponent = () => {
if (showNewFormField) {
return (
<>
<TextInput
id="form-field-title"
name="title"
labelText="Title"
value={formFieldTitle}
onChange={(event: any) => {
onFormFieldTitleChange(event.srcElement.value);
}}
/>
<TextInput
id="json-form-field-id"
name="id"
labelText="ID"
value={formFieldId}
onChange={(event: any) => {
setFormFieldIdHasBeenUpdatedByUser(true);
setFormFieldId(event.srcElement.value);
}}
/>
<Select
id="form-field-type"
labelText="Type"
onChange={handleFormFieldTypeChange}
>
{formFieldTypes.map((fft: string) => {
return <SelectItem text={fft} value={fft} />;
})}
</Select>
{showFormFieldSelectTextField ? (
<TextInput
id="json-form-field-select-options"
name="select-options"
labelText="Select Options"
onChange={(event: any) => {
setFormFieldSelectOptions(event.srcElement.value);
}}
/>
) : null}
<Button onClick={addFormField}>Add Field</Button>
</>
);
}
return null;
};
const formFieldArea = () => {
if (formFields.length > 0) {
return formFields.map((formField: FormField) => {
return <p>Form Field: {formField.id}</p>;
});
}
return null;
};
const handleSaveCallback = (result: any) => {
console.log('result', result);
};
const uploadFile = (file: File) => {
const url = `/process-models/${modifiedProcessModelId}/files`;
const httpMethod = 'POST';
const formData = new FormData();
formData.append('file', file);
formData.append('fileName', file.name);
HttpService.makeCallToBackend({
path: url,
successCallback: handleSaveCallback,
httpMethod,
postBody: formData,
});
};
const saveFile = () => {
const formJsonFileName = `${formId}-schema.json`;
const formUiJsonFileName = `${formId}-uischema.json`;
uploadFile(new File([renderFormJson()], formJsonFileName));
uploadFile(new File([renderFormUiJson()], formUiJsonFileName));
};
const jsonFormArea = () => {
return (
<>
<Button onClick={saveFile}>Save</Button>
<TextInput
id="json-form-title"
name="title"
labelText="Title"
value={formTitle}
onChange={(event: any) => {
onFormTitleChange(event.srcElement.value);
}}
/>
<TextInput
id="json-form-id"
name="id"
labelText="ID"
value={formId}
onChange={(event: any) => {
setFormIdHasBeenUpdatedByUser(true);
setFormId(event.srcElement.value);
}}
/>
<TextInput
id="form-description"
name="description"
labelText="Description"
value={formDescription}
onChange={(event: any) => {
setFormDescription(event.srcElement.value);
}}
/>
<Button
onClick={() => {
setFormFieldId('');
setFormFieldTitle('');
setFormFieldType('');
setFormFieldSelectOptions('');
setShowFormFieldSelectTextField(false);
setShowNewFormField(true);
}}
>
New Field
</Button>
{formFieldArea()}
{newFormFieldComponent()}
</>
);
};
return <>{jsonFormArea()}</>;
}

View File

@ -111,6 +111,7 @@ export default function ProcessGroupShow() {
]}
/>
<h1>Process Group: {processGroup.display_name}</h1>
<p className="process-description">{processGroup.description}</p>
<ul>
<Stack orientation="horizontal" gap={3}>
<Can I="POST" a={targetUris.processGroupListPath} ability={ability}>

View File

@ -44,9 +44,9 @@ export default function ProcessInstanceReportList() {
const headerStuff = (
<>
<h1>Process Instance Reports</h1>
<h1>Process Instance Perspectives</h1>
<Button href="/admin/process-instances/reports/new">
Add a process instance report
Add a process instance perspective
</Button>
</>
);
@ -61,7 +61,7 @@ export default function ProcessInstanceReportList() {
return (
<main>
{headerStuff}
<p>No reports found</p>
<p>No perspectives found</p>
</main>
);
}

View File

@ -56,7 +56,7 @@ export default function ProcessInstanceReportNew() {
return (
<>
<ProcessBreadcrumb />
<h1>Add Process Model</h1>
<h1>Add Process Instance Perspective</h1>
<form onSubmit={addProcessInstanceReport}>
<label htmlFor="identifier">
identifier:

View File

@ -80,11 +80,11 @@ export default function ProcessInstanceReport() {
processGroupId={params.process_group_id}
linkProcessModel
/>
<h1>Process Instance Report: {params.report_identifier}</h1>
<h1>Process Instance Perspective: {params.report_identifier}</h1>
<Button
href={`/admin/process-instances/reports/${params.report_identifier}/edit`}
>
Edit process instance report
Edit process instance perspective
</Button>
<PaginationForTable
page={page}

View File

@ -3,6 +3,7 @@ import { useParams } from 'react-router-dom';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import { ProcessModel } from '../interfaces';
import ProcessModelForm from '../components/ProcessModelForm';
import { unModifyProcessModelPath } from '../helpers';
export default function ProcessModelNew() {
const params = useParams();
@ -28,7 +29,7 @@ export default function ProcessModelNew() {
<h1>Add Process Model</h1>
<ProcessModelForm
mode="new"
processGroupId={params.process_group_id}
processGroupId={unModifyProcessModelPath(params.process_group_id || '')}
processModel={processModel}
setProcessModel={setProcessModel}
/>

View File

@ -7,6 +7,7 @@ import {
TrashCan,
Favorite,
Edit,
ArrowRight,
// @ts-ignore
} from '@carbon/icons-react';
import {
@ -514,6 +515,35 @@ export default function ProcessModelShow() {
);
};
const processInstanceListTableButton = () => {
if (processModel) {
return (
<Grid fullWidth>
<Column
sm={{ span: 1, offset: 3 }}
md={{ span: 1, offset: 7 }}
lg={{ span: 1, offset: 15 }}
>
<Button
data-qa="process-instance-list-link"
kind="ghost"
renderIcon={ArrowRight}
iconDescription="Go to Filterable List"
hasIconOnly
size="lg"
onClick={() =>
navigate(
`/admin/process-instances?process_model_identifier=${processModel.id}`
)
}
/>
</Column>
</Grid>
);
}
return null;
};
if (processModel) {
return (
<>
@ -535,6 +565,7 @@ export default function ProcessModelShow() {
<Can I="DELETE" a={targetUris.processModelShowPath} ability={ability}>
<ButtonWithConfirmation
kind="ghost"
data-qa="delete-process-model-button"
renderIcon={TrashCan}
iconDescription="Delete Process Model"
hasIconOnly
@ -570,6 +601,7 @@ export default function ProcessModelShow() {
{processInstanceRunResultTag()}
<br />
<Can I="GET" a={targetUris.processInstanceListPath} ability={ability}>
{processInstanceListTableButton()}
<ProcessInstanceListTable
filtersEnabled={false}
processModelFullIdentifier={processModel.id}

View File

@ -175,6 +175,19 @@ export default function ReactFormEditor() {
<Button onClick={saveFile} variant="danger" data-qa="file-save-button">
Save
</Button>
{params.file_name ? null : (
<Button
onClick={() =>
navigate(
`/admin/process-models/${params.process_model_id}/form-builder`
)
}
variant="danger"
data-qa="form-builder-button"
>
Form Builder
</Button>
)}
{params.file_name ? (
<ButtonWithConfirmation
description={`Delete file ${params.file_name}?`}