Merge pull request #69 from sartography/feature/api_permission_cleanup

Feature/api permission cleanup
This commit is contained in:
Kevin Burnett 2022-12-06 13:13:00 -08:00 committed by GitHub
commit 9454ee332a
23 changed files with 342 additions and 214 deletions

View File

@ -338,9 +338,9 @@ paths:
schema: schema:
$ref: "#/components/schemas/ProcessModel" $ref: "#/components/schemas/ProcessModel"
/process-models/{modified_process_model_id}/files: /process-models/{modified_process_model_identifier}/files:
parameters: parameters:
- name: modified_process_model_id - name: modified_process_model_identifier
in: path in: path
required: true required: true
description: The process_model_id, modified to replace slashes (/) description: The process_model_id, modified to replace slashes (/)
@ -565,33 +565,6 @@ paths:
items: items:
$ref: "#/components/schemas/Workflow" $ref: "#/components/schemas/Workflow"
/process-instances/{process_instance_id}/task/{task_id}/update:
parameters:
- name: process_instance_id
in: path
required: true
description: The unique id of the process instance
schema:
type: string
- name: task_id
in: path
required: true
description: The unique id of the task
schema:
type: string
post:
operationId: spiffworkflow_backend.routes.process_api_blueprint.update_task_data
summary: Update the task data for requested instance and task
tags:
- Process Instances
responses:
"200":
description: Task Updated Successfully
content:
application/json:
schema:
$ref: "#/components/schemas/Workflow"
/process-models/{process_group_id}/{process_model_id}/script-unit-tests: /process-models/{process_group_id}/{process_model_id}/script-unit-tests:
parameters: parameters:
- name: process_group_id - name: process_group_id
@ -646,15 +619,14 @@ paths:
schema: schema:
$ref: "#/components/schemas/Workflow" $ref: "#/components/schemas/Workflow"
/process-models/{modified_process_model_id}/process-instances: /process-instances/{modified_process_model_identifier}:
parameters: parameters:
- name: modified_process_model_id - name: modified_process_model_identifier
in: path in: path
required: true required: true
description: The unique id of an existing process model. description: The unique id of an existing process model.
schema: schema:
type: string type: string
# process_instance_create
post: post:
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_create operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_create
summary: Creates an process instance from a process model and returns the instance summary: Creates an process instance from a process model and returns the instance
@ -668,28 +640,7 @@ paths:
schema: schema:
$ref: "#/components/schemas/Workflow" $ref: "#/components/schemas/Workflow"
/process-instances/{process_instance_id}: /process-instances/{modified_process_model_identifier}/{process_instance_id}:
parameters:
- name: process_instance_id
in: path
required: true
description: The unique id of an existing process instance.
schema:
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: parameters:
- name: modified_process_model_identifier - name: modified_process_model_identifier
in: path in: path
@ -715,6 +666,18 @@ paths:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/Workflow" $ref: "#/components/schemas/Workflow"
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-instances/{modified_process_model_identifier}/{process_instance_id}/run: /process-instances/{modified_process_model_identifier}/{process_instance_id}/run:
parameters: parameters:
@ -743,7 +706,7 @@ paths:
schema: schema:
$ref: "#/components/schemas/Workflow" $ref: "#/components/schemas/Workflow"
/process-instances/{process_instance_id}/terminate: /process-instances/{modified_process_model_identifier}/{process_instance_id}/terminate:
parameters: parameters:
- name: process_instance_id - name: process_instance_id
in: path in: path
@ -764,7 +727,7 @@ paths:
schema: schema:
$ref: "#/components/schemas/OkTrue" $ref: "#/components/schemas/OkTrue"
/process-instances/{process_instance_id}/suspend: /process-instances/{modified_process_model_identifier}/{process_instance_id}/suspend:
parameters: parameters:
- name: process_instance_id - name: process_instance_id
in: path in: path
@ -785,7 +748,7 @@ paths:
schema: schema:
$ref: "#/components/schemas/OkTrue" $ref: "#/components/schemas/OkTrue"
/process-instances/{process_instance_id}/resume: /process-instances/{modified_process_model_identifier}/{process_instance_id}/resume:
parameters: parameters:
- name: process_instance_id - name: process_instance_id
in: path in: path
@ -922,9 +885,9 @@ paths:
schema: schema:
$ref: "#/components/schemas/OkTrue" $ref: "#/components/schemas/OkTrue"
/process-models/{modified_process_model_id}/files/{file_name}: /process-models/{modified_process_model_identifier}/files/{file_name}:
parameters: parameters:
- name: modified_process_model_id - name: modified_process_model_identifier
in: path in: path
required: true required: true
description: The modified process model id description: The modified process model id
@ -1101,9 +1064,9 @@ paths:
items: items:
$ref: "#/components/schemas/Task" $ref: "#/components/schemas/Task"
/process-instances/{modified_process_model_id}/{process_instance_id}/tasks: /task-data/{modified_process_model_identifier}/{process_instance_id}:
parameters: parameters:
- name: modified_process_model_id - name: modified_process_model_identifier
in: path in: path
required: true required: true
description: The modified id of an existing process model description: The modified id of an existing process model
@ -1142,11 +1105,44 @@ paths:
items: items:
$ref: "#/components/schemas/Task" $ref: "#/components/schemas/Task"
/service_tasks: /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
put:
operationId: spiffworkflow_backend.routes.process_api_blueprint.update_task_data
summary: Update the task data for requested instance and task
tags:
- Process Instances
responses:
"200":
description: Task Updated Successfully
content:
application/json:
schema:
$ref: "#/components/schemas/Workflow"
/service-tasks:
get: get:
tags: tags:
- Service Tasks - Service Tasks
operationId: spiffworkflow_backend.routes.process_api_blueprint.service_tasks_show operationId: spiffworkflow_backend.routes.process_api_blueprint.service_task_list
summary: Gets all available service task connectors summary: Gets all available service task connectors
responses: responses:
"200": "200":
@ -1326,7 +1322,7 @@ paths:
schema: schema:
$ref: "#/components/schemas/Workflow" $ref: "#/components/schemas/Workflow"
/process-instances/{process_instance_id}/logs: /logs/{modified_process_model_identifier}/{process_instance_id}:
parameters: parameters:
- name: process_instance_id - name: process_instance_id
in: path in: path
@ -1346,6 +1342,12 @@ paths:
description: The number of items to show per page. Defaults to page 10. description: The number of items to show per page. Defaults to page 10.
schema: schema:
type: integer type: integer
- name: detailed
in: query
required: false
description: Show the detailed view, which includes all log entries
schema:
type: boolean
get: get:
tags: tags:
- Process Instances - Process Instances

View File

@ -12,7 +12,6 @@ groups:
mike, mike,
jason, jason,
j, j,
amir,
jarrad, jarrad,
elizabeth, elizabeth,
jon, jon,
@ -70,6 +69,12 @@ permissions:
users: [] users: []
allowed_permissions: [create, read, update, delete] allowed_permissions: [create, read, update, delete]
uri: /v1.0/tasks/* uri: /v1.0/tasks/*
service-tasks:
groups: [everybody]
users: []
allowed_permissions: [read]
uri: /v1.0/service-tasks
# read all for everybody # read all for everybody
read-all-process-groups: read-all-process-groups:
@ -98,6 +103,12 @@ permissions:
allowed_permissions: [read] allowed_permissions: [read]
uri: /v1.0/processes uri: /v1.0/processes
task-data-read:
groups: [demo]
users: []
allowed_permissions: [read]
uri: /v1.0/task-data/*
manage-procurement-admin: manage-procurement-admin:
groups: ["Project Lead"] groups: ["Project Lead"]
@ -170,17 +181,17 @@ permissions:
uri: /v1.0/process-instances/manage-procurement:vendor-lifecycle-management:* uri: /v1.0/process-instances/manage-procurement:vendor-lifecycle-management:*
core1-admin-models-instantiate: core1-admin-models-instantiate:
groups: ["core-contributor"] groups: ["core-contributor", "Finance Team"]
users: [] users: []
allowed_permissions: [create] allowed_permissions: [create]
uri: /v1.0/process-models/misc:category_number_one:process-model-with-form/process-instances uri: /v1.0/process-models/misc:category_number_one:process-model-with-form/process-instances
core1-admin-instances: core1-admin-instances:
groups: ["core-contributor"] groups: ["core-contributor", "Finance Team"]
users: [] users: []
allowed_permissions: [create, read] allowed_permissions: [create, read]
uri: /v1.0/process-instances/misc:category_number_one:process-model-with-form:* uri: /v1.0/process-instances/misc:category_number_one:process-model-with-form:*
core1-admin-instances-slash: core1-admin-instances-slash:
groups: ["core-contributor"] groups: ["core-contributor", "Finance Team"]
users: [] users: []
allowed_permissions: [create, read] allowed_permissions: [create, read]
uri: /v1.0/process-instances/misc:category_number_one:process-model-with-form/* uri: /v1.0/process-instances/misc:category_number_one:process-model-with-form/*

View File

@ -12,7 +12,6 @@ groups:
mike, mike,
jason, jason,
j, j,
amir,
jarrad, jarrad,
elizabeth, elizabeth,
jon, jon,
@ -98,6 +97,12 @@ permissions:
allowed_permissions: [read] allowed_permissions: [read]
uri: /v1.0/processes uri: /v1.0/processes
task-data-read:
groups: [demo]
users: []
allowed_permissions: [read]
uri: /v1.0/task-data/*
manage-procurement-admin: manage-procurement-admin:
groups: ["Project Lead"] groups: ["Project Lead"]

View File

@ -158,9 +158,9 @@ def modify_process_model_id(process_model_id: str) -> str:
return process_model_id.replace("/", ":") return process_model_id.replace("/", ":")
def un_modify_modified_process_model_id(modified_process_model_id: str) -> str: def un_modify_modified_process_model_id(modified_process_model_identifier: str) -> str:
"""Un_modify_modified_process_model_id.""" """Un_modify_modified_process_model_id."""
return modified_process_model_id.replace(":", "/") return modified_process_model_identifier.replace(":", "/")
def process_group_add(body: dict) -> flask.wrappers.Response: def process_group_add(body: dict) -> flask.wrappers.Response:
@ -411,9 +411,9 @@ def process_list() -> Any:
return SpecReferenceSchema(many=True).dump(references) return SpecReferenceSchema(many=True).dump(references)
def get_file(modified_process_model_id: str, file_name: str) -> Any: def get_file(modified_process_model_identifier: str, file_name: str) -> Any:
"""Get_file.""" """Get_file."""
process_model_identifier = modified_process_model_id.replace(":", "/") process_model_identifier = modified_process_model_identifier.replace(":", "/")
process_model = get_process_model(process_model_identifier) process_model = get_process_model(process_model_identifier)
files = SpecFileService.get_files(process_model, file_name) files = SpecFileService.get_files(process_model, file_name)
if len(files) == 0: if len(files) == 0:
@ -433,10 +433,10 @@ def get_file(modified_process_model_id: str, file_name: str) -> Any:
def process_model_file_update( def process_model_file_update(
modified_process_model_id: str, file_name: str modified_process_model_identifier: str, file_name: str
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_model_file_update.""" """Process_model_file_update."""
process_model_identifier = modified_process_model_id.replace(":", "/") process_model_identifier = modified_process_model_identifier.replace(":", "/")
process_model = get_process_model(process_model_identifier) process_model = get_process_model(process_model_identifier)
request_file = get_file_from_request() request_file = get_file_from_request()
@ -462,10 +462,10 @@ def process_model_file_update(
def process_model_file_delete( def process_model_file_delete(
modified_process_model_id: str, file_name: str modified_process_model_identifier: str, file_name: str
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_model_file_delete.""" """Process_model_file_delete."""
process_model_identifier = modified_process_model_id.replace(":", "/") process_model_identifier = modified_process_model_identifier.replace(":", "/")
process_model = get_process_model(process_model_identifier) process_model = get_process_model(process_model_identifier)
try: try:
SpecFileService.delete_file(process_model, file_name) SpecFileService.delete_file(process_model, file_name)
@ -481,9 +481,9 @@ def process_model_file_delete(
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
def add_file(modified_process_model_id: str) -> flask.wrappers.Response: def add_file(modified_process_model_identifier: str) -> flask.wrappers.Response:
"""Add_file.""" """Add_file."""
process_model_identifier = modified_process_model_id.replace(":", "/") process_model_identifier = modified_process_model_identifier.replace(":", "/")
process_model = get_process_model(process_model_identifier) process_model = get_process_model(process_model_identifier)
request_file = get_file_from_request() request_file = get_file_from_request()
if not request_file.filename: if not request_file.filename:
@ -504,10 +504,12 @@ def add_file(modified_process_model_id: str) -> flask.wrappers.Response:
) )
def process_instance_create(modified_process_model_id: str) -> flask.wrappers.Response: def process_instance_create(
modified_process_model_identifier: str,
) -> flask.wrappers.Response:
"""Create_process_instance.""" """Create_process_instance."""
process_model_identifier = un_modify_modified_process_model_id( process_model_identifier = un_modify_modified_process_model_id(
modified_process_model_id modified_process_model_identifier
) )
process_instance = ( process_instance = (
ProcessInstanceService.create_process_instance_from_process_model_identifier( ProcessInstanceService.create_process_instance_from_process_model_identifier(
@ -565,6 +567,7 @@ def process_instance_run(
def process_instance_terminate( def process_instance_terminate(
process_instance_id: int, process_instance_id: int,
modified_process_model_identifier: str,
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_instance_run.""" """Process_instance_run."""
process_instance = ProcessInstanceService().get_process_instance( process_instance = ProcessInstanceService().get_process_instance(
@ -577,6 +580,7 @@ def process_instance_terminate(
def process_instance_suspend( def process_instance_suspend(
process_instance_id: int, process_instance_id: int,
modified_process_model_identifier: str,
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_instance_suspend.""" """Process_instance_suspend."""
process_instance = ProcessInstanceService().get_process_instance( process_instance = ProcessInstanceService().get_process_instance(
@ -589,6 +593,7 @@ def process_instance_suspend(
def process_instance_resume( def process_instance_resume(
process_instance_id: int, process_instance_id: int,
modified_process_model_identifier: str,
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_instance_resume.""" """Process_instance_resume."""
process_instance = ProcessInstanceService().get_process_instance( process_instance = ProcessInstanceService().get_process_instance(
@ -600,19 +605,24 @@ def process_instance_resume(
def process_instance_log_list( def process_instance_log_list(
modified_process_model_identifier: str,
process_instance_id: int, process_instance_id: int,
page: int = 1, page: int = 1,
per_page: int = 100, per_page: int = 100,
detailed: bool = False,
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:
"""Process_instance_log_list.""" """Process_instance_log_list."""
# to make sure the process instance exists # to make sure the process instance exists
process_instance = find_process_instance_by_id_or_raise(process_instance_id) process_instance = find_process_instance_by_id_or_raise(process_instance_id)
log_query = SpiffLoggingModel.query.filter(
SpiffLoggingModel.process_instance_id == process_instance.id
)
if not detailed:
log_query = log_query.filter(SpiffLoggingModel.message.in_(["State change to COMPLETED"])) # type: ignore
logs = ( logs = (
SpiffLoggingModel.query.filter( log_query.order_by(SpiffLoggingModel.timestamp.desc()) # type: ignore
SpiffLoggingModel.process_instance_id == process_instance.id
)
.order_by(SpiffLoggingModel.timestamp.desc()) # type: ignore
.join( .join(
UserModel, UserModel.id == SpiffLoggingModel.current_user_id, isouter=True UserModel, UserModel.id == SpiffLoggingModel.current_user_id, isouter=True
) # isouter since if we don't have a user, we still want the log ) # isouter since if we don't have a user, we still want the log
@ -1071,7 +1081,9 @@ def process_instance_show(
return make_response(jsonify(process_instance), 200) return make_response(jsonify(process_instance), 200)
def process_instance_delete(process_instance_id: int) -> flask.wrappers.Response: def process_instance_delete(
process_instance_id: int, modified_process_model_identifier: str
) -> flask.wrappers.Response:
"""Create_process_instance.""" """Create_process_instance."""
process_instance = find_process_instance_by_id_or_raise(process_instance_id) process_instance = find_process_instance_by_id_or_raise(process_instance_id)
@ -1153,8 +1165,8 @@ def process_instance_report_delete(
return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") return Response(json.dumps({"ok": True}), status=200, mimetype="application/json")
def service_tasks_show() -> flask.wrappers.Response: def service_task_list() -> flask.wrappers.Response:
"""Service_tasks_show.""" """Service_task_list."""
available_connectors = ServiceTaskService.available_connectors() available_connectors = ServiceTaskService.available_connectors()
return Response( return Response(
json.dumps(available_connectors), status=200, mimetype="application/json" json.dumps(available_connectors), status=200, mimetype="application/json"
@ -1361,7 +1373,7 @@ def get_tasks(
def process_instance_task_list( def process_instance_task_list(
modified_process_model_id: str, modified_process_model_identifier: str,
process_instance_id: int, process_instance_id: int,
all_tasks: bool = False, all_tasks: bool = False,
spiff_step: int = 0, spiff_step: int = 0,
@ -1922,7 +1934,12 @@ def _update_form_schema_with_task_data_as_needed(
_update_form_schema_with_task_data_as_needed(o, task_data) _update_form_schema_with_task_data_as_needed(o, task_data)
def update_task_data(process_instance_id: str, task_id: str, body: Dict) -> Response: def update_task_data(
process_instance_id: str,
modified_process_model_identifier: str,
task_id: str,
body: Dict,
) -> Response:
"""Update task data.""" """Update task data."""
process_instance = ProcessInstanceModel.query.filter( process_instance = ProcessInstanceModel.query.filter(
ProcessInstanceModel.id == int(process_instance_id) ProcessInstanceModel.id == int(process_instance_id)

View File

@ -265,7 +265,7 @@ class BaseTest:
) )
modified_process_model_id = test_process_model_id.replace("/", ":") modified_process_model_id = test_process_model_id.replace("/", ":")
response = client.post( response = client.post(
f"/v1.0/process-models/{modified_process_model_id}/process-instances", f"/v1.0/process-instances/{modified_process_model_id}",
headers=headers, headers=headers,
) )
assert response.status_code == 201 assert response.status_code == 201

View File

@ -57,7 +57,7 @@ class TestLoggingService(BaseTest):
assert response.status_code == 200 assert response.status_code == 200
log_response = client.get( log_response = client.get(
f"/v1.0/process-instances/{process_instance_id}/logs", f"/v1.0/logs/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}",
headers=headers, headers=headers,
) )
assert log_response.status_code == 200 assert log_response.status_code == 200

View File

@ -912,7 +912,7 @@ class TestProcessApi(BaseTest):
modified_process_model_identifier = process_model_identifier.replace("/", ":") modified_process_model_identifier = process_model_identifier.replace("/", ":")
response = client.post( response = client.post(
f"/v1.0/process-models/{modified_process_model_identifier}/process-instances", f"/v1.0/process-instances/{modified_process_model_identifier}",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
) )
assert response.status_code == 201 assert response.status_code == 201
@ -1154,10 +1154,11 @@ class TestProcessApi(BaseTest):
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
) )
show_response = client.get( show_response = client.get(
f"/v1.0/process-models/{modified_process_model_identifier}/process-instances/{process_instance_id}", f"/v1.0/process-instances/{modified_process_model_identifier}/{process_instance_id}",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
) )
assert show_response.json is not None assert show_response.json is not None
assert show_response.status_code == 200
file_system_root = FileSystemService.root_path() file_system_root = FileSystemService.root_path()
file_path = ( file_path = (
f"{file_system_root}/{process_model_identifier}/{process_model_id}.bpmn" f"{file_system_root}/{process_model_identifier}/{process_model_id}.bpmn"
@ -1320,7 +1321,7 @@ class TestProcessApi(BaseTest):
assert response.json is not None assert response.json is not None
response = client.post( response = client.post(
f"/v1.0/process-instances/{process_instance_id}/terminate", f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/terminate",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
) )
assert response.status_code == 200 assert response.status_code == 200
@ -1367,7 +1368,7 @@ class TestProcessApi(BaseTest):
assert response.json is not None assert response.json is not None
delete_response = client.delete( delete_response = client.delete(
f"/v1.0/process-instances/{process_instance_id}", f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
) )
assert delete_response.status_code == 200 assert delete_response.status_code == 200
@ -2366,7 +2367,7 @@ class TestProcessApi(BaseTest):
assert process_instance.status == "user_input_required" assert process_instance.status == "user_input_required"
client.post( client.post(
f"/v1.0/process-instances/{process_instance_id}/suspend", f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/suspend",
headers=self.logged_in_headers(with_super_admin_user), headers=self.logged_in_headers(with_super_admin_user),
) )
process_instance = ProcessInstanceService().get_process_instance( process_instance = ProcessInstanceService().get_process_instance(

View File

@ -372,15 +372,18 @@ export default function ProcessInstanceListTable({
titleOperation = 'Created'; titleOperation = 'Created';
} }
return ( return (
<InlineNotification <>
title={`Perspective ${titleOperation}:`} <InlineNotification
subtitle={`'${ title={`Perspective ${titleOperation}:`}
processInstanceReportSelection subtitle={`'${
? processInstanceReportSelection.identifier processInstanceReportSelection
: '' ? processInstanceReportSelection.identifier
}'`} : ''
kind="success" }'`}
/> kind="success"
/>
<br />
</>
); );
} }
return null; return null;
@ -935,6 +938,15 @@ export default function ProcessInstanceListTable({
if (!showFilterOptions) { if (!showFilterOptions) {
return null; return null;
} }
// get the columns anytime we display the filter options if they are empty
if (availableReportColumns.length < 1) {
HttpService.makeCallToBackend({
path: `/process-instances/reports/columns`,
successCallback: setAvailableReportColumns,
});
}
return ( return (
<> <>
<Grid fullWidth className="with-bottom-margin"> <Grid fullWidth className="with-bottom-margin">
@ -1059,7 +1071,7 @@ export default function ProcessInstanceListTable({
return ( return (
<Link <Link
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${id}`} to={`/admin/process-instances/${modifiedProcessModelId}/${id}`}
title={`View process instance ${id}`} title={`View process instance ${id}`}
> >
{id} {id}
@ -1134,10 +1146,6 @@ export default function ProcessInstanceListTable({
const toggleShowFilterOptions = () => { const toggleShowFilterOptions = () => {
setShowFilterOptions(!showFilterOptions); setShowFilterOptions(!showFilterOptions);
HttpService.makeCallToBackend({
path: `/process-instances/reports/columns`,
successCallback: setAvailableReportColumns,
});
}; };
const reportSearchComponent = () => { const reportSearchComponent = () => {
@ -1166,6 +1174,9 @@ export default function ProcessInstanceListTable({
return ( return (
<> <>
<Grid fullWidth> <Grid fullWidth>
<Column sm={2} md={4} lg={7}>
{reportSearchComponent()}
</Column>
<Column <Column
className="filterIcon" className="filterIcon"
sm={{ span: 1, offset: 3 }} sm={{ span: 1, offset: 3 }}
@ -1204,7 +1215,6 @@ export default function ProcessInstanceListTable({
{reportColumnForm()} {reportColumnForm()}
{processInstanceReportSaveTag()} {processInstanceReportSaveTag()}
{filterComponent()} {filterComponent()}
{reportSearchComponent()}
<PaginationForTable <PaginationForTable
page={page} page={page}
perPage={perPage} perPage={perPage}

View File

@ -83,9 +83,9 @@ export default function ProcessInstanceRun({
processModel.id processModel.id
); );
const processInstanceActionPath = `/v1.0/process-models/${modifiedProcessModelId}/process-instances`; const processInstanceCreatePath = `/v1.0/process-instances/${modifiedProcessModelId}`;
let permissionRequestData: PermissionsToCheck = { let permissionRequestData: PermissionsToCheck = {
[processInstanceActionPath]: ['POST'], [processInstanceCreatePath]: ['POST'],
}; };
if (!checkPermissions) { if (!checkPermissions) {
@ -117,14 +117,14 @@ export default function ProcessInstanceRun({
const processInstanceCreateAndRun = () => { const processInstanceCreateAndRun = () => {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: processInstanceActionPath, path: processInstanceCreatePath,
successCallback: processModelRun, successCallback: processModelRun,
httpMethod: 'POST', httpMethod: 'POST',
}); });
}; };
if (checkPermissions) { if (checkPermissions) {
return ( return (
<Can I="POST" a={processInstanceActionPath} ability={ability}> <Can I="POST" a={processInstanceCreatePath} ability={ability}>
<Button onClick={processInstanceCreateAndRun} className={className}> <Button onClick={processInstanceCreateAndRun} className={className}>
Start Start
</Button> </Button>

View File

@ -194,7 +194,6 @@ export default function ProcessModelForm({
onChange={(event: any) => { onChange={(event: any) => {
onDisplayNameChanged(event.target.value); onDisplayNameChanged(event.target.value);
}} }}
onBlur={(event: any) => console.log('event', event)}
/>, />,
]; ];

View File

@ -54,9 +54,9 @@ export default function ProcessModelListTiles({
<p> <p>
Process Instance {processInstance.id} kicked off ( Process Instance {processInstance.id} kicked off (
<Link <Link
to={`/admin/process-models/${modifyProcessIdentifierForPathParam( to={`/admin/process-instances/${modifyProcessIdentifierForPathParam(
processInstance.process_model_identifier processInstance.process_model_identifier
)}/process-instances/${processInstance.id}`} )}/${processInstance.id}`}
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
> >
view view

View File

@ -55,7 +55,7 @@ export default function MyOpenProcesses() {
<td> <td>
<Link <Link
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
to={`/admin/process-models/${modifiedProcessModelIdentifier}/process-instances/${rowToUse.process_instance_id}`} to={`/admin/process-instances/${modifiedProcessModelIdentifier}/${rowToUse.process_instance_id}`}
title={`View process instance ${rowToUse.process_instance_id}`} title={`View process instance ${rowToUse.process_instance_id}`}
> >
{rowToUse.process_instance_id} {rowToUse.process_instance_id}

View File

@ -47,7 +47,7 @@ export default function TasksWaitingForMe() {
<td> <td>
<Link <Link
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
to={`/admin/process-models/${modifiedProcessModelIdentifier}/process-instances/${rowToUse.process_instance_id}`} to={`/admin/${modifiedProcessModelIdentifier}/${rowToUse.process_instance_id}`}
title={`View process instance ${rowToUse.process_instance_id}`} title={`View process instance ${rowToUse.process_instance_id}`}
> >
{rowToUse.process_instance_id} {rowToUse.process_instance_id}

View File

@ -55,7 +55,7 @@ export default function TasksWaitingForMyGroups() {
<td> <td>
<Link <Link
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
to={`/admin/process-models/${modifiedProcessModelIdentifier}/process-instances/${rowToUse.process_instance_id}`} to={`/admin/process-instances/${modifiedProcessModelIdentifier}/${rowToUse.process_instance_id}`}
title={`View process instance ${rowToUse.process_instance_id}`} title={`View process instance ${rowToUse.process_instance_id}`}
> >
{rowToUse.process_instance_id} {rowToUse.process_instance_id}

View File

@ -9,10 +9,12 @@ export const useUriListForPermissions = () => {
messageInstanceListPath: '/v1.0/messages', messageInstanceListPath: '/v1.0/messages',
processGroupListPath: '/v1.0/process-groups', processGroupListPath: '/v1.0/process-groups',
processGroupShowPath: `/v1.0/process-groups/${params.process_group_id}`, processGroupShowPath: `/v1.0/process-groups/${params.process_group_id}`,
processInstanceActionPath: `/v1.0/process-models/${params.process_model_id}/process-instances`, processInstanceCreatePath: `/v1.0/process-instances/${params.process_model_id}`,
processInstanceActionPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}`,
processInstanceListPath: '/v1.0/process-instances', processInstanceListPath: '/v1.0/process-instances',
processInstanceTaskListPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}/tasks`, processInstanceLogListPath: `/v1.0/logs/${params.process_model_id}/${params.process_instance_id}`,
processInstanceReportListPath: '/v1.0/process-instances/reports', processInstanceReportListPath: '/v1.0/process-instances/reports',
processInstanceTaskListPath: `/v1.0/task-data/${params.process_model_id}/${params.process_instance_id}`,
processModelCreatePath: `/v1.0/process-models/${params.process_group_id}`, processModelCreatePath: `/v1.0/process-models/${params.process_group_id}`,
processModelFileCreatePath: `/v1.0/process-models/${params.process_model_id}/files`, processModelFileCreatePath: `/v1.0/process-models/${params.process_model_id}/files`,
processModelFileShowPath: `/v1.0/process-models/${params.process_model_id}/files/${params.file_name}`, processModelFileShowPath: `/v1.0/process-models/${params.process_model_id}/files/${params.file_name}`,

View File

@ -71,11 +71,11 @@ export default function AdminRoutes() {
element={<ProcessModelEdit />} element={<ProcessModelEdit />}
/> />
<Route <Route
path="process-models/:process_model_id/process-instances/:process_instance_id" path="process-instances/:process_model_id/:process_instance_id"
element={<ProcessInstanceShow />} element={<ProcessInstanceShow />}
/> />
<Route <Route
path="process-models/:process_model_id/process-instances/:process_instance_id/:spiff_step" path="process-instances/:process_model_id/:process_instance_id/:spiff_step"
element={<ProcessInstanceShow />} element={<ProcessInstanceShow />}
/> />
<Route <Route
@ -103,7 +103,7 @@ export default function AdminRoutes() {
element={<ReactFormEditor />} element={<ReactFormEditor />}
/> />
<Route <Route
path="process-models/:process_model_id/process-instances/:process_instance_id/logs" path="logs/:process_model_id/:process_instance_id"
element={<ProcessInstanceLogList />} element={<ProcessInstanceLogList />}
/> />
<Route path="process-instances" element={<ProcessInstanceList />} /> <Route path="process-instances" element={<ProcessInstanceList />} />

View File

@ -102,9 +102,9 @@ export default function MessageInstanceList() {
<td> <td>
<Link <Link
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
to={`/admin/process-models/${modifyProcessIdentifierForPathParam( to={`/admin/process-instances/${modifyProcessIdentifierForPathParam(
row.process_model_identifier row.process_model_identifier
)}/process-instances/${row.process_instance_id}`} )}/${row.process_instance_id}`}
> >
{row.process_instance_id} {row.process_instance_id}
</Link> </Link>
@ -163,9 +163,9 @@ export default function MessageInstanceList() {
}, },
[ [
`Process Instance: ${searchParams.get('process_instance_id')}`, `Process Instance: ${searchParams.get('process_instance_id')}`,
`/admin/process-models/${searchParams.get( `/admin/process-instances/${searchParams.get(
'process_model_id' 'process_model_id'
)}/process-instances/${searchParams.get('process_instance_id')}`, )}/${searchParams.get('process_instance_id')}`,
], ],
['Messages'], ['Messages'],
]} ]}

View File

@ -55,9 +55,9 @@ export default function MyTasks() {
<p> <p>
Process Instance {processInstance.id} kicked off ( Process Instance {processInstance.id} kicked off (
<Link <Link
to={`/admin/process-models/${modifyProcessIdentifierForPathParam( to={`/admin/process-instances/${modifyProcessIdentifierForPathParam(
processInstance.process_model_identifier processInstance.process_model_identifier
)}/process-instances/${processInstance.id}`} )}/${processInstance.id}`}
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
> >
view view
@ -95,7 +95,7 @@ export default function MyTasks() {
<td> <td>
<Link <Link
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
to={`/admin/process-models/${modifiedProcessModelIdentifier}/process-instances/${rowToUse.process_instance_id}`} to={`/admin/process-instances/${modifiedProcessModelIdentifier}/${rowToUse.process_instance_id}`}
> >
{rowToUse.process_instance_id} {rowToUse.process_instance_id}
</Link> </Link>

View File

@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
// @ts-ignore // @ts-ignore
import { Table } from '@carbon/react'; import { Table, Tabs, TabList, Tab } from '@carbon/react';
import { useParams, useSearchParams, Link } from 'react-router-dom'; import { useParams, useSearchParams, Link } from 'react-router-dom';
import PaginationForTable from '../components/PaginationForTable'; import PaginationForTable from '../components/PaginationForTable';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
@ -10,15 +10,18 @@ import {
convertSecondsToFormattedDateTime, convertSecondsToFormattedDateTime,
} from '../helpers'; } from '../helpers';
import HttpService from '../services/HttpService'; import HttpService from '../services/HttpService';
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
export default function ProcessInstanceLogList() { export default function ProcessInstanceLogList() {
const params = useParams(); const params = useParams();
const [searchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const [processInstanceLogs, setProcessInstanceLogs] = useState([]); const [processInstanceLogs, setProcessInstanceLogs] = useState([]);
const [pagination, setPagination] = useState(null); const [pagination, setPagination] = useState(null);
const modifiedProcessModelId = modifyProcessIdentifierForPathParam( const modifiedProcessModelId = modifyProcessIdentifierForPathParam(
`${params.process_model_id}` `${params.process_model_id}`
); );
const { targetUris } = useUriListForPermissions();
const isDetailedView = searchParams.get('detailed') === 'true';
useEffect(() => { useEffect(() => {
const setProcessInstanceLogListFromResult = (result: any) => { const setProcessInstanceLogListFromResult = (result: any) => {
@ -27,26 +30,36 @@ export default function ProcessInstanceLogList() {
}; };
const { page, perPage } = getPageInfoFromSearchParams(searchParams); const { page, perPage } = getPageInfoFromSearchParams(searchParams);
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-instances/${params.process_instance_id}/logs?per_page=${perPage}&page=${page}`, path: `${targetUris.processInstanceLogListPath}?per_page=${perPage}&page=${page}&detailed=${isDetailedView}`,
successCallback: setProcessInstanceLogListFromResult, successCallback: setProcessInstanceLogListFromResult,
}); });
}, [searchParams, params]); }, [
searchParams,
params,
targetUris.processInstanceLogListPath,
isDetailedView,
]);
const buildTable = () => { const buildTable = () => {
const rows = processInstanceLogs.map((row) => { const rows = processInstanceLogs.map((row) => {
const rowToUse = row as any; const rowToUse = row as any;
return ( return (
<tr key={rowToUse.id}> <tr key={rowToUse.id}>
<td>{rowToUse.bpmn_process_identifier}</td> <td>{rowToUse.id}</td>
<td>{rowToUse.message}</td> <td>{rowToUse.message}</td>
<td>{rowToUse.bpmn_task_identifier}</td>
<td>{rowToUse.bpmn_task_name}</td> <td>{rowToUse.bpmn_task_name}</td>
<td>{rowToUse.bpmn_task_type}</td> {isDetailedView && (
<>
<td>{rowToUse.bpmn_task_identifier}</td>
<td>{rowToUse.bpmn_task_type}</td>
<td>{rowToUse.bpmn_process_identifier}</td>
</>
)}
<td>{rowToUse.username}</td> <td>{rowToUse.username}</td>
<td> <td>
<Link <Link
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${rowToUse.process_instance_id}/${rowToUse.spiff_step}`} to={`/admin/process-instances/${modifiedProcessModelId}/${rowToUse.process_instance_id}/${rowToUse.spiff_step}`}
> >
{convertSecondsToFormattedDateTime(rowToUse.timestamp)} {convertSecondsToFormattedDateTime(rowToUse.timestamp)}
</Link> </Link>
@ -58,11 +71,16 @@ export default function ProcessInstanceLogList() {
<Table size="lg"> <Table size="lg">
<thead> <thead>
<tr> <tr>
<th>Bpmn Process Identifier</th> <th>Id</th>
<th>Message</th> <th>Message</th>
<th>Task Identifier</th>
<th>Task Name</th> <th>Task Name</th>
<th>Task Type</th> {isDetailedView && (
<>
<th>Task Identifier</th>
<th>Task Type</th>
<th>Bpmn Process Identifier</th>
</>
)}
<th>User</th> <th>User</th>
<th>Timestamp</th> <th>Timestamp</th>
</tr> </tr>
@ -71,11 +89,12 @@ export default function ProcessInstanceLogList() {
</Table> </Table>
); );
}; };
const selectedTabIndex = isDetailedView ? 1 : 0;
if (pagination) { if (pagination) {
const { page, perPage } = getPageInfoFromSearchParams(searchParams); const { page, perPage } = getPageInfoFromSearchParams(searchParams);
return ( return (
<main> <>
<ProcessBreadcrumb <ProcessBreadcrumb
hotCrumbs={[ hotCrumbs={[
['Process Groups', '/admin'], ['Process Groups', '/admin'],
@ -86,18 +105,41 @@ export default function ProcessInstanceLogList() {
}, },
[ [
`Process Instance: ${params.process_instance_id}`, `Process Instance: ${params.process_instance_id}`,
`/admin/process-models/${params.process_model_id}/process-instances/${params.process_instance_id}`, `/admin/process-instances/${params.process_model_id}/${params.process_instance_id}`,
], ],
['Logs'], ['Logs'],
]} ]}
/> />
<Tabs selectedIndex={selectedTabIndex}>
<TabList aria-label="List of tabs">
<Tab
title="Only show a subset of the logs, and show fewer columns"
onClick={() => {
searchParams.set('detailed', 'false');
setSearchParams(searchParams);
}}
>
Simple
</Tab>
<Tab
title="Show all logs for this process instance, and show extra columns that may be useful for debugging"
onClick={() => {
searchParams.set('detailed', 'true');
setSearchParams(searchParams);
}}
>
Detailed
</Tab>
</TabList>
</Tabs>
<br />
<PaginationForTable <PaginationForTable
page={page} page={page}
perPage={perPage} perPage={perPage}
pagination={pagination} pagination={pagination}
tableToDisplay={buildTable()} tableToDisplay={buildTable()}
/> />
</main> </>
); );
} }
return null; return null;

View File

@ -59,6 +59,11 @@ export default function ProcessInstanceShow() {
const permissionRequestData: PermissionsToCheck = { const permissionRequestData: PermissionsToCheck = {
[targetUris.messageInstanceListPath]: ['GET'], [targetUris.messageInstanceListPath]: ['GET'],
[targetUris.processInstanceTaskListPath]: ['GET'], [targetUris.processInstanceTaskListPath]: ['GET'],
[targetUris.processInstanceActionPath]: ['DELETE'],
[targetUris.processInstanceLogListPath]: ['GET'],
[`${targetUris.processInstanceActionPath}/suspend`]: ['PUT'],
[`${targetUris.processInstanceActionPath}/terminate`]: ['PUT'],
[`${targetUris.processInstanceActionPath}/resume`]: ['PUT'],
}; };
const { ability, permissionsLoaded } = usePermissionFetcher( const { ability, permissionsLoaded } = usePermissionFetcher(
permissionRequestData permissionRequestData
@ -76,7 +81,7 @@ export default function ProcessInstanceShow() {
setTasksCallHadError(true); setTasksCallHadError(true);
}; };
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-models/${modifiedProcessModelId}/process-instances/${params.process_instance_id}`, path: `/process-instances/${modifiedProcessModelId}/${params.process_instance_id}`,
successCallback: setProcessInstance, successCallback: setProcessInstance,
}); });
let taskParams = '?all_tasks=true'; let taskParams = '?all_tasks=true';
@ -85,7 +90,7 @@ export default function ProcessInstanceShow() {
} }
if (ability.can('GET', targetUris.processInstanceTaskListPath)) { if (ability.can('GET', targetUris.processInstanceTaskListPath)) {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-instances/${modifiedProcessModelId}/${params.process_instance_id}/tasks${taskParams}`, path: `${targetUris.processInstanceTaskListPath}${taskParams}`,
successCallback: setTasks, successCallback: setTasks,
failureCallback: processTaskFailure, failureCallback: processTaskFailure,
}); });
@ -97,7 +102,7 @@ export default function ProcessInstanceShow() {
const deleteProcessInstance = () => { const deleteProcessInstance = () => {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-instances/${params.process_instance_id}`, path: targetUris.processInstanceActionPath,
successCallback: navigateToProcessInstances, successCallback: navigateToProcessInstances,
httpMethod: 'DELETE', httpMethod: 'DELETE',
}); });
@ -110,7 +115,7 @@ export default function ProcessInstanceShow() {
const terminateProcessInstance = () => { const terminateProcessInstance = () => {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-instances/${params.process_instance_id}/terminate`, path: `${targetUris.processInstanceActionPath}/terminate`,
successCallback: refreshPage, successCallback: refreshPage,
httpMethod: 'POST', httpMethod: 'POST',
}); });
@ -118,7 +123,7 @@ export default function ProcessInstanceShow() {
const suspendProcessInstance = () => { const suspendProcessInstance = () => {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-instances/${params.process_instance_id}/suspend`, path: `${targetUris.processInstanceActionPath}/suspend`,
successCallback: refreshPage, successCallback: refreshPage,
httpMethod: 'POST', httpMethod: 'POST',
}); });
@ -126,7 +131,7 @@ export default function ProcessInstanceShow() {
const resumeProcessInstance = () => { const resumeProcessInstance = () => {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-instances/${params.process_instance_id}/resume`, path: `${targetUris.processInstanceActionPath}/resume`,
successCallback: refreshPage, successCallback: refreshPage,
httpMethod: 'POST', httpMethod: 'POST',
}); });
@ -174,7 +179,7 @@ export default function ProcessInstanceShow() {
<Link <Link
reloadDocument reloadDocument
data-qa="process-instance-step-link" data-qa="process-instance-step-link"
to={`/admin/process-models/${ to={`/admin/process-instances/${
params.process_model_id params.process_model_id
}/process-instances/${params.process_instance_id}/${ }/process-instances/${params.process_instance_id}/${
currentSpiffStep(processInstanceToUse) + distance currentSpiffStep(processInstanceToUse) + distance
@ -209,7 +214,7 @@ export default function ProcessInstanceShow() {
if (currentEndDate) { if (currentEndDate) {
currentEndDateTag = ( currentEndDateTag = (
<Grid condensed fullWidth> <Grid condensed fullWidth>
<Column sm={1} md={1} lg={1} className="grid-list-title"> <Column sm={1} md={1} lg={2} className="grid-list-title">
Completed:{' '} Completed:{' '}
</Column> </Column>
<Column sm={3} md={3} lg={3} className="grid-date"> <Column sm={3} md={3} lg={3} className="grid-date">
@ -235,7 +240,7 @@ export default function ProcessInstanceShow() {
return ( return (
<> <>
<Grid condensed fullWidth> <Grid condensed fullWidth>
<Column sm={1} md={1} lg={1} className="grid-list-title"> <Column sm={1} md={1} lg={2} className="grid-list-title">
Started:{' '} Started:{' '}
</Column> </Column>
<Column sm={3} md={3} lg={3} className="grid-date"> <Column sm={3} md={3} lg={3} className="grid-date">
@ -246,7 +251,7 @@ export default function ProcessInstanceShow() {
</Grid> </Grid>
{currentEndDateTag} {currentEndDateTag}
<Grid condensed fullWidth> <Grid condensed fullWidth>
<Column sm={1} md={1} lg={1} className="grid-list-title"> <Column sm={1} md={1} lg={2} className="grid-list-title">
Status:{' '} Status:{' '}
</Column> </Column>
<Column sm={3} md={3} lg={3}> <Column sm={3} md={3} lg={3}>
@ -259,14 +264,20 @@ export default function ProcessInstanceShow() {
<Grid condensed fullWidth> <Grid condensed fullWidth>
<Column sm={2} md={2} lg={2}> <Column sm={2} md={2} lg={2}>
<ButtonSet> <ButtonSet>
<Button <Can
size="sm" I="GET"
className="button-white-background" a={targetUris.processInstanceLogListPath}
data-qa="process-instance-log-list-link" ability={ability}
href={`/admin/process-models/${modifiedProcessModelId}/process-instances/${params.process_instance_id}/logs`}
> >
Logs <Button
</Button> size="sm"
className="button-white-background"
data-qa="process-instance-log-list-link"
href={`/admin/logs/${modifiedProcessModelId}/${params.process_instance_id}`}
>
Logs
</Button>
</Can>
<Can <Can
I="GET" I="GET"
a={targetUris.messageInstanceListPath} a={targetUris.messageInstanceListPath}
@ -436,8 +447,8 @@ export default function ProcessInstanceShow() {
// 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: any = { ...taskToDisplay, data: taskDataToDisplay };
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-instances/${params.process_instance_id}/task/${taskToUse.id}/update`, path: `/task-data/${modifiedProcessModelId}/${params.process_instance_id}/${taskToUse.id}`,
httpMethod: 'POST', httpMethod: 'PUT',
successCallback: saveTaskDataResult, successCallback: saveTaskDataResult,
failureCallback: saveTaskDataFailure, failureCallback: saveTaskDataFailure,
postBody: { postBody: {
@ -544,21 +555,33 @@ export default function ProcessInstanceShow() {
const buttonIcons = (processInstanceToUse: any) => { const buttonIcons = (processInstanceToUse: any) => {
const elements = []; const elements = [];
elements.push(terminateButton(processInstanceToUse)); if (
elements.push(suspendButton(processInstanceToUse)); ability.can('POST', `${targetUris.processInstanceActionPath}/terminate`)
elements.push(resumeButton(processInstanceToUse)); ) {
elements.push( elements.push(terminateButton(processInstanceToUse));
<ButtonWithConfirmation }
data-qa="process-instance-delete" if (
kind="ghost" ability.can('POST', `${targetUris.processInstanceActionPath}/suspend`)
renderIcon={TrashCan} ) {
iconDescription="Delete" elements.push(suspendButton(processInstanceToUse));
hasIconOnly }
description={`Delete Process Instance: ${processInstanceToUse.id}`} if (ability.can('POST', `${targetUris.processInstanceActionPath}/resume`)) {
onConfirmation={deleteProcessInstance} elements.push(resumeButton(processInstanceToUse));
confirmButtonLabel="Delete" }
/> if (ability.can('DELETE', targetUris.processInstanceActionPath)) {
); elements.push(
<ButtonWithConfirmation
data-qa="process-instance-delete"
kind="ghost"
renderIcon={TrashCan}
iconDescription="Delete"
hasIconOnly
description={`Delete Process Instance: ${processInstanceToUse.id}`}
onConfirmation={deleteProcessInstance}
confirmButtonLabel="Delete"
/>
);
}
return elements; return elements;
}; };

View File

@ -283,7 +283,7 @@ export default function ProcessModelEditDiagram() {
const onServiceTasksRequested = (event: any) => { const onServiceTasksRequested = (event: any) => {
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/service_tasks`, path: `/service-tasks`,
successCallback: makeApiHandler(event), successCallback: makeApiHandler(event),
}); });
}; };

View File

@ -66,7 +66,7 @@ export default function ProcessModelShow() {
const permissionRequestData: PermissionsToCheck = { const permissionRequestData: PermissionsToCheck = {
[targetUris.processModelShowPath]: ['PUT', 'DELETE'], [targetUris.processModelShowPath]: ['PUT', 'DELETE'],
[targetUris.processInstanceListPath]: ['GET'], [targetUris.processInstanceListPath]: ['GET'],
[targetUris.processInstanceActionPath]: ['POST'], [targetUris.processInstanceCreatePath]: ['POST'],
[targetUris.processModelFileCreatePath]: ['POST', 'PUT', 'GET', 'DELETE'], [targetUris.processModelFileCreatePath]: ['POST', 'PUT', 'GET', 'DELETE'],
}; };
const { ability, permissionsLoaded } = usePermissionFetcher( const { ability, permissionsLoaded } = usePermissionFetcher(
@ -95,7 +95,7 @@ export default function ProcessModelShow() {
<p> <p>
Process Instance {processInstance.id} kicked off ( Process Instance {processInstance.id} kicked off (
<Link <Link
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${processInstance.id}`} to={`/admin/process-instances/${modifiedProcessModelId}/${processInstance.id}`}
data-qa="process-instance-show-link" data-qa="process-instance-show-link"
> >
view view
@ -556,7 +556,7 @@ export default function ProcessModelShow() {
<Stack orientation="horizontal" gap={3}> <Stack orientation="horizontal" gap={3}>
<Can <Can
I="POST" I="POST"
a={targetUris.processInstanceActionPath} a={targetUris.processInstanceCreatePath}
ability={ability} ability={ability}
> >
<> <>

View File

@ -26,6 +26,9 @@ import Form from '../themes/carbon';
import HttpService from '../services/HttpService'; import HttpService from '../services/HttpService';
import ErrorContext from '../contexts/ErrorContext'; import ErrorContext from '../contexts/ErrorContext';
import { modifyProcessIdentifierForPathParam } from '../helpers'; import { modifyProcessIdentifierForPathParam } from '../helpers';
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
import { PermissionsToCheck } from '../interfaces';
import { usePermissionFetcher } from '../hooks/PermissionService';
export default function TaskShow() { export default function TaskShow() {
const [task, setTask] = useState(null); const [task, setTask] = useState(null);
@ -35,24 +38,36 @@ export default function TaskShow() {
const setErrorMessage = (useContext as any)(ErrorContext)[1]; const setErrorMessage = (useContext as any)(ErrorContext)[1];
useEffect(() => { const { targetUris } = useUriListForPermissions();
const processResult = (result: any) => { const permissionRequestData: PermissionsToCheck = {
setTask(result); [targetUris.processInstanceTaskListPath]: ['GET'],
HttpService.makeCallToBackend({ };
path: `/process-instances/${modifyProcessIdentifierForPathParam( const { ability, permissionsLoaded } = usePermissionFetcher(
result.process_model_identifier permissionRequestData
)}/${params.process_instance_id}/tasks`, );
successCallback: setUserTasks,
});
};
HttpService.makeCallToBackend({ useEffect(() => {
path: `/tasks/${params.process_instance_id}/${params.task_id}`, if (permissionsLoaded) {
successCallback: processResult, const processResult = (result: any) => {
// This causes the page to continuously reload setTask(result);
// failureCallback: setErrorMessage, if (ability.can('GET', targetUris.processInstanceTaskListPath)) {
}); HttpService.makeCallToBackend({
}, [params]); path: `/task-data/${modifyProcessIdentifierForPathParam(
result.process_model_identifier
)}/${params.process_instance_id}`,
successCallback: setUserTasks,
});
}
};
HttpService.makeCallToBackend({
path: `/tasks/${params.process_instance_id}/${params.task_id}`,
successCallback: processResult,
// This causes the page to continuously reload
// failureCallback: setErrorMessage,
});
}
}, [params, permissionsLoaded, ability, targetUris]);
const processSubmitResult = (result: any) => { const processSubmitResult = (result: any) => {
setErrorMessage(null); setErrorMessage(null);
@ -116,17 +131,18 @@ export default function TaskShow() {
} }
return null; return null;
}); });
return (
<Tabs
title="Steps in this process instance involving people"
selectedIndex={selectedTabIndex}
>
<TabList aria-label="List of tabs" contained>
{userTasksElement}
</TabList>
</Tabs>
);
} }
return ( return null;
<Tabs
title="Steps in this process instance involving people"
selectedIndex={selectedTabIndex}
>
<TabList aria-label="List of tabs" contained>
{userTasksElement}
</TabList>
</Tabs>
);
}; };
const formElement = (taskToUse: any) => { const formElement = (taskToUse: any) => {
@ -207,7 +223,7 @@ export default function TaskShow() {
); );
}; };
if (task && userTasks) { if (task) {
const taskToUse = task as any; const taskToUse = task as any;
let statusString = ''; let statusString = '';
if (taskToUse.state !== 'READY') { if (taskToUse.state !== 'READY') {