Merge pull request #25 from sartography/feature/nested-groups
Feature/nested groups
This commit is contained in:
commit
04b2e7c8fc
|
@ -0,0 +1,22 @@
|
|||
"""Updates all JSON files, based on the current state of BPMN_SPEC_ABSOLUTE_DIR"""
|
||||
from spiffworkflow_backend import get_hacked_up_app_for_script
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Main."""
|
||||
app = get_hacked_up_app_for_script()
|
||||
with app.app_context():
|
||||
|
||||
groups = ProcessModelService().get_process_groups()
|
||||
for group in groups:
|
||||
for process_model in group.process_models:
|
||||
update_items = {
|
||||
'process_group_id': '',
|
||||
'id': f"{group.id}/{process_model.id}"
|
||||
}
|
||||
ProcessModelService().update_spec(process_model, update_items)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -4,6 +4,7 @@ import shutil
|
|||
|
||||
import pytest
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.models.db import db
|
||||
from flask_bpmn.models.db import SpiffworkflowBaseDBModel
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
|
@ -66,17 +67,35 @@ def with_super_admin_user() -> UserModel:
|
|||
|
||||
|
||||
@pytest.fixture()
|
||||
def setup_process_instances_for_reports() -> list[ProcessInstanceModel]:
|
||||
def setup_process_instances_for_reports(client: FlaskClient, with_super_admin_user: UserModel) -> list[ProcessInstanceModel]:
|
||||
"""Setup_process_instances_for_reports."""
|
||||
user = BaseTest.find_or_create_user()
|
||||
user = with_super_admin_user
|
||||
process_group_id = "runs_without_input"
|
||||
process_model_id = "sample"
|
||||
load_test_spec(process_group_id=process_group_id, process_model_id=process_model_id)
|
||||
bpmn_file_name = "sample.bpmn"
|
||||
bpmn_file_location = "sample"
|
||||
process_model_identifier = BaseTest().basic_test_setup(
|
||||
client,
|
||||
with_super_admin_user,
|
||||
process_group_id=process_group_id,
|
||||
process_model_id=process_model_id,
|
||||
# bpmn_file_name=bpmn_file_name,
|
||||
bpmn_file_location=bpmn_file_location
|
||||
)
|
||||
|
||||
# BaseTest().create_process_group(
|
||||
# client=client, user=user, process_group_id=process_group_id, display_name=process_group_id
|
||||
# )
|
||||
# process_model_id = "runs_without_input/sample"
|
||||
# load_test_spec(
|
||||
# process_model_id=f"{process_group_id}/{process_model_id}",
|
||||
# process_model_source_directory="sample"
|
||||
# )
|
||||
process_instances = []
|
||||
for data in [kay(), ray(), jay()]:
|
||||
process_instance = ProcessInstanceService.create_process_instance(
|
||||
process_group_identifier=process_group_id,
|
||||
process_model_identifier=process_model_id,
|
||||
# process_group_identifier=process_group_id,
|
||||
process_model_identifier=process_model_identifier,
|
||||
user=user,
|
||||
)
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import with_statement
|
||||
|
||||
import logging
|
||||
from logging.config import fileConfig
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: 7c12964efde1
|
||||
Revision ID: 50dd2e016d94
|
||||
Revises:
|
||||
Create Date: 2022-11-08 07:48:44.265652
|
||||
Create Date: 2022-11-08 16:28:18.991635
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
|
@ -10,7 +10,7 @@ import sqlalchemy as sa
|
|||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '7c12964efde1'
|
||||
revision = '50dd2e016d94'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
@ -95,7 +95,7 @@ def upgrade():
|
|||
)
|
||||
op.create_table('process_instance',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('process_model_identifier', sa.String(length=50), 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),
|
|
@ -286,21 +286,14 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/ProcessModel"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/files:
|
||||
/process-models/{modified_process_model_id}/files:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
- name: modified_process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The group containing the models we want to return
|
||||
description: The process_model_id, modified to replace slashes (/)
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model to validate.
|
||||
schema:
|
||||
type: string
|
||||
# add_file
|
||||
post:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.add_file
|
||||
summary: Add a new workflow spec file
|
||||
|
@ -322,36 +315,15 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/File"
|
||||
# get:
|
||||
# operationId: spiffworkflow_backend.api.process_api_blueprint.get_files
|
||||
# summary: Provide a list of workflow spec files for the given workflow_spec_id. IMPORTANT, only includes metadata, not the file content.
|
||||
# tags:
|
||||
# - Process Model Files
|
||||
# responses:
|
||||
# '200':
|
||||
# description: An array of file descriptions (not the file content)
|
||||
# content:
|
||||
# application/json:
|
||||
# schema:
|
||||
# type: array
|
||||
# items:
|
||||
# $ref: "#/components/schemas/File"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}:
|
||||
/process-models/{modified_process_model_identifier}:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
- name: modified_process_model_identifier
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
description: the modified process model id
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
schema:
|
||||
type: string
|
||||
# process_model_show
|
||||
get:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_show
|
||||
summary: Returns a single process model
|
||||
|
@ -364,22 +336,9 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProcessModel"
|
||||
# process_model_delete
|
||||
delete:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_delete
|
||||
summary: Removes an existing process model
|
||||
tags:
|
||||
- Process Models
|
||||
responses:
|
||||
"200":
|
||||
description: The process model has been removed.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
put:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_update
|
||||
summary: Modifies an existing process mosel with the given parameters.
|
||||
summary: Modifies an existing process model with the given parameters.
|
||||
tags:
|
||||
- Process Models
|
||||
requestBody:
|
||||
|
@ -394,15 +353,21 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProcessModel"
|
||||
delete:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_delete
|
||||
summary: Removes an existing process model
|
||||
tags:
|
||||
- Process Models
|
||||
responses:
|
||||
"200":
|
||||
description: The process model has been removed.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-instances:
|
||||
parameters:
|
||||
- name: process_group_identifier
|
||||
in: query
|
||||
required: false
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_identifier
|
||||
in: query
|
||||
required: false
|
||||
|
@ -548,15 +513,9 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances:
|
||||
/process-models/{modified_process_model_id}/process-instances:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
- name: modified_process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
|
@ -576,18 +535,33 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}:
|
||||
/process-instances/{process_instance_id}:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
- name: process_instance_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
description: The unique id of an existing process instance.
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
type: integer
|
||||
delete:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_delete
|
||||
summary: Deletes a single process instance
|
||||
tags:
|
||||
- Process Instances
|
||||
responses:
|
||||
"200":
|
||||
description: The process instance was deleted.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{modified_process_model_identifier}/process-instances/{process_instance_id}:
|
||||
parameters:
|
||||
- name: modified_process_model_identifier
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
description: The unique id of an existing process model
|
||||
schema:
|
||||
type: string
|
||||
- name: process_instance_id
|
||||
|
@ -608,34 +582,9 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
# process_instance_delete
|
||||
delete:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_delete
|
||||
summary: Deletes a single process instance
|
||||
tags:
|
||||
- Process Instances
|
||||
responses:
|
||||
"200":
|
||||
description: The process instance was deleted.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run:
|
||||
/process-instances/{process_instance_id}/run:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
schema:
|
||||
type: string
|
||||
- name: process_instance_id
|
||||
in: path
|
||||
required: true
|
||||
|
@ -662,20 +611,8 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/terminate:
|
||||
/process-instances/{process_instance_id}/terminate:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
schema:
|
||||
type: string
|
||||
- name: process_instance_id
|
||||
in: path
|
||||
required: true
|
||||
|
@ -695,20 +632,8 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/suspend:
|
||||
/process-instances/{process_instance_id}/suspend:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
schema:
|
||||
type: string
|
||||
- name: process_instance_id
|
||||
in: path
|
||||
required: true
|
||||
|
@ -728,20 +653,8 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/resume:
|
||||
/process-instances/{process_instance_id}/resume:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
schema:
|
||||
type: string
|
||||
- name: process_instance_id
|
||||
in: path
|
||||
required: true
|
||||
|
@ -789,6 +702,33 @@ paths:
|
|||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/reports:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
schema:
|
||||
type: string
|
||||
- name: page
|
||||
in: query
|
||||
required: false
|
||||
description: The page number to return. Defaults to page 1.
|
||||
schema:
|
||||
type: integer
|
||||
- name: per_page
|
||||
in: query
|
||||
required: false
|
||||
description: The page number to return. Defaults to page 1.
|
||||
schema:
|
||||
type: integer
|
||||
post:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_create
|
||||
summary: Returns all process instance reports for process model
|
||||
|
@ -836,6 +776,39 @@ paths:
|
|||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/reports/{report_identifier}:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
schema:
|
||||
type: string
|
||||
- name: report_identifier
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing report
|
||||
schema:
|
||||
type: string
|
||||
- name: page
|
||||
in: query
|
||||
required: false
|
||||
description: The page number to return. Defaults to page 1.
|
||||
schema:
|
||||
type: integer
|
||||
- name: per_page
|
||||
in: query
|
||||
required: false
|
||||
description: The page number to return. Defaults to page 1.
|
||||
schema:
|
||||
type: integer
|
||||
put:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_update
|
||||
summary: Updates a process instance report
|
||||
|
@ -861,18 +834,12 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/OkTrue"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/files/{file_name}:
|
||||
/process-models/{modified_process_model_id}/files/{file_name}:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
- name: modified_process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model to validate.
|
||||
description: The modified process model id
|
||||
schema:
|
||||
type: string
|
||||
- name: file_name
|
||||
|
@ -881,7 +848,6 @@ paths:
|
|||
description: The id of the spec file
|
||||
schema:
|
||||
type: string
|
||||
# get_file
|
||||
get:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.get_file
|
||||
summary: Returns metadata about the file
|
||||
|
@ -1179,20 +1145,8 @@ paths:
|
|||
schema:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/logs:
|
||||
/process-instances/{process_instance_id}/logs:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process group
|
||||
schema:
|
||||
type: string
|
||||
- name: process_model_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of an existing process model.
|
||||
schema:
|
||||
type: string
|
||||
- name: process_instance_id
|
||||
in: path
|
||||
required: true
|
||||
|
|
|
@ -41,3 +41,15 @@ permissions:
|
|||
users: [testuser4]
|
||||
allowed_permissions: [create, read, update, delete]
|
||||
uri: /v1.0/process-models/finance/*
|
||||
|
||||
finance-admin-model-lanes:
|
||||
groups: ["Finance Team"]
|
||||
users: [testuser4]
|
||||
allowed_permissions: [create, read, update, delete]
|
||||
uri: /v1.0/process-models/finance:model_with_lanes/*
|
||||
|
||||
finance-admin-instance-run:
|
||||
groups: ["Finance Team"]
|
||||
users: [testuser4]
|
||||
allowed_permissions: [create, read, update, delete]
|
||||
uri: /v1.0/process-instances/*
|
||||
|
|
|
@ -20,6 +20,9 @@ SPIFFWORKFLOW_BACKEND_LOG_LEVEL = environ.get(
|
|||
# different places and this allows us to know exactly where we are at the start
|
||||
BPMN_SPEC_ABSOLUTE_DIR = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"tests",
|
||||
"spiffworkflow_backend",
|
||||
"files",
|
||||
|
|
|
@ -72,7 +72,7 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
|
|||
|
||||
__tablename__ = "process_instance"
|
||||
id: int = db.Column(db.Integer, primary_key=True)
|
||||
process_model_identifier: str = db.Column(db.String(50), nullable=False, index=True)
|
||||
process_model_identifier: str = db.Column(db.String(255), nullable=False, index=True)
|
||||
process_group_identifier: str = db.Column(db.String(50), nullable=False, index=True)
|
||||
process_initiator_id: int = db.Column(ForeignKey(UserModel.id), nullable=False)
|
||||
process_initiator = relationship("UserModel")
|
||||
|
|
|
@ -109,6 +109,9 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
|
|||
def add_fixtures(cls) -> None:
|
||||
"""Add_fixtures."""
|
||||
try:
|
||||
# process_model = ProcessModelService().get_process_model(
|
||||
# process_model_id="sartography-admin/ticket"
|
||||
# )
|
||||
user = UserModel.query.first()
|
||||
columns = [
|
||||
{"Header": "id", "accessor": "id"},
|
||||
|
@ -235,8 +238,18 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
|
|||
user: UserModel,
|
||||
) -> ProcessInstanceReportModel:
|
||||
"""Create_with_attributes."""
|
||||
# <<<<<<< HEAD
|
||||
# process_model = ProcessModelService().get_process_model(
|
||||
# process_model_id=f"{process_model_identifier}"
|
||||
# )
|
||||
# process_instance_report = cls(
|
||||
# identifier=identifier,
|
||||
# process_group_identifier="process_model.process_group_id",
|
||||
# process_model_identifier=process_model.id,
|
||||
# =======
|
||||
process_instance_report = cls(
|
||||
identifier=identifier,
|
||||
# >>>>>>> main
|
||||
created_by_id=user.id,
|
||||
report_metadata=report_metadata,
|
||||
)
|
||||
|
|
|
@ -29,7 +29,7 @@ class ProcessModelInfo:
|
|||
id: str
|
||||
display_name: str
|
||||
description: str
|
||||
process_group_id: str = ""
|
||||
process_group: Any | None = None
|
||||
primary_file_name: str | None = None
|
||||
primary_process_id: str | None = None
|
||||
display_order: int | None = 0
|
||||
|
@ -40,7 +40,7 @@ class ProcessModelInfo:
|
|||
|
||||
def __post_init__(self) -> None:
|
||||
"""__post_init__."""
|
||||
self.sort_index = f"{self.process_group_id}:{self.id}"
|
||||
self.sort_index = self.id
|
||||
|
||||
def __eq__(self, other: Any) -> bool:
|
||||
"""__eq__."""
|
||||
|
@ -66,7 +66,6 @@ class ProcessModelInfoSchema(Schema):
|
|||
primary_file_name = marshmallow.fields.String(allow_none=True)
|
||||
primary_process_id = marshmallow.fields.String(allow_none=True)
|
||||
is_review = marshmallow.fields.Boolean(allow_none=True)
|
||||
process_group_id = marshmallow.fields.String(allow_none=True)
|
||||
files = marshmallow.fields.List(marshmallow.fields.Nested("FileSchema"))
|
||||
fault_or_suspend_on_exception = marshmallow.fields.String()
|
||||
exception_notification_addresses = marshmallow.fields.List(
|
||||
|
|
|
@ -137,6 +137,14 @@ def permissions_check(body: Dict[str, Dict[str, list[str]]]) -> flask.wrappers.R
|
|||
return make_response(jsonify({"results": response_dict}), 200)
|
||||
|
||||
|
||||
def modify_process_model_id(process_model_id: str) -> str:
|
||||
return process_model_id.replace('/', ':')
|
||||
|
||||
|
||||
def un_modify_modified_process_model_id(modified_process_model_id: str) -> str:
|
||||
return modified_process_model_id.replace(':', '/')
|
||||
|
||||
|
||||
def process_group_add(body: dict) -> flask.wrappers.Response:
|
||||
"""Add_process_group."""
|
||||
process_model_service = ProcessModelService()
|
||||
|
@ -216,9 +224,10 @@ def process_model_add(
|
|||
status_code=400,
|
||||
)
|
||||
|
||||
process_group_id, _ = os.path.split(process_model_info.id)
|
||||
process_model_service = ProcessModelService()
|
||||
process_group = process_model_service.get_process_group(
|
||||
process_model_info.process_group_id
|
||||
process_group_id
|
||||
)
|
||||
if process_group is None:
|
||||
raise ApiError(
|
||||
|
@ -236,17 +245,20 @@ def process_model_add(
|
|||
|
||||
|
||||
def process_model_delete(
|
||||
process_group_id: str, process_model_id: str
|
||||
modified_process_model_identifier: str
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_model_delete."""
|
||||
ProcessModelService().process_model_delete(process_model_id)
|
||||
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
||||
# process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
ProcessModelService().process_model_delete(process_model_identifier)
|
||||
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
|
||||
|
||||
|
||||
def process_model_update(
|
||||
process_group_id: str, process_model_id: str, body: Dict[str, Union[str, bool, int]]
|
||||
modified_process_model_identifier: str, body: Dict[str, Union[str, bool, int]]
|
||||
) -> Any:
|
||||
"""Process_model_update."""
|
||||
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
||||
body_include_list = ["display_name", "primary_file_name", "primary_process_id", "description"]
|
||||
body_filtered = {
|
||||
include_item: body[include_item]
|
||||
|
@ -254,14 +266,19 @@ def process_model_update(
|
|||
if include_item in body
|
||||
}
|
||||
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
# process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
process_model = get_process_model(process_model_identifier)
|
||||
ProcessModelService().update_spec(process_model, body_filtered)
|
||||
return ProcessModelInfoSchema().dump(process_model)
|
||||
|
||||
|
||||
def process_model_show(process_group_id: str, process_model_id: str) -> Any:
|
||||
def process_model_show(modified_process_model_identifier: str) -> Any:
|
||||
"""Process_model_show."""
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
||||
# process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
process_model = get_process_model(process_model_identifier)
|
||||
# TODO: Temporary. Should not need the next line once models have correct ids
|
||||
# process_model.id = process_model_identifier
|
||||
files = sorted(SpecFileService.get_files(process_model))
|
||||
process_model.files = files
|
||||
for file in process_model.files:
|
||||
|
@ -298,15 +315,16 @@ def process_model_list(
|
|||
return Response(json.dumps(response_json), status=200, mimetype="application/json")
|
||||
|
||||
|
||||
def get_file(process_group_id: str, process_model_id: str, file_name: str) -> Any:
|
||||
def get_file(modified_process_model_id: str, file_name: str) -> Any:
|
||||
"""Get_file."""
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
process_model_identifier = modified_process_model_id.replace(":", "/")
|
||||
process_model = get_process_model(process_model_identifier)
|
||||
files = SpecFileService.get_files(process_model, file_name)
|
||||
if len(files) == 0:
|
||||
raise ApiError(
|
||||
error_code="unknown file",
|
||||
message=f"No information exists for file {file_name}"
|
||||
f" it does not exist in workflow {process_model_id}.",
|
||||
f" it does not exist in workflow {process_model_identifier}.",
|
||||
status_code=404,
|
||||
)
|
||||
|
||||
|
@ -314,15 +332,17 @@ def get_file(process_group_id: str, process_model_id: str, file_name: str) -> An
|
|||
file_contents = SpecFileService.get_data(process_model, file.name)
|
||||
file.file_contents = file_contents
|
||||
file.process_model_id = process_model.id
|
||||
file.process_group_id = process_model.process_group_id
|
||||
# file.process_group_id = process_model.process_group_id
|
||||
return FileSchema().dump(file)
|
||||
|
||||
|
||||
def process_model_file_update(
|
||||
process_group_id: str, process_model_id: str, file_name: str
|
||||
modified_process_model_id: str, file_name: str
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_model_file_update."""
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
process_model_identifier = modified_process_model_id.replace(":", "/")
|
||||
# process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
process_model = get_process_model(process_model_identifier)
|
||||
|
||||
request_file = get_file_from_request()
|
||||
request_file_contents = request_file.stream.read()
|
||||
|
@ -337,7 +357,7 @@ def process_model_file_update(
|
|||
|
||||
if current_app.config["GIT_COMMIT_ON_SAVE"]:
|
||||
git_output = GitService.commit(
|
||||
message=f"User: {g.user.username} clicked save for {process_group_id}/{process_model_id}/{file_name}"
|
||||
message=f"User: {g.user.username} clicked save for {process_model_identifier}/{file_name}"
|
||||
)
|
||||
current_app.logger.info(f"git output: {git_output}")
|
||||
else:
|
||||
|
@ -347,10 +367,11 @@ def process_model_file_update(
|
|||
|
||||
|
||||
def process_model_file_delete(
|
||||
process_group_id: str, process_model_id: str, file_name: str
|
||||
modified_process_model_id: str, file_name: str
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_model_file_delete."""
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
process_model_identifier = modified_process_model_id.replace(":", "/")
|
||||
process_model = get_process_model(process_model_identifier)
|
||||
try:
|
||||
SpecFileService.delete_file(process_model, file_name)
|
||||
except FileNotFoundError as exception:
|
||||
|
@ -365,9 +386,10 @@ def process_model_file_delete(
|
|||
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
|
||||
|
||||
|
||||
def add_file(process_group_id: str, process_model_id: str) -> flask.wrappers.Response:
|
||||
def add_file(modified_process_model_id: str) -> flask.wrappers.Response:
|
||||
"""Add_file."""
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
process_model_identifier = modified_process_model_id.replace(":", "/")
|
||||
process_model = get_process_model(process_model_identifier)
|
||||
request_file = get_file_from_request()
|
||||
if not request_file.filename:
|
||||
raise ApiError(
|
||||
|
@ -382,18 +404,18 @@ def add_file(process_group_id: str, process_model_id: str) -> flask.wrappers.Res
|
|||
file_contents = SpecFileService.get_data(process_model, file.name)
|
||||
file.file_contents = file_contents
|
||||
file.process_model_id = process_model.id
|
||||
file.process_group_id = process_model.process_group_id
|
||||
return Response(
|
||||
json.dumps(FileSchema().dump(file)), status=201, mimetype="application/json"
|
||||
)
|
||||
|
||||
|
||||
def process_instance_create(
|
||||
process_group_id: str, process_model_id: str
|
||||
modified_process_model_id: str
|
||||
) -> flask.wrappers.Response:
|
||||
"""Create_process_instance."""
|
||||
process_model_identifier = un_modify_modified_process_model_id(modified_process_model_id)
|
||||
process_instance = ProcessInstanceService.create_process_instance(
|
||||
process_model_id, g.user, process_group_identifier=process_group_id
|
||||
process_model_identifier, g.user
|
||||
)
|
||||
return Response(
|
||||
json.dumps(ProcessInstanceModelSchema().dump(process_instance)),
|
||||
|
@ -403,8 +425,6 @@ def process_instance_create(
|
|||
|
||||
|
||||
def process_instance_run(
|
||||
process_group_id: str,
|
||||
process_model_id: str,
|
||||
process_instance_id: int,
|
||||
do_engine_steps: bool = True,
|
||||
) -> flask.wrappers.Response:
|
||||
|
@ -446,10 +466,7 @@ def process_instance_run(
|
|||
|
||||
|
||||
def process_instance_terminate(
|
||||
process_group_id: str,
|
||||
process_model_id: str,
|
||||
process_instance_id: int,
|
||||
do_engine_steps: bool = True,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_instance_run."""
|
||||
process_instance = ProcessInstanceService().get_process_instance(
|
||||
|
@ -461,8 +478,6 @@ def process_instance_terminate(
|
|||
|
||||
|
||||
def process_instance_suspend(
|
||||
process_group_id: str,
|
||||
process_model_id: str,
|
||||
process_instance_id: int,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_instance_suspend."""
|
||||
|
@ -475,8 +490,6 @@ def process_instance_suspend(
|
|||
|
||||
|
||||
def process_instance_resume(
|
||||
process_group_id: str,
|
||||
process_model_id: str,
|
||||
process_instance_id: int,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_instance_resume."""
|
||||
|
@ -489,8 +502,6 @@ def process_instance_resume(
|
|||
|
||||
|
||||
def process_instance_log_list(
|
||||
process_group_id: str,
|
||||
process_model_id: str,
|
||||
process_instance_id: int,
|
||||
page: int = 1,
|
||||
per_page: int = 100,
|
||||
|
@ -651,7 +662,6 @@ def message_start(
|
|||
|
||||
|
||||
def process_instance_list(
|
||||
process_group_identifier: Optional[str] = None,
|
||||
process_model_identifier: Optional[str] = None,
|
||||
page: int = 1,
|
||||
per_page: int = 100,
|
||||
|
@ -662,10 +672,11 @@ def process_instance_list(
|
|||
process_status: Optional[str] = None,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_instance_list."""
|
||||
# process_model_identifier = un_modify_modified_process_model_id(modified_process_model_identifier)
|
||||
process_instance_query = ProcessInstanceModel.query
|
||||
if process_model_identifier is not None and process_group_identifier is not None:
|
||||
if process_model_identifier is not None:
|
||||
process_model = get_process_model(
|
||||
process_model_identifier, process_group_identifier
|
||||
f"{process_model_identifier}",
|
||||
)
|
||||
|
||||
process_instance_query = process_instance_query.filter_by(
|
||||
|
@ -743,12 +754,13 @@ def process_instance_list(
|
|||
|
||||
|
||||
def process_instance_show(
|
||||
process_group_id: str, process_model_id: str, process_instance_id: int
|
||||
modified_process_model_identifier: str, process_instance_id: int
|
||||
) -> flask.wrappers.Response:
|
||||
"""Create_process_instance."""
|
||||
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
||||
process_instance = find_process_instance_by_id_or_raise(process_instance_id)
|
||||
current_version_control_revision = GitService.get_current_revision()
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
process_model = get_process_model(process_model_identifier)
|
||||
|
||||
if process_model.primary_file_name:
|
||||
if (
|
||||
|
@ -768,7 +780,7 @@ def process_instance_show(
|
|||
|
||||
|
||||
def process_instance_delete(
|
||||
process_group_id: str, process_model_id: str, process_instance_id: int
|
||||
process_instance_id: int
|
||||
) -> flask.wrappers.Response:
|
||||
"""Create_process_instance."""
|
||||
process_instance = find_process_instance_by_id_or_raise(process_instance_id)
|
||||
|
@ -888,6 +900,7 @@ def process_instance_report_show(
|
|||
per_page: int = 100,
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process_instance_list."""
|
||||
|
||||
process_instances = ProcessInstanceModel.query.order_by( # .filter_by(process_model_identifier=process_model.id)
|
||||
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
|
||||
).paginate(
|
||||
|
@ -1008,7 +1021,6 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response
|
|||
|
||||
process_model = get_process_model(
|
||||
process_instance.process_model_identifier,
|
||||
process_instance.process_group_identifier,
|
||||
)
|
||||
|
||||
form_schema_file_name = ""
|
||||
|
@ -1160,7 +1172,7 @@ def task_submit(
|
|||
def script_unit_test_create(
|
||||
process_group_id: str, process_model_id: str, body: Dict[str, Union[str, bool, int]]
|
||||
) -> flask.wrappers.Response:
|
||||
"""Script_unit_test_run."""
|
||||
"""Script_unit_test_create."""
|
||||
bpmn_task_identifier = _get_required_parameter_or_raise(
|
||||
"bpmn_task_identifier", body
|
||||
)
|
||||
|
@ -1169,7 +1181,8 @@ def script_unit_test_create(
|
|||
"expected_output_json", body
|
||||
)
|
||||
|
||||
process_model = get_process_model(process_model_id, process_group_id)
|
||||
process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
process_model = get_process_model(process_model_identifier)
|
||||
file = SpecFileService.get_files(process_model, process_model.primary_file_name)[0]
|
||||
if file is None:
|
||||
raise ApiError(
|
||||
|
@ -1279,12 +1292,12 @@ def get_file_from_request() -> Any:
|
|||
return request_file
|
||||
|
||||
|
||||
def get_process_model(process_model_id: str, process_group_id: str) -> ProcessModelInfo:
|
||||
def get_process_model(process_model_id: str) -> ProcessModelInfo:
|
||||
"""Get_process_model."""
|
||||
process_model = None
|
||||
try:
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
process_model_id, group_id=process_group_id
|
||||
process_model_id
|
||||
)
|
||||
except ProcessEntityNotFoundError as exception:
|
||||
raise (
|
||||
|
|
|
@ -46,6 +46,7 @@ def verify_token(
|
|||
ApiError: If not on production and token is not valid, returns an 'invalid_token' 403 error.
|
||||
If on production and user is not authenticated, returns a 'no_user' 403 error.
|
||||
"""
|
||||
user_info = None
|
||||
if not force_run and AuthorizationService.should_disable_auth_for_request():
|
||||
return None
|
||||
|
||||
|
@ -104,6 +105,7 @@ def verify_token(
|
|||
raise ApiError(
|
||||
error_code="fail_get_user_info",
|
||||
message="Cannot get user info from token",
|
||||
status_code=401
|
||||
) from e
|
||||
|
||||
if (
|
||||
|
|
|
@ -35,7 +35,7 @@ class ErrorHandlingService:
|
|||
) -> None:
|
||||
"""On unhandled exceptions, set instance.status based on model.fault_or_suspend_on_exception."""
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
_processor.process_model_identifier, _processor.process_group_identifier
|
||||
_processor.process_model_identifier
|
||||
)
|
||||
if process_model.fault_or_suspend_on_exception == "suspend":
|
||||
self.set_instance_status(
|
||||
|
|
|
@ -54,18 +54,20 @@ class FileSystemService:
|
|||
@staticmethod
|
||||
def process_group_path_for_spec(spec: ProcessModelInfo) -> str:
|
||||
"""Category_path_for_spec."""
|
||||
return FileSystemService.process_group_path(spec.process_group_id)
|
||||
process_group_id, _ = os.path.split(spec.id)
|
||||
return FileSystemService.process_group_path(process_group_id)
|
||||
|
||||
@staticmethod
|
||||
def workflow_path(spec: ProcessModelInfo) -> str:
|
||||
"""Workflow_path."""
|
||||
process_group_path = FileSystemService.process_group_path_for_spec(spec)
|
||||
return os.path.join(process_group_path, spec.id)
|
||||
process_model_path = os.path.join(FileSystemService.root_path(), spec.id)
|
||||
# process_group_path = FileSystemService.process_group_path_for_spec(spec)
|
||||
return process_model_path
|
||||
|
||||
@staticmethod
|
||||
def full_path_to_process_model_file(spec: ProcessModelInfo, file_name: str) -> str:
|
||||
def full_path_to_process_model_file(spec: ProcessModelInfo) -> str:
|
||||
"""Full_path_to_process_model_file."""
|
||||
return os.path.join(FileSystemService.workflow_path(spec), file_name)
|
||||
return os.path.join(FileSystemService.workflow_path(spec), spec.primary_file_name)
|
||||
|
||||
def next_display_order(self, spec: ProcessModelInfo) -> int:
|
||||
"""Next_display_order."""
|
||||
|
|
|
@ -120,7 +120,6 @@ class MessageService:
|
|||
process_instance_receive = ProcessInstanceService.create_process_instance(
|
||||
message_triggerable_process_model.process_model_identifier,
|
||||
user,
|
||||
process_group_identifier=message_triggerable_process_model.process_group_identifier,
|
||||
)
|
||||
processor_receive = ProcessInstanceProcessor(process_instance_receive)
|
||||
processor_receive.do_engine_steps(save=False)
|
||||
|
|
|
@ -307,8 +307,7 @@ class ProcessInstanceProcessor:
|
|||
bpmn_process_spec,
|
||||
subprocesses,
|
||||
) = ProcessInstanceProcessor.get_process_model_and_subprocesses(
|
||||
process_instance_model.process_model_identifier,
|
||||
process_instance_model.process_group_identifier,
|
||||
process_instance_model.process_model_identifier
|
||||
)
|
||||
else:
|
||||
bpmn_json_length = len(process_instance_model.bpmn_json.encode("utf-8"))
|
||||
|
@ -359,7 +358,7 @@ class ProcessInstanceProcessor:
|
|||
check_sub_specs(test_spec, 5)
|
||||
|
||||
self.process_model_identifier = process_instance_model.process_model_identifier
|
||||
self.process_group_identifier = process_instance_model.process_group_identifier
|
||||
# self.process_group_identifier = process_instance_model.process_group_identifier
|
||||
|
||||
try:
|
||||
self.bpmn_process_instance = self.__get_bpmn_process_instance(
|
||||
|
@ -394,17 +393,17 @@ class ProcessInstanceProcessor:
|
|||
|
||||
@classmethod
|
||||
def get_process_model_and_subprocesses(
|
||||
cls, process_model_identifier: str, process_group_identifier: str
|
||||
cls, process_model_identifier: str
|
||||
) -> Tuple[BpmnProcessSpec, IdToBpmnProcessSpecMapping]:
|
||||
"""Get_process_model_and_subprocesses."""
|
||||
process_model_info = ProcessModelService().get_process_model(
|
||||
process_model_identifier, process_group_identifier
|
||||
process_model_identifier
|
||||
)
|
||||
if process_model_info is None:
|
||||
raise (
|
||||
ApiError(
|
||||
"process_model_not_found",
|
||||
f"The given process model was not found: {process_group_identifier}/{process_model_identifier}.",
|
||||
f"The given process model was not found: {process_model_identifier}.",
|
||||
)
|
||||
)
|
||||
spec_files = SpecFileService.get_files(process_model_info)
|
||||
|
@ -412,12 +411,11 @@ class ProcessInstanceProcessor:
|
|||
|
||||
@classmethod
|
||||
def get_bpmn_process_instance_from_process_model(
|
||||
cls, process_model_identifier: str, process_group_identifier: str
|
||||
cls, process_model_identifier: str
|
||||
) -> BpmnWorkflow:
|
||||
"""Get_all_bpmn_process_identifiers_for_process_model."""
|
||||
(bpmn_process_spec, subprocesses) = cls.get_process_model_and_subprocesses(
|
||||
process_model_identifier,
|
||||
process_group_identifier,
|
||||
)
|
||||
return cls.get_bpmn_process_instance_from_workflow_spec(
|
||||
bpmn_process_spec, subprocesses
|
||||
|
@ -698,7 +696,7 @@ class ProcessInstanceProcessor:
|
|||
etree_element,
|
||||
)
|
||||
return FileSystemService.full_path_to_process_model_file(
|
||||
process_model, process_model.primary_file_name
|
||||
process_model
|
||||
)
|
||||
return None
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ class ProcessInstanceService:
|
|||
def create_process_instance(
|
||||
process_model_identifier: str,
|
||||
user: UserModel,
|
||||
process_group_identifier: Optional[str] = None,
|
||||
) -> ProcessInstanceModel:
|
||||
"""Get_process_instance_from_spec."""
|
||||
current_git_revision = GitService.get_current_revision()
|
||||
|
@ -41,7 +40,7 @@ class ProcessInstanceService:
|
|||
status=ProcessInstanceStatus.not_started.value,
|
||||
process_initiator=user,
|
||||
process_model_identifier=process_model_identifier,
|
||||
process_group_identifier=process_group_identifier,
|
||||
process_group_identifier="",
|
||||
start_in_seconds=round(time.time()),
|
||||
bpmn_version_control_type="git",
|
||||
bpmn_version_control_identifier=current_git_revision,
|
||||
|
@ -98,7 +97,7 @@ class ProcessInstanceService:
|
|||
next_task=None,
|
||||
# navigation=navigation,
|
||||
process_model_identifier=processor.process_model_identifier,
|
||||
process_group_identifier=processor.process_group_identifier,
|
||||
process_group_identifier="",
|
||||
# total_tasks=len(navigation),
|
||||
completed_tasks=processor.process_instance_model.completed_tasks,
|
||||
updated_at_in_seconds=processor.process_instance_model.updated_at_in_seconds,
|
||||
|
|
|
@ -34,6 +34,18 @@ class ProcessModelService(FileSystemService):
|
|||
GROUP_SCHEMA = ProcessGroupSchema()
|
||||
WF_SCHEMA = ProcessModelInfoSchema()
|
||||
|
||||
def is_group(self, path):
|
||||
group_json_path = os.path.join(path, self.CAT_JSON_FILE)
|
||||
if os.path.exists(group_json_path):
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_model(self, path):
|
||||
model_json_path = os.path.join(path, self.WF_JSON_FILE)
|
||||
if os.path.exists(model_json_path):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_batch(
|
||||
items: list[T],
|
||||
|
@ -62,7 +74,7 @@ class ProcessModelService(FileSystemService):
|
|||
|
||||
def save_process_model(self, process_model: ProcessModelInfo) -> None:
|
||||
"""Save_process_model."""
|
||||
spec_path = self.workflow_path(process_model)
|
||||
spec_path = os.path.join(FileSystemService.root_path(), process_model.id)
|
||||
os.makedirs(spec_path, exist_ok=True)
|
||||
json_path = os.path.join(spec_path, self.WF_JSON_FILE)
|
||||
with open(json_path, "w") as wf_json:
|
||||
|
@ -81,7 +93,8 @@ class ProcessModelService(FileSystemService):
|
|||
message=f"We cannot delete the model `{process_model_id}`, there are existing instances that depend on it.",
|
||||
)
|
||||
process_model = self.get_process_model(process_model_id)
|
||||
path = self.workflow_path(process_model)
|
||||
# path = self.workflow_path(process_model)
|
||||
path = f"{FileSystemService.root_path()}/{process_model_id}"
|
||||
shutil.rmtree(path)
|
||||
|
||||
@classmethod
|
||||
|
@ -89,36 +102,43 @@ class ProcessModelService(FileSystemService):
|
|||
cls, relative_path: str
|
||||
) -> ProcessModelInfo:
|
||||
"""Get_process_model_from_relative_path."""
|
||||
process_group_identifier = os.path.dirname(relative_path)
|
||||
process_group_identifier, _ = os.path.split(relative_path)
|
||||
process_group = cls().get_process_group(process_group_identifier)
|
||||
path = os.path.join(FileSystemService.root_path(), relative_path)
|
||||
return cls().__scan_spec(path, process_group=process_group)
|
||||
|
||||
def get_process_model(
|
||||
self, process_model_id: str, group_id: Optional[str] = None
|
||||
self, process_model_id: str
|
||||
) -> ProcessModelInfo:
|
||||
"""Get a process model from a model and group id."""
|
||||
"""Get a process model from a model and group id.
|
||||
process_model_id is the full path to the model--including groups"""
|
||||
if not os.path.exists(FileSystemService.root_path()):
|
||||
raise ProcessEntityNotFoundError("process_model_not_found")
|
||||
raise ProcessEntityNotFoundError("process_model_root_not_found")
|
||||
|
||||
if group_id is not None:
|
||||
process_group = self.get_process_group(group_id)
|
||||
if process_group is not None:
|
||||
for process_model in process_group.process_models:
|
||||
if process_model_id == process_model.id:
|
||||
return process_model
|
||||
with os.scandir(FileSystemService.root_path()) as process_group_dirs:
|
||||
for item in process_group_dirs:
|
||||
process_group_dir = item
|
||||
if item.is_dir():
|
||||
with os.scandir(item.path) as spec_dirs:
|
||||
for sd in spec_dirs:
|
||||
if sd.name == process_model_id:
|
||||
# Now we have the process_group direcotry, and spec directory
|
||||
process_group = self.__scan_process_group(
|
||||
process_group_dir
|
||||
)
|
||||
return self.__scan_spec(sd.path, sd.name, process_group)
|
||||
model_path = os.path.join(FileSystemService.root_path(), process_model_id)
|
||||
if self.is_model(model_path):
|
||||
process_model = self.get_process_model_from_relative_path(process_model_id)
|
||||
return process_model
|
||||
|
||||
# group_path, model_id = os.path.split(process_model_id)
|
||||
# if group_path is not None:
|
||||
# process_group = self.get_process_group(group_path)
|
||||
# if process_group is not None:
|
||||
# for process_model in process_group.process_models:
|
||||
# if process_model_id == process_model.id:
|
||||
# return process_model
|
||||
# with os.scandir(FileSystemService.root_path()) as process_group_dirs:
|
||||
# for item in process_group_dirs:
|
||||
# process_group_dir = item
|
||||
# if item.is_dir():
|
||||
# with os.scandir(item.path) as spec_dirs:
|
||||
# for sd in spec_dirs:
|
||||
# if sd.name == process_model_id:
|
||||
# # Now we have the process_group directory, and spec directory
|
||||
# process_group = self.__scan_process_group(
|
||||
# process_group_dir
|
||||
# )
|
||||
# return self.__scan_spec(sd.path, sd.name, process_group)
|
||||
raise ProcessEntityNotFoundError("process_model_not_found")
|
||||
|
||||
def get_process_models(
|
||||
|
@ -148,10 +168,22 @@ class ProcessModelService(FileSystemService):
|
|||
def get_process_group(self, process_group_id: str) -> ProcessGroup:
|
||||
"""Look for a given process_group, and return it."""
|
||||
if os.path.exists(FileSystemService.root_path()):
|
||||
with os.scandir(FileSystemService.root_path()) as directory_items:
|
||||
for item in directory_items:
|
||||
if item.is_dir() and item.name == process_group_id:
|
||||
return self.__scan_process_group(item)
|
||||
process_group_path = os.path.join(FileSystemService.root_path(), process_group_id)
|
||||
if self.is_group(process_group_path):
|
||||
return self.__scan_process_group(process_group_path)
|
||||
# nested_groups = []
|
||||
# process_group_dir = os.scandir(process_group_path)
|
||||
# for item in process_group_dir:
|
||||
# if self.is_group(item.path):
|
||||
# nested_group = self.get_process_group(os.path.join(process_group_path, item.path))
|
||||
# nested_groups.append(nested_group)
|
||||
# elif self.is_model(item.path):
|
||||
# print("get_process_group: ")
|
||||
# return self.__scan_process_group(process_group_path)
|
||||
# with os.scandir(FileSystemService.root_path()) as directory_items:
|
||||
# for item in directory_items:
|
||||
# if item.is_dir() and item.name == process_group_id:
|
||||
# return self.__scan_process_group(item)
|
||||
|
||||
raise ProcessEntityNotFoundError(
|
||||
"process_group_not_found", f"Process Group Id: {process_group_id}"
|
||||
|
@ -202,13 +234,15 @@ class ProcessModelService(FileSystemService):
|
|||
with os.scandir(FileSystemService.root_path()) as directory_items:
|
||||
process_groups = []
|
||||
for item in directory_items:
|
||||
if item.is_dir() and not item.name[0] == ".":
|
||||
process_groups.append(self.__scan_process_group(item))
|
||||
# if item.is_dir() and not item.name[0] == ".":
|
||||
if item.is_dir() and self.is_group(item):
|
||||
scanned_process_group = self.__scan_process_group(item.path)
|
||||
process_groups.append(scanned_process_group)
|
||||
return process_groups
|
||||
|
||||
def __scan_process_group(self, dir_item: os.DirEntry) -> ProcessGroup:
|
||||
"""Reads the process_group.json file, and any workflow directories."""
|
||||
cat_path = os.path.join(dir_item.path, self.CAT_JSON_FILE)
|
||||
def __scan_process_group(self, dir_path: str) -> ProcessGroup:
|
||||
"""Reads the process_group.json file, and any nested directories."""
|
||||
cat_path = os.path.join(dir_path, self.CAT_JSON_FILE)
|
||||
if os.path.exists(cat_path):
|
||||
with open(cat_path) as cat_json:
|
||||
data = json.load(cat_json)
|
||||
|
@ -216,26 +250,32 @@ class ProcessModelService(FileSystemService):
|
|||
if process_group is None:
|
||||
raise ApiError(
|
||||
error_code="process_group_could_not_be_loaded_from_disk",
|
||||
message=f"We could not load the process_group from disk from: {dir_item}",
|
||||
message=f"We could not load the process_group from disk from: {dir_path}",
|
||||
)
|
||||
else:
|
||||
process_group_id = dir_path.replace(FileSystemService.root_path(), '')
|
||||
process_group = ProcessGroup(
|
||||
id=dir_item.name,
|
||||
display_name=dir_item.name,
|
||||
id=process_group_id,
|
||||
display_name=process_group_id,
|
||||
display_order=10000,
|
||||
admin=False,
|
||||
)
|
||||
with open(cat_path, "w") as wf_json:
|
||||
json.dump(self.GROUP_SCHEMA.dump(process_group), wf_json, indent=4)
|
||||
with os.scandir(dir_item.path) as workflow_dirs:
|
||||
with os.scandir(dir_path) as nested_items:
|
||||
process_group.process_models = []
|
||||
for item in workflow_dirs:
|
||||
if item.is_dir():
|
||||
process_group.process_models.append(
|
||||
self.__scan_spec(
|
||||
item.path, item.name, process_group=process_group
|
||||
for nested_item in nested_items:
|
||||
if nested_item.is_dir():
|
||||
# TODO: check whether this is a group or model
|
||||
if self.is_group(nested_item.path):
|
||||
# This is a nested group
|
||||
...
|
||||
elif self.is_model(nested_item.path):
|
||||
process_group.process_models.append(
|
||||
self.__scan_spec(
|
||||
nested_item.path, nested_item.name, process_group=process_group
|
||||
)
|
||||
)
|
||||
)
|
||||
process_group.process_models.sort()
|
||||
return process_group
|
||||
|
||||
|
@ -251,6 +291,8 @@ class ProcessModelService(FileSystemService):
|
|||
if os.path.exists(spec_path):
|
||||
with open(spec_path) as wf_json:
|
||||
data = json.load(wf_json)
|
||||
if "process_group_id" in data:
|
||||
data.pop("process_group_id")
|
||||
spec = ProcessModelInfo(**data)
|
||||
if spec is None:
|
||||
raise ApiError(
|
||||
|
|
|
@ -48,7 +48,8 @@ class SpecFileService(FileSystemService):
|
|||
extension_filter: str = "",
|
||||
) -> List[File]:
|
||||
"""Return all files associated with a workflow specification."""
|
||||
path = SpecFileService.workflow_path(process_model_info)
|
||||
# path = SpecFileService.workflow_path(process_model_info)
|
||||
path = os.path.join(FileSystemService.root_path(), process_model_info.id)
|
||||
files = SpecFileService._get_files(path, file_name)
|
||||
if extension_filter != "":
|
||||
files = list(
|
||||
|
@ -105,7 +106,8 @@ class SpecFileService(FileSystemService):
|
|||
) -> File:
|
||||
"""Update_file."""
|
||||
SpecFileService.assert_valid_file_name(file_name)
|
||||
file_path = SpecFileService.file_path(process_model_info, file_name)
|
||||
# file_path = SpecFileService.file_path(process_model_info, file_name)
|
||||
file_path = os.path.join(FileSystemService.root_path(), process_model_info.id, file_name)
|
||||
SpecFileService.write_file_data_to_system(file_path, binary_data)
|
||||
file = SpecFileService.to_file_object(file_name, file_path)
|
||||
|
||||
|
@ -129,7 +131,8 @@ class SpecFileService(FileSystemService):
|
|||
@staticmethod
|
||||
def get_data(process_model_info: ProcessModelInfo, file_name: str) -> bytes:
|
||||
"""Get_data."""
|
||||
file_path = SpecFileService.file_path(process_model_info, file_name)
|
||||
# file_path = SpecFileService.file_path(process_model_info, file_name)
|
||||
file_path = os.path.join(FileSystemService.root_path(), process_model_info.id, file_name)
|
||||
if not os.path.exists(file_path):
|
||||
raise ProcessModelFileNotFoundError(
|
||||
f"No file found with name {file_name} in {process_model_info.display_name}"
|
||||
|
@ -163,7 +166,8 @@ class SpecFileService(FileSystemService):
|
|||
# for lf in lookup_files:
|
||||
# session.query(LookupDataModel).filter_by(lookup_file_model_id=lf.id).delete()
|
||||
# session.query(LookupFileModel).filter_by(id=lf.id).delete()
|
||||
file_path = SpecFileService.file_path(spec, file_name)
|
||||
# file_path = SpecFileService.file_path(spec, file_name)
|
||||
file_path = os.path.join(FileSystemService.root_path(), spec.id, file_name)
|
||||
os.remove(file_path)
|
||||
|
||||
@staticmethod
|
||||
|
@ -367,9 +371,8 @@ class SpecFileService(FileSystemService):
|
|||
process_model_info: ProcessModelInfo, bpmn_file_name: str, et_root: _Element
|
||||
) -> None:
|
||||
"""Store_bpmn_process_identifiers."""
|
||||
relative_process_model_path = SpecFileService.process_model_relative_path(
|
||||
process_model_info
|
||||
)
|
||||
relative_process_model_path = process_model_info.id
|
||||
|
||||
relative_bpmn_file_path = os.path.join(
|
||||
relative_process_model_path, bpmn_file_name
|
||||
)
|
||||
|
@ -465,7 +468,7 @@ class SpecFileService(FileSystemService):
|
|||
message_triggerable_process_model = MessageTriggerableProcessModel(
|
||||
message_model_id=message_model.id,
|
||||
process_model_identifier=process_model_info.id,
|
||||
process_group_identifier=process_model_info.process_group_id,
|
||||
process_group_identifier="process_group_identifier",
|
||||
)
|
||||
db.session.add(message_triggerable_process_model)
|
||||
db.session.commit()
|
||||
|
@ -473,8 +476,8 @@ class SpecFileService(FileSystemService):
|
|||
if (
|
||||
message_triggerable_process_model.process_model_identifier
|
||||
!= process_model_info.id
|
||||
or message_triggerable_process_model.process_group_identifier
|
||||
!= process_model_info.process_group_id
|
||||
# or message_triggerable_process_model.process_group_identifier
|
||||
# != process_model_info.process_group_id
|
||||
):
|
||||
raise ValidationException(
|
||||
"Message model is already used to start process model"
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
||||
<bpmn:process id="Proccess_ManualTask" name="Manual Task" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1xlck7g</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1xlck7g" sourceRef="StartEvent_1" targetRef="Activity_Hello" />
|
||||
<bpmn:endEvent id="Event_0ia26nb">
|
||||
<bpmn:incoming>Flow_0nnh2x9</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0nnh2x9" sourceRef="Activity_Hello" targetRef="Event_0ia26nb" />
|
||||
<bpmn:manualTask id="Activity_Hello" name="Hello">
|
||||
<bpmn:extensionElements>
|
||||
<spiffworkflow:instructionsForEndUser>## Hello</spiffworkflow:instructionsForEndUser>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_1xlck7g</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0nnh2x9</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Proccess_ManualTask">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="159" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0ia26nb_di" bpmnElement="Event_0ia26nb">
|
||||
<dc:Bounds x="432" y="159" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1rcj16n_di" bpmnElement="Activity_Hello">
|
||||
<dc:Bounds x="270" y="137" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_1xlck7g_di" bpmnElement="Flow_1xlck7g">
|
||||
<di:waypoint x="215" y="177" />
|
||||
<di:waypoint x="270" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0nnh2x9_di" bpmnElement="Flow_0nnh2x9">
|
||||
<di:waypoint x="370" y="177" />
|
||||
<di:waypoint x="432" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -1,67 +1,87 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1kbzkan" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
|
||||
<bpmn:process id="Process_SimpleScript" name="Simple Script" isExecutable="true">
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
||||
<bpmn:process id="Proccess_SimpleScript" name="Simple Script" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1k9q28c</bpmn:outgoing>
|
||||
<bpmn:outgoing>Flow_0r3ua0i</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1k9q28c" sourceRef="StartEvent_1" targetRef="Activity_RunScript" />
|
||||
<bpmn:sequenceFlow id="Flow_1fviiob" sourceRef="Activity_RunScript" targetRef="Activity_DisplayData" />
|
||||
<bpmn:endEvent id="Event_1fep863">
|
||||
<bpmn:incoming>Flow_10610n2</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_10610n2" sourceRef="Activity_DisplayData" targetRef="Event_1fep863" />
|
||||
<bpmn:scriptTask id="Activity_RunScript" name="Run Script">
|
||||
<bpmn:incoming>Flow_1k9q28c</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1fviiob</bpmn:outgoing>
|
||||
<bpmn:sequenceFlow id="Flow_0r3ua0i" sourceRef="StartEvent_1" targetRef="Activity_SetInitialData" />
|
||||
<bpmn:scriptTask id="Activity_SetInitialData" name="Set Initial Data">
|
||||
<bpmn:incoming>Flow_0r3ua0i</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_19g4f88</bpmn:outgoing>
|
||||
<bpmn:script>a = 1
|
||||
b = 2
|
||||
c = a + b
|
||||
norris=fact_service(type='norris')</bpmn:script>
|
||||
b = 2</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_19g4f88" sourceRef="Activity_SetInitialData" targetRef="Activity_CalculateNewData" />
|
||||
<bpmn:scriptTask id="Activity_CalculateNewData" name="Calculate New Data">
|
||||
<bpmn:extensionElements>
|
||||
<spiffworkflow:unitTests>
|
||||
<spiffworkflow:unitTest id="ScriptUnitTest_SimpleScript">
|
||||
<spiffworkflow:inputJson>{'a': 1, 'b': 2}</spiffworkflow:inputJson>
|
||||
<spiffworkflow:expectedOutputJson>{'a': 1, 'b': 2, 'c': 3}</spiffworkflow:expectedOutputJson>
|
||||
</spiffworkflow:unitTest>
|
||||
</spiffworkflow:unitTests>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_19g4f88</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_152cqfw</bpmn:outgoing>
|
||||
<bpmn:script>c = a + b</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_152cqfw" sourceRef="Activity_CalculateNewData" targetRef="Activity_DisplayData" />
|
||||
<bpmn:manualTask id="Activity_DisplayData" name="Display Data">
|
||||
<bpmn:documentation>## Display Data
|
||||
<bpmn:extensionElements>
|
||||
<spiffworkflow:instructionsForEndUser>## Data
|
||||
|
||||
|
||||
### a
|
||||
### A
|
||||
{{ a }}
|
||||
|
||||
|
||||
### b
|
||||
### B
|
||||
{{ b }}
|
||||
|
||||
|
||||
### c
|
||||
{{ c }}</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_1fviiob</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_10610n2</bpmn:outgoing>
|
||||
### C
|
||||
{{ c }}</spiffworkflow:instructionsForEndUser>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_152cqfw</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1vqk60p</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
<bpmn:endEvent id="Event_19fiqu4">
|
||||
<bpmn:incoming>Flow_1vqk60p</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1vqk60p" sourceRef="Activity_DisplayData" targetRef="Event_19fiqu4" />
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_SimpleScript">
|
||||
<bpmndi:BPMNEdge id="Flow_10610n2_di" bpmnElement="Flow_10610n2">
|
||||
<di:waypoint x="530" y="117" />
|
||||
<di:waypoint x="592" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1fviiob_di" bpmnElement="Flow_1fviiob">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="430" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1k9q28c_di" bpmnElement="Flow_1k9q28c">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="270" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Proccess_SimpleScript">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
<dc:Bounds x="179" y="159" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_1fep863_di" bpmnElement="Event_1fep863">
|
||||
<dc:Bounds x="592" y="99" width="36" height="36" />
|
||||
<bpmndi:BPMNShape id="Activity_0l45w13_di" bpmnElement="Activity_SetInitialData">
|
||||
<dc:Bounds x="270" y="137" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_12kpu89_di" bpmnElement="Activity_RunScript">
|
||||
<dc:Bounds x="270" y="77" width="100" height="80" />
|
||||
<bpmndi:BPMNShape id="Activity_00n1s76_di" bpmnElement="Activity_CalculateNewData">
|
||||
<dc:Bounds x="430" y="137" width="100" height="80" />
|
||||
<bpmndi:BPMNLabel />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_17mrit2_di" bpmnElement="Activity_DisplayData">
|
||||
<dc:Bounds x="430" y="77" width="100" height="80" />
|
||||
<bpmndi:BPMNShape id="Activity_1nhghi0_di" bpmnElement="Activity_DisplayData">
|
||||
<dc:Bounds x="590" y="137" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_19fiqu4_di" bpmnElement="Event_19fiqu4">
|
||||
<dc:Bounds x="752" y="159" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_0r3ua0i_di" bpmnElement="Flow_0r3ua0i">
|
||||
<di:waypoint x="215" y="177" />
|
||||
<di:waypoint x="270" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_19g4f88_di" bpmnElement="Flow_19g4f88">
|
||||
<di:waypoint x="370" y="177" />
|
||||
<di:waypoint x="430" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_152cqfw_di" bpmnElement="Flow_152cqfw">
|
||||
<di:waypoint x="530" y="177" />
|
||||
<di:waypoint x="590" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1vqk60p_di" bpmnElement="Flow_1vqk60p">
|
||||
<di:waypoint x="690" y="177" />
|
||||
<di:waypoint x="752" y="177" />
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
||||
|
|
|
@ -12,6 +12,10 @@ from flask.app import Flask
|
|||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.api.api_error import ApiError
|
||||
from flask_bpmn.models.db import db
|
||||
|
||||
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
||||
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
|
||||
from spiffworkflow_backend.services.process_instance_service import ProcessInstanceService
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
from werkzeug.test import TestResponse # type: ignore
|
||||
|
||||
|
@ -34,6 +38,43 @@ from spiffworkflow_backend.services.user_service import UserService
|
|||
class BaseTest:
|
||||
"""BaseTest."""
|
||||
|
||||
def basic_test_setup(
|
||||
self,
|
||||
client: FlaskClient,
|
||||
user: UserModel,
|
||||
process_group_id: Optional[str] = "test_group",
|
||||
process_model_id: Optional[str] = "random_fact",
|
||||
bpmn_file_name: Optional[str] = None,
|
||||
bpmn_file_location: Optional[str] = None
|
||||
) -> str:
|
||||
"""Creates a process group
|
||||
Creates a process model
|
||||
Adds a bpmn file to the model"""
|
||||
|
||||
process_group_display_name = process_group_id
|
||||
process_group_description = process_group_id
|
||||
process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
if bpmn_file_location is None:
|
||||
bpmn_file_location = process_model_id
|
||||
|
||||
self.create_process_group(client, user, process_group_id, process_group_display_name)
|
||||
|
||||
self.create_process_model_with_api(
|
||||
client,
|
||||
process_model_id=process_model_identifier,
|
||||
process_model_display_name=process_group_display_name,
|
||||
process_model_description=process_group_description,
|
||||
user=user,
|
||||
)
|
||||
|
||||
load_test_spec(
|
||||
process_model_id=process_model_identifier,
|
||||
bpmn_file_name=bpmn_file_name,
|
||||
process_model_source_directory=bpmn_file_location
|
||||
)
|
||||
|
||||
return process_model_identifier
|
||||
|
||||
@staticmethod
|
||||
def find_or_create_user(username: str = "test_user_1") -> UserModel:
|
||||
"""Find_or_create_user."""
|
||||
|
@ -67,17 +108,18 @@ class BaseTest:
|
|||
open_id_client_secret_key,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def create_process_instance(
|
||||
self,
|
||||
client: FlaskClient,
|
||||
test_process_group_id: str,
|
||||
test_process_model_id: str,
|
||||
headers: Dict[str, str],
|
||||
) -> TestResponse:
|
||||
"""Create_process_instance."""
|
||||
load_test_spec(test_process_model_id, process_group_id=test_process_group_id)
|
||||
"""Create_process_instance.
|
||||
There must be an existing process model to instantiate."""
|
||||
|
||||
modified_process_model_id = test_process_model_id.replace("/", ":")
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{test_process_group_id}/{test_process_model_id}/process-instances",
|
||||
f"/v1.0/process-models/{modified_process_model_id}/process-instances",
|
||||
headers=headers,
|
||||
)
|
||||
assert response.status_code == 201
|
||||
|
@ -86,8 +128,7 @@ class BaseTest:
|
|||
def create_process_model_with_api(
|
||||
self,
|
||||
client: FlaskClient,
|
||||
process_group_id: Optional[str] = None,
|
||||
process_model_id: str = "make_cookies",
|
||||
process_model_id: Optional[str] = None,
|
||||
process_model_display_name: str = "Cooooookies",
|
||||
process_model_description: str = "Om nom nom delicious cookies",
|
||||
fault_or_suspend_on_exception: str = NotificationType.suspend.value,
|
||||
|
@ -97,65 +138,74 @@ class BaseTest:
|
|||
user: Optional[UserModel] = None,
|
||||
) -> TestResponse:
|
||||
"""Create_process_model."""
|
||||
process_model_service = ProcessModelService()
|
||||
|
||||
# make sure we have a group
|
||||
if process_group_id is None:
|
||||
process_group_tmp = ProcessGroup(
|
||||
id="test_cat",
|
||||
display_name="Test Category",
|
||||
display_order=0,
|
||||
admin=False,
|
||||
)
|
||||
process_group = process_model_service.add_process_group(process_group_tmp)
|
||||
if process_model_id is not None:
|
||||
|
||||
# make sure we have a group
|
||||
process_group_id, _ = os.path.split(process_model_id)
|
||||
process_group_path = f"{FileSystemService.root_path()}/{process_group_id}"
|
||||
if ProcessModelService().is_group(process_group_path):
|
||||
|
||||
if exception_notification_addresses is None:
|
||||
exception_notification_addresses = []
|
||||
|
||||
model = ProcessModelInfo(
|
||||
id=process_model_id,
|
||||
display_name=process_model_display_name,
|
||||
description=process_model_description,
|
||||
is_review=False,
|
||||
primary_process_id=primary_process_id,
|
||||
primary_file_name=primary_file_name,
|
||||
fault_or_suspend_on_exception=fault_or_suspend_on_exception,
|
||||
exception_notification_addresses=exception_notification_addresses,
|
||||
)
|
||||
if user is None:
|
||||
user = self.find_or_create_user()
|
||||
|
||||
response = client.post(
|
||||
"/v1.0/process-models",
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessModelInfoSchema().dump(model)),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 201
|
||||
return response
|
||||
|
||||
else:
|
||||
raise Exception("You must create the group first")
|
||||
else:
|
||||
process_group = ProcessModelService().get_process_group(process_group_id)
|
||||
|
||||
if exception_notification_addresses is None:
|
||||
exception_notification_addresses = []
|
||||
model = ProcessModelInfo(
|
||||
id=process_model_id,
|
||||
display_name=process_model_display_name,
|
||||
description=process_model_description,
|
||||
process_group_id=process_group.id,
|
||||
is_review=False,
|
||||
primary_process_id=primary_process_id,
|
||||
primary_file_name=primary_file_name,
|
||||
fault_or_suspend_on_exception=fault_or_suspend_on_exception,
|
||||
exception_notification_addresses=exception_notification_addresses,
|
||||
)
|
||||
if user is None:
|
||||
user = self.find_or_create_user()
|
||||
|
||||
response = client.post(
|
||||
"/v1.0/process-models",
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessModelInfoSchema().dump(model)),
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 201
|
||||
return response
|
||||
raise Exception("You must include the process_model_id, which must be a path to the model")
|
||||
|
||||
def create_spec_file(
|
||||
self,
|
||||
client: FlaskClient,
|
||||
process_group_id: str = "random_fact",
|
||||
process_model_id: str = "random_fact",
|
||||
process_model_id: str,
|
||||
process_model_location: Optional[str] = None,
|
||||
process_model: Optional[ProcessModelInfo] = None,
|
||||
file_name: str = "random_fact.svg",
|
||||
file_data: bytes = b"abcdef",
|
||||
user: Optional[UserModel] = None,
|
||||
) -> Any:
|
||||
"""Test_create_spec_file."""
|
||||
"""Test_create_spec_file.
|
||||
Adds a bpmn file to the model.
|
||||
process_model_id is the destination path
|
||||
process_model_location is the source path
|
||||
|
||||
because of permissions, user might be required now..., not sure yet"""
|
||||
if process_model_location is None:
|
||||
process_model_location = file_name.split(".")[0]
|
||||
if process_model is None:
|
||||
process_model = load_test_spec(
|
||||
process_model_id, process_group_id=process_group_id
|
||||
process_model_id=process_model_id,
|
||||
bpmn_file_name=file_name,
|
||||
process_model_source_directory=process_model_location
|
||||
)
|
||||
data = {"file": (io.BytesIO(file_data), file_name)}
|
||||
if user is None:
|
||||
user = self.find_or_create_user()
|
||||
modified_process_model_id = process_model.id.replace("/", ":")
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files",
|
||||
f"/v1.0/process-models/{modified_process_model_id}/files",
|
||||
data=data,
|
||||
follow_redirects=True,
|
||||
content_type="multipart/form-data",
|
||||
|
@ -168,7 +218,7 @@ class BaseTest:
|
|||
# assert "image/svg+xml" == file["content_type"]
|
||||
|
||||
response = client.get(
|
||||
f"/v1.0/process-models/{process_model.process_group_id}/{process_model.id}/files/{file_name}",
|
||||
f"/v1.0/process-models/{modified_process_model_id}/files/{file_name}",
|
||||
headers=self.logged_in_headers(user),
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
@ -221,7 +271,7 @@ class BaseTest:
|
|||
status=status,
|
||||
process_initiator=user,
|
||||
process_model_identifier=process_model.id,
|
||||
process_group_identifier=process_model.process_group_id,
|
||||
process_group_identifier="",
|
||||
updated_at_in_seconds=round(time.time()),
|
||||
start_in_seconds=current_time - (3600 * 1),
|
||||
end_in_seconds=current_time - (3600 * 1 - 20),
|
||||
|
|
|
@ -13,27 +13,30 @@ from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
|||
class ExampleDataLoader:
|
||||
"""ExampleDataLoader."""
|
||||
|
||||
@staticmethod
|
||||
def create_spec(
|
||||
self,
|
||||
process_model_id: str,
|
||||
display_name: str = "",
|
||||
description: str = "",
|
||||
process_group_id: str = "",
|
||||
display_order: int = 0,
|
||||
from_tests: bool = False,
|
||||
# from_tests: bool = False,
|
||||
bpmn_file_name: Optional[str] = None,
|
||||
process_model_source_directory: Optional[str] = None,
|
||||
process_model_source_directory: str = None,
|
||||
) -> ProcessModelInfo:
|
||||
"""Assumes that a directory exists in static/bpmn with the same name as the given process_model_id.
|
||||
"""Assumes that process_model_source_directory exists in static/bpmn and contains bpmn_file_name.
|
||||
|
||||
further assumes that the [process_model_id].bpmn is the primary file for the process model.
|
||||
returns an array of data models to be added to the database.
|
||||
further assumes that bpmn_file_name is the primary file for the process model.
|
||||
|
||||
if bpmn_file_name is None we load all files in process_model_source_directory,
|
||||
otherwise, we only load bpmn_file_name
|
||||
"""
|
||||
if process_model_source_directory is None:
|
||||
raise Exception("You must include `process_model_source_directory`.")
|
||||
|
||||
spec = ProcessModelInfo(
|
||||
id=process_model_id,
|
||||
display_name=display_name,
|
||||
description=description,
|
||||
process_group_id=process_group_id,
|
||||
display_order=display_order,
|
||||
is_review=False,
|
||||
)
|
||||
|
@ -55,25 +58,16 @@ class ExampleDataLoader:
|
|||
if bpmn_file_name:
|
||||
file_name_matcher = bpmn_file_name_with_extension
|
||||
|
||||
file_glob = ""
|
||||
if from_tests:
|
||||
file_glob = os.path.join(
|
||||
current_app.instance_path,
|
||||
"..",
|
||||
"..",
|
||||
"tests",
|
||||
"data",
|
||||
process_model_source_directory_to_use,
|
||||
file_name_matcher,
|
||||
)
|
||||
else:
|
||||
file_glob = os.path.join(
|
||||
current_app.root_path,
|
||||
"static",
|
||||
"bpmn",
|
||||
process_model_source_directory_to_use,
|
||||
file_name_matcher,
|
||||
)
|
||||
# file_glob = ""
|
||||
file_glob = os.path.join(
|
||||
current_app.root_path,
|
||||
"..",
|
||||
"..",
|
||||
"tests",
|
||||
"data",
|
||||
process_model_source_directory_to_use,
|
||||
file_name_matcher,
|
||||
)
|
||||
|
||||
files = glob.glob(file_glob)
|
||||
for file_path in files:
|
||||
|
|
|
@ -37,40 +37,18 @@ def assure_process_group_exists(process_group_id: Optional[str] = None) -> Proce
|
|||
|
||||
def load_test_spec(
|
||||
process_model_id: str,
|
||||
process_group_id: Optional[str] = None,
|
||||
bpmn_file_name: Optional[str] = None,
|
||||
process_model_source_directory: Optional[str] = None,
|
||||
process_model_source_directory: str = None,
|
||||
) -> ProcessModelInfo:
|
||||
"""Loads a process model into the bpmn dir based on a directory in tests/data."""
|
||||
process_group = None
|
||||
process_model_service = ProcessModelService()
|
||||
if process_group_id is None:
|
||||
process_group_id = "test_process_group_id"
|
||||
process_group = assure_process_group_exists(process_group_id)
|
||||
process_group_id = process_group.id
|
||||
"""Loads a bpmn file into the process model dir based on a directory in tests/data."""
|
||||
|
||||
try:
|
||||
return process_model_service.get_process_model(
|
||||
process_model_id, group_id=process_group_id
|
||||
)
|
||||
except ProcessEntityNotFoundError:
|
||||
spec = ExampleDataLoader().create_spec(
|
||||
process_model_id=process_model_id,
|
||||
from_tests=True,
|
||||
display_name=process_model_id,
|
||||
process_group_id=process_group_id,
|
||||
bpmn_file_name=bpmn_file_name,
|
||||
process_model_source_directory=process_model_source_directory,
|
||||
)
|
||||
return spec
|
||||
if process_model_source_directory is None:
|
||||
raise Exception("You must inclode a `process_model_source_directory`.")
|
||||
|
||||
|
||||
# def user_info_to_query_string(user_info, redirect_url):
|
||||
# query_string_list = []
|
||||
# items = user_info.items()
|
||||
# for key, value in items:
|
||||
# query_string_list.append('%s=%s' % (key, urllib.parse.quote(value)))
|
||||
#
|
||||
# query_string_list.append('redirect_url=%s' % redirect_url)
|
||||
#
|
||||
# return '?%s' % '&'.join(query_string_list)
|
||||
spec = ExampleDataLoader.create_spec(
|
||||
process_model_id=process_model_id,
|
||||
display_name=process_model_id,
|
||||
bpmn_file_name=bpmn_file_name,
|
||||
process_model_source_directory=process_model_source_directory,
|
||||
)
|
||||
return spec
|
||||
|
|
|
@ -19,20 +19,43 @@ class TestLoggingService(BaseTest):
|
|||
"""Test_process_instance_run."""
|
||||
process_group_id = "test_logging_spiff_logger"
|
||||
process_model_id = "simple_script"
|
||||
self.create_process_group(client=client, user=with_super_admin_user, process_group_id=process_group_id)
|
||||
process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
# create the model
|
||||
process_model_info = self.create_process_model_with_api(
|
||||
client=client,
|
||||
process_model_id=process_model_identifier,
|
||||
process_model_display_name="Simple Script",
|
||||
process_model_description="Simple Script",
|
||||
user=with_super_admin_user
|
||||
)
|
||||
|
||||
bpmn_file_name = "simple_script.bpmn"
|
||||
bpmn_file_data_bytes = self.get_test_data_file_contents(
|
||||
bpmn_file_name, "simple_script"
|
||||
)
|
||||
# add bpmn to the model
|
||||
self.create_spec_file(
|
||||
client=client,
|
||||
process_model_id=process_model_identifier,
|
||||
file_name=bpmn_file_name,
|
||||
file_data=bpmn_file_data_bytes,
|
||||
user=with_super_admin_user
|
||||
)
|
||||
headers = self.logged_in_headers(with_super_admin_user)
|
||||
response = self.create_process_instance(
|
||||
client, process_group_id, process_model_id, headers
|
||||
client, process_model_identifier, headers
|
||||
)
|
||||
assert response.json is not None
|
||||
process_instance_id = response.json["id"]
|
||||
response = client.post(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/run",
|
||||
f"/v1.0/process-instances/{process_instance_id}/run",
|
||||
headers=headers,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
log_response = client.get(
|
||||
f"/v1.0/process-models/{process_group_id}/{process_model_id}/process-instances/{process_instance_id}/logs",
|
||||
f"/v1.0/process-instances/{process_instance_id}/logs",
|
||||
headers=headers,
|
||||
)
|
||||
assert log_response.status_code == 200
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
import json
|
||||
|
||||
from spiffworkflow_backend.models.process_group import ProcessGroup, ProcessGroupSchema
|
||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo, ProcessModelInfoSchema
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
|
||||
|
||||
class TestNestedGroups(BaseTest):
|
||||
|
||||
def test_nested_groups(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
) -> None:
|
||||
# /process-groups/{process_group_path}/show
|
||||
target_uri = "/v1.0/process-groups/group_a,group_b"
|
||||
user = self.find_or_create_user()
|
||||
self.add_permissions_to_user(
|
||||
user, target_uri=target_uri, permission_names=["read"]
|
||||
)
|
||||
response = client.get(
|
||||
target_uri,
|
||||
headers=self.logged_in_headers(user)
|
||||
)
|
||||
print("test_nested_groups")
|
||||
|
||||
def test_add_nested_group(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
target_uri = "/process-groups"
|
||||
# user = self.find_or_create_user()
|
||||
# self.add_permissions_to_user(
|
||||
# user, target_uri=target_uri, permission_names=["read", "create"]
|
||||
# )
|
||||
process_group_a = ProcessGroup(
|
||||
id="group_a",
|
||||
display_name="Group A",
|
||||
display_order=0,
|
||||
admin=False,
|
||||
)
|
||||
response_a = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group_a)),
|
||||
)
|
||||
|
||||
process_group_b = ProcessGroup(
|
||||
id="group_a/group_b",
|
||||
display_name="Group B",
|
||||
display_order=0,
|
||||
admin=False,
|
||||
)
|
||||
response_b = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group_b)),
|
||||
)
|
||||
|
||||
process_group_c = ProcessGroup(
|
||||
id="group_a/group_b/group_c",
|
||||
display_name="Group C",
|
||||
display_order=0,
|
||||
admin=False,
|
||||
)
|
||||
response_c = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group_c)),
|
||||
)
|
||||
|
||||
print("test_add_nested_group")
|
||||
|
||||
def test_process_model_add(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
):
|
||||
process_group_a = ProcessGroup(
|
||||
id="group_a",
|
||||
display_name="Group A",
|
||||
display_order=0,
|
||||
admin=False,
|
||||
)
|
||||
response_a = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group_a)),
|
||||
)
|
||||
|
||||
process_group_b = ProcessGroup(
|
||||
id="group_a/group_b",
|
||||
display_name="Group B",
|
||||
display_order=0,
|
||||
admin=False,
|
||||
)
|
||||
response_b = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group_b)),
|
||||
)
|
||||
process_model = ProcessModelInfo(
|
||||
id="process_model",
|
||||
display_name="Process Model",
|
||||
description="Process Model",
|
||||
primary_file_name="primary_file.bpmn",
|
||||
primary_process_id="primary_process_id",
|
||||
display_order=0
|
||||
)
|
||||
model_response = client.post(
|
||||
"v1.0/process-models",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessModelInfoSchema().dump(process_model))
|
||||
)
|
||||
print("test_process_model_add")
|
||||
|
||||
def test_process_group_show(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel,
|
||||
) -> None:
|
||||
|
||||
# target_uri = "/process-groups/{process_group_id}"
|
||||
# user = self.find_or_create_user("testadmin1")
|
||||
# self.add_permissions_to_user(
|
||||
# user, target_uri="v1.0/process-groups", permission_names=["read", "create"]
|
||||
# )
|
||||
# self.add_permissions_to_user(
|
||||
# user, target_uri="/process-groups/{process_group_id}", permission_names=["read", "create"]
|
||||
# )
|
||||
|
||||
process_group_a = ProcessGroup(
|
||||
id="group_a",
|
||||
display_name="Group A",
|
||||
display_order=0,
|
||||
admin=False,
|
||||
)
|
||||
response_create_a = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group_a)),
|
||||
)
|
||||
|
||||
target_uri = "/v1.0/process-groups/group_a"
|
||||
user = self.find_or_create_user()
|
||||
self.add_permissions_to_user(
|
||||
user, target_uri=target_uri, permission_names=["read"]
|
||||
)
|
||||
response = client.get(
|
||||
target_uri,
|
||||
headers=self.logged_in_headers(user)
|
||||
)
|
||||
|
||||
print("test_process_group_show: ")
|
File diff suppressed because it is too large
Load Diff
|
@ -42,16 +42,16 @@ class SecretServiceTestHelpers(BaseTest):
|
|||
self.test_process_group_id,
|
||||
display_name=self.test_process_group_display_name,
|
||||
)
|
||||
process_model_identifier = f"{self.test_process_group_id}/{self.test_process_model_id}"
|
||||
self.create_process_model_with_api(
|
||||
client,
|
||||
process_group_id=self.test_process_group_id,
|
||||
process_model_id=self.test_process_model_id,
|
||||
process_model_id=process_model_identifier,
|
||||
process_model_display_name=self.test_process_model_display_name,
|
||||
process_model_description=self.test_process_model_description,
|
||||
user=user,
|
||||
)
|
||||
process_model_info = ProcessModelService().get_process_model(
|
||||
self.test_process_model_id, self.test_process_group_id
|
||||
process_model_identifier
|
||||
)
|
||||
return process_model_info
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
"""Test_get_localtime."""
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.models.db import db
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.group import GroupModel
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
|
@ -17,7 +19,9 @@ class TestGetGroupMembers(BaseTest):
|
|||
def test_can_get_members_of_a_group(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_get_members_of_a_group."""
|
||||
initiator_user = self.find_or_create_user("initiator_user")
|
||||
|
@ -34,9 +38,11 @@ class TestGetGroupMembers(BaseTest):
|
|||
UserService.add_user_to_group(testuser2, group_a)
|
||||
UserService.add_user_to_group(testuser3, group_b)
|
||||
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
process_model = load_test_spec(
|
||||
process_model_id="get_group_members",
|
||||
process_model_id="test_group/get_group_members",
|
||||
bpmn_file_name="get_group_members.bpmn",
|
||||
process_model_source_directory="get_group_members"
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model=process_model, user=initiator_user
|
||||
|
|
|
@ -49,8 +49,14 @@ class TestGetLocaltime(BaseTest):
|
|||
) -> None:
|
||||
"""Test_process_instance_run."""
|
||||
initiator_user = self.find_or_create_user("initiator_user")
|
||||
self.add_permissions_to_user(
|
||||
initiator_user, target_uri="/v1.0/process-groups", permission_names=["read", "create"]
|
||||
)
|
||||
self.create_process_group(client=client, user=initiator_user, process_group_id="test_group")
|
||||
process_model = load_test_spec(
|
||||
process_model_id="get_localtime", bpmn_file_name="get_localtime.bpmn"
|
||||
process_model_id="test_group/get_localtime",
|
||||
bpmn_file_name="get_localtime.bpmn",
|
||||
process_model_source_directory="get_localtime"
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model=process_model, user=initiator_user
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
"""Test_message_service."""
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from flask.testing import FlaskClient
|
||||
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.user import UserNotFoundError
|
||||
from spiffworkflow_backend.models.user import UserModel, UserNotFoundError
|
||||
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
|
@ -89,7 +92,11 @@ class TestAuthorizationService(BaseTest):
|
|||
)
|
||||
|
||||
def test_user_can_be_added_to_active_task_on_first_login(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_user_can_be_added_to_active_task_on_first_login."""
|
||||
initiator_user = self.find_or_create_user("initiator_user")
|
||||
|
@ -98,8 +105,17 @@ class TestAuthorizationService(BaseTest):
|
|||
self.find_or_create_user("testuser1")
|
||||
AuthorizationService.import_permissions_from_yaml_file()
|
||||
|
||||
process_model = load_test_spec(
|
||||
process_model_id="model_with_lanes", bpmn_file_name="lanes.bpmn"
|
||||
process_model_identifier = self.basic_test_setup(
|
||||
client=client,
|
||||
user=with_super_admin_user,
|
||||
process_group_id="test_group",
|
||||
process_model_id="model_with_lanes",
|
||||
bpmn_file_name="lanes.bpmn",
|
||||
bpmn_file_location="model_with_lanes"
|
||||
)
|
||||
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
process_model_id=process_model_identifier
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model=process_model, user=initiator_user
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
"""Test_various_bpmn_constructs."""
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
|
||||
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
|
@ -15,21 +19,30 @@ class TestDotNotation(BaseTest):
|
|||
"""TestVariousBpmnConstructs."""
|
||||
|
||||
def test_dot_notation(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_form_data_conversion_to_dot_dict."""
|
||||
process_model = load_test_spec(
|
||||
"test_dot_notation",
|
||||
bpmn_file_name="diagram.bpmn",
|
||||
process_model_source_directory="dot_notation",
|
||||
process_group_id = "dot_notation_group"
|
||||
process_model_id = "test_dot_notation"
|
||||
bpmn_file_name = "diagram.bpmn"
|
||||
bpmn_file_location = "dot_notation"
|
||||
process_model_identifier = self.basic_test_setup(
|
||||
client,
|
||||
with_super_admin_user,
|
||||
process_group_id=process_group_id,
|
||||
process_model_id=process_model_id,
|
||||
bpmn_file_name=bpmn_file_name,
|
||||
bpmn_file_location=bpmn_file_location
|
||||
)
|
||||
current_user = self.find_or_create_user()
|
||||
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model
|
||||
headers = self.logged_in_headers(with_super_admin_user)
|
||||
response = self.create_process_instance(
|
||||
client, process_model_identifier, headers
|
||||
)
|
||||
process_instance_id = response.json["id"]
|
||||
process_instance = ProcessInstanceService().get_process_instance(process_instance_id)
|
||||
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
|
||||
processor.do_engine_steps(save=True)
|
||||
|
||||
user_task = processor.get_ready_user_tasks()[0]
|
||||
|
@ -41,7 +54,7 @@ class TestDotNotation(BaseTest):
|
|||
"invoice.dueDate": "09/30/2022",
|
||||
}
|
||||
ProcessInstanceService.complete_form_task(
|
||||
processor, user_task, form_data, current_user
|
||||
processor, user_task, form_data, with_super_admin_user
|
||||
)
|
||||
|
||||
expected = {
|
||||
|
|
|
@ -1,24 +1,46 @@
|
|||
"""Test_message_instance."""
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.models.db import db
|
||||
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.message_instance import MessageInstanceModel
|
||||
from spiffworkflow_backend.models.message_model import MessageModel
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
|
||||
|
||||
class TestMessageInstance(BaseTest):
|
||||
"""TestMessageInstance."""
|
||||
|
||||
def setup_message_tests(self, client: FlaskClient, user: UserModel) -> str:
|
||||
process_group_id = "test_group"
|
||||
process_model_id = "hello_world"
|
||||
bpmn_file_name = "hello_world.bpmn"
|
||||
bpmn_file_location = "hello_world"
|
||||
process_model_identifier = self.basic_test_setup(
|
||||
client,
|
||||
user,
|
||||
process_group_id=process_group_id,
|
||||
process_model_id=process_model_id,
|
||||
bpmn_file_name=bpmn_file_name,
|
||||
bpmn_file_location=bpmn_file_location
|
||||
)
|
||||
return process_model_identifier
|
||||
|
||||
def test_can_create_message_instance(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_create_message_instance."""
|
||||
message_model_identifier = "message_model_one"
|
||||
message_model = self.create_message_model(message_model_identifier)
|
||||
process_model = load_test_spec("hello_world")
|
||||
process_model_identifier = self.setup_message_tests(client, with_super_admin_user)
|
||||
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
process_model_id=process_model_identifier
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model, "waiting"
|
||||
)
|
||||
|
@ -40,12 +62,16 @@ class TestMessageInstance(BaseTest):
|
|||
assert queued_message_from_query is not None
|
||||
|
||||
def test_cannot_set_invalid_status(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_cannot_set_invalid_status."""
|
||||
message_model_identifier = "message_model_one"
|
||||
message_model = self.create_message_model(message_model_identifier)
|
||||
process_model = load_test_spec("hello_world")
|
||||
process_model_identifier = self.setup_message_tests(client, with_super_admin_user)
|
||||
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
process_model_id=process_model_identifier
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model, "waiting"
|
||||
)
|
||||
|
@ -76,12 +102,16 @@ class TestMessageInstance(BaseTest):
|
|||
)
|
||||
|
||||
def test_cannot_set_invalid_message_type(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_cannot_set_invalid_message_type."""
|
||||
message_model_identifier = "message_model_one"
|
||||
message_model = self.create_message_model(message_model_identifier)
|
||||
process_model = load_test_spec("hello_world")
|
||||
process_model_identifier = self.setup_message_tests(client, with_super_admin_user)
|
||||
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
process_model_id=process_model_identifier
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model, "waiting"
|
||||
)
|
||||
|
@ -113,12 +143,16 @@ class TestMessageInstance(BaseTest):
|
|||
)
|
||||
|
||||
def test_force_failure_cause_if_status_is_failure(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_force_failure_cause_if_status_is_failure."""
|
||||
message_model_identifier = "message_model_one"
|
||||
message_model = self.create_message_model(message_model_identifier)
|
||||
process_model = load_test_spec("hello_world")
|
||||
process_model_identifier = self.setup_message_tests(client, with_super_admin_user)
|
||||
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
process_model_id=process_model_identifier
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model, "waiting"
|
||||
)
|
||||
|
@ -154,7 +188,8 @@ class TestMessageInstance(BaseTest):
|
|||
assert queued_message.id is not None
|
||||
assert queued_message.failure_cause == "THIS TEST FAILURE"
|
||||
|
||||
def create_message_model(self, message_model_identifier: str) -> MessageModel:
|
||||
@staticmethod
|
||||
def create_message_model(message_model_identifier: str) -> MessageModel:
|
||||
"""Create_message_model."""
|
||||
message_model = MessageModel(identifier=message_model_identifier)
|
||||
db.session.add(message_model)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""Test_message_service."""
|
||||
from flask import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
|
@ -9,6 +10,7 @@ from spiffworkflow_backend.models.message_correlation_message_instance import (
|
|||
)
|
||||
from spiffworkflow_backend.models.message_instance import MessageInstanceModel
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.message_service import MessageService
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
|
@ -22,25 +24,26 @@ class TestMessageService(BaseTest):
|
|||
"""TestMessageService."""
|
||||
|
||||
def test_can_send_message_to_waiting_message(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_send_message_to_waiting_message."""
|
||||
process_model_sender = load_test_spec(
|
||||
"message_sender",
|
||||
process_model_source_directory="message_send_one_conversation",
|
||||
bpmn_file_name="message_sender",
|
||||
)
|
||||
process_group_id = "test_group"
|
||||
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id)
|
||||
|
||||
load_test_spec(
|
||||
"message_receiver",
|
||||
"test_group/message_receiver",
|
||||
process_model_source_directory="message_send_one_conversation",
|
||||
bpmn_file_name="message_receiver",
|
||||
bpmn_file_name="message_receiver.bpmn"
|
||||
)
|
||||
process_model_sender = load_test_spec(
|
||||
"test_group/message_sender",
|
||||
process_model_source_directory="message_send_one_conversation",
|
||||
bpmn_file_name="message_sender.bpmn",
|
||||
)
|
||||
user = self.find_or_create_user()
|
||||
|
||||
process_instance_sender = ProcessInstanceService.create_process_instance(
|
||||
process_model_sender.id,
|
||||
user,
|
||||
process_group_identifier=process_model_sender.process_group_id,
|
||||
with_super_admin_user,
|
||||
)
|
||||
|
||||
processor_sender = ProcessInstanceProcessor(process_instance_sender)
|
||||
|
@ -115,21 +118,25 @@ class TestMessageService(BaseTest):
|
|||
assert process_instance.status == "complete"
|
||||
|
||||
def test_can_send_message_to_multiple_process_models(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_send_message_to_multiple_process_models."""
|
||||
|
||||
process_group_id = "test_group"
|
||||
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id)
|
||||
|
||||
process_model_sender = load_test_spec(
|
||||
"message_sender",
|
||||
"test_group/message_sender",
|
||||
process_model_source_directory="message_send_two_conversations",
|
||||
bpmn_file_name="message_sender",
|
||||
)
|
||||
load_test_spec(
|
||||
"message_receiver_one",
|
||||
"test_group/message_receiver_one",
|
||||
process_model_source_directory="message_send_two_conversations",
|
||||
bpmn_file_name="message_receiver_one",
|
||||
)
|
||||
load_test_spec(
|
||||
"message_receiver_two",
|
||||
"test_group/message_receiver_two",
|
||||
process_model_source_directory="message_send_two_conversations",
|
||||
bpmn_file_name="message_receiver_two",
|
||||
)
|
||||
|
@ -139,7 +146,7 @@ class TestMessageService(BaseTest):
|
|||
process_instance_sender = ProcessInstanceService.create_process_instance(
|
||||
process_model_sender.id,
|
||||
user,
|
||||
process_group_identifier=process_model_sender.process_group_id,
|
||||
# process_group_identifier=process_model_sender.process_group_id,
|
||||
)
|
||||
|
||||
processor_sender = ProcessInstanceProcessor(process_instance_sender)
|
||||
|
@ -189,24 +196,24 @@ class TestMessageService(BaseTest):
|
|||
|
||||
assert len(process_instance_result) == 3
|
||||
process_instance_receiver_one = ProcessInstanceModel.query.filter_by(
|
||||
process_model_identifier="message_receiver_one"
|
||||
process_model_identifier="test_group/message_receiver_one"
|
||||
).first()
|
||||
assert process_instance_receiver_one is not None
|
||||
process_instance_receiver_two = ProcessInstanceModel.query.filter_by(
|
||||
process_model_identifier="message_receiver_two"
|
||||
process_model_identifier="test_group/message_receiver_two"
|
||||
).first()
|
||||
assert process_instance_receiver_two is not None
|
||||
|
||||
# just make sure it's a different process instance
|
||||
assert (
|
||||
process_instance_receiver_one.process_model_identifier
|
||||
== "message_receiver_one"
|
||||
== "test_group/message_receiver_one"
|
||||
)
|
||||
assert process_instance_receiver_one.id != process_instance_sender.id
|
||||
assert process_instance_receiver_one.status == "complete"
|
||||
assert (
|
||||
process_instance_receiver_two.process_model_identifier
|
||||
== "message_receiver_two"
|
||||
== "test_group/message_receiver_two"
|
||||
)
|
||||
assert process_instance_receiver_two.id != process_instance_sender.id
|
||||
assert process_instance_receiver_two.status == "complete"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""Test Permissions."""
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.models.db import db
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
@ -8,6 +9,7 @@ from spiffworkflow_backend.models.group import GroupModel
|
|||
from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel
|
||||
from spiffworkflow_backend.models.permission_target import PermissionTargetModel
|
||||
from spiffworkflow_backend.models.principal import PrincipalModel
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.user_service import UserService
|
||||
|
||||
|
||||
|
@ -22,13 +24,15 @@ class TestPermissions(BaseTest):
|
|||
"""TestPermissions."""
|
||||
|
||||
def test_user_can_be_given_permission_to_administer_process_group(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_user_can_be_given_permission_to_administer_process_group."""
|
||||
process_group_id = "group-a"
|
||||
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id)
|
||||
load_test_spec(
|
||||
"timers_intermediate_catch_event",
|
||||
process_group_id=process_group_id,
|
||||
"group-a/timers_intermediate_catch_event",
|
||||
bpmn_file_name="timers_intermediate_catch_event.bpmn",
|
||||
process_model_source_directory="timers_intermediate_catch_event"
|
||||
)
|
||||
dan = self.find_or_create_user()
|
||||
principal = dan.principal
|
||||
|
@ -55,8 +59,9 @@ class TestPermissions(BaseTest):
|
|||
process_group_b_id = process_group_ids[1]
|
||||
for process_group_id in process_group_ids:
|
||||
load_test_spec(
|
||||
"timers_intermediate_catch_event",
|
||||
process_group_id=process_group_id,
|
||||
f"{process_group_id}/timers_intermediate_catch_event",
|
||||
bpmn_file_name="timers_intermediate_catch_event",
|
||||
process_model_source_directory="timers_intermediate_catch_event"
|
||||
)
|
||||
group_a_admin = self.find_or_create_user()
|
||||
|
||||
|
@ -86,11 +91,11 @@ class TestPermissions(BaseTest):
|
|||
"""Test_user_can_be_granted_access_through_a_group."""
|
||||
process_group_ids = ["group-a", "group-b"]
|
||||
process_group_a_id = process_group_ids[0]
|
||||
process_group_ids[1]
|
||||
for process_group_id in process_group_ids:
|
||||
load_test_spec(
|
||||
"timers_intermediate_catch_event",
|
||||
process_group_id=process_group_id,
|
||||
f"{process_group_id}/timers_intermediate_catch_event",
|
||||
bpmn_file_name="timers_intermediate_catch_event.bpmn",
|
||||
process_model_source_directory="timers_intermediate_catch_event"
|
||||
)
|
||||
user = self.find_or_create_user()
|
||||
group = GroupModel(identifier="groupA")
|
||||
|
@ -127,8 +132,9 @@ class TestPermissions(BaseTest):
|
|||
process_group_b_id = process_group_ids[1]
|
||||
for process_group_id in process_group_ids:
|
||||
load_test_spec(
|
||||
"timers_intermediate_catch_event",
|
||||
process_group_id=process_group_id,
|
||||
f"{process_group_id}/timers_intermediate_catch_event",
|
||||
bpmn_file_name="timers_intermediate_catch_event.bpmn",
|
||||
process_model_source_directory="timers_intermediate_catch_event"
|
||||
)
|
||||
group_a_admin = self.find_or_create_user()
|
||||
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
import pytest
|
||||
from flask import g
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.group import GroupModel
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
||||
from spiffworkflow_backend.services.authorization_service import (
|
||||
UserDoesNotHaveAccessToTaskError,
|
||||
|
@ -50,9 +52,12 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
def test_sets_permission_correctly_on_active_task(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_sets_permission_correctly_on_active_task."""
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
initiator_user = self.find_or_create_user("initiator_user")
|
||||
finance_user = self.find_or_create_user("testuser2")
|
||||
assert initiator_user.principal is not None
|
||||
|
@ -63,7 +68,9 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
assert finance_group is not None
|
||||
|
||||
process_model = load_test_spec(
|
||||
process_model_id="model_with_lanes", bpmn_file_name="lanes.bpmn"
|
||||
process_model_id="test_group/model_with_lanes",
|
||||
bpmn_file_name="lanes.bpmn",
|
||||
process_model_source_directory="model_with_lanes"
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model=process_model, user=initiator_user
|
||||
|
@ -123,9 +130,12 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
def test_sets_permission_correctly_on_active_task_when_using_dict(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_sets_permission_correctly_on_active_task_when_using_dict."""
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
initiator_user = self.find_or_create_user("initiator_user")
|
||||
finance_user_three = self.find_or_create_user("testuser3")
|
||||
finance_user_four = self.find_or_create_user("testuser4")
|
||||
|
@ -138,8 +148,9 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
assert finance_group is not None
|
||||
|
||||
process_model = load_test_spec(
|
||||
process_model_id="model_with_lanes",
|
||||
process_model_id="test_group/model_with_lanes",
|
||||
bpmn_file_name="lanes_with_owner_dict.bpmn",
|
||||
process_model_source_directory="model_with_lanes"
|
||||
)
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
process_model=process_model, user=initiator_user
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
"""Process Model."""
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.models.db import db
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
|
||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
|
@ -22,11 +24,13 @@ class TestProcessModel(BaseTest):
|
|||
assert process_model_one.files == []
|
||||
|
||||
def test_can_run_process_model_with_call_activities_when_in_same_process_model_directory(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_run_process_model_with_call_activities."""
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
process_model = load_test_spec(
|
||||
"call_activity_test",
|
||||
"test_group/call_activity_test",
|
||||
# bpmn_file_name="call_activity_test.bpmn",
|
||||
process_model_source_directory="call_activity_same_directory",
|
||||
)
|
||||
|
||||
|
@ -38,11 +42,12 @@ class TestProcessModel(BaseTest):
|
|||
assert process_instance.status == "complete"
|
||||
|
||||
def test_can_run_process_model_with_call_activities_when_not_in_same_directory(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_run_process_model_with_call_activities."""
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
process_model = load_test_spec(
|
||||
"call_activity_nested",
|
||||
"test_group/call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
)
|
||||
|
@ -54,7 +59,7 @@ class TestProcessModel(BaseTest):
|
|||
]
|
||||
for bpmn_file_name in bpmn_file_names:
|
||||
load_test_spec(
|
||||
bpmn_file_name,
|
||||
f"test_group/{bpmn_file_name}",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name=bpmn_file_name,
|
||||
)
|
||||
|
@ -66,11 +71,12 @@ class TestProcessModel(BaseTest):
|
|||
assert process_instance.status == "complete"
|
||||
|
||||
def test_can_run_process_model_with_call_activities_when_process_identifier_is_not_in_database(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_run_process_model_with_call_activities."""
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
process_model = load_test_spec(
|
||||
"call_activity_nested",
|
||||
"test_group/call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
)
|
||||
|
@ -82,7 +88,7 @@ class TestProcessModel(BaseTest):
|
|||
]
|
||||
for bpmn_file_name in bpmn_file_names:
|
||||
load_test_spec(
|
||||
bpmn_file_name,
|
||||
f"test_group/{bpmn_file_name}",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name=bpmn_file_name,
|
||||
)
|
||||
|
@ -93,6 +99,7 @@ class TestProcessModel(BaseTest):
|
|||
# delete all of the id lookup items to force to processor to find the correct
|
||||
# process model when running the process
|
||||
db.session.query(BpmnProcessIdLookup).delete()
|
||||
db.session.commit()
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
processor.do_engine_steps(save=True)
|
||||
assert process_instance.status == "complete"
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
"""Test_process_model_service."""
|
||||
from flask import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
|
||||
|
||||
|
@ -10,11 +12,16 @@ class TestProcessModelService(BaseTest):
|
|||
"""TestProcessModelService."""
|
||||
|
||||
def test_can_update_specified_attributes(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_update_specified_attributes."""
|
||||
process_model = load_test_spec("hello_world")
|
||||
assert process_model.display_name == "hello_world"
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
process_model = load_test_spec(
|
||||
"test_group/hello_world",
|
||||
bpmn_file_name="hello_world.bpmn",
|
||||
process_model_source_directory="hello_world"
|
||||
)
|
||||
assert process_model.display_name == "test_group/hello_world"
|
||||
|
||||
primary_process_id = process_model.primary_process_id
|
||||
assert primary_process_id == "Process_HelloWorld"
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
"""Test_various_bpmn_constructs."""
|
||||
import pytest
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.api.api_error import ApiError
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
|
@ -14,11 +16,12 @@ class TestOpenFile(BaseTest):
|
|||
"""TestVariousBpmnConstructs."""
|
||||
|
||||
def test_dot_notation(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_form_data_conversion_to_dot_dict."""
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
process_model = load_test_spec(
|
||||
"dangerous",
|
||||
"test_group/dangerous",
|
||||
bpmn_file_name="read_etc_passwd.bpmn",
|
||||
process_model_source_directory="dangerous-scripts",
|
||||
)
|
||||
|
@ -38,11 +41,12 @@ class TestImportModule(BaseTest):
|
|||
"""TestVariousBpmnConstructs."""
|
||||
|
||||
def test_dot_notation(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_form_data_conversion_to_dot_dict."""
|
||||
self.create_process_group(client, with_super_admin_user, "test_group", "test_group")
|
||||
process_model = load_test_spec(
|
||||
"dangerous",
|
||||
"test_group/dangerous",
|
||||
bpmn_file_name="read_env.bpmn",
|
||||
process_model_source_directory="dangerous-scripts",
|
||||
)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
"""Test Permissions."""
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
|
@ -16,21 +18,29 @@ class TestScriptUnitTestRunner(BaseTest):
|
|||
def test_takes_data_and_returns_expected_result(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_takes_data_and_returns_expected_result."""
|
||||
app.config["THREAD_LOCAL_DATA"].process_instance_id = None
|
||||
|
||||
process_group_id = "test_logging_spiff_logger"
|
||||
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id)
|
||||
process_model_id = "simple_script"
|
||||
load_test_spec(process_model_id, process_group_id=process_group_id)
|
||||
process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
load_test_spec(
|
||||
process_model_identifier,
|
||||
bpmn_file_name=process_model_id,
|
||||
process_model_source_directory=process_model_id
|
||||
)
|
||||
bpmn_process_instance = (
|
||||
ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model(
|
||||
process_model_id, process_group_id
|
||||
process_model_identifier
|
||||
)
|
||||
)
|
||||
task = ProcessInstanceProcessor.get_task_by_bpmn_identifier(
|
||||
"Activity_RunScript", bpmn_process_instance
|
||||
"Activity_CalculateNewData", bpmn_process_instance
|
||||
)
|
||||
assert task is not None
|
||||
|
||||
|
@ -48,21 +58,30 @@ class TestScriptUnitTestRunner(BaseTest):
|
|||
def test_fails_when_expected_output_does_not_match_actual_output(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_fails_when_expected_output_does_not_match_actual_output."""
|
||||
app.config["THREAD_LOCAL_DATA"].process_instance_id = None
|
||||
|
||||
process_group_id = "test_logging_spiff_logger"
|
||||
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id)
|
||||
|
||||
process_model_id = "simple_script"
|
||||
load_test_spec(process_model_id, process_group_id=process_group_id)
|
||||
process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
load_test_spec(
|
||||
process_model_identifier,
|
||||
bpmn_file_name=process_model_id,
|
||||
process_model_source_directory=process_model_id
|
||||
)
|
||||
bpmn_process_instance = (
|
||||
ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model(
|
||||
process_model_id, process_group_id
|
||||
process_model_identifier
|
||||
)
|
||||
)
|
||||
task = ProcessInstanceProcessor.get_task_by_bpmn_identifier(
|
||||
"Activity_RunScript", bpmn_process_instance
|
||||
"Activity_CalculateNewData", bpmn_process_instance
|
||||
)
|
||||
assert task is not None
|
||||
|
||||
|
@ -80,17 +99,26 @@ class TestScriptUnitTestRunner(BaseTest):
|
|||
def test_script_with_unit_tests_when_hey_is_passed_in(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_script_with_unit_tests_when_hey_is_passed_in."""
|
||||
app.config["THREAD_LOCAL_DATA"].process_instance_id = None
|
||||
|
||||
process_group_id = "script_with_unit_tests"
|
||||
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id)
|
||||
|
||||
process_model_id = "script_with_unit_tests"
|
||||
load_test_spec(process_model_id, process_group_id=process_group_id)
|
||||
process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
load_test_spec(
|
||||
process_model_identifier,
|
||||
bpmn_file_name=process_model_id,
|
||||
process_model_source_directory=process_model_id
|
||||
)
|
||||
bpmn_process_instance = (
|
||||
ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model(
|
||||
process_model_id, process_group_id
|
||||
process_model_identifier
|
||||
)
|
||||
)
|
||||
task = ProcessInstanceProcessor.get_task_by_bpmn_identifier(
|
||||
|
@ -110,17 +138,27 @@ class TestScriptUnitTestRunner(BaseTest):
|
|||
def test_script_with_unit_tests_when_hey_is_not_passed_in(
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_script_with_unit_tests_when_hey_is_not_passed_in."""
|
||||
app.config["THREAD_LOCAL_DATA"].process_instance_id = None
|
||||
|
||||
process_group_id = "script_with_unit_tests"
|
||||
self.create_process_group(client, with_super_admin_user, process_group_id, process_group_id)
|
||||
|
||||
process_model_id = "script_with_unit_tests"
|
||||
load_test_spec(process_model_id, process_group_id=process_group_id)
|
||||
process_model_identifier = f"{process_group_id}/{process_model_id}"
|
||||
|
||||
load_test_spec(
|
||||
process_model_identifier,
|
||||
bpmn_file_name=process_model_id,
|
||||
process_model_source_directory=process_model_id
|
||||
)
|
||||
bpmn_process_instance = (
|
||||
ProcessInstanceProcessor.get_bpmn_process_instance_from_process_model(
|
||||
process_model_id, process_group_id
|
||||
process_model_identifier
|
||||
)
|
||||
)
|
||||
task = ProcessInstanceProcessor.get_task_by_bpmn_identifier(
|
||||
|
|
|
@ -3,6 +3,7 @@ import os
|
|||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.api.api_error import ApiError
|
||||
from flask_bpmn.models.db import db
|
||||
from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser # type: ignore
|
||||
|
@ -10,6 +11,7 @@ from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
|||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.bpmn_process_id_lookup import BpmnProcessIdLookup
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
||||
|
||||
|
@ -17,18 +19,25 @@ from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
|||
class TestSpecFileService(BaseTest):
|
||||
"""TestSpecFileService."""
|
||||
|
||||
process_group_id = "test_process_group_id"
|
||||
process_model_id = "call_activity_nested"
|
||||
bpmn_file_name = "call_activity_nested.bpmn"
|
||||
|
||||
call_activity_nested_relative_file_path = os.path.join(
|
||||
"test_process_group_id", "call_activity_nested", "call_activity_nested.bpmn"
|
||||
process_group_id, process_model_id, bpmn_file_name
|
||||
)
|
||||
|
||||
def test_can_store_process_ids_for_lookup(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_can_store_process_ids_for_lookup."""
|
||||
load_test_spec(
|
||||
"call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
self.basic_test_setup(
|
||||
client=client,
|
||||
user=with_super_admin_user,
|
||||
process_group_id=self.process_group_id,
|
||||
process_model_id=self.process_model_id,
|
||||
bpmn_file_name=self.bpmn_file_name,
|
||||
bpmn_file_location="call_activity_nested"
|
||||
)
|
||||
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
|
||||
assert len(bpmn_process_id_lookups) == 1
|
||||
|
@ -39,14 +48,17 @@ class TestSpecFileService(BaseTest):
|
|||
)
|
||||
|
||||
def test_fails_to_save_duplicate_process_id(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_fails_to_save_duplicate_process_id."""
|
||||
bpmn_process_identifier = "Level1"
|
||||
load_test_spec(
|
||||
"call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
self.basic_test_setup(
|
||||
client=client,
|
||||
user=with_super_admin_user,
|
||||
process_group_id=self.process_group_id,
|
||||
process_model_id=self.process_model_id,
|
||||
bpmn_file_name=self.bpmn_file_name,
|
||||
bpmn_file_location=self.process_model_id
|
||||
)
|
||||
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
|
||||
assert len(bpmn_process_id_lookups) == 1
|
||||
|
@ -69,25 +81,26 @@ class TestSpecFileService(BaseTest):
|
|||
)
|
||||
|
||||
def test_updates_relative_file_path_when_appropriate(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_updates_relative_file_path_when_appropriate."""
|
||||
bpmn_process_identifier = "Level1"
|
||||
bpmn_file_relative_path = os.path.join(
|
||||
"test_process_group_id", "call_activity_nested", "new_bpmn_file.bpmn"
|
||||
)
|
||||
process_id_lookup = BpmnProcessIdLookup(
|
||||
bpmn_process_identifier=bpmn_process_identifier,
|
||||
bpmn_file_relative_path=bpmn_file_relative_path,
|
||||
bpmn_file_relative_path=self.call_activity_nested_relative_file_path,
|
||||
)
|
||||
db.session.add(process_id_lookup)
|
||||
db.session.commit()
|
||||
|
||||
load_test_spec(
|
||||
"call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
bpmn_file_name="call_activity_nested",
|
||||
self.basic_test_setup(
|
||||
client=client,
|
||||
user=with_super_admin_user,
|
||||
process_group_id=self.process_group_id,
|
||||
process_model_id=self.process_model_id,
|
||||
bpmn_file_name=self.bpmn_file_name,
|
||||
bpmn_file_location=self.process_model_id
|
||||
)
|
||||
|
||||
bpmn_process_id_lookups = BpmnProcessIdLookup.query.all()
|
||||
assert len(bpmn_process_id_lookups) == 1
|
||||
assert (
|
||||
|
@ -100,7 +113,7 @@ class TestSpecFileService(BaseTest):
|
|||
)
|
||||
|
||||
def test_load_reference_information(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self, app: Flask, client: FlaskClient, with_db_and_bpmn_file_cleanup: None, with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_load_reference_information.
|
||||
|
||||
|
@ -113,12 +126,23 @@ class TestSpecFileService(BaseTest):
|
|||
a DMN file can (theoretically) contain many decisions. So this
|
||||
is an array.
|
||||
"""
|
||||
load_test_spec(
|
||||
"call_activity_nested",
|
||||
process_model_source_directory="call_activity_nested",
|
||||
process_group_id = "test_group"
|
||||
process_model_id = "call_activity_nested"
|
||||
bpmn_file_name = "call_activity_nested.bpmn"
|
||||
process_model_identifier = self.basic_test_setup(
|
||||
client=client,
|
||||
user=with_super_admin_user,
|
||||
process_group_id=process_group_id,
|
||||
process_model_id=process_model_id,
|
||||
# bpmn_file_name=bpmn_file_name,
|
||||
bpmn_file_location=process_model_id
|
||||
)
|
||||
# load_test_spec(
|
||||
# ,
|
||||
# process_model_source_directory="call_activity_nested",
|
||||
# )
|
||||
process_model_info = ProcessModelService().get_process_model(
|
||||
"call_activity_nested"
|
||||
process_model_identifier
|
||||
)
|
||||
files = SpecFileService.get_files(process_model_info)
|
||||
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
"""Test_various_bpmn_constructs."""
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from spiffworkflow_backend.models.user import UserModel
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
|
||||
|
||||
class TestVariousBpmnConstructs(BaseTest):
|
||||
"""TestVariousBpmnConstructs."""
|
||||
|
||||
def test_running_process_with_timer_intermediate_catch_event(
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
self,
|
||||
app: Flask,
|
||||
client: FlaskClient,
|
||||
with_db_and_bpmn_file_cleanup: None,
|
||||
with_super_admin_user: UserModel
|
||||
) -> None:
|
||||
"""Test_running_process_with_timer_intermediate_catch_event."""
|
||||
process_model = load_test_spec(
|
||||
"timers_intermediate_catch_event",
|
||||
process_model_source_directory="timer_intermediate_catch_event",
|
||||
process_model_identifier = self.basic_test_setup(
|
||||
client,
|
||||
with_super_admin_user,
|
||||
"test_group",
|
||||
"timer_intermediate_catch_event"
|
||||
)
|
||||
|
||||
process_model = ProcessModelService().get_process_model(
|
||||
process_model_id=process_model_identifier
|
||||
)
|
||||
|
||||
process_instance = self.create_process_instance_from_process_model(
|
||||
|
|
|
@ -68,6 +68,7 @@ describe('process-instances', () => {
|
|||
cy.login();
|
||||
cy.navigateToProcessModel(
|
||||
'Acceptance Tests Group One',
|
||||
'Acceptance Tests Model 1',
|
||||
'acceptance-tests-model-1'
|
||||
);
|
||||
});
|
||||
|
@ -90,28 +91,29 @@ describe('process-instances', () => {
|
|||
cy.runPrimaryBpmnFile();
|
||||
|
||||
// Change dmn
|
||||
cy.contains(dmnFile).click();
|
||||
cy.contains(`Process Model File: ${dmnFile}`);
|
||||
cy.getBySel('files-accordion').click();
|
||||
cy.getBySel(`edit-file-${dmnFile.replace('.', '-')}`).click();
|
||||
updateDmnText(originalDmnOutputForKevin, newDmnOutputForKevin);
|
||||
|
||||
cy.contains('acceptance-tests-model-1').click();
|
||||
cy.runPrimaryBpmnFile();
|
||||
|
||||
cy.contains(dmnFile).click();
|
||||
cy.contains(`Process Model File: ${dmnFile}`);
|
||||
cy.getBySel('files-accordion').click();
|
||||
cy.getBySel(`edit-file-${dmnFile.replace('.', '-')}`).click();
|
||||
updateDmnText(newDmnOutputForKevin, originalDmnOutputForKevin);
|
||||
cy.contains('acceptance-tests-model-1').click();
|
||||
cy.runPrimaryBpmnFile();
|
||||
|
||||
// Change bpmn
|
||||
cy.contains(bpmnFile).click();
|
||||
cy.getBySel('files-accordion').click();
|
||||
cy.getBySel(`edit-file-${bpmnFile.replace('.', '-')}`).click();
|
||||
cy.contains(`Process Model File: ${bpmnFile}`);
|
||||
updateBpmnPythonScript(newPythonScript);
|
||||
cy.contains('acceptance-tests-model-1').click();
|
||||
cy.runPrimaryBpmnFile();
|
||||
|
||||
cy.contains(bpmnFile).click();
|
||||
cy.contains(`Process Model File: ${bpmnFile}`);
|
||||
cy.getBySel('files-accordion').click();
|
||||
cy.getBySel(`edit-file-${bpmnFile.replace('.', '-')}`).click();
|
||||
updateBpmnPythonScript(originalPythonScript);
|
||||
cy.contains('acceptance-tests-model-1').click();
|
||||
cy.runPrimaryBpmnFile();
|
||||
|
@ -125,13 +127,15 @@ describe('process-instances', () => {
|
|||
const bpmnFile = 'process_model_one.bpmn';
|
||||
|
||||
// Change bpmn
|
||||
cy.contains(bpmnFile).click();
|
||||
cy.getBySel('files-accordion').click();
|
||||
cy.getBySel(`edit-file-${bpmnFile.replace('.', '-')}`).click();
|
||||
cy.contains(`Process Model File: ${bpmnFile}`);
|
||||
updateBpmnPythonScriptWithMonaco(newPythonScript);
|
||||
cy.contains('acceptance-tests-model-1').click();
|
||||
cy.runPrimaryBpmnFile();
|
||||
|
||||
cy.contains(bpmnFile).click();
|
||||
cy.getBySel('files-accordion').click();
|
||||
cy.getBySel(`edit-file-${bpmnFile.replace('.', '-')}`).click();
|
||||
cy.contains(`Process Model File: ${bpmnFile}`);
|
||||
updateBpmnPythonScriptWithMonaco(originalPythonScript);
|
||||
cy.contains('acceptance-tests-model-1').click();
|
||||
|
|
|
@ -25,10 +25,11 @@ describe('tasks', () => {
|
|||
it('can complete and navigate a form', () => {
|
||||
const groupDisplayName = 'Acceptance Tests Group One';
|
||||
const modelId = `acceptance-tests-model-2`;
|
||||
const modelDisplayName = `Acceptance Tests Model 2`;
|
||||
const completedTaskClassName = 'completed-task-highlight';
|
||||
const activeTaskClassName = 'active-task-highlight';
|
||||
|
||||
cy.navigateToProcessModel(groupDisplayName, modelId);
|
||||
cy.navigateToProcessModel(groupDisplayName, modelDisplayName, modelId);
|
||||
|
||||
// avoid reloading so we can click on the task link that appears on running the process instance
|
||||
cy.runPrimaryBpmnFile(false);
|
||||
|
@ -67,7 +68,7 @@ describe('tasks', () => {
|
|||
);
|
||||
|
||||
cy.contains('Task: get_user_generated_number_four');
|
||||
cy.navigateToProcessModel(groupDisplayName, modelId);
|
||||
cy.navigateToProcessModel(groupDisplayName, modelDisplayName, modelId);
|
||||
cy.getBySel('process-instance-list-link').click();
|
||||
cy.assertAtLeastOneItemInPaginatedResults();
|
||||
|
||||
|
@ -84,7 +85,7 @@ describe('tasks', () => {
|
|||
checkTaskHasClass('form2', completedTaskClassName);
|
||||
checkTaskHasClass('form3', completedTaskClassName);
|
||||
checkTaskHasClass('form4', activeTaskClassName);
|
||||
cy.get('.modal .btn-close').click();
|
||||
cy.get('.is-visible .cds--modal-close').click();
|
||||
|
||||
cy.navigateToHome();
|
||||
cy.contains('Tasks').should('exist');
|
||||
|
@ -99,7 +100,7 @@ describe('tasks', () => {
|
|||
);
|
||||
cy.url().should('include', '/tasks');
|
||||
|
||||
cy.navigateToProcessModel(groupDisplayName, modelId);
|
||||
cy.navigateToProcessModel(groupDisplayName, modelDisplayName, modelId);
|
||||
cy.getBySel('process-instance-list-link').click();
|
||||
cy.assertAtLeastOneItemInPaginatedResults();
|
||||
|
||||
|
@ -112,6 +113,7 @@ describe('tasks', () => {
|
|||
it('can paginate items', () => {
|
||||
cy.navigateToProcessModel(
|
||||
'Acceptance Tests Group One',
|
||||
'Acceptance Tests Model 2',
|
||||
'acceptance-tests-model-2'
|
||||
);
|
||||
|
||||
|
|
|
@ -91,13 +91,12 @@ Cypress.Commands.add('runPrimaryBpmnFile', (reload = true) => {
|
|||
|
||||
Cypress.Commands.add(
|
||||
'navigateToProcessModel',
|
||||
(groupDisplayName, modelDisplayName) => {
|
||||
(groupDisplayName, modelDisplayName, modelIdentifier) => {
|
||||
cy.navigateToAdmin();
|
||||
cy.contains(groupDisplayName).click();
|
||||
cy.contains(`Process Group: ${groupDisplayName}`);
|
||||
// https://stackoverflow.com/q/51254946/6090676
|
||||
cy.getBySel('process-model-show-link').contains(modelDisplayName).click();
|
||||
// cy.url().should('include', `process-models/${groupDisplayName}/${modelDisplayName}`);
|
||||
cy.getBySel('process-model-show-link').contains(modelIdentifier).click();
|
||||
cy.contains(`Process Model: ${modelDisplayName}`);
|
||||
}
|
||||
);
|
||||
|
@ -115,10 +114,7 @@ Cypress.Commands.add('basicPaginationTest', () => {
|
|||
});
|
||||
|
||||
Cypress.Commands.add('assertAtLeastOneItemInPaginatedResults', () => {
|
||||
cy.getBySel('total-paginated-items')
|
||||
.invoke('text')
|
||||
.then(parseFloat)
|
||||
.should('be.gt', 0);
|
||||
cy.contains(/\b[1-9]\d*–[1-9]\d* of [1-9]\d*/);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('assertNoItemInPaginatedResults', () => {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { modifyProcessModelPath } from '../helpers';
|
||||
|
||||
type Props = {
|
||||
processGroupId: string;
|
||||
|
@ -27,7 +28,10 @@ export default class FileInput extends React.Component<Props> {
|
|||
|
||||
handleSubmit(event: any) {
|
||||
event.preventDefault();
|
||||
const url = `/process-models/${this.processGroupId}/${this.processModelId}/files`;
|
||||
const modifiedProcessModelId = modifyProcessModelPath(
|
||||
`${this.processGroupId}/${this.processModelId}`
|
||||
);
|
||||
const url = `/process-models/${modifiedProcessModelId}/files`;
|
||||
const formData = new FormData();
|
||||
formData.append('file', this.fileInput.current.files[0]);
|
||||
formData.append('fileName', this.fileInput.current.files[0].name);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// @ts-ignore
|
||||
import { Breadcrumb, BreadcrumbItem } from '@carbon/react';
|
||||
import { splitProcessModelId } from '../helpers';
|
||||
import { HotCrumbItem } from '../interfaces';
|
||||
|
||||
type OwnProps = {
|
||||
|
@ -9,6 +10,39 @@ type OwnProps = {
|
|||
hotCrumbs?: HotCrumbItem[];
|
||||
};
|
||||
|
||||
const explodeCrumb = (crumb: HotCrumbItem) => {
|
||||
const url: string = crumb[1] || '';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [_unused, processModelId, link] = url.split(':');
|
||||
const processModelIdSegments = splitProcessModelId(processModelId);
|
||||
const paths: string[] = [];
|
||||
const lastPathItem = processModelIdSegments.pop();
|
||||
const breadcrumbItems = processModelIdSegments.map(
|
||||
(processModelIdSegment: string) => {
|
||||
paths.push(processModelIdSegment);
|
||||
const fullUrl = `/admin/process-groups/${paths.join(':')}`;
|
||||
return (
|
||||
<BreadcrumbItem key={processModelIdSegment} href={fullUrl}>
|
||||
{processModelIdSegment}
|
||||
</BreadcrumbItem>
|
||||
);
|
||||
}
|
||||
);
|
||||
if (link === 'link') {
|
||||
const lastUrl = `/admin/process-models/${paths.join(':')}:${lastPathItem}`;
|
||||
breadcrumbItems.push(
|
||||
<BreadcrumbItem key={lastPathItem} href={lastUrl}>
|
||||
{lastPathItem}
|
||||
</BreadcrumbItem>
|
||||
);
|
||||
} else {
|
||||
breadcrumbItems.push(
|
||||
<BreadcrumbItem isCurrentPage>{lastPathItem}</BreadcrumbItem>
|
||||
);
|
||||
}
|
||||
return breadcrumbItems;
|
||||
};
|
||||
|
||||
export default function ProcessBreadcrumb({
|
||||
processModelId,
|
||||
processGroupId,
|
||||
|
@ -18,28 +52,22 @@ export default function ProcessBreadcrumb({
|
|||
let processGroupBreadcrumb = null;
|
||||
let processModelBreadcrumb = null;
|
||||
if (hotCrumbs) {
|
||||
const lastItem = hotCrumbs.pop();
|
||||
if (lastItem === undefined) {
|
||||
return null;
|
||||
}
|
||||
const lastCrumb = (
|
||||
<BreadcrumbItem isCurrentPage>{lastItem[0]}</BreadcrumbItem>
|
||||
);
|
||||
const leadingCrumbLinks = hotCrumbs.map((crumb: any) => {
|
||||
const valueLabel = crumb[0];
|
||||
const url = crumb[1];
|
||||
if (!url) {
|
||||
return <BreadcrumbItem isCurrentPage>{valueLabel}</BreadcrumbItem>;
|
||||
}
|
||||
if (url && url.startsWith('process_model:')) {
|
||||
return explodeCrumb(crumb);
|
||||
}
|
||||
return (
|
||||
<BreadcrumbItem key={valueLabel} href={url}>
|
||||
{valueLabel}
|
||||
</BreadcrumbItem>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<Breadcrumb noTrailingSlash>
|
||||
{leadingCrumbLinks}
|
||||
{lastCrumb}
|
||||
</Breadcrumb>
|
||||
);
|
||||
return <Breadcrumb noTrailingSlash>{leadingCrumbLinks}</Breadcrumb>;
|
||||
}
|
||||
if (processModelId) {
|
||||
if (linkProcessModel) {
|
||||
|
|
|
@ -2,7 +2,11 @@ import { useState } from 'react';
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
// @ts-ignore
|
||||
import { Button, ButtonSet, Form, Stack, TextInput } from '@carbon/react';
|
||||
import { slugifyString } from '../helpers';
|
||||
import {
|
||||
getGroupFromModifiedModelId,
|
||||
modifyProcessModelPath,
|
||||
slugifyString,
|
||||
} from '../helpers';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { ProcessModel } from '../interfaces';
|
||||
import ButtonWithConfirmation from './ButtonWithConfirmation';
|
||||
|
@ -23,17 +27,20 @@ export default function ProcessModelForm({
|
|||
useState<boolean>(false);
|
||||
const [displayNameInvalid, setDisplayNameInvalid] = useState<boolean>(false);
|
||||
const navigate = useNavigate();
|
||||
const modifiedProcessModelPath = modifyProcessModelPath(processModel.id);
|
||||
|
||||
const navigateToProcessModel = (_result: any) => {
|
||||
if (processModel) {
|
||||
navigate(
|
||||
`/admin/process-models/${processModel.process_group_id}/${processModel.id}`
|
||||
);
|
||||
navigate(`/admin/process-models/${modifiedProcessModelPath}`);
|
||||
}
|
||||
};
|
||||
|
||||
const navigateToProcessModels = (_result: any) => {
|
||||
navigate(`/admin/process-models/${processModel.process_group_id}`);
|
||||
navigate(
|
||||
`/admin/process-groups/${getGroupFromModifiedModelId(
|
||||
modifiedProcessModelPath
|
||||
)}`
|
||||
);
|
||||
};
|
||||
|
||||
const hasValidIdentifier = (identifierToCheck: string) => {
|
||||
|
@ -42,7 +49,7 @@ export default function ProcessModelForm({
|
|||
|
||||
const deleteProcessModel = () => {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${processModel.process_group_id}/${processModel.id}`,
|
||||
path: `/process-models/${modifiedProcessModelPath}`,
|
||||
successCallback: navigateToProcessModels,
|
||||
httpMethod: 'DELETE',
|
||||
});
|
||||
|
@ -64,7 +71,7 @@ export default function ProcessModelForm({
|
|||
}
|
||||
let path = `/process-models`;
|
||||
if (mode === 'edit') {
|
||||
path = `/process-models/${processModel.process_group_id}/${processModel.id}`;
|
||||
path = `/process-models/${modifiedProcessModelPath}`;
|
||||
}
|
||||
let httpMethod = 'POST';
|
||||
if (mode === 'edit') {
|
||||
|
@ -77,10 +84,9 @@ export default function ProcessModelForm({
|
|||
if (mode === 'new') {
|
||||
Object.assign(postBody, {
|
||||
id: processModel.id,
|
||||
process_group_id: processModel.process_group_id,
|
||||
});
|
||||
}
|
||||
console.log('postBody', postBody);
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
path,
|
||||
successCallback: navigateToProcessModel,
|
||||
|
@ -176,7 +182,6 @@ export default function ProcessModelForm({
|
|||
}
|
||||
return <ButtonSet>{buttons}</ButtonSet>;
|
||||
};
|
||||
console.log('processModel.process_group_id', processModel.process_group_id);
|
||||
return (
|
||||
<Form onSubmit={handleFormSubmission}>
|
||||
<Stack gap={5}>
|
||||
|
|
|
@ -21,7 +21,7 @@ export default function ProcessModelSearch({
|
|||
const shouldFilterProcessModel = (options: any) => {
|
||||
const processModel: ProcessModel = options.item;
|
||||
const { inputValue } = options;
|
||||
return `${processModel.process_group_id}/${processModel.id} (${processModel.display_name})`.includes(
|
||||
return `${processModel.id} (${processModel.display_name})`.includes(
|
||||
inputValue
|
||||
);
|
||||
};
|
||||
|
@ -33,9 +33,10 @@ export default function ProcessModelSearch({
|
|||
items={processModels}
|
||||
itemToString={(processModel: ProcessModel) => {
|
||||
if (processModel) {
|
||||
return `${processModel.process_group_id}/${
|
||||
processModel.id
|
||||
} (${truncateString(processModel.display_name, 20)})`;
|
||||
return `${processModel.id} (${truncateString(
|
||||
processModel.display_name,
|
||||
20
|
||||
)})`;
|
||||
}
|
||||
return null;
|
||||
}}
|
||||
|
|
|
@ -59,7 +59,6 @@ import { makeid } from '../helpers';
|
|||
|
||||
type OwnProps = {
|
||||
processModelId: string;
|
||||
processGroupId: string;
|
||||
diagramType: string;
|
||||
readyOrWaitingBpmnTaskIds?: string[] | null;
|
||||
completedTasksBpmnIds?: string[] | null;
|
||||
|
@ -83,7 +82,6 @@ type OwnProps = {
|
|||
// https://codesandbox.io/s/quizzical-lake-szfyo?file=/src/App.js was a handy reference
|
||||
export default function ReactDiagramEditor({
|
||||
processModelId,
|
||||
processGroupId,
|
||||
diagramType,
|
||||
readyOrWaitingBpmnTaskIds,
|
||||
completedTasksBpmnIds,
|
||||
|
@ -408,6 +406,7 @@ export default function ReactDiagramEditor({
|
|||
}
|
||||
|
||||
function fetchDiagramFromURL(urlToUse: any) {
|
||||
console.log(`urlToUse: ${urlToUse}`);
|
||||
fetch(urlToUse)
|
||||
.then((response) => response.text())
|
||||
.then((text) => {
|
||||
|
@ -424,7 +423,7 @@ export default function ReactDiagramEditor({
|
|||
|
||||
function fetchDiagramFromJsonAPI() {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${processGroupId}/${processModelId}/files/${fileName}`,
|
||||
path: `/process-models/${processModelId}/files/${fileName}`,
|
||||
successCallback: setDiagramXMLStringFromResponseJson,
|
||||
});
|
||||
}
|
||||
|
@ -470,7 +469,6 @@ export default function ReactDiagramEditor({
|
|||
completedTasksBpmnIds,
|
||||
fileName,
|
||||
performingXmlUpdates,
|
||||
processGroupId,
|
||||
processModelId,
|
||||
url,
|
||||
]);
|
||||
|
|
|
@ -113,3 +113,22 @@ export const truncateString = (text: string, len: number) => {
|
|||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
// Because of limitations in the way openapi defines parameters, we have to modify process models ids
|
||||
// which are basically paths to the models
|
||||
export const modifyProcessModelPath = (path: String) => {
|
||||
return path.replace('/', ':') || '';
|
||||
};
|
||||
|
||||
export const unModifyProcessModelPath = (path: String) => {
|
||||
return path.replace(':', '/') || '';
|
||||
};
|
||||
|
||||
export const getGroupFromModifiedModelId = (modifiedId: String) => {
|
||||
const finalSplitIndex = modifiedId.lastIndexOf(':');
|
||||
return modifiedId.slice(0, finalSplitIndex);
|
||||
};
|
||||
|
||||
export const splitProcessModelId = (processModelId: String) => {
|
||||
return processModelId.split('/');
|
||||
};
|
||||
|
|
|
@ -44,6 +44,14 @@ span.bjs-crumb {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.cds--breadcrumb {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.process-description {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.diagram-editor-canvas {
|
||||
border:1px solid #000000;
|
||||
height:70vh;
|
||||
|
|
|
@ -25,6 +25,21 @@
|
|||
// background-color: colors.$gray-100;
|
||||
color: white;
|
||||
}
|
||||
h1{
|
||||
height: 36px;
|
||||
font-family: 'IBM Plex Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 28px;
|
||||
line-height: 36px;
|
||||
color: #161616;
|
||||
flex: none;
|
||||
order: 0;
|
||||
align-self: stretch;
|
||||
flex-grow: 0;
|
||||
margin-bottom: 1em
|
||||
}
|
||||
|
||||
|
||||
.cds--breadcrumb-item a.cds--link:hover {
|
||||
color: #525252;
|
||||
|
|
|
@ -27,7 +27,6 @@ export interface ProcessFile {
|
|||
content_type: string;
|
||||
last_modified: string;
|
||||
name: string;
|
||||
process_group_id: string;
|
||||
process_model_id: string;
|
||||
references: ProcessFileReference[];
|
||||
size: number;
|
||||
|
@ -38,7 +37,6 @@ export interface ProcessFile {
|
|||
export interface ProcessModel {
|
||||
id: string;
|
||||
description: string;
|
||||
process_group_id: string;
|
||||
display_name: string;
|
||||
primary_file_name: string;
|
||||
files: ProcessFile[];
|
||||
|
|
|
@ -53,35 +53,35 @@ export default function AdminRoutes() {
|
|||
element={<ProcessModelNew />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id"
|
||||
path="process-models/:process_model_id"
|
||||
element={<ProcessModelShow />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/files"
|
||||
path="process-models/:process_model_id/files"
|
||||
element={<ProcessModelEditDiagram />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/files/:file_name"
|
||||
path="process-models/:process_model_id/files/:file_name"
|
||||
element={<ProcessModelEditDiagram />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/process-instances"
|
||||
path="process-models/:process_model_id/process-instances"
|
||||
element={<ProcessInstanceList />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/edit"
|
||||
path="process-models/:process_model_id/edit"
|
||||
element={<ProcessModelEdit />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/process-instances/:process_instance_id"
|
||||
path="process-models/:process_model_id/process-instances/:process_instance_id"
|
||||
element={<ProcessInstanceShow />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/process-instances/:process_instance_id/:spiff_step"
|
||||
path="process-models/:process_model_id/process-instances/:process_instance_id/:spiff_step"
|
||||
element={<ProcessInstanceShow />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/process-instances/reports"
|
||||
path="process-models/:process_model_id/process-instances/reports"
|
||||
element={<ProcessInstanceReportList />}
|
||||
/>
|
||||
<Route
|
||||
|
@ -97,15 +97,15 @@ export default function AdminRoutes() {
|
|||
element={<ProcessInstanceReportEdit />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/form"
|
||||
path="process-models/:process_model_id/form"
|
||||
element={<ReactFormEditor />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/form/:file_name"
|
||||
path="process-models/:process_model_id/form/:file_name"
|
||||
element={<ReactFormEditor />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/:process_model_id/process-instances/:process_instance_id/logs"
|
||||
path="process-models/:process_model_id/process-instances/:process_instance_id/logs"
|
||||
element={<ProcessInstanceLogList />}
|
||||
/>
|
||||
<Route path="process-instances" element={<ProcessInstanceList />} />
|
||||
|
|
|
@ -3,7 +3,10 @@ import { useEffect, useState } from 'react';
|
|||
import { Button, Table } from '@carbon/react';
|
||||
import { Link, useSearchParams } from 'react-router-dom';
|
||||
import PaginationForTable from '../components/PaginationForTable';
|
||||
import { getPageInfoFromSearchParams } from '../helpers';
|
||||
import {
|
||||
getPageInfoFromSearchParams,
|
||||
modifyProcessModelPath,
|
||||
} from '../helpers';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { PaginationObject, RecentProcessModel } from '../interfaces';
|
||||
|
||||
|
@ -39,12 +42,15 @@ export default function HomePage() {
|
|||
const rows = tasks.map((row) => {
|
||||
const rowToUse = row as any;
|
||||
const taskUrl = `/tasks/${rowToUse.process_instance_id}/${rowToUse.id}`;
|
||||
const modifiedProcessModelIdentifier = modifyProcessModelPath(
|
||||
rowToUse.process_model_identifier
|
||||
);
|
||||
return (
|
||||
<tr key={rowToUse.id}>
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-model-show-link"
|
||||
to={`/admin/process-models/${rowToUse.process_group_identifier}/${rowToUse.process_model_identifier}`}
|
||||
to={`/admin/process-models/${modifiedProcessModelIdentifier}`}
|
||||
>
|
||||
{rowToUse.process_model_display_name}
|
||||
</Link>
|
||||
|
@ -52,7 +58,7 @@ export default function HomePage() {
|
|||
<td>
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-models/${rowToUse.process_group_identifier}/${rowToUse.process_model_identifier}/process-instances/${rowToUse.process_instance_id}`}
|
||||
to={`/admin/process-models/${modifiedProcessModelIdentifier}/process-instances/${rowToUse.process_instance_id}`}
|
||||
>
|
||||
View {rowToUse.process_instance_id}
|
||||
</Link>
|
||||
|
@ -96,6 +102,9 @@ export default function HomePage() {
|
|||
const buildRecentProcessModelSection = () => {
|
||||
const rows = recentProcessModels.map((row) => {
|
||||
const rowToUse = row as any;
|
||||
const modifiedProcessModelId = modifyProcessModelPath(
|
||||
rowToUse.processModelIdentifier
|
||||
);
|
||||
return (
|
||||
<tr
|
||||
key={`${rowToUse.processGroupIdentifier}/${rowToUse.processModelIdentifier}`}
|
||||
|
@ -103,7 +112,7 @@ export default function HomePage() {
|
|||
<td>
|
||||
<Link
|
||||
data-qa="process-model-show-link"
|
||||
to={`/admin/process-models/${rowToUse.processGroupIdentifier}/${rowToUse.processModelIdentifier}`}
|
||||
to={`/admin/process-models/${modifiedProcessModelId}`}
|
||||
>
|
||||
{rowToUse.processModelDisplayName}
|
||||
</Link>
|
||||
|
|
|
@ -13,7 +13,10 @@ import {
|
|||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import PaginationForTable from '../components/PaginationForTable';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { getPageInfoFromSearchParams } from '../helpers';
|
||||
import {
|
||||
getPageInfoFromSearchParams,
|
||||
modifyProcessModelPath,
|
||||
} from '../helpers';
|
||||
import { CarbonComboBoxSelection, ProcessGroup } from '../interfaces';
|
||||
import ProcessModelSearch from '../components/ProcessModelSearch';
|
||||
|
||||
|
@ -36,7 +39,7 @@ export default function ProcessGroupList() {
|
|||
};
|
||||
const processResultForProcessModels = (result: any) => {
|
||||
const selectionArray = result.results.map((item: any) => {
|
||||
const label = `${item.process_group_id}/${item.id}`;
|
||||
const label = `${item.id}`;
|
||||
Object.assign(item, { label });
|
||||
return item;
|
||||
});
|
||||
|
@ -120,7 +123,7 @@ export default function ProcessGroupList() {
|
|||
const processModelSearchOnChange = (selection: CarbonComboBoxSelection) => {
|
||||
const processModel = selection.selectedItem;
|
||||
navigate(
|
||||
`/admin/process-models/${processModel.process_group_id}/${processModel.id}`
|
||||
`/admin/process-models/${modifyProcessModelPath(processModel.id)}`
|
||||
);
|
||||
};
|
||||
return (
|
||||
|
|
|
@ -24,6 +24,7 @@ export default function ProcessGroupShow() {
|
|||
setPagination(result.pagination);
|
||||
};
|
||||
const processResult = (result: any) => {
|
||||
console.log(result);
|
||||
setProcessGroup(result);
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models?process_group_identifier=${params.process_group_id}&per_page=${perPage}&page=${page}`,
|
||||
|
@ -41,11 +42,12 @@ export default function ProcessGroupShow() {
|
|||
return null;
|
||||
}
|
||||
const rows = processModels.map((row) => {
|
||||
const modifiedProcessModelId: String = (row as any).id.replace('/', ':');
|
||||
return (
|
||||
<tr key={(row as any).id}>
|
||||
<td>
|
||||
<Link
|
||||
to={`/admin/process-models/${processGroup.id}/${(row as any).id}`}
|
||||
to={`/admin/process-models/${modifiedProcessModelId}`}
|
||||
data-qa="process-model-show-link"
|
||||
>
|
||||
{(row as any).id}
|
||||
|
|
|
@ -30,6 +30,7 @@ import {
|
|||
convertSecondsToFormattedDate,
|
||||
getPageInfoFromSearchParams,
|
||||
getProcessModelFullIdentifierFromSearchParams,
|
||||
modifyProcessModelPath,
|
||||
} from '../helpers';
|
||||
|
||||
import PaginationForTable from '../components/PaginationForTable';
|
||||
|
@ -85,7 +86,6 @@ export default function ProcessInstanceList() {
|
|||
|
||||
const parametersToGetFromSearchParams = useMemo(() => {
|
||||
return {
|
||||
process_group_identifier: null,
|
||||
process_model_identifier: null,
|
||||
process_status: null,
|
||||
};
|
||||
|
@ -137,7 +137,7 @@ export default function ProcessInstanceList() {
|
|||
const processModelFullIdentifier =
|
||||
getProcessModelFullIdentifierFromSearchParams(searchParams);
|
||||
const selectionArray = result.results.map((item: any) => {
|
||||
const label = `${item.process_group_id}/${item.id}`;
|
||||
const label = `${item.id}`;
|
||||
Object.assign(item, { label });
|
||||
if (label === processModelFullIdentifier) {
|
||||
setProcessModelSelection(item);
|
||||
|
@ -243,7 +243,7 @@ export default function ProcessInstanceList() {
|
|||
}
|
||||
|
||||
if (processModelSelection) {
|
||||
queryParamString += `&process_group_identifier=${processModelSelection.process_group_id}&process_model_identifier=${processModelSelection.id}`;
|
||||
queryParamString += `&process_model_identifier=${processModelSelection.id}`;
|
||||
}
|
||||
|
||||
setErrorMessage(null);
|
||||
|
@ -382,7 +382,6 @@ export default function ProcessInstanceList() {
|
|||
const buildTable = () => {
|
||||
const headerLabels: Record<string, string> = {
|
||||
id: 'Process Instance Id',
|
||||
process_group_identifier: 'Process Group',
|
||||
process_model_identifier: 'Process Model',
|
||||
start_in_seconds: 'Start Time',
|
||||
end_in_seconds: 'End Time',
|
||||
|
@ -397,10 +396,13 @@ export default function ProcessInstanceList() {
|
|||
});
|
||||
|
||||
const formatProcessInstanceId = (row: any, id: any) => {
|
||||
const modifiedProcessModelId: String = modifyProcessModelPath(
|
||||
(row as any).process_model_identifier
|
||||
);
|
||||
return (
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-models/${row.process_group_identifier}/${row.process_model_identifier}/process-instances/${row.id}`}
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${row.id}`}
|
||||
>
|
||||
{id}
|
||||
</Link>
|
||||
|
@ -414,7 +416,7 @@ export default function ProcessInstanceList() {
|
|||
const formatProcessModelIdentifier = (row: any, identifier: any) => {
|
||||
return (
|
||||
<Link
|
||||
to={`/admin/process-models/${row.process_group_identifier}/${identifier}`}
|
||||
to={`/admin/process-models/${modifyProcessModelPath(identifier)}`}
|
||||
>
|
||||
{identifier}
|
||||
</Link>
|
||||
|
@ -429,7 +431,6 @@ export default function ProcessInstanceList() {
|
|||
|
||||
const columnFormatters: Record<string, any> = {
|
||||
id: formatProcessInstanceId,
|
||||
process_group_identifier: formatProcessGroupIdentifier,
|
||||
process_model_identifier: formatProcessModelIdentifier,
|
||||
start_in_seconds: formatSecondsForDisplay,
|
||||
end_in_seconds: formatSecondsForDisplay,
|
||||
|
|
|
@ -7,6 +7,7 @@ import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
|||
import {
|
||||
getPageInfoFromSearchParams,
|
||||
convertSecondsToFormattedDate,
|
||||
modifyProcessModelPath,
|
||||
} from '../helpers';
|
||||
import HttpService from '../services/HttpService';
|
||||
|
||||
|
@ -15,6 +16,9 @@ export default function ProcessInstanceLogList() {
|
|||
const [searchParams] = useSearchParams();
|
||||
const [processInstanceLogs, setProcessInstanceLogs] = useState([]);
|
||||
const [pagination, setPagination] = useState(null);
|
||||
const modifiedProcessModelId = modifyProcessModelPath(
|
||||
`${params.process_model_id}`
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const setProcessInstanceLogListFromResult = (result: any) => {
|
||||
|
@ -23,7 +27,7 @@ export default function ProcessInstanceLogList() {
|
|||
};
|
||||
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${params.process_instance_id}/logs?per_page=${perPage}&page=${page}`,
|
||||
path: `/process-instances/${params.process_instance_id}/logs?per_page=${perPage}&page=${page}`,
|
||||
successCallback: setProcessInstanceLogListFromResult,
|
||||
});
|
||||
}, [searchParams, params]);
|
||||
|
@ -32,6 +36,7 @@ export default function ProcessInstanceLogList() {
|
|||
// return null;
|
||||
const rows = processInstanceLogs.map((row) => {
|
||||
const rowToUse = row as any;
|
||||
console.log(`rowToUse: ${rowToUse}`);
|
||||
return (
|
||||
<tr key={rowToUse.id}>
|
||||
<td>{rowToUse.bpmn_process_identifier}</td>
|
||||
|
@ -43,7 +48,7 @@ export default function ProcessInstanceLogList() {
|
|||
<td>
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${rowToUse.process_instance_id}/${rowToUse.spiff_step}`}
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${rowToUse.process_instance_id}/${rowToUse.spiff_step}`}
|
||||
>
|
||||
{convertSecondsToFormattedDate(rowToUse.timestamp)}
|
||||
</Link>
|
||||
|
@ -83,7 +88,7 @@ export default function ProcessInstanceLogList() {
|
|||
perPage={perPage}
|
||||
pagination={pagination}
|
||||
tableToDisplay={buildTable()}
|
||||
path={`/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${params.process_instance_id}/logs`}
|
||||
path={`/admin/process-instances/${params.process_instance_id}/logs`}
|
||||
/>
|
||||
</main>
|
||||
);
|
||||
|
|
|
@ -4,10 +4,14 @@ import { Button, Table } from '@carbon/react';
|
|||
import { useParams, Link } from 'react-router-dom';
|
||||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { modifyProcessModelPath } from '../helpers';
|
||||
|
||||
export default function ProcessInstanceReportList() {
|
||||
const params = useParams();
|
||||
const [processInstanceReports, setProcessInstanceReports] = useState([]);
|
||||
const modifiedProcessModelId = modifyProcessModelPath(
|
||||
params.process_model_id || ''
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
HttpService.makeCallToBackend({
|
||||
|
@ -23,7 +27,7 @@ export default function ProcessInstanceReportList() {
|
|||
<tr key={(row as any).id}>
|
||||
<td>
|
||||
<Link
|
||||
to={`/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/${rowToUse.identifier}`}
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/reports/${rowToUse.identifier}`}
|
||||
>
|
||||
{rowToUse.identifier}
|
||||
</Link>
|
||||
|
@ -52,7 +56,7 @@ export default function ProcessInstanceReportList() {
|
|||
/>
|
||||
<h2>Reports for Process Model: {params.process_model_id}</h2>
|
||||
<Button
|
||||
href={`/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/reports/new`}
|
||||
href={`/admin/process-models/${modifiedProcessModelId}/process-instances/reports/new`}
|
||||
>
|
||||
Add a process instance report
|
||||
</Button>
|
||||
|
|
|
@ -6,7 +6,10 @@ import { Button, Modal, Stack } from '@carbon/react';
|
|||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import HttpService from '../services/HttpService';
|
||||
import ReactDiagramEditor from '../components/ReactDiagramEditor';
|
||||
import { convertSecondsToFormattedDate } from '../helpers';
|
||||
import {
|
||||
convertSecondsToFormattedDate,
|
||||
unModifyProcessModelPath,
|
||||
} from '../helpers';
|
||||
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
|
||||
import ErrorContext from '../contexts/ErrorContext';
|
||||
|
||||
|
@ -22,15 +25,20 @@ export default function ProcessInstanceShow() {
|
|||
|
||||
const setErrorMessage = (useContext as any)(ErrorContext)[1];
|
||||
|
||||
const unModifiedProcessModelId = unModifyProcessModelPath(
|
||||
`${params.process_model_id}`
|
||||
);
|
||||
const modifiedProcessModelId = params.process_model_id;
|
||||
|
||||
const navigateToProcessInstances = (_result: any) => {
|
||||
navigate(
|
||||
`/admin/process-instances?process_group_identifier=${params.process_group_id}&process_model_identifier=${params.process_model_id}`
|
||||
`/admin/process-instances?process_model_identifier=${unModifiedProcessModelId}`
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${params.process_instance_id}`,
|
||||
path: `/process-models/${modifiedProcessModelId}/process-instances/${params.process_instance_id}`,
|
||||
successCallback: setProcessInstance,
|
||||
});
|
||||
if (typeof params.spiff_step === 'undefined')
|
||||
|
@ -43,11 +51,11 @@ export default function ProcessInstanceShow() {
|
|||
path: `/process-instance/${params.process_instance_id}/tasks?all_tasks=true&spiff_step=${params.spiff_step}`,
|
||||
successCallback: setTasks,
|
||||
});
|
||||
}, [params]);
|
||||
}, [params, modifiedProcessModelId]);
|
||||
|
||||
const deleteProcessInstance = () => {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${params.process_instance_id}`,
|
||||
path: `/process-instances/${params.process_instance_id}`,
|
||||
successCallback: navigateToProcessInstances,
|
||||
httpMethod: 'DELETE',
|
||||
});
|
||||
|
@ -60,7 +68,7 @@ export default function ProcessInstanceShow() {
|
|||
|
||||
const terminateProcessInstance = () => {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${params.process_instance_id}/terminate`,
|
||||
path: `/process-instances/${params.process_instance_id}/terminate`,
|
||||
successCallback: refreshPage,
|
||||
httpMethod: 'POST',
|
||||
});
|
||||
|
@ -68,7 +76,7 @@ export default function ProcessInstanceShow() {
|
|||
|
||||
const suspendProcessInstance = () => {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${params.process_instance_id}/suspend`,
|
||||
path: `/process-instances/${params.process_instance_id}/suspend`,
|
||||
successCallback: refreshPage,
|
||||
httpMethod: 'POST',
|
||||
});
|
||||
|
@ -76,7 +84,7 @@ export default function ProcessInstanceShow() {
|
|||
|
||||
const resumeProcessInstance = () => {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${params.process_instance_id}/resume`,
|
||||
path: `/process-instances/${params.process_instance_id}/resume`,
|
||||
successCallback: refreshPage,
|
||||
httpMethod: 'POST',
|
||||
});
|
||||
|
@ -125,7 +133,7 @@ export default function ProcessInstanceShow() {
|
|||
<Link
|
||||
reloadDocument
|
||||
data-qa="process-instance-step-link"
|
||||
to={`/admin/process-models/${params.process_group_id}/${
|
||||
to={`/admin/process-models/${
|
||||
params.process_model_id
|
||||
}/process-instances/${params.process_instance_id}/${
|
||||
currentSpiffStep(processInstanceToUse) + distance
|
||||
|
@ -179,7 +187,7 @@ export default function ProcessInstanceShow() {
|
|||
<li>
|
||||
<Link
|
||||
data-qa="process-instance-log-list-link"
|
||||
to={`/admin/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${params.process_instance_id}/logs`}
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${params.process_instance_id}/logs`}
|
||||
>
|
||||
Logs
|
||||
</Link>
|
||||
|
@ -187,7 +195,7 @@ export default function ProcessInstanceShow() {
|
|||
<li>
|
||||
<Link
|
||||
data-qa="process-instance-message-instance-list-link"
|
||||
to={`/admin/messages?process_group_id=${params.process_group_id}&process_model_id=${params.process_model_id}&process_instance_id=${params.process_instance_id}`}
|
||||
to={`/admin/messages?process_model_id=${params.process_model_id}&process_instance_id=${params.process_instance_id}`}
|
||||
>
|
||||
Messages
|
||||
</Link>
|
||||
|
@ -284,7 +292,7 @@ export default function ProcessInstanceShow() {
|
|||
const taskToUse: any = taskToDisplay;
|
||||
const previousTask: any = getTaskById(taskToUse.parent);
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/script-unit-tests`,
|
||||
path: `/process-models/${modifiedProcessModelId}/script-unit-tests`,
|
||||
httpMethod: 'POST',
|
||||
successCallback: processScriptUnitTestCreateResult,
|
||||
postBody: {
|
||||
|
@ -428,11 +436,14 @@ export default function ProcessInstanceShow() {
|
|||
if (processInstance && tasks) {
|
||||
const processInstanceToUse = processInstance as any;
|
||||
const taskIds = getTaskIds();
|
||||
const processModelId = unModifyProcessModelPath(
|
||||
params.process_model_id ? params.process_model_id : ''
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ProcessBreadcrumb
|
||||
processModelId={params.process_model_id}
|
||||
processModelId={processModelId}
|
||||
processGroupId={params.process_group_id}
|
||||
linkProcessModel
|
||||
/>
|
||||
|
@ -450,8 +461,7 @@ export default function ProcessInstanceShow() {
|
|||
{getInfoTag(processInstanceToUse)}
|
||||
{taskDataDisplayArea()}
|
||||
<ReactDiagramEditor
|
||||
processModelId={params.process_model_id || ''}
|
||||
processGroupId={params.process_group_id || ''}
|
||||
processModelId={processModelId || ''}
|
||||
diagramXML={processInstanceToUse.bpmn_xml_file_contents || ''}
|
||||
fileName={processInstanceToUse.bpmn_xml_file_contents || ''}
|
||||
readyOrWaitingBpmnTaskIds={taskIds.readyOrWaiting}
|
||||
|
|
|
@ -8,7 +8,7 @@ import ProcessModelForm from '../components/ProcessModelForm';
|
|||
export default function ProcessModelEdit() {
|
||||
const params = useParams();
|
||||
const [processModel, setProcessModel] = useState(null);
|
||||
const processModelPath = `process-models/${params.process_group_id}/${params.process_model_id}`;
|
||||
const processModelPath = `process-models/${params.process_model_id}`;
|
||||
|
||||
useEffect(() => {
|
||||
HttpService.makeCallToBackend({
|
||||
|
|
|
@ -17,7 +17,7 @@ import ReactDiagramEditor from '../components/ReactDiagramEditor';
|
|||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import HttpService from '../services/HttpService';
|
||||
import ErrorContext from '../contexts/ErrorContext';
|
||||
import { makeid } from '../helpers';
|
||||
import { makeid, modifyProcessModelPath } from '../helpers';
|
||||
import { ProcessFile, ProcessModel } from '../interfaces';
|
||||
|
||||
export default function ProcessModelEditDiagram() {
|
||||
|
@ -77,12 +77,18 @@ export default function ProcessModelEditDiagram() {
|
|||
const [searchParams] = useSearchParams();
|
||||
|
||||
const setErrorMessage = (useContext as any)(ErrorContext)[1];
|
||||
const [processModelFile, setProcessModelFile] = useState(null);
|
||||
const [processModelFile, setProcessModelFile] = useState<ProcessFile | null>(
|
||||
null
|
||||
);
|
||||
const [newFileName, setNewFileName] = useState('');
|
||||
const [bpmnXmlForDiagramRendering, setBpmnXmlForDiagramRendering] =
|
||||
useState(null);
|
||||
|
||||
const processModelPath = `process-models/${params.process_group_id}/${params.process_model_id}`;
|
||||
const modifiedProcessModelId = modifyProcessModelPath(
|
||||
(params as any).process_model_id
|
||||
);
|
||||
|
||||
const processModelPath = `process-models/${modifiedProcessModelId}`;
|
||||
|
||||
useEffect(() => {
|
||||
const processResult = (result: ProcessModel) => {
|
||||
|
@ -101,6 +107,7 @@ export default function ProcessModelEditDiagram() {
|
|||
};
|
||||
|
||||
if (params.file_name) {
|
||||
console.log(`processModelPath: ${processModelPath}`);
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/${processModelPath}/files/${params.file_name}`,
|
||||
successCallback: fileResult,
|
||||
|
@ -119,7 +126,7 @@ export default function ProcessModelEditDiagram() {
|
|||
'file_type'
|
||||
)}`;
|
||||
navigate(
|
||||
`/admin/process-models/${params.process_group_id}/${params.process_model_id}/files/${fileNameWithExtension}`
|
||||
`/admin/process-models/${modifiedProcessModelId}/files/${fileNameWithExtension}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -128,7 +135,7 @@ export default function ProcessModelEditDiagram() {
|
|||
setErrorMessage(null);
|
||||
setBpmnXmlForDiagramRendering(bpmnXML);
|
||||
|
||||
let url = `/process-models/${params.process_group_id}/${params.process_model_id}/files`;
|
||||
let url = `/process-models/${modifiedProcessModelId}/files`;
|
||||
let httpMethod = 'PUT';
|
||||
let fileNameWithExtension = fileName;
|
||||
|
||||
|
@ -162,13 +169,11 @@ export default function ProcessModelEditDiagram() {
|
|||
};
|
||||
|
||||
const onDeleteFile = (fileName = params.file_name) => {
|
||||
const url = `/process-models/${params.process_group_id}/${params.process_model_id}/files/${fileName}`;
|
||||
const url = `/process-models/${modifiedProcessModelId}/files/${fileName}`;
|
||||
const httpMethod = 'DELETE';
|
||||
|
||||
const navigateToProcessModelShow = (_httpResult: any) => {
|
||||
navigate(
|
||||
`/admin/process-models/${params.process_group_id}/${params.process_model_id}`
|
||||
);
|
||||
navigate(`/admin/process-models/${modifiedProcessModelId}`);
|
||||
};
|
||||
HttpService.makeCallToBackend({
|
||||
path: url,
|
||||
|
@ -178,7 +183,7 @@ export default function ProcessModelEditDiagram() {
|
|||
};
|
||||
|
||||
const onSetPrimaryFile = (fileName = params.file_name) => {
|
||||
const url = `/process-models/${params.process_group_id}/${params.process_model_id}`;
|
||||
const url = `/process-models/${modifiedProcessModelId}`;
|
||||
const httpMethod = 'PUT';
|
||||
|
||||
const navigateToProcessModelShow = (_httpResult: any) => {
|
||||
|
@ -428,7 +433,7 @@ export default function ProcessModelEditDiagram() {
|
|||
if (currentScriptUnitTest && scriptElement) {
|
||||
resetUnitTextResult();
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/script-unit-tests/run`,
|
||||
path: `/process-models/${modifiedProcessModelId}/script-unit-tests/run`,
|
||||
httpMethod: 'POST',
|
||||
successCallback: processScriptUnitTestRunResult,
|
||||
postBody: {
|
||||
|
@ -730,7 +735,6 @@ export default function ProcessModelEditDiagram() {
|
|||
return (
|
||||
<ReactDiagramEditor
|
||||
processModelId={params.process_model_id || ''}
|
||||
processGroupId={params.process_group_id || ''}
|
||||
saveDiagram={saveDiagram}
|
||||
onDeleteFile={onDeleteFile}
|
||||
diagramXML={bpmnXmlForDiagramRendering}
|
||||
|
@ -752,7 +756,6 @@ export default function ProcessModelEditDiagram() {
|
|||
return (
|
||||
<ReactDiagramEditor
|
||||
processModelId={params.process_model_id || ''}
|
||||
processGroupId={params.process_group_id || ''}
|
||||
saveDiagram={saveDiagram}
|
||||
onDeleteFile={onDeleteFile}
|
||||
onSetPrimaryFile={onSetPrimaryFileCallback}
|
||||
|
@ -773,16 +776,24 @@ export default function ProcessModelEditDiagram() {
|
|||
|
||||
// if a file name is not given then this is a new model and the ReactDiagramEditor component will handle it
|
||||
if ((bpmnXmlForDiagramRendering || !params.file_name) && processModel) {
|
||||
const processModelFileName = processModelFile
|
||||
? `: ${processModelFile.name}`
|
||||
: '';
|
||||
return (
|
||||
<>
|
||||
<ProcessBreadcrumb
|
||||
processGroupId={params.process_group_id}
|
||||
processModelId={params.process_model_id}
|
||||
linkProcessModel
|
||||
hotCrumbs={[
|
||||
['Process Groups', '/admin'],
|
||||
[
|
||||
`Process Model: ${processModel.id}`,
|
||||
`process_model:${processModel.id}:link`,
|
||||
],
|
||||
[processModelFileName],
|
||||
]}
|
||||
/>
|
||||
<h2>
|
||||
Process Model File
|
||||
{processModelFile ? `: ${(processModelFile as any).name}` : ''}
|
||||
{processModelFileName}
|
||||
</h2>
|
||||
{appropriateEditor()}
|
||||
{newFileNameBox()}
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
import { useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import { ProcessModel } from '../interfaces';
|
||||
import ProcessModelForm from '../components/ProcessModelForm';
|
||||
|
||||
export default function ProcessModelNew() {
|
||||
const params = useParams();
|
||||
|
||||
const [processModel, setProcessModel] = useState<ProcessModel>({
|
||||
id: '',
|
||||
display_name: '',
|
||||
description: '',
|
||||
process_group_id: params.process_group_id || '',
|
||||
primary_file_name: '',
|
||||
files: [],
|
||||
});
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import HttpService from '../services/HttpService';
|
||||
import ErrorContext from '../contexts/ErrorContext';
|
||||
import { modifyProcessModelPath, unModifyProcessModelPath } from '../helpers';
|
||||
import { ProcessFile, ProcessModel, RecentProcessModel } from '../interfaces';
|
||||
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
|
||||
|
||||
|
@ -97,6 +98,10 @@ export default function ProcessModelShow() {
|
|||
useState<boolean>(false);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const modifiedProcessModelId = modifyProcessModelPath(
|
||||
`${params.process_model_id}`
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const processResult = (result: ProcessModel) => {
|
||||
setProcessModel(result);
|
||||
|
@ -104,15 +109,15 @@ export default function ProcessModelShow() {
|
|||
storeRecentProcessModelInLocalStorage(result, params);
|
||||
};
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}`,
|
||||
path: `/process-models/${modifiedProcessModelId}`,
|
||||
successCallback: processResult,
|
||||
});
|
||||
}, [params, reloadModel]);
|
||||
}, [params, reloadModel, modifiedProcessModelId]);
|
||||
|
||||
const processModelRun = (processInstance: any) => {
|
||||
setErrorMessage(null);
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/process-instances/${processInstance.id}/run`,
|
||||
path: `/process-instances/${processInstance.id}/run`,
|
||||
successCallback: setProcessInstanceResult,
|
||||
failureCallback: setErrorMessage,
|
||||
httpMethod: 'POST',
|
||||
|
@ -121,7 +126,7 @@ export default function ProcessModelShow() {
|
|||
|
||||
const processInstanceCreateAndRun = () => {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/process-instances`,
|
||||
path: `/process-models/${modifiedProcessModelId}/process-instances`,
|
||||
successCallback: processModelRun,
|
||||
httpMethod: 'POST',
|
||||
});
|
||||
|
@ -149,7 +154,7 @@ export default function ProcessModelShow() {
|
|||
<p>
|
||||
Process Instance {processInstanceId} kicked off (
|
||||
<Link
|
||||
to={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/process-instances/${processInstanceId}`}
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${processInstanceId}`}
|
||||
data-qa="process-instance-show-link"
|
||||
>
|
||||
view
|
||||
|
@ -171,7 +176,7 @@ export default function ProcessModelShow() {
|
|||
|
||||
// Remove this code from
|
||||
const onDeleteFile = (fileName: string) => {
|
||||
const url = `/process-models/${params.process_group_id}/${params.process_model_id}/files/${fileName}`;
|
||||
const url = `/process-models/${modifiedProcessModelId}/files/${fileName}`;
|
||||
const httpMethod = 'DELETE';
|
||||
HttpService.makeCallToBackend({
|
||||
path: url,
|
||||
|
@ -181,7 +186,7 @@ export default function ProcessModelShow() {
|
|||
};
|
||||
|
||||
const onSetPrimaryFile = (fileName: string) => {
|
||||
const url = `/process-models/${params.process_group_id}/${params.process_model_id}`;
|
||||
const url = `/process-models/${modifiedProcessModelId}`;
|
||||
const httpMethod = 'PUT';
|
||||
|
||||
const processModelToPass = {
|
||||
|
@ -221,7 +226,7 @@ export default function ProcessModelShow() {
|
|||
|
||||
const downloadFile = (fileName: string) => {
|
||||
setErrorMessage(null);
|
||||
const processModelPath = `process-models/${params.process_group_id}/${params.process_model_id}`;
|
||||
const processModelPath = `process-models/${modifiedProcessModelId}`;
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/${processModelPath}/files/${fileName}`,
|
||||
successCallback: handleProcessModelFileResult,
|
||||
|
@ -232,11 +237,11 @@ export default function ProcessModelShow() {
|
|||
if (processModel) {
|
||||
if (processModelFile.name.match(/\.(dmn|bpmn)$/)) {
|
||||
navigate(
|
||||
`/admin/process-models/${processModel.process_group_id}/${processModel.id}/files/${processModelFile.name}`
|
||||
`/admin/process-models/${modifiedProcessModelId}/files/${processModelFile.name}`
|
||||
);
|
||||
} else if (processModelFile.name.match(/\.(json|md)$/)) {
|
||||
navigate(
|
||||
`/admin/process-models/${processModel.process_group_id}/${processModel.id}/form/${processModelFile.name}`
|
||||
`/admin/process-models/${modifiedProcessModelId}/form/${processModelFile.name}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -254,6 +259,7 @@ export default function ProcessModelShow() {
|
|||
iconDescription="Edit File"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
data-qa={`edit-file-${processModelFile.name.replace('.', '-')}`}
|
||||
onClick={() => navigateToFileEdit(processModelFile)}
|
||||
/>
|
||||
);
|
||||
|
@ -349,6 +355,9 @@ export default function ProcessModelShow() {
|
|||
};
|
||||
|
||||
const processInstancesUl = () => {
|
||||
const unmodifiedProcessModelId: String = unModifyProcessModelPath(
|
||||
`${params.process_model_id}`
|
||||
);
|
||||
if (!processModel) {
|
||||
return null;
|
||||
}
|
||||
|
@ -356,7 +365,7 @@ export default function ProcessModelShow() {
|
|||
<ul>
|
||||
<li>
|
||||
<Link
|
||||
to={`/admin/process-instances?process_group_identifier=${processModel.process_group_id}&process_model_identifier=${processModel.id}`}
|
||||
to={`/admin/process-instances?process_model_identifier=${unmodifiedProcessModelId}`}
|
||||
data-qa="process-instance-list-link"
|
||||
>
|
||||
List
|
||||
|
@ -364,7 +373,7 @@ export default function ProcessModelShow() {
|
|||
</li>
|
||||
<li>
|
||||
<Link
|
||||
to={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/process-instances/reports`}
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/reports`}
|
||||
data-qa="process-instance-reports-link"
|
||||
>
|
||||
Reports
|
||||
|
@ -381,7 +390,7 @@ export default function ProcessModelShow() {
|
|||
const handleFileUpload = (event: any) => {
|
||||
if (processModel) {
|
||||
event.preventDefault();
|
||||
const url = `/process-models/${processModel.process_group_id}/${processModel.id}/files`;
|
||||
const url = `/process-models/${modifiedProcessModelId}/files`;
|
||||
const formData = new FormData();
|
||||
formData.append('file', filesToUpload[0]);
|
||||
formData.append('fileName', filesToUpload[0].name);
|
||||
|
@ -432,6 +441,7 @@ export default function ProcessModelShow() {
|
|||
return (
|
||||
<Accordion>
|
||||
<AccordionItem
|
||||
data-qa="files-accordion"
|
||||
title={
|
||||
<Stack orientation="horizontal">
|
||||
<span>
|
||||
|
@ -454,28 +464,28 @@ export default function ProcessModelShow() {
|
|||
</Button>
|
||||
<Button
|
||||
renderIcon={Add}
|
||||
href={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/files?file_type=bpmn`}
|
||||
href={`/admin/process-models/${modifiedProcessModelId}/files?file_type=bpmn`}
|
||||
size="sm"
|
||||
>
|
||||
New BPMN File
|
||||
</Button>
|
||||
<Button
|
||||
renderIcon={Add}
|
||||
href={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/files?file_type=dmn`}
|
||||
href={`/admin/process-models/${modifiedProcessModelId}/files?file_type=dmn`}
|
||||
size="sm"
|
||||
>
|
||||
New DMN File
|
||||
</Button>
|
||||
<Button
|
||||
renderIcon={Add}
|
||||
href={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/form?file_ext=json`}
|
||||
href={`/admin/process-models/${modifiedProcessModelId}/form?file_ext=json`}
|
||||
size="sm"
|
||||
>
|
||||
New JSON File
|
||||
</Button>
|
||||
<Button
|
||||
renderIcon={Add}
|
||||
href={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/form?file_ext=md`}
|
||||
href={`/admin/process-models/${modifiedProcessModelId}/form?file_ext=md`}
|
||||
size="sm"
|
||||
>
|
||||
New Markdown File
|
||||
|
@ -493,17 +503,22 @@ export default function ProcessModelShow() {
|
|||
<>
|
||||
{fileUploadModal()}
|
||||
<ProcessBreadcrumb
|
||||
processGroupId={processModel.process_group_id}
|
||||
processModelId={processModel.id}
|
||||
hotCrumbs={[
|
||||
['Process Groups', '/admin'],
|
||||
[
|
||||
`Process Model: ${processModel.id}`,
|
||||
`process_model:${processModel.id}`,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
<h1>{processModel.display_name}</h1>
|
||||
<p>{processModel.description}</p>
|
||||
<h1>Process Model: {processModel.display_name}</h1>
|
||||
<p className="process-description">{processModel.description}</p>
|
||||
<Stack orientation="horizontal" gap={3}>
|
||||
<Button onClick={processInstanceCreateAndRun} variant="primary">
|
||||
Run
|
||||
</Button>
|
||||
<Button
|
||||
href={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/edit`}
|
||||
href={`/admin/process-models/${modifiedProcessModelId}/edit`}
|
||||
variant="secondary"
|
||||
>
|
||||
Edit process model
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Button, Modal } from '@carbon/react';
|
|||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import HttpService from '../services/HttpService';
|
||||
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
|
||||
import { modifyProcessModelPath } from '../helpers';
|
||||
|
||||
// NOTE: This is mostly the same as ProcessModelEditDiagram and if we go this route could
|
||||
// possibly be merged into it. I'm leaving as a separate file now in case it does
|
||||
|
@ -34,6 +35,10 @@ export default function ReactFormEditor() {
|
|||
|
||||
const editorDefaultLanguage = fileExtension === 'md' ? 'markdown' : 'json';
|
||||
|
||||
const modifiedProcessModelId = modifyProcessModelPath(
|
||||
`${params.process_model_id}`
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const processResult = (result: any) => {
|
||||
setProcessModelFile(result);
|
||||
|
@ -42,23 +47,23 @@ export default function ReactFormEditor() {
|
|||
|
||||
if (params.file_name) {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-models/${params.process_group_id}/${params.process_model_id}/files/${params.file_name}`,
|
||||
path: `/process-models/${modifiedProcessModelId}/files/${params.file_name}`,
|
||||
successCallback: processResult,
|
||||
});
|
||||
}
|
||||
}, [params]);
|
||||
}, [params, modifiedProcessModelId]);
|
||||
|
||||
const navigateToProcessModelFile = (_result: any) => {
|
||||
if (!params.file_name) {
|
||||
const fileNameWithExtension = `${newFileName}.${fileExtension}`;
|
||||
navigate(
|
||||
`/admin/process-models/${params.process_group_id}/${params.process_model_id}/form/${fileNameWithExtension}`
|
||||
`/admin/process-models/${modifiedProcessModelId}/form/${fileNameWithExtension}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const saveFile = () => {
|
||||
let url = `/process-models/${params.process_group_id}/${params.process_model_id}/files`;
|
||||
let url = `/process-models/${modifiedProcessModelId}/files`;
|
||||
let httpMethod = 'PUT';
|
||||
let fileNameWithExtension = params.file_name;
|
||||
|
||||
|
@ -90,13 +95,11 @@ export default function ReactFormEditor() {
|
|||
};
|
||||
|
||||
const deleteFile = () => {
|
||||
const url = `/process-models/${params.process_group_id}/${params.process_model_id}/files/${params.file_name}`;
|
||||
const url = `/process-models/${modifiedProcessModelId}/files/${params.file_name}`;
|
||||
const httpMethod = 'DELETE';
|
||||
|
||||
const navigateToProcessModelShow = (_httpResult: any) => {
|
||||
navigate(
|
||||
`/admin/process-models/${params.process_group_id}/${params.process_model_id}`
|
||||
);
|
||||
navigate(`/admin/process-models/${modifiedProcessModelId}`);
|
||||
};
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
|
@ -149,6 +152,14 @@ export default function ReactFormEditor() {
|
|||
processGroupId={params.process_group_id}
|
||||
processModelId={params.process_model_id}
|
||||
linkProcessModel
|
||||
hotCrumbs={[
|
||||
['Process Groups', '/admin'],
|
||||
[
|
||||
`Process Model: ${params.process_model_id}`,
|
||||
`process_model:${params.process_model_id}:link`,
|
||||
],
|
||||
[(processModelFile as any).name || ''],
|
||||
]}
|
||||
/>
|
||||
<h2>
|
||||
Process Model File
|
||||
|
|
Loading…
Reference in New Issue