use consistent types for tasks in webui instance show page and mark the to task guid task as ready in backend

This commit is contained in:
jasquat 2023-03-21 10:45:10 -04:00
parent b1e9e8fabe
commit 8baa38d22b
3 changed files with 68 additions and 161 deletions

View File

@ -610,54 +610,6 @@ def process_instance_task_list(
most_recent_tasks_only: bool = False, most_recent_tasks_only: bool = False,
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_instance_task_list.""" """Process_instance_task_list."""
# step_detail_query = db.session.query(SpiffStepDetailsModel).filter(
# SpiffStepDetailsModel.process_instance_id == process_instance.id,
# )
#
# if spiff_step > 0:
# step_detail_query = step_detail_query.filter(SpiffStepDetailsModel.spiff_step <= spiff_step)
#
# step_details = step_detail_query.all()
#
# processor = ProcessInstanceProcessor(process_instance)
# full_bpmn_process_dict = processor.full_bpmn_process_dict
# tasks = full_bpmn_process_dict["tasks"]
# subprocesses = full_bpmn_process_dict["subprocesses"]
#
# steps_by_id = {step_detail.task_id: step_detail for step_detail in step_details}
#
# def restore_task(spiff_task: dict[str, Any], step_ended: float) -> None:
# if spiff_task["last_state_change"] > step_ended:
# spiff_task["state"] = Task.task_state_name_to_int("FUTURE")
# spiff_task["data"] = {}
#
# if spiff_step > 0:
# last_change = step_details[-1].end_in_seconds or 0
# for spiff_task in tasks.values():
# restore_task(spiff_task, last_change)
# for subprocess in subprocesses.values():
# for spiff_task in subprocess["tasks"].values():
# restore_task(spiff_task, last_change)
#
# bpmn_process_instance = ProcessInstanceProcessor._serializer.workflow_from_dict(full_bpmn_process_dict)
# if spiff_step > 0:
# bpmn_process_instance.complete_task_from_id(UUID(step_details[-1].task_id))
# for subprocess_id, subprocess in bpmn_process_instance.subprocesses.items():
# if not subprocess.is_completed():
# task = bpmn_process_instance.get_task(subprocess_id)
# task._set_state(TaskState.WAITING)
# guid: string;
# bpmn_identifier: string;
#
# bpmn_name?: string;
#
# state: string;
# typename: string;
# calling_subprocess_task_guid: string; -> bpmn_process_direct_parent_guid
# call_activity_process_bpmn_identifier?: string; -> bpmn_process_direct_parent_bpmn_identifier
bpmn_process_ids = [] bpmn_process_ids = []
if bpmn_process_guid: if bpmn_process_guid:
bpmn_process = BpmnProcessModel.query.filter_by(guid=bpmn_process_guid).first() bpmn_process = BpmnProcessModel.query.filter_by(guid=bpmn_process_guid).first()
@ -704,90 +656,24 @@ def process_instance_task_list(
TaskDefinitionModel.bpmn_name, TaskDefinitionModel.bpmn_name,
TaskDefinitionModel.typename, TaskDefinitionModel.typename,
TaskDefinitionModel.properties_json.label('task_definition_properties_json'), # type: ignore TaskDefinitionModel.properties_json.label('task_definition_properties_json'), # type: ignore
TaskModel.guid,
TaskModel.state,
) )
) )
if len(bpmn_process_ids) > 0: if len(bpmn_process_ids) > 0:
print(f"bpmn_process_ids: {bpmn_process_ids}")
task_model_query = ( task_model_query = (
task_model_query.filter(bpmn_process_alias.id.in_(bpmn_process_ids)) task_model_query.filter(bpmn_process_alias.id.in_(bpmn_process_ids))
) )
task_models = task_model_query.all() task_models = task_model_query.all()
# import pdb; pdb.set_trace()
# processor = ProcessInstanceProcessor(process_instance) if to_task_guid is not None:
# full_bpmn_process_dict = processor.full_bpmn_process_dict task_models_dict = json.loads(current_app.json.dumps(task_models))
# tasks = full_bpmn_process_dict["tasks"] for task_model in task_models_dict:
# subprocesses = full_bpmn_process_dict["subprocesses"] if task_model['guid'] == to_task_guid and task_model['state'] == "COMPLETED":
# task_model['state'] = "READY"
# steps_by_id = {step_detail.task_id: step_detail for step_detail in step_details} return make_response(jsonify(task_models_dict), 200)
#
# def restore_task(spiff_task: dict[str, Any], step_ended: float) -> None:
# if spiff_task["last_state_change"] > step_ended:
# spiff_task["state"] = Task.task_state_name_to_int("FUTURE")
# spiff_task["data"] = {}
#
# if spiff_step > 0:
# last_change = step_details[-1].end_in_seconds or 0
# for spiff_task in tasks.values():
# restore_task(spiff_task, last_change)
# for subprocess in subprocesses.values():
# for spiff_task in subprocess["tasks"].values():
# restore_task(spiff_task, last_change)
#
# bpmn_process_instance = ProcessInstanceProcessor._serializer.workflow_from_dict(full_bpmn_process_dict)
# if spiff_step > 0:
# bpmn_process_instance.complete_task_from_id(UUID(step_details[-1].task_id))
# for subprocess_id, subprocess in bpmn_process_instance.subprocesses.items():
# if not subprocess.is_completed():
# task = bpmn_process_instance.get_task(subprocess_id)
# task._set_state(TaskState.WAITING)
# spiff_tasks = None
# if all_tasks:
# spiff_tasks = bpmn_process_instance.get_tasks(TaskState.ANY_MASK)
# else:
# spiff_tasks = processor.get_all_user_tasks()
#
# (
# subprocesses_by_child_task_ids,
# task_typename_by_task_id,
# ) = processor.get_subprocesses_by_child_task_ids()
# processor.get_highest_level_calling_subprocesses_by_child_task_ids(
# subprocesses_by_child_task_ids, task_typename_by_task_id
# )
#
# spiff_tasks_to_process = spiff_tasks
# if most_recent_tasks_only:
# spiff_tasks_by_process_id_and_task_name: dict[str, SpiffTask] = {}
# current_tasks = {}
# for spiff_task in spiff_tasks_to_process:
# row_id = f"{spiff_task.task_spec._wf_spec.name}:{spiff_task.task_spec.name}"
# if spiff_task.state in [TaskState.READY, TaskState.WAITING]:
# current_tasks[row_id] = spiff_task
# if (
# row_id not in spiff_tasks_by_process_id_and_task_name
# or spiff_task.state > spiff_tasks_by_process_id_and_task_name[row_id].state
# ):
# spiff_tasks_by_process_id_and_task_name[row_id] = spiff_task
# spiff_tasks_by_process_id_and_task_name.update(current_tasks)
# spiff_tasks_to_process = spiff_tasks_by_process_id_and_task_name.values()
#
# response = []
# for spiff_task in spiff_tasks_to_process:
# task_spiff_step: Optional[int] = None
# if str(spiff_task.id) in steps_by_id:
# task_spiff_step = steps_by_id[str(spiff_task.id)].spiff_step
# calling_subprocess_task_id = subprocesses_by_child_task_ids.get(str(spiff_task.id), None)
# task = ProcessInstanceService.spiff_task_to_api_task(
# processor,
# spiff_task,
# calling_subprocess_task_id=calling_subprocess_task_id,
# task_spiff_step=task_spiff_step,
# )
# if task.state in ["MAYBE", "LIKELY"]:
# task.state = "FUTURE"
# response.append(task)
return make_response(jsonify(task_models), 200) return make_response(jsonify(task_models), 200)

View File

@ -21,10 +21,22 @@ export interface RecentProcessModel {
processModelDisplayName: string; processModelDisplayName: string;
} }
export interface TaskPropertiesJson {
parent: string;
}
export interface TaskDefinitionPropertiesJson { export interface TaskDefinitionPropertiesJson {
spec: string; spec: string;
} }
export interface EventDefinition {
typename: string;
payload: any;
event_definitions: [EventDefinition];
message_var?: string;
}
export interface Task { export interface Task {
id: number; id: number;
guid: string; guid: string;
@ -37,12 +49,20 @@ export interface Task {
data: any; data: any;
state: string; state: string;
typename: string; typename: string;
properties_json: TaskPropertiesJson;
task_definition_properties_json: TaskDefinitionPropertiesJson; task_definition_properties_json: TaskDefinitionPropertiesJson;
event_definition?: EventDefinition;
// TOOD: DELETE THIS! // TOOD: DELETE THIS!
task_spiff_step?: number; task_spiff_step?: number;
} }
export interface TaskIds {
completed: Task[];
readyOrWaiting: Task[];
}
export interface ProcessInstanceTask { export interface ProcessInstanceTask {
id: string; id: string;
task_id: string; task_id: string;

View File

@ -42,12 +42,14 @@ import {
import ButtonWithConfirmation from '../components/ButtonWithConfirmation'; import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
import { useUriListForPermissions } from '../hooks/UriListForPermissions'; import { useUriListForPermissions } from '../hooks/UriListForPermissions';
import { import {
EventDefinition,
PermissionsToCheck, PermissionsToCheck,
ProcessData, ProcessData,
ProcessInstance, ProcessInstance,
ProcessInstanceMetadata, ProcessInstanceMetadata,
Task, Task,
TaskDefinitionPropertiesJson, TaskDefinitionPropertiesJson,
TaskIds,
} from '../interfaces'; } from '../interfaces';
import { usePermissionFetcher } from '../hooks/PermissionService'; import { usePermissionFetcher } from '../hooks/PermissionService';
import ProcessInstanceClass from '../classes/ProcessInstanceClass'; import ProcessInstanceClass from '../classes/ProcessInstanceClass';
@ -215,14 +217,14 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
}; };
const getTaskIds = () => { const getTaskIds = () => {
const taskIds = { completed: [], readyOrWaiting: [] }; const taskIds: TaskIds = { completed: [], readyOrWaiting: [] };
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 as any).push(task); taskIds.completed.push(task);
} }
if (task.state === 'READY' || task.state === 'WAITING') { if (task.state === 'READY' || task.state === 'WAITING') {
(taskIds.readyOrWaiting as any).push(task); taskIds.readyOrWaiting.push(task);
} }
return null; return null;
}); });
@ -230,20 +232,14 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
return taskIds; return taskIds;
}; };
const currentSpiffStep = () => { const currentToTaskGuid = () => {
if (processInstance && typeof params.to_task_guid === 'undefined') { return params.to_task_guid;
return processInstance.spiff_step || 0;
}
return Number(params.spiff_step);
};
const showingFirstSpiffStep = () => {
return currentSpiffStep() === 1;
}; };
const showingLastSpiffStep = () => { const showingLastSpiffStep = () => {
return processInstance && currentSpiffStep() === processInstance.spiff_step; return (
processInstance && currentToTaskGuid() === processInstance.spiff_step
);
}; };
const completionViewLink = (label: any, taskGuid: string) => { const completionViewLink = (label: any, taskGuid: string) => {
@ -278,7 +274,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
const resetProcessInstance = () => { const resetProcessInstance = () => {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `${targetUris.processInstanceResetPath}/${currentSpiffStep()}`, path: `${targetUris.processInstanceResetPath}/${currentToTaskGuid()}`,
successCallback: returnToLastSpiffStep, successCallback: returnToLastSpiffStep,
httpMethod: 'POST', httpMethod: 'POST',
}); });
@ -580,7 +576,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
const getTaskById = (taskId: string) => { const getTaskById = (taskId: string) => {
if (tasks !== null) { if (tasks !== null) {
return tasks.find((task: any) => task.id === taskId); return tasks.find((task: Task) => task.guid === taskId) || null;
} }
return null; return null;
}; };
@ -589,24 +585,29 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
console.log('result', result); console.log('result', result);
}; };
const getParentTaskFromTask = (task: Task) => {
return task.properties_json.parent;
};
const createScriptUnitTest = () => { const createScriptUnitTest = () => {
if (taskToDisplay) { if (taskToDisplay) {
const taskToUse: any = taskToDisplay; const previousTask: Task | null = getTaskById(
const previousTask: any = getTaskById(taskToUse.parent); getParentTaskFromTask(taskToDisplay)
);
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-models/${modifiedProcessModelId}/script-unit-tests`, path: `/process-models/${modifiedProcessModelId}/script-unit-tests`,
httpMethod: 'POST', httpMethod: 'POST',
successCallback: processScriptUnitTestCreateResult, successCallback: processScriptUnitTestCreateResult,
postBody: { postBody: {
bpmn_task_identifier: taskToUse.bpmn_identifier, bpmn_task_identifier: taskToDisplay.bpmn_identifier,
input_json: previousTask.data, input_json: previousTask ? previousTask.data : '',
expected_output_json: taskToUse.data, expected_output_json: taskToDisplay.data,
}, },
}); });
} }
}; };
const isCurrentTask = (task: any) => { const isCurrentTask = (task: Task) => {
const subprocessTypes = [ const subprocessTypes = [
'Subprocess', 'Subprocess',
'Call Activity', 'Call Activity',
@ -619,7 +620,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
); );
}; };
const canEditTaskData = (task: any) => { const canEditTaskData = (task: Task) => {
return ( return (
processInstance && processInstance &&
ability.can('PUT', targetUris.processInstanceTaskDataPath) && ability.can('PUT', targetUris.processInstanceTaskDataPath) &&
@ -629,7 +630,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
); );
}; };
const canSendEvent = (task: any) => { const canSendEvent = (task: Task) => {
// We actually could allow this for any waiting events // We actually could allow this for any waiting events
const taskTypes = ['Event Based Gateway']; const taskTypes = ['Event Based Gateway'];
return ( return (
@ -642,7 +643,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
); );
}; };
const canCompleteTask = (task: any) => { const canCompleteTask = (task: Task) => {
return ( return (
processInstance && processInstance &&
processInstance.status === 'suspended' && processInstance.status === 'suspended' &&
@ -652,7 +653,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
); );
}; };
const canResetProcess = (task: any) => { const canResetProcess = (task: Task) => {
return ( return (
ability.can('POST', targetUris.processInstanceResetPath) && ability.can('POST', targetUris.processInstanceResetPath) &&
processInstance && processInstance &&
@ -662,8 +663,8 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
); );
}; };
const getEvents = (task: any) => { const getEvents = (task: Task) => {
const handleMessage = (eventDefinition: any) => { const handleMessage = (eventDefinition: EventDefinition) => {
if (eventDefinition.typename === 'MessageEventDefinition') { if (eventDefinition.typename === 'MessageEventDefinition') {
const newEvent = eventDefinition; const newEvent = eventDefinition;
delete newEvent.message_var; delete newEvent.message_var;
@ -673,7 +674,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
return eventDefinition; return eventDefinition;
}; };
if (task.event_definition && task.event_definition.event_definitions) if (task.event_definition && task.event_definition.event_definitions)
return task.event_definition.event_definitions.map((e: any) => return task.event_definition.event_definitions.map((e: EventDefinition) =>
handleMessage(e) handleMessage(e)
); );
if (task.event_definition) return [handleMessage(task.event_definition)]; if (task.event_definition) return [handleMessage(task.event_definition)];
@ -710,11 +711,10 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
if (!taskToDisplay) { if (!taskToDisplay) {
return; return;
} }
console.log('saveTaskData');
removeError(); removeError();
// taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute // taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute
const taskToUse: any = { ...taskToDisplay, data: taskDataToDisplay }; const taskToUse: Task = { ...taskToDisplay, data: taskDataToDisplay };
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `${targetUris.processInstanceTaskDataPath}/${taskToUse.id}`, path: `${targetUris.processInstanceTaskDataPath}/${taskToUse.id}`,
httpMethod: 'PUT', httpMethod: 'PUT',
@ -739,13 +739,14 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
}; };
const completeTask = (execute: boolean) => { const completeTask = (execute: boolean) => {
const taskToUse: any = taskToDisplay; if (taskToDisplay) {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/task-complete/${modifiedProcessModelId}/${params.process_instance_id}/${taskToUse.id}`, path: `/task-complete/${modifiedProcessModelId}/${params.process_instance_id}/${taskToDisplay.guid}`,
httpMethod: 'POST', httpMethod: 'POST',
successCallback: returnToLastSpiffStep, successCallback: returnToLastSpiffStep,
postBody: { execute }, postBody: { execute },
}); });
}
}; };
const taskDisplayButtons = (task: Task) => { const taskDisplayButtons = (task: Task) => {