Merge pull request #34 from sartography/feature/completed_instances_page
Feature/completed instances page
This commit is contained in:
commit
e7ce009fcb
|
@ -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():
|
||||
|
|
|
@ -0,0 +1,313 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: 88c2d7081664
|
||||
Revises:
|
||||
Create Date: 2022-11-14 15:16:42.833331
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '88c2d7081664'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
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('display_name', 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_index(op.f('ix_bpmn_process_id_lookup_display_name'), 'bpmn_process_id_lookup', ['display_name'], 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_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('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_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_display_name'), table_name='bpmn_process_id_lookup')
|
||||
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 ###
|
|
@ -1,550 +0,0 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: fd00c59e1f60
|
||||
Revises:
|
||||
Create Date: 2022-11-09 14:04:14.169379
|
||||
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "fd00c59e1f60"
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
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.Column("display_name", 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_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(
|
||||
"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(
|
||||
"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_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(
|
||||
"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("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 ###
|
|
@ -1,10 +1,14 @@
|
|||
"""Spiff_step_details."""
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from flask_bpmn.models.db import db
|
||||
from flask_bpmn.models.db import SpiffworkflowBaseDBModel
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy.orm import deferred
|
||||
|
||||
from spiffworkflow_backend.models.group import GroupModel
|
||||
|
||||
|
||||
@dataclass
|
||||
class SpiffStepDetailsModel(SpiffworkflowBaseDBModel):
|
||||
|
@ -17,3 +21,6 @@ class SpiffStepDetailsModel(SpiffworkflowBaseDBModel):
|
|||
task_json: str = deferred(db.Column(db.JSON, nullable=False)) # type: ignore
|
||||
timestamp: float = db.Column(db.DECIMAL(17, 6), nullable=False)
|
||||
completed_by_user_id: int = db.Column(db.Integer, nullable=True)
|
||||
lane_assignment_id: Optional[int] = db.Column(
|
||||
ForeignKey(GroupModel.id), nullable=True
|
||||
)
|
||||
|
|
|
@ -1264,7 +1264,25 @@ def task_submit(
|
|||
if terminate_loop and spiff_task.is_looping():
|
||||
spiff_task.terminate_loop()
|
||||
|
||||
ProcessInstanceService.complete_form_task(processor, spiff_task, body, g.user)
|
||||
active_task = ActiveTaskModel.query.filter_by(
|
||||
process_instance_id=process_instance_id, task_id=task_id
|
||||
).first()
|
||||
if active_task is None:
|
||||
raise (
|
||||
ApiError(
|
||||
error_code="no_active_task",
|
||||
message="Cannot find an active task with task id '{task_id}' for process instance {process_instance_id}.",
|
||||
status_code=500,
|
||||
)
|
||||
)
|
||||
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor=processor,
|
||||
spiff_task=spiff_task,
|
||||
data=body,
|
||||
user=g.user,
|
||||
active_task=active_task,
|
||||
)
|
||||
|
||||
# If we need to update all tasks, then get the next ready task and if it a multi-instance with the same
|
||||
# task spec, complete that form as well.
|
||||
|
|
|
@ -580,9 +580,10 @@ class ProcessInstanceProcessor:
|
|||
)
|
||||
return details_model
|
||||
|
||||
def save_spiff_step_details(self) -> None:
|
||||
def save_spiff_step_details(self, active_task: ActiveTaskModel) -> None:
|
||||
"""SaveSpiffStepDetails."""
|
||||
details_model = self.spiff_step_details()
|
||||
details_model.lane_assignment_id = active_task.lane_assignment_id
|
||||
db.session.add(details_model)
|
||||
db.session.commit()
|
||||
|
||||
|
@ -1129,11 +1130,11 @@ class ProcessInstanceProcessor:
|
|||
)
|
||||
return user_tasks # type: ignore
|
||||
|
||||
def complete_task(self, task: SpiffTask) -> None:
|
||||
def complete_task(self, task: SpiffTask, active_task: ActiveTaskModel) -> None:
|
||||
"""Complete_task."""
|
||||
self.increment_spiff_step()
|
||||
self.bpmn_process_instance.complete_task_from_id(task.id)
|
||||
self.save_spiff_step_details()
|
||||
self.save_spiff_step_details(active_task)
|
||||
|
||||
def get_data(self) -> dict[str, Any]:
|
||||
"""Get_data."""
|
||||
|
|
|
@ -8,6 +8,7 @@ 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.active_task import ActiveTaskModel
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceApi
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
|
||||
|
@ -188,6 +189,7 @@ class ProcessInstanceService:
|
|||
spiff_task: SpiffTask,
|
||||
data: dict[str, Any],
|
||||
user: UserModel,
|
||||
active_task: ActiveTaskModel,
|
||||
) -> None:
|
||||
"""All the things that need to happen when we complete a form.
|
||||
|
||||
|
@ -201,7 +203,7 @@ class ProcessInstanceService:
|
|||
dot_dct = ProcessInstanceService.create_dot_dict(data)
|
||||
spiff_task.update_data(dot_dct)
|
||||
# ProcessInstanceService.post_process_form(spiff_task) # some properties may update the data store.
|
||||
processor.complete_task(spiff_task)
|
||||
processor.complete_task(spiff_task, active_task)
|
||||
processor.do_engine_steps(save=True)
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
}</spiffworkflow:messagePayload>
|
||||
</bpmn:extensionElements>
|
||||
</bpmn:message>
|
||||
<bpmn:process id="message_receiver_process_one" name="Message Receiver Process" isExecutable="true">
|
||||
<bpmn:process id="message_receiver_process_one" name="Message Receiver Process One" isExecutable="true">
|
||||
<bpmn:sequenceFlow id="Flow_11r9uiw" sourceRef="send_message_response" targetRef="Event_0q5otqd" />
|
||||
<bpmn:endEvent id="Event_0q5otqd">
|
||||
<bpmn:incoming>Flow_11r9uiw</bpmn:incoming>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
}</spiffworkflow:messagePayload>
|
||||
</bpmn:extensionElements>
|
||||
</bpmn:message>
|
||||
<bpmn:process id="message_receiver_process_two" name="Message Receiver Process" isExecutable="true">
|
||||
<bpmn:process id="message_receiver_process_two" name="Message Receiver Process Two" isExecutable="true">
|
||||
<bpmn:sequenceFlow id="Flow_11r9uiw" sourceRef="send_message_response" targetRef="Event_0q5otqd" />
|
||||
<bpmn:endEvent id="Event_0q5otqd">
|
||||
<bpmn:incoming>Flow_11r9uiw</bpmn:incoming>
|
||||
|
|
|
@ -74,7 +74,11 @@ class TestGetLocaltime(BaseTest):
|
|||
)
|
||||
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {"timezone": "US/Pacific"}, initiator_user
|
||||
processor,
|
||||
spiff_task,
|
||||
{"timezone": "US/Pacific"},
|
||||
initiator_user,
|
||||
active_task,
|
||||
)
|
||||
|
||||
active_task = process_instance.active_tasks[0]
|
||||
|
|
|
@ -126,7 +126,7 @@ class TestAuthorizationService(BaseTest):
|
|||
active_task.task_name, processor.bpmn_process_instance
|
||||
)
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
|
||||
active_task = process_instance.active_tasks[0]
|
||||
|
@ -137,5 +137,5 @@ class TestAuthorizationService(BaseTest):
|
|||
{"username": "testuser2", "sub": "open_id"}
|
||||
)
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, finance_user
|
||||
processor, spiff_task, {}, finance_user, active_task
|
||||
)
|
||||
|
|
|
@ -47,6 +47,7 @@ class TestDotNotation(BaseTest):
|
|||
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
processor.do_engine_steps(save=True)
|
||||
active_task = process_instance.active_tasks[0]
|
||||
|
||||
user_task = processor.get_ready_user_tasks()[0]
|
||||
form_data = {
|
||||
|
@ -57,7 +58,7 @@ class TestDotNotation(BaseTest):
|
|||
"invoice.dueDate": "09/30/2022",
|
||||
}
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, user_task, form_data, with_super_admin_user
|
||||
processor, user_task, form_data, with_super_admin_user, active_task
|
||||
)
|
||||
|
||||
expected = {
|
||||
|
|
|
@ -91,10 +91,10 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
)
|
||||
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, finance_user
|
||||
processor, spiff_task, {}, finance_user, active_task
|
||||
)
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
|
||||
assert len(process_instance.active_tasks) == 1
|
||||
|
@ -108,11 +108,11 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
)
|
||||
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, finance_user
|
||||
processor, spiff_task, {}, finance_user, active_task
|
||||
)
|
||||
assert len(process_instance.active_tasks) == 1
|
||||
active_task = process_instance.active_tasks[0]
|
||||
|
@ -124,7 +124,7 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
active_task.task_name, processor.bpmn_process_instance
|
||||
)
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
|
||||
assert process_instance.status == ProcessInstanceStatus.complete.value
|
||||
|
@ -173,10 +173,10 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
)
|
||||
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, finance_user_three
|
||||
processor, spiff_task, {}, finance_user_three, active_task
|
||||
)
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
|
||||
assert len(process_instance.active_tasks) == 1
|
||||
|
@ -190,12 +190,12 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
)
|
||||
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
|
||||
g.user = finance_user_three
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, finance_user_three
|
||||
processor, spiff_task, {}, finance_user_three, active_task
|
||||
)
|
||||
assert len(process_instance.active_tasks) == 1
|
||||
active_task = process_instance.active_tasks[0]
|
||||
|
@ -208,11 +208,11 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
)
|
||||
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, finance_user_four
|
||||
processor, spiff_task, {}, finance_user_four, active_task
|
||||
)
|
||||
assert len(process_instance.active_tasks) == 1
|
||||
active_task = process_instance.active_tasks[0]
|
||||
|
@ -224,7 +224,7 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
active_task.task_name, processor.bpmn_process_instance
|
||||
)
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
|
||||
assert len(process_instance.active_tasks) == 1
|
||||
|
@ -234,8 +234,10 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
)
|
||||
with pytest.raises(UserDoesNotHaveAccessToTaskError):
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, initiator_user
|
||||
processor, spiff_task, {}, initiator_user, active_task
|
||||
)
|
||||
ProcessInstanceService.complete_form_task(processor, spiff_task, {}, testadmin1)
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, spiff_task, {}, testadmin1, active_task
|
||||
)
|
||||
|
||||
assert process_instance.status == ProcessInstanceStatus.complete.value
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import ProcessInstanceListTable from './ProcessInstanceListTable';
|
||||
|
||||
const paginationQueryParamPrefix = 'my_completed_instances';
|
||||
|
||||
export default function MyCompletedInstances() {
|
||||
return (
|
||||
<ProcessInstanceListTable
|
||||
filtersEnabled={false}
|
||||
paginationQueryParamPrefix={paginationQueryParamPrefix}
|
||||
perPageOptions={[2, 5, 25]}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
// @ts-ignore
|
||||
import { Pagination } from '@carbon/react';
|
||||
|
@ -13,8 +13,7 @@ type OwnProps = {
|
|||
perPageOptions?: number[];
|
||||
pagination: PaginationObject | null;
|
||||
tableToDisplay: any;
|
||||
queryParamString?: string;
|
||||
path: string;
|
||||
paginationQueryParamPrefix?: string;
|
||||
};
|
||||
|
||||
export default function PaginationForTable({
|
||||
|
@ -23,16 +22,21 @@ export default function PaginationForTable({
|
|||
perPageOptions,
|
||||
pagination,
|
||||
tableToDisplay,
|
||||
queryParamString = '',
|
||||
path,
|
||||
paginationQueryParamPrefix,
|
||||
}: OwnProps) {
|
||||
const PER_PAGE_OPTIONS = [2, 10, 50, 100];
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const paginationQueryParamPrefixToUse = paginationQueryParamPrefix
|
||||
? `${paginationQueryParamPrefix}_`
|
||||
: '';
|
||||
|
||||
const updateRows = (args: any) => {
|
||||
const newPage = args.page;
|
||||
const { pageSize } = args;
|
||||
navigate(`${path}?page=${newPage}&per_page=${pageSize}${queryParamString}`);
|
||||
|
||||
searchParams.set(`${paginationQueryParamPrefixToUse}page`, newPage);
|
||||
searchParams.set(`${paginationQueryParamPrefixToUse}per_page`, pageSize);
|
||||
setSearchParams(searchParams);
|
||||
};
|
||||
|
||||
if (pagination) {
|
||||
|
|
|
@ -0,0 +1,557 @@
|
|||
import { useContext, useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
Link,
|
||||
useNavigate,
|
||||
useParams,
|
||||
useSearchParams,
|
||||
} from 'react-router-dom';
|
||||
|
||||
// @ts-ignore
|
||||
import { Filter } from '@carbon/icons-react';
|
||||
import {
|
||||
Button,
|
||||
ButtonSet,
|
||||
DatePicker,
|
||||
DatePickerInput,
|
||||
Table,
|
||||
Grid,
|
||||
Column,
|
||||
MultiSelect,
|
||||
TableHeader,
|
||||
TableHead,
|
||||
TableRow,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config';
|
||||
import {
|
||||
convertDateStringToSeconds,
|
||||
convertSecondsToFormattedDate,
|
||||
getPageInfoFromSearchParams,
|
||||
getProcessModelFullIdentifierFromSearchParams,
|
||||
modifyProcessModelPath,
|
||||
} from '../helpers';
|
||||
|
||||
import PaginationForTable from './PaginationForTable';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
|
||||
import ErrorContext from '../contexts/ErrorContext';
|
||||
import HttpService from '../services/HttpService';
|
||||
|
||||
import 'react-bootstrap-typeahead/css/Typeahead.css';
|
||||
import 'react-bootstrap-typeahead/css/Typeahead.bs5.css';
|
||||
import { PaginationObject, ProcessModel } from '../interfaces';
|
||||
import ProcessModelSearch from './ProcessModelSearch';
|
||||
|
||||
type OwnProps = {
|
||||
filtersEnabled?: boolean;
|
||||
processModelFullIdentifier?: string;
|
||||
paginationQueryParamPrefix?: string;
|
||||
perPageOptions?: number[];
|
||||
};
|
||||
|
||||
export default function ProcessInstanceListTable({
|
||||
filtersEnabled = true,
|
||||
processModelFullIdentifier,
|
||||
paginationQueryParamPrefix,
|
||||
perPageOptions,
|
||||
}: OwnProps) {
|
||||
const params = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [processInstances, setProcessInstances] = useState([]);
|
||||
const [reportMetadata, setReportMetadata] = useState({});
|
||||
const [pagination, setPagination] = useState<PaginationObject | null>(null);
|
||||
|
||||
const oneHourInSeconds = 3600;
|
||||
const oneMonthInSeconds = oneHourInSeconds * 24 * 30;
|
||||
const [startFrom, setStartFrom] = useState<string>('');
|
||||
const [startTo, setStartTo] = useState<string>('');
|
||||
const [endFrom, setEndFrom] = useState<string>('');
|
||||
const [endTo, setEndTo] = useState<string>('');
|
||||
const [showFilterOptions, setShowFilterOptions] = useState<boolean>(false);
|
||||
|
||||
const setErrorMessage = (useContext as any)(ErrorContext)[1];
|
||||
|
||||
const [processStatusAllOptions, setProcessStatusAllOptions] = useState<any[]>(
|
||||
[]
|
||||
);
|
||||
const [processStatusSelection, setProcessStatusSelection] = useState<
|
||||
string[]
|
||||
>([]);
|
||||
const [processModelAvailableItems, setProcessModelAvailableItems] = useState<
|
||||
ProcessModel[]
|
||||
>([]);
|
||||
const [processModelSelection, setProcessModelSelection] =
|
||||
useState<ProcessModel | null>(null);
|
||||
|
||||
const parametersToAlwaysFilterBy = useMemo(() => {
|
||||
return {
|
||||
start_from: setStartFrom,
|
||||
start_to: setStartTo,
|
||||
end_from: setEndFrom,
|
||||
end_to: setEndTo,
|
||||
};
|
||||
}, [setStartFrom, setStartTo, setEndFrom, setEndTo]);
|
||||
|
||||
const parametersToGetFromSearchParams = useMemo(() => {
|
||||
return {
|
||||
process_model_identifier: null,
|
||||
process_status: null,
|
||||
};
|
||||
}, []);
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
useEffect(() => {
|
||||
function setProcessInstancesFromResult(result: any) {
|
||||
const processInstancesFromApi = result.results;
|
||||
setProcessInstances(processInstancesFromApi);
|
||||
setReportMetadata(result.report_metadata);
|
||||
setPagination(result.pagination);
|
||||
}
|
||||
function getProcessInstances() {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
undefined,
|
||||
undefined,
|
||||
paginationQueryParamPrefix
|
||||
);
|
||||
if (perPageOptions && !perPageOptions.includes(perPage)) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
perPage = perPageOptions[1];
|
||||
}
|
||||
let queryParamString = `per_page=${perPage}&page=${page}`;
|
||||
|
||||
Object.keys(parametersToAlwaysFilterBy).forEach((paramName: string) => {
|
||||
// @ts-expect-error TS(7053) FIXME:
|
||||
const functionToCall = parametersToAlwaysFilterBy[paramName];
|
||||
const searchParamValue = searchParams.get(paramName);
|
||||
if (searchParamValue) {
|
||||
queryParamString += `&${paramName}=${searchParamValue}`;
|
||||
const dateString = convertSecondsToFormattedDate(
|
||||
searchParamValue as any
|
||||
);
|
||||
functionToCall(dateString);
|
||||
setShowFilterOptions(true);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(parametersToGetFromSearchParams).forEach(
|
||||
(paramName: string) => {
|
||||
if (
|
||||
paramName === 'process_model_identifier' &&
|
||||
processModelFullIdentifier
|
||||
) {
|
||||
queryParamString += `&process_model_identifier=${processModelFullIdentifier}`;
|
||||
} else if (searchParams.get(paramName)) {
|
||||
// @ts-expect-error TS(7053) FIXME:
|
||||
const functionToCall = parametersToGetFromSearchParams[paramName];
|
||||
queryParamString += `&${paramName}=${searchParams.get(paramName)}`;
|
||||
if (functionToCall !== null) {
|
||||
functionToCall(searchParams.get(paramName) || '');
|
||||
}
|
||||
setShowFilterOptions(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-instances?${queryParamString}`,
|
||||
successCallback: setProcessInstancesFromResult,
|
||||
});
|
||||
}
|
||||
function processResultForProcessModels(result: any) {
|
||||
const processModelFullIdentifierFromSearchParams =
|
||||
getProcessModelFullIdentifierFromSearchParams(searchParams);
|
||||
const selectionArray = result.results.map((item: any) => {
|
||||
const label = `${item.id}`;
|
||||
Object.assign(item, { label });
|
||||
if (label === processModelFullIdentifierFromSearchParams) {
|
||||
setProcessModelSelection(item);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
setProcessModelAvailableItems(selectionArray);
|
||||
|
||||
const processStatusSelectedArray: string[] = [];
|
||||
const processStatusAllOptionsArray = PROCESS_STATUSES.map(
|
||||
(processStatusOption: any) => {
|
||||
const regex = new RegExp(`\\b${processStatusOption}\\b`);
|
||||
if ((searchParams.get('process_status') || '').match(regex)) {
|
||||
processStatusSelectedArray.push(processStatusOption);
|
||||
}
|
||||
return processStatusOption;
|
||||
}
|
||||
);
|
||||
setProcessStatusSelection(processStatusSelectedArray);
|
||||
setProcessStatusAllOptions(processStatusAllOptionsArray);
|
||||
|
||||
getProcessInstances();
|
||||
}
|
||||
|
||||
if (filtersEnabled) {
|
||||
// populate process model selection
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models?per_page=1000`,
|
||||
successCallback: processResultForProcessModels,
|
||||
});
|
||||
} else {
|
||||
getProcessInstances();
|
||||
}
|
||||
}, [
|
||||
searchParams,
|
||||
params,
|
||||
oneMonthInSeconds,
|
||||
oneHourInSeconds,
|
||||
parametersToAlwaysFilterBy,
|
||||
parametersToGetFromSearchParams,
|
||||
filtersEnabled,
|
||||
paginationQueryParamPrefix,
|
||||
processModelFullIdentifier,
|
||||
perPageOptions,
|
||||
]);
|
||||
|
||||
// does the comparison, but also returns false if either argument
|
||||
// is not truthy and therefore not comparable.
|
||||
const isTrueComparison = (param1: any, operation: any, param2: any) => {
|
||||
if (param1 && param2) {
|
||||
switch (operation) {
|
||||
case '<':
|
||||
return param1 < param2;
|
||||
case '>':
|
||||
return param1 > param2;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const applyFilter = (event: any) => {
|
||||
event.preventDefault();
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
undefined,
|
||||
undefined,
|
||||
paginationQueryParamPrefix
|
||||
);
|
||||
let queryParamString = `per_page=${perPage}&page=${page}`;
|
||||
|
||||
const startFromSeconds = convertDateStringToSeconds(startFrom);
|
||||
const endFromSeconds = convertDateStringToSeconds(endFrom);
|
||||
const startToSeconds = convertDateStringToSeconds(startTo);
|
||||
const endToSeconds = convertDateStringToSeconds(endTo);
|
||||
if (isTrueComparison(startFromSeconds, '>', startToSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"Start date from" cannot be after "start date to"',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isTrueComparison(endFromSeconds, '>', endToSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"End date from" cannot be after "end date to"',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isTrueComparison(startFromSeconds, '>', endFromSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"Start date from" cannot be after "end date from"',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isTrueComparison(startToSeconds, '>', endToSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"Start date to" cannot be after "end date to"',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (startFromSeconds) {
|
||||
queryParamString += `&start_from=${startFromSeconds}`;
|
||||
}
|
||||
if (startToSeconds) {
|
||||
queryParamString += `&start_to=${startToSeconds}`;
|
||||
}
|
||||
if (endFromSeconds) {
|
||||
queryParamString += `&end_from=${endFromSeconds}`;
|
||||
}
|
||||
if (endToSeconds) {
|
||||
queryParamString += `&end_to=${endToSeconds}`;
|
||||
}
|
||||
if (processStatusSelection.length > 0) {
|
||||
queryParamString += `&process_status=${processStatusSelection}`;
|
||||
}
|
||||
|
||||
if (processModelSelection) {
|
||||
queryParamString += `&process_model_identifier=${processModelSelection.id}`;
|
||||
}
|
||||
|
||||
setErrorMessage(null);
|
||||
navigate(`/admin/process-instances?${queryParamString}`);
|
||||
};
|
||||
|
||||
const dateComponent = (
|
||||
labelString: any,
|
||||
name: any,
|
||||
initialDate: any,
|
||||
onChangeFunction: any
|
||||
) => {
|
||||
return (
|
||||
<DatePicker dateFormat={DATE_FORMAT_CARBON} datePickerType="single">
|
||||
<DatePickerInput
|
||||
id={`date-picker-${name}`}
|
||||
placeholder={DATE_FORMAT}
|
||||
labelText={labelString}
|
||||
type="text"
|
||||
size="md"
|
||||
autocomplete="off"
|
||||
allowInput={false}
|
||||
onChange={(dateChangeEvent: any) => {
|
||||
onChangeFunction(dateChangeEvent.srcElement.value);
|
||||
}}
|
||||
value={initialDate}
|
||||
/>
|
||||
</DatePicker>
|
||||
);
|
||||
};
|
||||
|
||||
const processStatusSearch = () => {
|
||||
return (
|
||||
<MultiSelect
|
||||
label="Choose Status"
|
||||
className="our-class"
|
||||
id="process-instance-status-select"
|
||||
titleText="Status"
|
||||
items={processStatusAllOptions}
|
||||
onChange={(selection: any) => {
|
||||
setProcessStatusSelection(selection.selectedItems);
|
||||
}}
|
||||
itemToString={(item: any) => {
|
||||
return item || '';
|
||||
}}
|
||||
selectionFeedback="top-after-reopen"
|
||||
selectedItems={processStatusSelection}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const clearFilters = () => {
|
||||
setProcessModelSelection(null);
|
||||
setProcessStatusSelection([]);
|
||||
setStartFrom('');
|
||||
setStartTo('');
|
||||
setEndFrom('');
|
||||
setEndTo('');
|
||||
};
|
||||
|
||||
const filterOptions = () => {
|
||||
if (!showFilterOptions) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={8}>
|
||||
<ProcessModelSearch
|
||||
onChange={(selection: any) =>
|
||||
setProcessModelSelection(selection.selectedItem)
|
||||
}
|
||||
processModels={processModelAvailableItems}
|
||||
selectedItem={processModelSelection}
|
||||
/>
|
||||
</Column>
|
||||
<Column md={8}>{processStatusSearch()}</Column>
|
||||
</Grid>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={4}>
|
||||
{dateComponent(
|
||||
'Start date from',
|
||||
'start-from',
|
||||
startFrom,
|
||||
setStartFrom
|
||||
)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('Start date to', 'start-to', startTo, setStartTo)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('End date from', 'end-from', endFrom, setEndFrom)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('End date to', 'end-to', endTo, setEndTo)}
|
||||
</Column>
|
||||
</Grid>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={4}>
|
||||
<ButtonSet>
|
||||
<Button
|
||||
kind=""
|
||||
className="button-white-background"
|
||||
onClick={clearFilters}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
<Button
|
||||
kind="secondary"
|
||||
onClick={applyFilter}
|
||||
data-qa="filter-button"
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
</ButtonSet>
|
||||
</Column>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const buildTable = () => {
|
||||
const headerLabels: Record<string, string> = {
|
||||
id: 'Process Instance Id',
|
||||
process_model_identifier: 'Process Model',
|
||||
start_in_seconds: 'Start Time',
|
||||
end_in_seconds: 'End Time',
|
||||
status: 'Status',
|
||||
spiff_step: 'SpiffWorkflow Step',
|
||||
};
|
||||
const getHeaderLabel = (header: string) => {
|
||||
return headerLabels[header] ?? header;
|
||||
};
|
||||
const headers = (reportMetadata as any).columns.map((column: any) => {
|
||||
// return <th>{getHeaderLabel((column as any).Header)}</th>;
|
||||
return getHeaderLabel((column as any).Header);
|
||||
});
|
||||
|
||||
const formatProcessInstanceId = (row: any, id: any) => {
|
||||
const modifiedProcessModelId: String = modifyProcessModelPath(
|
||||
row.process_model_identifier
|
||||
);
|
||||
return (
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${row.id}`}
|
||||
>
|
||||
{id}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
const formatProcessModelIdentifier = (_row: any, identifier: any) => {
|
||||
return (
|
||||
<Link
|
||||
to={`/admin/process-models/${modifyProcessModelPath(identifier)}`}
|
||||
>
|
||||
{identifier}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
const formatSecondsForDisplay = (_row: any, seconds: any) => {
|
||||
return convertSecondsToFormattedDate(seconds) || '-';
|
||||
};
|
||||
const defaultFormatter = (_row: any, value: any) => {
|
||||
return value;
|
||||
};
|
||||
|
||||
const columnFormatters: Record<string, any> = {
|
||||
id: formatProcessInstanceId,
|
||||
process_model_identifier: formatProcessModelIdentifier,
|
||||
start_in_seconds: formatSecondsForDisplay,
|
||||
end_in_seconds: formatSecondsForDisplay,
|
||||
};
|
||||
const formattedColumn = (row: any, column: any) => {
|
||||
const formatter = columnFormatters[column.accessor] ?? defaultFormatter;
|
||||
const value = row[column.accessor];
|
||||
if (column.accessor === 'status') {
|
||||
return (
|
||||
<td data-qa={`process-instance-status-${value}`}>
|
||||
{formatter(row, value)}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
return <td>{formatter(row, value)}</td>;
|
||||
};
|
||||
|
||||
const rows = processInstances.map((row: any) => {
|
||||
const currentRow = (reportMetadata as any).columns.map((column: any) => {
|
||||
return formattedColumn(row, column);
|
||||
});
|
||||
return <tr key={row.id}>{currentRow}</tr>;
|
||||
});
|
||||
|
||||
return (
|
||||
<Table size="lg">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
{headers.map((header: any) => (
|
||||
<TableHeader key={header}>{header}</TableHeader>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<tbody>{rows}</tbody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
const toggleShowFilterOptions = () => {
|
||||
setShowFilterOptions(!showFilterOptions);
|
||||
};
|
||||
|
||||
const filterComponent = () => {
|
||||
if (!filtersEnabled) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Grid fullWidth>
|
||||
<Column
|
||||
sm={{ span: 1, offset: 3 }}
|
||||
md={{ span: 1, offset: 7 }}
|
||||
lg={{ span: 1, offset: 15 }}
|
||||
>
|
||||
<Button
|
||||
data-qa="filter-section-expand-toggle"
|
||||
kind="ghost"
|
||||
renderIcon={Filter}
|
||||
iconDescription="Filter Options"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
onClick={toggleShowFilterOptions}
|
||||
/>
|
||||
</Column>
|
||||
</Grid>
|
||||
{filterOptions()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
if (pagination) {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
undefined,
|
||||
undefined,
|
||||
paginationQueryParamPrefix
|
||||
);
|
||||
if (perPageOptions && !perPageOptions.includes(perPage)) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
perPage = perPageOptions[1];
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{filterComponent()}
|
||||
<br />
|
||||
<PaginationForTable
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
paginationQueryParamPrefix={paginationQueryParamPrefix}
|
||||
perPageOptions={perPageOptions}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
|
@ -12,6 +12,7 @@ import HttpService from '../services/HttpService';
|
|||
import { PaginationObject } from '../interfaces';
|
||||
|
||||
const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5;
|
||||
const paginationQueryParamPrefix = 'tasks_for_my_open_processes';
|
||||
|
||||
export default function MyOpenProcesses() {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
@ -21,7 +22,9 @@ export default function MyOpenProcesses() {
|
|||
useEffect(() => {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE,
|
||||
undefined,
|
||||
paginationQueryParamPrefix
|
||||
);
|
||||
const setTasksFromResult = (result: any) => {
|
||||
setTasks(result.results);
|
||||
|
@ -113,7 +116,9 @@ export default function MyOpenProcesses() {
|
|||
}
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE,
|
||||
undefined,
|
||||
paginationQueryParamPrefix
|
||||
);
|
||||
return (
|
||||
<>
|
||||
|
@ -124,7 +129,7 @@ export default function MyOpenProcesses() {
|
|||
perPageOptions={[2, PER_PAGE_FOR_TASKS_ON_HOME_PAGE, 25]}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
path="/tasks/grouped"
|
||||
paginationQueryParamPrefix={paginationQueryParamPrefix}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -21,7 +21,9 @@ export default function TasksWaitingForMe() {
|
|||
useEffect(() => {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE,
|
||||
undefined,
|
||||
'tasks_waiting_for_me'
|
||||
);
|
||||
const setTasksFromResult = (result: any) => {
|
||||
setTasks(result.results);
|
||||
|
@ -115,7 +117,9 @@ export default function TasksWaitingForMe() {
|
|||
}
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE,
|
||||
undefined,
|
||||
'tasks_waiting_for_me'
|
||||
);
|
||||
return (
|
||||
<>
|
||||
|
@ -126,7 +130,7 @@ export default function TasksWaitingForMe() {
|
|||
perPageOptions={[2, PER_PAGE_FOR_TASKS_ON_HOME_PAGE, 25]}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
path="/tasks/grouped"
|
||||
paginationQueryParamPrefix="tasks_waiting_for_me"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -12,6 +12,7 @@ import HttpService from '../services/HttpService';
|
|||
import { PaginationObject } from '../interfaces';
|
||||
|
||||
const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5;
|
||||
const paginationQueryParamPrefix = 'tasks_waiting_for_my_groups';
|
||||
|
||||
export default function TasksForWaitingForMyGroups() {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
@ -21,7 +22,9 @@ export default function TasksForWaitingForMyGroups() {
|
|||
useEffect(() => {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE,
|
||||
undefined,
|
||||
paginationQueryParamPrefix
|
||||
);
|
||||
const setTasksFromResult = (result: any) => {
|
||||
setTasks(result.results);
|
||||
|
@ -115,7 +118,9 @@ export default function TasksForWaitingForMyGroups() {
|
|||
}
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE,
|
||||
undefined,
|
||||
paginationQueryParamPrefix
|
||||
);
|
||||
return (
|
||||
<>
|
||||
|
@ -126,7 +131,7 @@ export default function TasksForWaitingForMyGroups() {
|
|||
perPageOptions={[2, PER_PAGE_FOR_TASKS_ON_HOME_PAGE, 25]}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
path="/tasks/grouped"
|
||||
paginationQueryParamPrefix={paginationQueryParamPrefix}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -79,11 +79,20 @@ export const objectIsEmpty = (obj: object) => {
|
|||
export const getPageInfoFromSearchParams = (
|
||||
searchParams: any,
|
||||
defaultPerPage: string | number = DEFAULT_PER_PAGE,
|
||||
defaultPage: string | number = DEFAULT_PAGE
|
||||
defaultPage: string | number = DEFAULT_PAGE,
|
||||
paginationQueryParamPrefix: string | null = null
|
||||
) => {
|
||||
const page = parseInt(searchParams.get('page') || defaultPage.toString(), 10);
|
||||
const paginationQueryParamPrefixToUse = paginationQueryParamPrefix
|
||||
? `${paginationQueryParamPrefix}_`
|
||||
: '';
|
||||
const page = parseInt(
|
||||
searchParams.get(`${paginationQueryParamPrefixToUse}page`) ||
|
||||
defaultPage.toString(),
|
||||
10
|
||||
);
|
||||
const perPage = parseInt(
|
||||
searchParams.get('per_page') || defaultPerPage.toString(),
|
||||
searchParams.get(`${paginationQueryParamPrefixToUse}per_page`) ||
|
||||
defaultPerPage.toString(),
|
||||
10
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import MyCompletedInstances from '../components/MyCompletedInstances';
|
||||
|
||||
export default function CompletedInstances() {
|
||||
return <MyCompletedInstances />;
|
||||
}
|
|
@ -6,6 +6,7 @@ import TaskShow from './TaskShow';
|
|||
import ErrorContext from '../contexts/ErrorContext';
|
||||
import MyTasks from './MyTasks';
|
||||
import GroupedTasks from './GroupedTasks';
|
||||
import CompletedInstances from './CompletedInstances';
|
||||
|
||||
export default function HomePageRoutes() {
|
||||
const location = useLocation();
|
||||
|
@ -18,6 +19,8 @@ export default function HomePageRoutes() {
|
|||
let newSelectedTabIndex = 0;
|
||||
if (location.pathname.match(/^\/tasks\/grouped\b/)) {
|
||||
newSelectedTabIndex = 1;
|
||||
} else if (location.pathname.match(/^\/tasks\/completed-instances\b/)) {
|
||||
newSelectedTabIndex = 2;
|
||||
}
|
||||
setSelectedTabIndex(newSelectedTabIndex);
|
||||
}, [location, setErrorMessage]);
|
||||
|
@ -28,6 +31,9 @@ export default function HomePageRoutes() {
|
|||
<TabList aria-label="List of tabs">
|
||||
<Tab onClick={() => navigate('/tasks/my-tasks')}>My Tasks</Tab>
|
||||
<Tab onClick={() => navigate('/tasks/grouped')}>Grouped Tasks</Tab>
|
||||
<Tab onClick={() => navigate('/tasks/completed-instances')}>
|
||||
Completed Instances
|
||||
</Tab>
|
||||
</TabList>
|
||||
</Tabs>
|
||||
<br />
|
||||
|
@ -36,6 +42,7 @@ export default function HomePageRoutes() {
|
|||
<Route path="my-tasks" element={<MyTasks />} />
|
||||
<Route path=":process_instance_id/:task_id" element={<TaskShow />} />
|
||||
<Route path="grouped" element={<GroupedTasks />} />
|
||||
<Route path="completed-instances" element={<CompletedInstances />} />
|
||||
</Routes>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -94,14 +94,8 @@ export default function MessageInstanceList() {
|
|||
|
||||
if (pagination) {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
|
||||
let queryParamString = '';
|
||||
let breadcrumbElement = null;
|
||||
if (searchParams.get('process_instance_id')) {
|
||||
queryParamString += `&process_group_id=${searchParams.get(
|
||||
'process_group_id'
|
||||
)}&process_model_id=${searchParams.get(
|
||||
'process_model_id'
|
||||
)}&process_instance_id=${searchParams.get('process_instance_id')}`;
|
||||
breadcrumbElement = (
|
||||
<ProcessBreadcrumb
|
||||
hotCrumbs={[
|
||||
|
@ -132,8 +126,6 @@ export default function MessageInstanceList() {
|
|||
perPage={perPage}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
queryParamString={queryParamString}
|
||||
path="/admin/messages"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -152,7 +152,6 @@ export default function MyTasks() {
|
|||
perPageOptions={[2, PER_PAGE_FOR_TASKS_ON_HOME_PAGE, 25]}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
path="/tasks"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -109,7 +109,6 @@ export default function ProcessGroupList() {
|
|||
perPage={perPage}
|
||||
pagination={pagination as any}
|
||||
tableToDisplay={buildTable()}
|
||||
path="/admin/process-groups"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -170,7 +170,6 @@ export default function ProcessGroupShow() {
|
|||
perPage={perPage}
|
||||
pagination={modelPagination}
|
||||
tableToDisplay={buildModelTable()}
|
||||
path={`/admin/process-groups/${processGroup.id}`}
|
||||
/>
|
||||
)}
|
||||
<br />
|
||||
|
@ -182,7 +181,6 @@ export default function ProcessGroupShow() {
|
|||
perPage={perPage}
|
||||
pagination={groupPagination}
|
||||
tableToDisplay={buildGroupTable()}
|
||||
path={`/admin/process-groups/${processGroup.id}`}
|
||||
/>
|
||||
)}
|
||||
</ul>
|
||||
|
|
|
@ -1,482 +1,15 @@
|
|||
import { useContext, useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
Link,
|
||||
useNavigate,
|
||||
useParams,
|
||||
useSearchParams,
|
||||
} from 'react-router-dom';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
// @ts-ignore
|
||||
import { Filter } from '@carbon/icons-react';
|
||||
import {
|
||||
Button,
|
||||
ButtonSet,
|
||||
DatePicker,
|
||||
DatePickerInput,
|
||||
Table,
|
||||
Grid,
|
||||
Column,
|
||||
MultiSelect,
|
||||
TableHeader,
|
||||
TableHead,
|
||||
TableRow,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config';
|
||||
import {
|
||||
convertDateStringToSeconds,
|
||||
convertSecondsToFormattedDate,
|
||||
getPageInfoFromSearchParams,
|
||||
getProcessModelFullIdentifierFromSearchParams,
|
||||
modifyProcessModelPath,
|
||||
} from '../helpers';
|
||||
|
||||
import PaginationForTable from '../components/PaginationForTable';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
|
||||
import ErrorContext from '../contexts/ErrorContext';
|
||||
import HttpService from '../services/HttpService';
|
||||
|
||||
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';
|
||||
import ProcessInstanceListTable from '../components/ProcessInstanceListTable';
|
||||
import { getProcessModelFullIdentifierFromSearchParams } from '../helpers';
|
||||
|
||||
export default function ProcessInstanceList() {
|
||||
const params = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [processInstances, setProcessInstances] = useState([]);
|
||||
const [reportMetadata, setReportMetadata] = useState({});
|
||||
const [pagination, setPagination] = useState<PaginationObject | null>(null);
|
||||
|
||||
const oneHourInSeconds = 3600;
|
||||
const oneMonthInSeconds = oneHourInSeconds * 24 * 30;
|
||||
const [startFrom, setStartFrom] = useState<string>('');
|
||||
const [startTo, setStartTo] = useState<string>('');
|
||||
const [endFrom, setEndFrom] = useState<string>('');
|
||||
const [endTo, setEndTo] = useState<string>('');
|
||||
const [showFilterOptions, setShowFilterOptions] = useState<boolean>(false);
|
||||
|
||||
const setErrorMessage = (useContext as any)(ErrorContext)[1];
|
||||
|
||||
const [processStatusAllOptions, setProcessStatusAllOptions] = useState<any[]>(
|
||||
[]
|
||||
);
|
||||
const [processStatusSelection, setProcessStatusSelection] = useState<
|
||||
string[]
|
||||
>([]);
|
||||
const [processModelAvailableItems, setProcessModelAvailableItems] = useState<
|
||||
ProcessModel[]
|
||||
>([]);
|
||||
const [processModelSelection, setProcessModelSelection] =
|
||||
useState<ProcessModel | null>(null);
|
||||
|
||||
const parametersToAlwaysFilterBy = useMemo(() => {
|
||||
return {
|
||||
start_from: setStartFrom,
|
||||
start_to: setStartTo,
|
||||
end_from: setEndFrom,
|
||||
end_to: setEndTo,
|
||||
};
|
||||
}, [setStartFrom, setStartTo, setEndFrom, setEndTo]);
|
||||
|
||||
const parametersToGetFromSearchParams = useMemo(() => {
|
||||
return {
|
||||
process_model_identifier: null,
|
||||
process_status: null,
|
||||
};
|
||||
}, []);
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
useEffect(() => {
|
||||
function setProcessInstancesFromResult(result: any) {
|
||||
const processInstancesFromApi = result.results;
|
||||
setProcessInstances(processInstancesFromApi);
|
||||
setReportMetadata(result.report_metadata);
|
||||
setPagination(result.pagination);
|
||||
}
|
||||
function getProcessInstances() {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
|
||||
let queryParamString = `per_page=${perPage}&page=${page}`;
|
||||
|
||||
Object.keys(parametersToAlwaysFilterBy).forEach((paramName: string) => {
|
||||
// @ts-expect-error TS(7053) FIXME:
|
||||
const functionToCall = parametersToAlwaysFilterBy[paramName];
|
||||
const searchParamValue = searchParams.get(paramName);
|
||||
if (searchParamValue) {
|
||||
queryParamString += `&${paramName}=${searchParamValue}`;
|
||||
const dateString = convertSecondsToFormattedDate(
|
||||
searchParamValue as any
|
||||
);
|
||||
functionToCall(dateString);
|
||||
setShowFilterOptions(true);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(parametersToGetFromSearchParams).forEach(
|
||||
(paramName: string) => {
|
||||
if (searchParams.get(paramName)) {
|
||||
// @ts-expect-error TS(7053) FIXME:
|
||||
const functionToCall = parametersToGetFromSearchParams[paramName];
|
||||
queryParamString += `&${paramName}=${searchParams.get(paramName)}`;
|
||||
if (functionToCall !== null) {
|
||||
functionToCall(searchParams.get(paramName) || '');
|
||||
}
|
||||
setShowFilterOptions(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-instances?${queryParamString}`,
|
||||
successCallback: setProcessInstancesFromResult,
|
||||
});
|
||||
}
|
||||
function processResultForProcessModels(result: any) {
|
||||
const processModelFullIdentifier =
|
||||
getProcessModelFullIdentifierFromSearchParams(searchParams);
|
||||
const selectionArray = result.results.map((item: any) => {
|
||||
const label = `${item.id}`;
|
||||
Object.assign(item, { label });
|
||||
if (label === processModelFullIdentifier) {
|
||||
setProcessModelSelection(item);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
setProcessModelAvailableItems(selectionArray);
|
||||
|
||||
const processStatusSelectedArray: string[] = [];
|
||||
const processStatusAllOptionsArray = PROCESS_STATUSES.map(
|
||||
(processStatusOption: any) => {
|
||||
const regex = new RegExp(`\\b${processStatusOption}\\b`);
|
||||
if ((searchParams.get('process_status') || '').match(regex)) {
|
||||
processStatusSelectedArray.push(processStatusOption);
|
||||
}
|
||||
return processStatusOption;
|
||||
}
|
||||
);
|
||||
setProcessStatusSelection(processStatusSelectedArray);
|
||||
setProcessStatusAllOptions(processStatusAllOptionsArray);
|
||||
|
||||
getProcessInstances();
|
||||
}
|
||||
|
||||
// populate process model selection
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models?per_page=1000`,
|
||||
successCallback: processResultForProcessModels,
|
||||
});
|
||||
}, [
|
||||
searchParams,
|
||||
params,
|
||||
oneMonthInSeconds,
|
||||
oneHourInSeconds,
|
||||
parametersToAlwaysFilterBy,
|
||||
parametersToGetFromSearchParams,
|
||||
]);
|
||||
|
||||
// does the comparison, but also returns false if either argument
|
||||
// is not truthy and therefore not comparable.
|
||||
const isTrueComparison = (param1: any, operation: any, param2: any) => {
|
||||
if (param1 && param2) {
|
||||
switch (operation) {
|
||||
case '<':
|
||||
return param1 < param2;
|
||||
case '>':
|
||||
return param1 > param2;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const applyFilter = (event: any) => {
|
||||
event.preventDefault();
|
||||
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
|
||||
let queryParamString = `per_page=${perPage}&page=${page}`;
|
||||
|
||||
const startFromSeconds = convertDateStringToSeconds(startFrom);
|
||||
const endFromSeconds = convertDateStringToSeconds(endFrom);
|
||||
const startToSeconds = convertDateStringToSeconds(startTo);
|
||||
const endToSeconds = convertDateStringToSeconds(endTo);
|
||||
if (isTrueComparison(startFromSeconds, '>', startToSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"Start date from" cannot be after "start date to"',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isTrueComparison(endFromSeconds, '>', endToSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"End date from" cannot be after "end date to"',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isTrueComparison(startFromSeconds, '>', endFromSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"Start date from" cannot be after "end date from"',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isTrueComparison(startToSeconds, '>', endToSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"Start date to" cannot be after "end date to"',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (startFromSeconds) {
|
||||
queryParamString += `&start_from=${startFromSeconds}`;
|
||||
}
|
||||
if (startToSeconds) {
|
||||
queryParamString += `&start_to=${startToSeconds}`;
|
||||
}
|
||||
if (endFromSeconds) {
|
||||
queryParamString += `&end_from=${endFromSeconds}`;
|
||||
}
|
||||
if (endToSeconds) {
|
||||
queryParamString += `&end_to=${endToSeconds}`;
|
||||
}
|
||||
if (processStatusSelection.length > 0) {
|
||||
queryParamString += `&process_status=${processStatusSelection}`;
|
||||
}
|
||||
|
||||
if (processModelSelection) {
|
||||
queryParamString += `&process_model_identifier=${processModelSelection.id}`;
|
||||
}
|
||||
|
||||
setErrorMessage(null);
|
||||
navigate(`/admin/process-instances?${queryParamString}`);
|
||||
};
|
||||
|
||||
const dateComponent = (
|
||||
labelString: any,
|
||||
name: any,
|
||||
initialDate: any,
|
||||
onChangeFunction: any
|
||||
) => {
|
||||
return (
|
||||
<DatePicker dateFormat={DATE_FORMAT_CARBON} datePickerType="single">
|
||||
<DatePickerInput
|
||||
id={`date-picker-${name}`}
|
||||
placeholder={DATE_FORMAT}
|
||||
labelText={labelString}
|
||||
type="text"
|
||||
size="md"
|
||||
autocomplete="off"
|
||||
allowInput={false}
|
||||
onChange={(dateChangeEvent: any) => {
|
||||
onChangeFunction(dateChangeEvent.srcElement.value);
|
||||
}}
|
||||
value={initialDate}
|
||||
/>
|
||||
</DatePicker>
|
||||
);
|
||||
};
|
||||
const processStatusSearch = () => {
|
||||
return (
|
||||
<MultiSelect
|
||||
label="Choose Status"
|
||||
className="our-class"
|
||||
id="process-instance-status-select"
|
||||
titleText="Status"
|
||||
items={processStatusAllOptions}
|
||||
onChange={(selection: any) => {
|
||||
setProcessStatusSelection(selection.selectedItems);
|
||||
}}
|
||||
itemToString={(item: any) => {
|
||||
return item || '';
|
||||
}}
|
||||
selectionFeedback="top-after-reopen"
|
||||
selectedItems={processStatusSelection}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const clearFilters = () => {
|
||||
setProcessModelSelection(null);
|
||||
setProcessStatusSelection([]);
|
||||
setStartFrom('');
|
||||
setStartTo('');
|
||||
setEndFrom('');
|
||||
setEndTo('');
|
||||
};
|
||||
const filterOptions = () => {
|
||||
if (!showFilterOptions) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={8}>
|
||||
<ProcessModelSearch
|
||||
onChange={(selection: any) =>
|
||||
setProcessModelSelection(selection.selectedItem)
|
||||
}
|
||||
processModels={processModelAvailableItems}
|
||||
selectedItem={processModelSelection}
|
||||
/>
|
||||
</Column>
|
||||
<Column md={8}>{processStatusSearch()}</Column>
|
||||
</Grid>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={4}>
|
||||
{dateComponent(
|
||||
'Start date from',
|
||||
'start-from',
|
||||
startFrom,
|
||||
setStartFrom
|
||||
)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('Start date to', 'start-to', startTo, setStartTo)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('End date from', 'end-from', endFrom, setEndFrom)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('End date to', 'end-to', endTo, setEndTo)}
|
||||
</Column>
|
||||
</Grid>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
<Column md={4}>
|
||||
<ButtonSet>
|
||||
<Button
|
||||
kind=""
|
||||
className="button-white-background"
|
||||
onClick={clearFilters}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
<Button
|
||||
kind="secondary"
|
||||
onClick={applyFilter}
|
||||
data-qa="filter-button"
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
</ButtonSet>
|
||||
</Column>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
const toggleShowFilterOptions = () => {
|
||||
setShowFilterOptions(!showFilterOptions);
|
||||
};
|
||||
const filterComponent = () => {
|
||||
return (
|
||||
<>
|
||||
<Grid fullWidth>
|
||||
<Column
|
||||
sm={{ span: 1, offset: 3 }}
|
||||
md={{ span: 1, offset: 7 }}
|
||||
lg={{ span: 1, offset: 15 }}
|
||||
>
|
||||
<Button
|
||||
data-qa="filter-section-expand-toggle"
|
||||
kind="ghost"
|
||||
renderIcon={Filter}
|
||||
iconDescription="Filter Options"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
onClick={toggleShowFilterOptions}
|
||||
/>
|
||||
</Column>
|
||||
</Grid>
|
||||
{filterOptions()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const buildTable = () => {
|
||||
const headerLabels: Record<string, string> = {
|
||||
id: 'Process Instance Id',
|
||||
process_model_identifier: 'Process Model',
|
||||
start_in_seconds: 'Start Time',
|
||||
end_in_seconds: 'End Time',
|
||||
status: 'Status',
|
||||
spiff_step: 'SpiffWorkflow Step',
|
||||
};
|
||||
const getHeaderLabel = (header: string) => {
|
||||
return headerLabels[header] ?? header;
|
||||
};
|
||||
const headers = (reportMetadata as any).columns.map((column: any) => {
|
||||
// return <th>{getHeaderLabel((column as any).Header)}</th>;
|
||||
return getHeaderLabel((column as any).Header);
|
||||
});
|
||||
|
||||
const formatProcessInstanceId = (row: any, id: any) => {
|
||||
const modifiedProcessModelId: String = modifyProcessModelPath(
|
||||
row.process_model_identifier
|
||||
);
|
||||
return (
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${row.id}`}
|
||||
>
|
||||
{id}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
const formatProcessModelIdentifier = (_row: any, identifier: any) => {
|
||||
return (
|
||||
<Link
|
||||
to={`/admin/process-models/${modifyProcessModelPath(identifier)}`}
|
||||
>
|
||||
{identifier}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
const formatSecondsForDisplay = (_row: any, seconds: any) => {
|
||||
return convertSecondsToFormattedDate(seconds) || '-';
|
||||
};
|
||||
const defaultFormatter = (_row: any, value: any) => {
|
||||
return value;
|
||||
};
|
||||
|
||||
const columnFormatters: Record<string, any> = {
|
||||
id: formatProcessInstanceId,
|
||||
process_model_identifier: formatProcessModelIdentifier,
|
||||
start_in_seconds: formatSecondsForDisplay,
|
||||
end_in_seconds: formatSecondsForDisplay,
|
||||
};
|
||||
const formattedColumn = (row: any, column: any) => {
|
||||
const formatter = columnFormatters[column.accessor] ?? defaultFormatter;
|
||||
const value = row[column.accessor];
|
||||
if (column.accessor === 'status') {
|
||||
return (
|
||||
<td data-qa={`process-instance-status-${value}`}>
|
||||
{formatter(row, value)}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
return <td>{formatter(row, value)}</td>;
|
||||
};
|
||||
|
||||
const rows = processInstances.map((row: any) => {
|
||||
const currentRow = (reportMetadata as any).columns.map((column: any) => {
|
||||
return formattedColumn(row, column);
|
||||
});
|
||||
return <tr key={row.id}>{currentRow}</tr>;
|
||||
});
|
||||
|
||||
return (
|
||||
<Table size="lg">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
{headers.map((header: any) => (
|
||||
<TableHeader key={header}>{header}</TableHeader>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<tbody>{rows}</tbody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
const processInstanceBreadcrumbElement = () => {
|
||||
const processModelFullIdentifier =
|
||||
getProcessModelFullIdentifierFromSearchParams(searchParams);
|
||||
|
@ -498,48 +31,14 @@ export default function ProcessInstanceList() {
|
|||
);
|
||||
};
|
||||
|
||||
const getSearchParamsAsQueryString = () => {
|
||||
let queryParamString = '';
|
||||
Object.keys(parametersToAlwaysFilterBy).forEach((paramName) => {
|
||||
const searchParamValue = searchParams.get(paramName);
|
||||
if (searchParamValue) {
|
||||
queryParamString += `&${paramName}=${searchParamValue}`;
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(parametersToGetFromSearchParams).forEach(
|
||||
(paramName: string) => {
|
||||
if (searchParams.get(paramName)) {
|
||||
queryParamString += `&${paramName}=${searchParams.get(paramName)}`;
|
||||
}
|
||||
}
|
||||
);
|
||||
return queryParamString;
|
||||
};
|
||||
|
||||
const processInstanceTitleElement = () => {
|
||||
return <h1>Process Instances</h1>;
|
||||
};
|
||||
|
||||
if (pagination) {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
|
||||
return (
|
||||
<>
|
||||
{processInstanceBreadcrumbElement()}
|
||||
{processInstanceTitleElement()}
|
||||
{filterComponent()}
|
||||
<br />
|
||||
<PaginationForTable
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
queryParamString={getSearchParamsAsQueryString()}
|
||||
path="/admin/process-instances"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
return (
|
||||
<>
|
||||
{processInstanceBreadcrumbElement()}
|
||||
{processInstanceTitleElement()}
|
||||
<ProcessInstanceListTable />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -99,7 +99,6 @@ export default function ProcessInstanceLogList() {
|
|||
perPage={perPage}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
path={`/admin/process-models/${modifiedProcessModelId}/process-instances/${params.process_instance_id}/logs`}
|
||||
/>
|
||||
</main>
|
||||
);
|
||||
|
|
|
@ -91,7 +91,6 @@ export default function ProcessInstanceReport() {
|
|||
perPage={perPage}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
path={`/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/report`}
|
||||
/>
|
||||
</main>
|
||||
);
|
||||
|
|
|
@ -33,6 +33,7 @@ import ErrorContext from '../contexts/ErrorContext';
|
|||
import { modifyProcessModelPath, unModifyProcessModelPath } from '../helpers';
|
||||
import { ProcessFile, ProcessModel, RecentProcessModel } from '../interfaces';
|
||||
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
|
||||
import ProcessInstanceListTable from '../components/ProcessInstanceListTable';
|
||||
|
||||
const storeRecentProcessModelInLocalStorage = (
|
||||
processModelForStorage: ProcessModel
|
||||
|
@ -538,6 +539,11 @@ export default function ProcessModelShow() {
|
|||
{processInstancesUl()}
|
||||
<br />
|
||||
{processModelButtons()}
|
||||
<br />
|
||||
<ProcessInstanceListTable
|
||||
filtersEnabled={false}
|
||||
processModelFullIdentifier={processModel.id}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -83,7 +83,6 @@ export default function SecretList() {
|
|||
perPage={perPage}
|
||||
pagination={pagination as any}
|
||||
tableToDisplay={buildTable()}
|
||||
path="/admin/secrets"
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue