mirror of
https://github.com/sartography/spiff-arena.git
synced 2025-01-26 17:29:13 +00:00
fixed editing task data and skipping tasks, moved task and task data methods from process_api_blueprint to tasks_controller, and updated to favor task_guid over task_id in some places
This commit is contained in:
parent
f45f2c1cc6
commit
77ae760586
@ -1590,7 +1590,7 @@ paths:
|
|||||||
- name: task_guid
|
- name: task_guid
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: The guid of the task to show.
|
description: The unique id of the task.
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
get:
|
get:
|
||||||
@ -1605,35 +1605,8 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Task"
|
$ref: "#/components/schemas/Task"
|
||||||
|
|
||||||
/task-data/{modified_process_model_identifier}/{process_instance_id}/{task_id}:
|
|
||||||
parameters:
|
|
||||||
- name: modified_process_model_identifier
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
description: The modified id of an existing process model
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- name: process_instance_id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
description: The unique id of an existing process instance.
|
|
||||||
schema:
|
|
||||||
type: integer
|
|
||||||
- name: task_id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
description: The unique id of the task.
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- name: task_guid
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
description: The guid of the task to show.
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
put:
|
put:
|
||||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.task_data_update
|
operationId: spiffworkflow_backend.routes.tasks_controller.task_data_update
|
||||||
summary: Update the task data for requested instance and task
|
summary: Update the task data for requested instance and task
|
||||||
tags:
|
tags:
|
||||||
- Process Instances
|
- Process Instances
|
||||||
@ -1738,7 +1711,7 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/Workflow"
|
$ref: "#/components/schemas/Workflow"
|
||||||
|
|
||||||
/task-complete/{modified_process_model_identifier}/{process_instance_id}/{task_id}:
|
/task-complete/{modified_process_model_identifier}/{process_instance_id}/{task_guid}:
|
||||||
parameters:
|
parameters:
|
||||||
- name: modified_process_model_identifier
|
- name: modified_process_model_identifier
|
||||||
in: path
|
in: path
|
||||||
@ -1752,14 +1725,14 @@ paths:
|
|||||||
description: The unique id of the process instance
|
description: The unique id of the process instance
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
- name: task_id
|
- name: task_guid
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: The unique id of the task.
|
description: The unique id of the task.
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
post:
|
post:
|
||||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.manual_complete_task
|
operationId: spiffworkflow_backend.routes.tasks_controller.manual_complete_task
|
||||||
summary: Mark a task complete without executing it
|
summary: Mark a task complete without executing it
|
||||||
tags:
|
tags:
|
||||||
- Process Instances
|
- Process Instances
|
||||||
@ -1838,9 +1811,9 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/ServiceTask"
|
$ref: "#/components/schemas/ServiceTask"
|
||||||
|
|
||||||
/tasks/{process_instance_id}/{task_id}:
|
/tasks/{process_instance_id}/{task_guid}:
|
||||||
parameters:
|
parameters:
|
||||||
- name: task_id
|
- name: task_guid
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: The unique id of an existing process group.
|
description: The unique id of an existing process group.
|
||||||
|
@ -16,15 +16,9 @@ from spiffworkflow_backend.exceptions.api_error import ApiError
|
|||||||
from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
|
from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
|
||||||
ProcessEntityNotFoundError,
|
ProcessEntityNotFoundError,
|
||||||
)
|
)
|
||||||
from spiffworkflow_backend.models.db import db
|
|
||||||
from spiffworkflow_backend.models.json_data import JsonDataModel
|
|
||||||
from spiffworkflow_backend.models.principal import PrincipalModel
|
from spiffworkflow_backend.models.principal import PrincipalModel
|
||||||
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 import (
|
|
||||||
ProcessInstanceTaskDataCannotBeUpdatedError,
|
|
||||||
)
|
|
||||||
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
|
|
||||||
from spiffworkflow_backend.models.process_instance_file_data import (
|
from spiffworkflow_backend.models.process_instance_file_data import (
|
||||||
ProcessInstanceFileDataModel,
|
ProcessInstanceFileDataModel,
|
||||||
)
|
)
|
||||||
@ -38,7 +32,6 @@ from spiffworkflow_backend.services.process_instance_processor import (
|
|||||||
ProcessInstanceProcessor,
|
ProcessInstanceProcessor,
|
||||||
)
|
)
|
||||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||||
from spiffworkflow_backend.services.task_service import TaskService
|
|
||||||
|
|
||||||
|
|
||||||
process_api_blueprint = Blueprint("process_api", __name__)
|
process_api_blueprint = Blueprint("process_api", __name__)
|
||||||
@ -169,60 +162,6 @@ def github_webhook_receive(body: Dict) -> Response:
|
|||||||
return Response(json.dumps({"git_pull": result}), status=200, mimetype="application/json")
|
return Response(json.dumps({"git_pull": result}), status=200, mimetype="application/json")
|
||||||
|
|
||||||
|
|
||||||
def task_data_update(
|
|
||||||
process_instance_id: str,
|
|
||||||
modified_process_model_identifier: str,
|
|
||||||
task_id: str,
|
|
||||||
body: Dict,
|
|
||||||
) -> Response:
|
|
||||||
"""Update task data."""
|
|
||||||
process_instance = ProcessInstanceModel.query.filter(ProcessInstanceModel.id == int(process_instance_id)).first()
|
|
||||||
if process_instance:
|
|
||||||
if process_instance.status != "suspended":
|
|
||||||
raise ProcessInstanceTaskDataCannotBeUpdatedError(
|
|
||||||
"The process instance needs to be suspended to update the task-data."
|
|
||||||
f" It is currently: {process_instance.status}"
|
|
||||||
)
|
|
||||||
|
|
||||||
task_model = TaskModel.query.filter_by(guid=task_id).first()
|
|
||||||
if task_model is None:
|
|
||||||
raise ApiError(
|
|
||||||
error_code="update_task_data_error",
|
|
||||||
message=f"Could not find Task: {task_id} in Instance: {process_instance_id}.",
|
|
||||||
)
|
|
||||||
|
|
||||||
if "new_task_data" in body:
|
|
||||||
new_task_data_str: str = body["new_task_data"]
|
|
||||||
new_task_data_dict = json.loads(new_task_data_str)
|
|
||||||
json_data_dict = TaskService.update_task_data_on_task_model(
|
|
||||||
task_model, new_task_data_dict, "json_data_hash"
|
|
||||||
)
|
|
||||||
if json_data_dict is not None:
|
|
||||||
json_data = JsonDataModel(**json_data_dict)
|
|
||||||
db.session.add(json_data)
|
|
||||||
ProcessInstanceProcessor.add_event_to_process_instance(
|
|
||||||
process_instance, ProcessInstanceEventType.task_data_edited.value, task_guid=task_id
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
db.session.commit()
|
|
||||||
except Exception as e:
|
|
||||||
db.session.rollback()
|
|
||||||
raise ApiError(
|
|
||||||
error_code="update_task_data_error",
|
|
||||||
message=f"Could not update the Instance. Original error is {e}",
|
|
||||||
) from e
|
|
||||||
else:
|
|
||||||
raise ApiError(
|
|
||||||
error_code="update_task_data_error",
|
|
||||||
message=f"Could not update task data for Instance: {process_instance_id}, and Task: {task_id}.",
|
|
||||||
)
|
|
||||||
return Response(
|
|
||||||
json.dumps(ProcessInstanceModelSchema().dump(process_instance)),
|
|
||||||
status=200,
|
|
||||||
mimetype="application/json",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _get_required_parameter_or_raise(parameter: str, post_body: dict[str, Any]) -> Any:
|
def _get_required_parameter_or_raise(parameter: str, post_body: dict[str, Any]) -> Any:
|
||||||
"""Get_required_parameter_or_raise."""
|
"""Get_required_parameter_or_raise."""
|
||||||
return_value = None
|
return_value = None
|
||||||
@ -263,30 +202,6 @@ def send_bpmn_event(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def manual_complete_task(
|
|
||||||
modified_process_model_identifier: str,
|
|
||||||
process_instance_id: str,
|
|
||||||
task_id: str,
|
|
||||||
body: Dict,
|
|
||||||
) -> Response:
|
|
||||||
"""Mark a task complete without executing it."""
|
|
||||||
execute = body.get("execute", True)
|
|
||||||
process_instance = ProcessInstanceModel.query.filter(ProcessInstanceModel.id == int(process_instance_id)).first()
|
|
||||||
if process_instance:
|
|
||||||
processor = ProcessInstanceProcessor(process_instance)
|
|
||||||
processor.manual_complete_task(task_id, execute)
|
|
||||||
else:
|
|
||||||
raise ApiError(
|
|
||||||
error_code="complete_task",
|
|
||||||
message=f"Could not complete Task {task_id} in Instance {process_instance_id}",
|
|
||||||
)
|
|
||||||
return Response(
|
|
||||||
json.dumps(ProcessInstanceModelSchema().dump(process_instance)),
|
|
||||||
status=200,
|
|
||||||
mimetype="application/json",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _commit_and_push_to_git(message: str) -> None:
|
def _commit_and_push_to_git(message: str) -> None:
|
||||||
"""Commit_and_push_to_git."""
|
"""Commit_and_push_to_git."""
|
||||||
if current_app.config["SPIFFWORKFLOW_BACKEND_GIT_COMMIT_ON_SAVE"]:
|
if current_app.config["SPIFFWORKFLOW_BACKEND_GIT_COMMIT_ON_SAVE"]:
|
||||||
|
@ -218,6 +218,7 @@ def process_instance_resume(
|
|||||||
try:
|
try:
|
||||||
processor.lock_process_instance("Web")
|
processor.lock_process_instance("Web")
|
||||||
processor.resume()
|
processor.resume()
|
||||||
|
processor.do_engine_steps(save=True)
|
||||||
except (ProcessInstanceIsNotEnqueuedError, ProcessInstanceIsAlreadyLockedError) as e:
|
except (ProcessInstanceIsNotEnqueuedError, ProcessInstanceIsAlreadyLockedError) as e:
|
||||||
ErrorHandlingService().handle_error(processor, e)
|
ErrorHandlingService().handle_error(processor, e)
|
||||||
raise e
|
raise e
|
||||||
|
@ -33,8 +33,14 @@ from spiffworkflow_backend.models.db import db
|
|||||||
from spiffworkflow_backend.models.group import GroupModel
|
from spiffworkflow_backend.models.group import GroupModel
|
||||||
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
|
||||||
|
from spiffworkflow_backend.models.json_data import JsonDataModel
|
||||||
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 ProcessInstanceStatus
|
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
|
||||||
|
from spiffworkflow_backend.models.process_instance import (
|
||||||
|
ProcessInstanceTaskDataCannotBeUpdatedError,
|
||||||
|
)
|
||||||
|
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType
|
||||||
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
from spiffworkflow_backend.models.process_model import ProcessModelInfo
|
||||||
from spiffworkflow_backend.models.task import Task
|
from spiffworkflow_backend.models.task import Task
|
||||||
from spiffworkflow_backend.models.task import TaskModel # noqa: F401
|
from spiffworkflow_backend.models.task import TaskModel # noqa: F401
|
||||||
@ -56,6 +62,7 @@ from spiffworkflow_backend.services.process_instance_service import (
|
|||||||
)
|
)
|
||||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||||
from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
||||||
|
from spiffworkflow_backend.services.task_service import TaskService
|
||||||
|
|
||||||
|
|
||||||
class TaskDataSelectOption(TypedDict):
|
class TaskDataSelectOption(TypedDict):
|
||||||
@ -182,24 +189,85 @@ def task_data_show(
|
|||||||
return make_response(jsonify(task_model), 200)
|
return make_response(jsonify(task_model), 200)
|
||||||
|
|
||||||
|
|
||||||
def _munge_form_ui_schema_based_on_hidden_fields_in_task_data(task: Task) -> None:
|
def task_data_update(
|
||||||
if task.form_ui_schema is None:
|
process_instance_id: str,
|
||||||
task.form_ui_schema = {}
|
modified_process_model_identifier: str,
|
||||||
|
task_guid: str,
|
||||||
|
body: Dict,
|
||||||
|
) -> Response:
|
||||||
|
"""Update task data."""
|
||||||
|
process_instance = ProcessInstanceModel.query.filter(ProcessInstanceModel.id == int(process_instance_id)).first()
|
||||||
|
if process_instance:
|
||||||
|
if process_instance.status != "suspended":
|
||||||
|
raise ProcessInstanceTaskDataCannotBeUpdatedError(
|
||||||
|
"The process instance needs to be suspended to update the task-data."
|
||||||
|
f" It is currently: {process_instance.status}"
|
||||||
|
)
|
||||||
|
|
||||||
if task.data and "form_ui_hidden_fields" in task.data:
|
task_model = TaskModel.query.filter_by(guid=task_guid).first()
|
||||||
hidden_fields = task.data["form_ui_hidden_fields"]
|
if task_model is None:
|
||||||
for hidden_field in hidden_fields:
|
raise ApiError(
|
||||||
hidden_field_parts = hidden_field.split(".")
|
error_code="update_task_data_error",
|
||||||
relevant_depth_of_ui_schema = task.form_ui_schema
|
message=f"Could not find Task: {task_guid} in Instance: {process_instance_id}.",
|
||||||
for ii, hidden_field_part in enumerate(hidden_field_parts):
|
)
|
||||||
if hidden_field_part not in relevant_depth_of_ui_schema:
|
|
||||||
relevant_depth_of_ui_schema[hidden_field_part] = {}
|
if "new_task_data" in body:
|
||||||
relevant_depth_of_ui_schema = relevant_depth_of_ui_schema[hidden_field_part]
|
new_task_data_str: str = body["new_task_data"]
|
||||||
if len(hidden_field_parts) == ii + 1:
|
new_task_data_dict = json.loads(new_task_data_str)
|
||||||
relevant_depth_of_ui_schema["ui:widget"] = "hidden"
|
json_data_dict = TaskService.update_task_data_on_task_model(
|
||||||
|
task_model, new_task_data_dict, "json_data_hash"
|
||||||
|
)
|
||||||
|
if json_data_dict is not None:
|
||||||
|
json_data = JsonDataModel(**json_data_dict)
|
||||||
|
db.session.add(json_data)
|
||||||
|
ProcessInstanceProcessor.add_event_to_process_instance(
|
||||||
|
process_instance, ProcessInstanceEventType.task_data_edited.value, task_guid=task_guid
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
raise ApiError(
|
||||||
|
error_code="update_task_data_error",
|
||||||
|
message=f"Could not update the Instance. Original error is {e}",
|
||||||
|
) from e
|
||||||
|
else:
|
||||||
|
raise ApiError(
|
||||||
|
error_code="update_task_data_error",
|
||||||
|
message=f"Could not update task data for Instance: {process_instance_id}, and Task: {task_guid}.",
|
||||||
|
)
|
||||||
|
return Response(
|
||||||
|
json.dumps(ProcessInstanceModelSchema().dump(process_instance)),
|
||||||
|
status=200,
|
||||||
|
mimetype="application/json",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response:
|
def manual_complete_task(
|
||||||
|
modified_process_model_identifier: str,
|
||||||
|
process_instance_id: str,
|
||||||
|
task_guid: str,
|
||||||
|
body: Dict,
|
||||||
|
) -> Response:
|
||||||
|
"""Mark a task complete without executing it."""
|
||||||
|
execute = body.get("execute", True)
|
||||||
|
process_instance = ProcessInstanceModel.query.filter(ProcessInstanceModel.id == int(process_instance_id)).first()
|
||||||
|
if process_instance:
|
||||||
|
processor = ProcessInstanceProcessor(process_instance)
|
||||||
|
processor.manual_complete_task(task_guid, execute)
|
||||||
|
else:
|
||||||
|
raise ApiError(
|
||||||
|
error_code="complete_task",
|
||||||
|
message=f"Could not complete Task {task_guid} in Instance {process_instance_id}",
|
||||||
|
)
|
||||||
|
return Response(
|
||||||
|
json.dumps(ProcessInstanceModelSchema().dump(process_instance)),
|
||||||
|
status=200,
|
||||||
|
mimetype="application/json",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def task_show(process_instance_id: int, task_guid: str) -> flask.wrappers.Response:
|
||||||
"""Task_show."""
|
"""Task_show."""
|
||||||
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
|
process_instance = _find_process_instance_by_id_or_raise(process_instance_id)
|
||||||
|
|
||||||
@ -214,12 +282,12 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response
|
|||||||
process_instance.process_model_identifier,
|
process_instance.process_model_identifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
_find_human_task_or_raise(process_instance_id, task_id)
|
_find_human_task_or_raise(process_instance_id, task_guid)
|
||||||
|
|
||||||
form_schema_file_name = ""
|
form_schema_file_name = ""
|
||||||
form_ui_schema_file_name = ""
|
form_ui_schema_file_name = ""
|
||||||
processor = ProcessInstanceProcessor(process_instance)
|
processor = ProcessInstanceProcessor(process_instance)
|
||||||
spiff_task = _get_spiff_task_from_process_instance(task_id, process_instance, processor=processor)
|
spiff_task = _get_spiff_task_from_process_instance(task_guid, process_instance, processor=processor)
|
||||||
extensions = spiff_task.task_spec.extensions
|
extensions = spiff_task.task_spec.extensions
|
||||||
|
|
||||||
if "properties" in extensions:
|
if "properties" in extensions:
|
||||||
@ -252,7 +320,8 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response
|
|||||||
ApiError(
|
ApiError(
|
||||||
error_code="missing_form_file",
|
error_code="missing_form_file",
|
||||||
message=(
|
message=(
|
||||||
f"Cannot find a form file for process_instance_id: {process_instance_id}, task_id: {task_id}"
|
f"Cannot find a form file for process_instance_id: {process_instance_id}, task_guid:"
|
||||||
|
f" {task_guid}"
|
||||||
),
|
),
|
||||||
status_code=400,
|
status_code=400,
|
||||||
)
|
)
|
||||||
@ -319,7 +388,7 @@ def process_data_show(
|
|||||||
|
|
||||||
def task_submit_shared(
|
def task_submit_shared(
|
||||||
process_instance_id: int,
|
process_instance_id: int,
|
||||||
task_id: str,
|
task_guid: str,
|
||||||
body: Dict[str, Any],
|
body: Dict[str, Any],
|
||||||
terminate_loop: bool = False,
|
terminate_loop: bool = False,
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
@ -336,7 +405,7 @@ def task_submit_shared(
|
|||||||
)
|
)
|
||||||
|
|
||||||
processor = ProcessInstanceProcessor(process_instance)
|
processor = ProcessInstanceProcessor(process_instance)
|
||||||
spiff_task = _get_spiff_task_from_process_instance(task_id, process_instance, processor=processor)
|
spiff_task = _get_spiff_task_from_process_instance(task_guid, process_instance, processor=processor)
|
||||||
AuthorizationService.assert_user_can_complete_spiff_task(process_instance.id, spiff_task, principal.user)
|
AuthorizationService.assert_user_can_complete_spiff_task(process_instance.id, spiff_task, principal.user)
|
||||||
|
|
||||||
if spiff_task.state != TaskState.READY:
|
if spiff_task.state != TaskState.READY:
|
||||||
@ -353,7 +422,7 @@ def task_submit_shared(
|
|||||||
|
|
||||||
human_task = _find_human_task_or_raise(
|
human_task = _find_human_task_or_raise(
|
||||||
process_instance_id=process_instance_id,
|
process_instance_id=process_instance_id,
|
||||||
task_id=task_id,
|
task_guid=task_guid,
|
||||||
only_tasks_that_can_be_completed=True,
|
only_tasks_that_can_be_completed=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -398,13 +467,13 @@ def task_submit_shared(
|
|||||||
|
|
||||||
def task_submit(
|
def task_submit(
|
||||||
process_instance_id: int,
|
process_instance_id: int,
|
||||||
task_id: str,
|
task_guid: str,
|
||||||
body: Dict[str, Any],
|
body: Dict[str, Any],
|
||||||
terminate_loop: bool = False,
|
terminate_loop: bool = False,
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Task_submit_user_data."""
|
"""Task_submit_user_data."""
|
||||||
with sentry_sdk.start_span(op="controller_action", description="tasks_controller.task_submit"):
|
with sentry_sdk.start_span(op="controller_action", description="tasks_controller.task_submit"):
|
||||||
return task_submit_shared(process_instance_id, task_id, body, terminate_loop)
|
return task_submit_shared(process_instance_id, task_guid, body, terminate_loop)
|
||||||
|
|
||||||
|
|
||||||
def _get_tasks(
|
def _get_tasks(
|
||||||
@ -559,14 +628,14 @@ def _render_jinja_template(unprocessed_template: str, spiff_task: SpiffTask) ->
|
|||||||
|
|
||||||
|
|
||||||
def _get_spiff_task_from_process_instance(
|
def _get_spiff_task_from_process_instance(
|
||||||
task_id: str,
|
task_guid: str,
|
||||||
process_instance: ProcessInstanceModel,
|
process_instance: ProcessInstanceModel,
|
||||||
processor: Union[ProcessInstanceProcessor, None] = None,
|
processor: Union[ProcessInstanceProcessor, None] = None,
|
||||||
) -> SpiffTask:
|
) -> SpiffTask:
|
||||||
"""Get_spiff_task_from_process_instance."""
|
"""Get_spiff_task_from_process_instance."""
|
||||||
if processor is None:
|
if processor is None:
|
||||||
processor = ProcessInstanceProcessor(process_instance)
|
processor = ProcessInstanceProcessor(process_instance)
|
||||||
task_uuid = uuid.UUID(task_id)
|
task_uuid = uuid.UUID(task_guid)
|
||||||
spiff_task = processor.bpmn_process_instance.get_task(task_uuid)
|
spiff_task = processor.bpmn_process_instance.get_task(task_uuid)
|
||||||
|
|
||||||
if spiff_task is None:
|
if spiff_task is None:
|
||||||
@ -658,15 +727,15 @@ def _get_potential_owner_usernames(assigned_user: AliasedClass) -> Any:
|
|||||||
|
|
||||||
def _find_human_task_or_raise(
|
def _find_human_task_or_raise(
|
||||||
process_instance_id: int,
|
process_instance_id: int,
|
||||||
task_id: str,
|
task_guid: str,
|
||||||
only_tasks_that_can_be_completed: bool = False,
|
only_tasks_that_can_be_completed: bool = False,
|
||||||
) -> HumanTaskModel:
|
) -> HumanTaskModel:
|
||||||
if only_tasks_that_can_be_completed:
|
if only_tasks_that_can_be_completed:
|
||||||
human_task_query = HumanTaskModel.query.filter_by(
|
human_task_query = HumanTaskModel.query.filter_by(
|
||||||
process_instance_id=process_instance_id, task_id=task_id, completed=False
|
process_instance_id=process_instance_id, task_id=task_guid, completed=False
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
human_task_query = HumanTaskModel.query.filter_by(process_instance_id=process_instance_id, task_id=task_id)
|
human_task_query = HumanTaskModel.query.filter_by(process_instance_id=process_instance_id, task_id=task_guid)
|
||||||
|
|
||||||
human_task: HumanTaskModel = human_task_query.first()
|
human_task: HumanTaskModel = human_task_query.first()
|
||||||
if human_task is None:
|
if human_task is None:
|
||||||
@ -674,10 +743,27 @@ def _find_human_task_or_raise(
|
|||||||
ApiError(
|
ApiError(
|
||||||
error_code="no_human_task",
|
error_code="no_human_task",
|
||||||
message=(
|
message=(
|
||||||
f"Cannot find a task to complete for task id '{task_id}' and"
|
f"Cannot find a task to complete for task id '{task_guid}' and"
|
||||||
f" process instance {process_instance_id}."
|
f" process instance {process_instance_id}."
|
||||||
),
|
),
|
||||||
status_code=500,
|
status_code=500,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return human_task
|
return human_task
|
||||||
|
|
||||||
|
|
||||||
|
def _munge_form_ui_schema_based_on_hidden_fields_in_task_data(task: Task) -> None:
|
||||||
|
if task.form_ui_schema is None:
|
||||||
|
task.form_ui_schema = {}
|
||||||
|
|
||||||
|
if task.data and "form_ui_hidden_fields" in task.data:
|
||||||
|
hidden_fields = task.data["form_ui_hidden_fields"]
|
||||||
|
for hidden_field in hidden_fields:
|
||||||
|
hidden_field_parts = hidden_field.split(".")
|
||||||
|
relevant_depth_of_ui_schema = task.form_ui_schema
|
||||||
|
for ii, hidden_field_part in enumerate(hidden_field_parts):
|
||||||
|
if hidden_field_part not in relevant_depth_of_ui_schema:
|
||||||
|
relevant_depth_of_ui_schema[hidden_field_part] = {}
|
||||||
|
relevant_depth_of_ui_schema = relevant_depth_of_ui_schema[hidden_field_part]
|
||||||
|
if len(hidden_field_parts) == ii + 1:
|
||||||
|
relevant_depth_of_ui_schema["ui:widget"] = "hidden"
|
||||||
|
@ -234,10 +234,11 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
return params.to_task_guid;
|
return params.to_task_guid;
|
||||||
};
|
};
|
||||||
|
|
||||||
const showingLastSpiffStep = () => {
|
// right now this just assume if to_task_guid was passed in then
|
||||||
return (
|
// this cannot be the active task.
|
||||||
processInstance && currentToTaskGuid() === processInstance.spiff_step
|
// we may need a better way to figure this out.
|
||||||
);
|
const showingActiveTask = () => {
|
||||||
|
return !params.to_task_guid;
|
||||||
};
|
};
|
||||||
|
|
||||||
const completionViewLink = (label: any, taskGuid: string) => {
|
const completionViewLink = (label: any, taskGuid: string) => {
|
||||||
@ -496,7 +497,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
const initializeTaskDataToDisplay = (task: Task | null) => {
|
const initializeTaskDataToDisplay = (task: Task | null) => {
|
||||||
if (
|
if (
|
||||||
task &&
|
task &&
|
||||||
task.state === 'COMPLETED' &&
|
(task.state === 'COMPLETED' || task.state === 'READY') &&
|
||||||
ability.can('GET', targetUris.processInstanceTaskDataPath)
|
ability.can('GET', targetUris.processInstanceTaskDataPath)
|
||||||
) {
|
) {
|
||||||
setShowTaskDataLoading(true);
|
setShowTaskDataLoading(true);
|
||||||
@ -624,7 +625,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
ability.can('PUT', targetUris.processInstanceTaskDataPath) &&
|
ability.can('PUT', targetUris.processInstanceTaskDataPath) &&
|
||||||
isActiveTask(task) &&
|
isActiveTask(task) &&
|
||||||
processInstance.status === 'suspended' &&
|
processInstance.status === 'suspended' &&
|
||||||
showingLastSpiffStep()
|
showingActiveTask()
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -637,7 +638,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
ability.can('POST', targetUris.processInstanceSendEventPath) &&
|
ability.can('POST', targetUris.processInstanceSendEventPath) &&
|
||||||
taskTypes.filter((t) => t === task.typename).length > 0 &&
|
taskTypes.filter((t) => t === task.typename).length > 0 &&
|
||||||
task.state === 'WAITING' &&
|
task.state === 'WAITING' &&
|
||||||
showingLastSpiffStep()
|
showingActiveTask()
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -647,18 +648,20 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
processInstance.status === 'suspended' &&
|
processInstance.status === 'suspended' &&
|
||||||
ability.can('POST', targetUris.processInstanceCompleteTaskPath) &&
|
ability.can('POST', targetUris.processInstanceCompleteTaskPath) &&
|
||||||
isActiveTask(task) &&
|
isActiveTask(task) &&
|
||||||
showingLastSpiffStep()
|
showingActiveTask()
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const canResetProcess = (task: Task) => {
|
const canResetProcess = (_task: Task) => {
|
||||||
return (
|
// disabling this feature for now
|
||||||
ability.can('POST', targetUris.processInstanceResetPath) &&
|
return false;
|
||||||
processInstance &&
|
// return (
|
||||||
processInstance.status === 'suspended' &&
|
// ability.can('POST', targetUris.processInstanceResetPath) &&
|
||||||
task.state === 'READY' &&
|
// processInstance &&
|
||||||
!showingLastSpiffStep()
|
// processInstance.status === 'suspended' &&
|
||||||
);
|
// task.state === 'READY' &&
|
||||||
|
// !showingActiveTask()
|
||||||
|
// );
|
||||||
};
|
};
|
||||||
|
|
||||||
const getEvents = (task: Task) => {
|
const getEvents = (task: Task) => {
|
||||||
@ -714,7 +717,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
// taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute
|
// taskToUse is copy of taskToDisplay, with taskDataToDisplay in data attribute
|
||||||
const taskToUse: Task = { ...taskToDisplay, data: taskDataToDisplay };
|
const taskToUse: Task = { ...taskToDisplay, data: taskDataToDisplay };
|
||||||
HttpService.makeCallToBackend({
|
HttpService.makeCallToBackend({
|
||||||
path: `${targetUris.processInstanceTaskDataPath}/${taskToUse.id}`,
|
path: `${targetUris.processInstanceTaskDataPath}/${taskToUse.guid}`,
|
||||||
httpMethod: 'PUT',
|
httpMethod: 'PUT',
|
||||||
successCallback: saveTaskDataResult,
|
successCallback: saveTaskDataResult,
|
||||||
failureCallback: addError,
|
failureCallback: addError,
|
||||||
@ -976,7 +979,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
): {taskToUse.state}
|
): {taskToUse.state}
|
||||||
{taskDisplayButtons(taskToUse)}
|
{taskDisplayButtons(taskToUse)}
|
||||||
</Stack>
|
</Stack>
|
||||||
{taskToUse.state == 'COMPLETED' ? (
|
{taskToUse.state === 'COMPLETED' ? (
|
||||||
<div>
|
<div>
|
||||||
<Stack orientation="horizontal" gap={2}>
|
<Stack orientation="horizontal" gap={2}>
|
||||||
{completionViewLink(
|
{completionViewLink(
|
||||||
@ -1031,15 +1034,8 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
|||||||
return elements;
|
return elements;
|
||||||
};
|
};
|
||||||
|
|
||||||
// right now this just assume if to_task_guid was passed in then
|
|
||||||
// this cannot be the active task.
|
|
||||||
// we may need a better way to figure this out.
|
|
||||||
const showingActiveTask = () => {
|
|
||||||
return !!params.to_task_guid;
|
|
||||||
};
|
|
||||||
|
|
||||||
const viewMostRecentStateComponent = () => {
|
const viewMostRecentStateComponent = () => {
|
||||||
if (!showingActiveTask()) {
|
if (showingActiveTask()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user