Fix that dreadful unknown "KeyError" exception that was cropping up.

Adding a bit of detail to the spiffworkflow exceptions when a duplicate process model is found.
Disable the submit button on tasks after you click submit (avoid the double click and give users a better experience)
This commit is contained in:
Dan 2023-02-03 17:01:03 -05:00
parent cd7c109a00
commit d010c2bce6
5 changed files with 31 additions and 13 deletions

View File

@ -48,7 +48,7 @@ from .task_parsers import (
GatewayParser,
ConditionalGatewayParser,
CallActivityParser,
ScriptTaskParser,
ScriptTaskParser,
SubWorkflowParser,
)
from .event_parsers import (
@ -254,9 +254,9 @@ class BpmnParser(object):
def create_parser(self, node, filename=None, lane=None):
parser = self.PROCESS_PARSER_CLASS(self, node, self.namespaces, filename=filename, lane=lane)
if parser.get_id() in self.process_parsers:
raise ValidationException('Duplicate process ID', node=node, file_name=filename)
raise ValidationException(f'Duplicate process ID: {parser.get_id()}', node=node, file_name=filename)
if parser.get_name() in self.process_parsers_by_name:
raise ValidationException('Duplicate process name', node=node, file_name=filename)
raise ValidationException(f'Duplicate process name: {parser.get_name()}', node=node, file_name=filename)
self.process_parsers[parser.get_id()] = parser
self.process_parsers_by_name[parser.get_name()] = parser

View File

@ -242,6 +242,10 @@ def handle_exception(exception: Exception) -> flask.wrappers.Response:
api_exception = None
if isinstance(exception, ApiError):
api_exception = exception
elif isinstance(exception, SpiffWorkflowException):
api_exception = ApiError.from_workflow_exception(
"unexpected_workflow_exception", "Unexpected Workflow Error", exception
)
else:
api_exception = ApiError(
error_code=error_code,

View File

@ -275,7 +275,7 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response
) from exception
if task.data:
_update_form_schema_with_task_data_as_needed(form_dict, task)
_update_form_schema_with_task_data_as_needed(form_dict, task, spiff_task)
if form_contents:
task.form_schema = form_dict
@ -588,7 +588,9 @@ def _get_spiff_task_from_process_instance(
# originally from: https://bitcoden.com/answers/python-nested-dictionary-update-value-where-any-nested-key-matches
def _update_form_schema_with_task_data_as_needed(in_dict: dict, task: Task) -> None:
def _update_form_schema_with_task_data_as_needed(
in_dict: dict, task: Task, spiff_task: SpiffTask
) -> None:
"""Update_nested."""
if task.data is None:
return None
@ -615,7 +617,7 @@ def _update_form_schema_with_task_data_as_needed(in_dict: dict, task: Task) -> N
f" '{task_data_var}' but it doesn't exist in"
" the Task Data."
),
task=task,
task=spiff_task,
)
raise (
ApiError.from_workflow_exception(
@ -648,11 +650,11 @@ def _update_form_schema_with_task_data_as_needed(in_dict: dict, task: Task) -> N
in_dict[k] = options_for_react_json_schema_form
elif isinstance(value, dict):
_update_form_schema_with_task_data_as_needed(value, task)
_update_form_schema_with_task_data_as_needed(value, task, spiff_task)
elif isinstance(value, list):
for o in value:
if isinstance(o, dict):
_update_form_schema_with_task_data_as_needed(o, task)
_update_form_schema_with_task_data_as_needed(o, task, spiff_task)
def _get_potential_owner_usernames(assigned_user: AliasedClass) -> Any:

View File

@ -499,7 +499,10 @@ class ProcessModelService(FileSystemService):
if name is None:
raise ApiError(
error_code="missing_name_of_process_model",
message="Missing name of process model. It should be given",
message=(
"Missing name of process model. Path not found:"
f" {json_file_path}"
),
)
process_model_info = ProcessModelInfo(

View File

@ -41,7 +41,10 @@ export default function TaskShow() {
// instead of passing the process model identifier in through the params
HttpService.makeCallToBackend({
path: url,
successCallback: setUserTasks,
successCallback: (tasks: any) => {
setDisabled(false);
setUserTasks(tasks);
},
onUnauthorized: () => {},
failureCallback: (error: any) => {
addError(error);
@ -59,7 +62,6 @@ export default function TaskShow() {
const processSubmitResult = (result: any) => {
removeError();
setDisabled(false);
if (result.ok) {
navigate(`/tasks`);
} else if (result.process_instance_id) {
@ -212,10 +214,16 @@ export default function TaskShow() {
reactFragmentToHideSubmitButton = <div />;
}
if (task.type === 'Manual Task' && task.state === 'READY') {
if (task.state === 'READY') {
let buttonText = 'Submit';
if (task.type === 'Manual Task') {
buttonText = 'Continue';
}
reactFragmentToHideSubmitButton = (
<div>
<Button type="submit">Continue</Button>
<Button type="submit" disabled={disabled}>
{buttonText}
</Button>
</div>
);
}
@ -228,6 +236,7 @@ export default function TaskShow() {
<Grid fullWidth condensed>
<Column sm={4} md={5} lg={8}>
<Form
disabled={disabled}
formData={taskData}
onSubmit={handleFormSubmit}
schema={jsonSchema}