Merge remote-tracking branch 'origin/main' into feature/home_page_refactor

This commit is contained in:
jasquat 2023-04-14 09:20:30 -04:00
commit 0aa0698557
No known key found for this signature in database
6 changed files with 69 additions and 15 deletions

View File

@ -1916,7 +1916,7 @@ lxml = "*"
type = "git" type = "git"
url = "https://github.com/sartography/SpiffWorkflow" url = "https://github.com/sartography/SpiffWorkflow"
reference = "main" reference = "main"
resolved_reference = "98a1b37e01a00faea60025f517a89867b7261432" resolved_reference = "162a1c5f56cf12fc589a1e368704c0819bfcc0cd"
[[package]] [[package]]
name = "sqlalchemy" name = "sqlalchemy"

View File

@ -18,7 +18,9 @@ from sqlalchemy.orm import aliased
from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.exceptions.api_error import ApiError
from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel
from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel from spiffworkflow_backend.models.bpmn_process_definition import (
BpmnProcessDefinitionModel,
)
from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.human_task import HumanTaskModel from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel
@ -28,7 +30,9 @@ from spiffworkflow_backend.models.process_instance import (
) )
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModelSchema from spiffworkflow_backend.models.process_instance import ProcessInstanceModelSchema
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventModel from spiffworkflow_backend.models.process_instance_event import (
ProcessInstanceEventModel,
)
from spiffworkflow_backend.models.process_instance_metadata import ( from spiffworkflow_backend.models.process_instance_metadata import (
ProcessInstanceMetadataModel, ProcessInstanceMetadataModel,
) )
@ -168,7 +172,10 @@ def process_instance_terminate(
try: try:
with ProcessInstanceQueueService.dequeued(process_instance): with ProcessInstanceQueueService.dequeued(process_instance):
processor.terminate() processor.terminate()
except (ProcessInstanceIsNotEnqueuedError, ProcessInstanceIsAlreadyLockedError) as e: except (
ProcessInstanceIsNotEnqueuedError,
ProcessInstanceIsAlreadyLockedError,
) as e:
ErrorHandlingService().handle_error(processor, e) ErrorHandlingService().handle_error(processor, e)
raise e raise e
@ -186,7 +193,10 @@ def process_instance_suspend(
try: try:
with ProcessInstanceQueueService.dequeued(process_instance): with ProcessInstanceQueueService.dequeued(process_instance):
processor.suspend() processor.suspend()
except (ProcessInstanceIsNotEnqueuedError, ProcessInstanceIsAlreadyLockedError) as e: except (
ProcessInstanceIsNotEnqueuedError,
ProcessInstanceIsAlreadyLockedError,
) as e:
ErrorHandlingService().handle_error(processor, e) ErrorHandlingService().handle_error(processor, e)
raise e raise e
@ -204,7 +214,10 @@ def process_instance_resume(
try: try:
with ProcessInstanceQueueService.dequeued(process_instance): with ProcessInstanceQueueService.dequeued(process_instance):
processor.resume() processor.resume()
except (ProcessInstanceIsNotEnqueuedError, ProcessInstanceIsAlreadyLockedError) as e: except (
ProcessInstanceIsNotEnqueuedError,
ProcessInstanceIsAlreadyLockedError,
) as e:
ErrorHandlingService().handle_error(processor, e) ErrorHandlingService().handle_error(processor, e)
raise e raise e
@ -227,7 +240,8 @@ def process_instance_log_list(
.outerjoin(TaskModel, TaskModel.guid == ProcessInstanceEventModel.task_guid) .outerjoin(TaskModel, TaskModel.guid == ProcessInstanceEventModel.task_guid)
.outerjoin(TaskDefinitionModel, TaskDefinitionModel.id == TaskModel.task_definition_id) .outerjoin(TaskDefinitionModel, TaskDefinitionModel.id == TaskModel.task_definition_id)
.outerjoin( .outerjoin(
BpmnProcessDefinitionModel, BpmnProcessDefinitionModel.id == TaskDefinitionModel.bpmn_process_definition_id BpmnProcessDefinitionModel,
BpmnProcessDefinitionModel.id == TaskDefinitionModel.bpmn_process_definition_id,
) )
) )
if not detailed: if not detailed:
@ -374,7 +388,9 @@ def process_instance_list(
return make_response(jsonify(response_json), 200) return make_response(jsonify(response_json), 200)
def process_instance_report_column_list(process_model_identifier: Optional[str] = None) -> flask.wrappers.Response: def process_instance_report_column_list(
process_model_identifier: Optional[str] = None,
) -> flask.wrappers.Response:
"""Process_instance_report_column_list.""" """Process_instance_report_column_list."""
table_columns = ProcessInstanceReportService.builtin_column_options() table_columns = ProcessInstanceReportService.builtin_column_options()
columns_for_metadata_query = ( columns_for_metadata_query = (
@ -646,7 +662,8 @@ def process_instance_task_list(
== direct_parent_bpmn_process_alias.bpmn_process_definition_id, == direct_parent_bpmn_process_alias.bpmn_process_definition_id,
) )
.join( .join(
BpmnProcessDefinitionModel, BpmnProcessDefinitionModel.id == TaskDefinitionModel.bpmn_process_definition_id BpmnProcessDefinitionModel,
BpmnProcessDefinitionModel.id == TaskDefinitionModel.bpmn_process_definition_id,
) )
.add_columns( .add_columns(
BpmnProcessDefinitionModel.bpmn_identifier.label("bpmn_process_definition_identifier"), # type: ignore BpmnProcessDefinitionModel.bpmn_identifier.label("bpmn_process_definition_identifier"), # type: ignore
@ -672,14 +689,22 @@ def process_instance_task_list(
task_model_query = task_model_query.filter(bpmn_process_alias.id.in_(bpmn_process_ids)) task_model_query = task_model_query.filter(bpmn_process_alias.id.in_(bpmn_process_ids))
task_models = task_model_query.all() task_models = task_model_query.all()
task_model_list = {}
if most_recent_tasks_only: if most_recent_tasks_only:
most_recent_tasks = {}
most_recent_subprocesses = set()
for task_model in task_models: for task_model in task_models:
bpmn_process_guid = task_model.bpmn_process_guid or "TOP" bpmn_process_guid = task_model.bpmn_process_guid or "TOP"
row_key = f"{bpmn_process_guid}:::{task_model.bpmn_identifier}" row_key = f"{bpmn_process_guid}:::{task_model.bpmn_identifier}"
if row_key not in task_model_list: if row_key not in most_recent_tasks:
task_model_list[row_key] = task_model most_recent_tasks[row_key] = task_model
task_models = list(task_model_list.values()) if task_model.typename in ["SubWorkflowTask", "CallActivity"]:
most_recent_subprocesses.add(task_model.guid)
task_models = [
task_model
for task_model in most_recent_tasks.values()
if task_model.bpmn_process_guid in most_recent_subprocesses or task_model.bpmn_process_guid is None
]
if to_task_model is not None: if to_task_model is not None:
task_models_dict = json.loads(current_app.json.dumps(task_models)) task_models_dict = json.loads(current_app.json.dumps(task_models))

View File

@ -68,6 +68,7 @@ type OwnProps = {
diagramType: string; diagramType: string;
readyOrWaitingProcessInstanceTasks?: Task[] | null; readyOrWaitingProcessInstanceTasks?: Task[] | null;
completedProcessInstanceTasks?: Task[] | null; completedProcessInstanceTasks?: Task[] | null;
cancelledProcessInstanceTasks?: Task[] | null;
saveDiagram?: (..._args: any[]) => any; saveDiagram?: (..._args: any[]) => any;
onDeleteFile?: (..._args: any[]) => any; onDeleteFile?: (..._args: any[]) => any;
isPrimaryFile?: boolean; isPrimaryFile?: boolean;
@ -94,6 +95,7 @@ export default function ReactDiagramEditor({
diagramType, diagramType,
readyOrWaitingProcessInstanceTasks, readyOrWaitingProcessInstanceTasks,
completedProcessInstanceTasks, completedProcessInstanceTasks,
cancelledProcessInstanceTasks,
saveDiagram, saveDiagram,
onDeleteFile, onDeleteFile,
isPrimaryFile, isPrimaryFile,
@ -358,7 +360,8 @@ export default function ReactDiagramEditor({
function checkTaskCanBeHighlighted(taskBpmnId: string) { function checkTaskCanBeHighlighted(taskBpmnId: string) {
return ( return (
!taskSpecsThatCannotBeHighlighted.includes(taskBpmnId) && !taskSpecsThatCannotBeHighlighted.includes(taskBpmnId) &&
!taskBpmnId.match(/EndJoin/) !taskBpmnId.match(/EndJoin/) &&
!taskBpmnId.match(/BoundaryEventParent/)
); );
} }
@ -441,6 +444,19 @@ export default function ReactDiagramEditor({
); );
}); });
} }
if (cancelledProcessInstanceTasks) {
const bpmnProcessIdentifiers = getBpmnProcessIdentifiers(
canvas.getRootElement()
);
cancelledProcessInstanceTasks.forEach((cancelledTask) => {
highlightBpmnIoElement(
canvas,
cancelledTask,
'cancelled-task-highlight',
bpmnProcessIdentifiers
);
});
}
} }
function displayDiagram( function displayDiagram(
@ -518,6 +534,7 @@ export default function ReactDiagramEditor({
diagramXMLString, diagramXMLString,
readyOrWaitingProcessInstanceTasks, readyOrWaitingProcessInstanceTasks,
completedProcessInstanceTasks, completedProcessInstanceTasks,
cancelledProcessInstanceTasks,
fileName, fileName,
performingXmlUpdates, performingXmlUpdates,
processModelId, processModelId,

View File

@ -142,6 +142,10 @@ code {
fill: grey !important; fill: grey !important;
opacity: .4; opacity: .4;
} }
.cancelled-task-highlight:not(.djs-connection) .djs-visual > :nth-child(1) {
fill: blue !important;
opacity: .2;
}
.accordion-item-label { .accordion-item-label {
vertical-align: middle; vertical-align: middle;

View File

@ -58,6 +58,7 @@ export interface Task {
export interface TaskIds { export interface TaskIds {
completed: Task[]; completed: Task[];
readyOrWaiting: Task[]; readyOrWaiting: Task[];
cancelled: Task[];
} }
export interface ProcessInstanceTask { export interface ProcessInstanceTask {

View File

@ -231,13 +231,19 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
}; };
const getTaskIds = () => { const getTaskIds = () => {
const taskIds: TaskIds = { completed: [], readyOrWaiting: [] }; const taskIds: TaskIds = {
completed: [],
readyOrWaiting: [],
cancelled: [],
};
if (tasks) { if (tasks) {
tasks.forEach(function getUserTasksElement(task: Task) { tasks.forEach(function getUserTasksElement(task: Task) {
if (task.state === 'COMPLETED') { if (task.state === 'COMPLETED') {
taskIds.completed.push(task); taskIds.completed.push(task);
} else if (task.state === 'READY' || task.state === 'WAITING') { } else if (task.state === 'READY' || task.state === 'WAITING') {
taskIds.readyOrWaiting.push(task); taskIds.readyOrWaiting.push(task);
} else if (task.state === 'CANCELLED') {
taskIds.cancelled.push(task);
} }
return null; return null;
}); });
@ -1152,6 +1158,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
fileName={processInstance.bpmn_xml_file_contents || ''} fileName={processInstance.bpmn_xml_file_contents || ''}
readyOrWaitingProcessInstanceTasks={taskIds.readyOrWaiting} readyOrWaitingProcessInstanceTasks={taskIds.readyOrWaiting}
completedProcessInstanceTasks={taskIds.completed} completedProcessInstanceTasks={taskIds.completed}
cancelledProcessInstanceTasks={taskIds.cancelled}
diagramType="readonly" diagramType="readonly"
onElementClick={handleClickedDiagramTask} onElementClick={handleClickedDiagramTask}
/> />