diff --git a/spiffworkflow-backend/bin/git_commit_bpmn_models_repo b/spiffworkflow-backend/bin/git_commit_bpmn_models_repo index 62fc0cab0..0ba512021 100755 --- a/spiffworkflow-backend/bin/git_commit_bpmn_models_repo +++ b/spiffworkflow-backend/bin/git_commit_bpmn_models_repo @@ -14,21 +14,39 @@ git_commit_message="$2" git_branch="$3" git_commit_username="$4" git_commit_email="$5" +git_commit_password="$6" -if [[ -z "${5:-}" ]]; then +if [[ -z "${6:-}" ]]; then >&2 echo "usage: $(basename "$0") [bpmn_models_absolute_dir] [git_commit_message] [git_branch] [git_commit_username] [git_commit_email]" exit 1 fi -cd "$bpmn_models_absolute_dir" -git add . +function failed_to_get_lock() { + >&2 echo "ERROR: Failed to get lock." + exit 1 +} -# https://unix.stackexchange.com/a/155077/456630 -if [ -z "$(git status --porcelain)" ]; then - echo "No changes to commit" -else - git config --local user.name "$git_commit_username" - git config --local user.email "$git_commit_email" - git commit -m "$git_commit_message" - git push --set-upstream origin "$git_branch" -fi +function run() { + cd "$bpmn_models_absolute_dir" + git add . + + # https://unix.stackexchange.com/a/155077/456630 + if [ -z "$(git status --porcelain)" ]; then + echo "No changes to commit" + else + PAT="${git_commit_username}:${git_commit_password}" + AUTH=$(echo -n "$PAT" | openssl base64 | tr -d '\n') + + git config --local user.name "$git_commit_username" + git config --local user.email "$git_commit_email" + git config --local http.extraHeader "Authorization: Basic $AUTH" + git commit -m "$git_commit_message" + git push --set-upstream origin "$git_branch" + git config --unset --local http.extraHeader + fi +} + +exec {lock_fd}>/var/lock/mylockfile || failed_to_get_lock +flock --timeout 60 "$lock_fd" || failed_to_get_lock +run +flock -u "$lock_fd" diff --git a/spiffworkflow-backend/migrations/env.py b/spiffworkflow-backend/migrations/env.py index 630e381ad..68feded2a 100644 --- a/spiffworkflow-backend/migrations/env.py +++ b/spiffworkflow-backend/migrations/env.py @@ -1,3 +1,5 @@ +from __future__ import with_statement + import logging from logging.config import fileConfig diff --git a/spiffworkflow-backend/migrations/versions/90dcaa99faa7_.py b/spiffworkflow-backend/migrations/versions/9538a3575b63_.py similarity index 98% rename from spiffworkflow-backend/migrations/versions/90dcaa99faa7_.py rename to spiffworkflow-backend/migrations/versions/9538a3575b63_.py index 5e018dd00..299c32751 100644 --- a/spiffworkflow-backend/migrations/versions/90dcaa99faa7_.py +++ b/spiffworkflow-backend/migrations/versions/9538a3575b63_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: 90dcaa99faa7 +Revision ID: 9538a3575b63 Revises: -Create Date: 2022-12-16 16:40:22.246123 +Create Date: 2022-12-19 14:51:21.949731 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '90dcaa99faa7' +revision = '9538a3575b63' down_revision = None branch_labels = None depends_on = None @@ -77,6 +77,8 @@ def upgrade(): sa.Column('service_id', sa.String(length=255), nullable=False), sa.Column('name', sa.String(length=255), nullable=True), sa.Column('email', sa.String(length=255), nullable=True), + sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), + sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('service', 'service_id', name='service_key'), sa.UniqueConstraint('uid') diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index 07ba8d634..43e7685c6 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -804,7 +804,7 @@ paths: schema: $ref: "#/components/schemas/Workflow" - /process-instances/{modified_process_model_identifier}/{process_instance_id}/terminate: + /process-instance-terminate/{modified_process_model_identifier}/{process_instance_id}: parameters: - name: process_instance_id in: path @@ -825,7 +825,7 @@ paths: schema: $ref: "#/components/schemas/OkTrue" - /process-instances/{modified_process_model_identifier}/{process_instance_id}/suspend: + /process-instance-suspend/{modified_process_model_identifier}/{process_instance_id}: parameters: - name: process_instance_id in: path @@ -846,7 +846,7 @@ paths: schema: $ref: "#/components/schemas/OkTrue" - /process-instances/{modified_process_model_identifier}/{process_instance_id}/resume: + /process-instance-resume/{modified_process_model_identifier}/{process_instance_id}: parameters: - name: process_instance_id in: path diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml index 10045b88f..df2839f32 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/development.yml @@ -123,7 +123,7 @@ permissions: read-process-instance-reports: groups: [everybody] users: [] - allowed_permissions: [read] + allowed_permissions: [create, read, update, delete] uri: /v1.0/process-instances/reports/* processes-read: groups: [everybody] diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/staging.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/staging.yml index 1300f36b5..d6cb2eb7d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/staging.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/staging.yml @@ -103,10 +103,10 @@ permissions: users: [] allowed_permissions: [read] uri: /v1.0/process-instances/* - read-process-instance-reports: + manage-process-instance-reports: groups: [everybody] users: [] - allowed_permissions: [read] + allowed_permissions: [create, read, update, delete] uri: /v1.0/process-instances/reports/* processes-read: groups: [everybody] diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/terraform_deployed_environment.yml b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/terraform_deployed_environment.yml index 19ce385db..63a613d5e 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/terraform_deployed_environment.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/permissions/terraform_deployed_environment.yml @@ -101,7 +101,7 @@ permissions: read-process-instance-reports: groups: [everybody] users: [] - allowed_permissions: [read] + allowed_permissions: [create, read, update, delete] uri: /v1.0/process-instances/reports/* processes-read: groups: [everybody] diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index 8572d6d62..220e8106d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -26,34 +26,12 @@ class ProcessInstanceNotFoundError(Exception): """ProcessInstanceNotFoundError.""" -class NavigationItemSchema(Schema): - """NavigationItemSchema.""" +class ProcessInstanceTaskDataCannotBeUpdatedError(Exception): + """ProcessInstanceTaskDataCannotBeUpdatedError.""" - class Meta: - """Meta.""" - fields = [ - "spec_id", - "name", - "spec_type", - "task_id", - "description", - "backtracks", - "indent", - "lane", - "state", - "children", - ] - unknown = INCLUDE - - state = marshmallow.fields.String(required=False, allow_none=True) - description = marshmallow.fields.String(required=False, allow_none=True) - backtracks = marshmallow.fields.String(required=False, allow_none=True) - lane = marshmallow.fields.String(required=False, allow_none=True) - task_id = marshmallow.fields.String(required=False, allow_none=True) - children = marshmallow.fields.List( - marshmallow.fields.Nested(lambda: NavigationItemSchema()) - ) +class ProcessInstanceCannotBeDeletedError(Exception): + """ProcessInstanceCannotBeDeletedError.""" class ProcessInstanceStatus(SpiffEnum): @@ -135,6 +113,19 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): """Validate_status.""" return self.validate_enum_field(key, value, ProcessInstanceStatus) + def can_submit_task(self) -> bool: + """Can_submit_task.""" + return not self.has_terminal_status() and self.status != "suspended" + + def has_terminal_status(self) -> bool: + """Has_terminal_status.""" + return self.status in self.terminal_statuses() + + @classmethod + def terminal_statuses(cls) -> list[str]: + """Terminal_statuses.""" + return ["complete", "error", "terminated"] + class ProcessInstanceModelSchema(Schema): """ProcessInstanceModelSchema.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py index b8c83d0f7..5fa09896d 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/user.py @@ -37,6 +37,8 @@ class UserModel(SpiffworkflowBaseDBModel): service_id = db.Column(db.String(255), nullable=False, unique=False) name = db.Column(db.String(255)) email = db.Column(db.String(255)) + updated_at_in_seconds: int = db.Column(db.Integer) + created_at_in_seconds: int = db.Column(db.Integer) user_group_assignments = relationship("UserGroupAssignmentModel", cascade="delete") # type: ignore groups = relationship( # type: ignore diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py index 977af599c..d1f761dbe 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -54,9 +54,15 @@ from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.process_group import ProcessGroup from spiffworkflow_backend.models.process_group import ProcessGroupSchema from spiffworkflow_backend.models.process_instance import ProcessInstanceApiSchema +from spiffworkflow_backend.models.process_instance import ( + ProcessInstanceCannotBeDeletedError, +) 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 ( + ProcessInstanceTaskDataCannotBeUpdatedError, +) from spiffworkflow_backend.models.process_instance_metadata import ( ProcessInstanceMetadataModel, ) @@ -578,6 +584,13 @@ def process_instance_run( process_instance = ProcessInstanceService().get_process_instance( process_instance_id ) + if process_instance.status != "not_started": + raise ApiError( + error_code="process_instance_not_runnable", + message=f"Process Instance ({process_instance.id}) is currently running or has already run.", + status_code=400, + ) + processor = ProcessInstanceProcessor(process_instance) if do_engine_steps: @@ -958,7 +971,7 @@ def process_instance_list( if report_filter.initiated_by_me is True: process_instance_query = process_instance_query.filter( - ProcessInstanceModel.status.in_(["complete", "error", "terminated"]) # type: ignore + ProcessInstanceModel.status.in_(ProcessInstanceModel.terminal_statuses()) # type: ignore ) process_instance_query = process_instance_query.filter_by( process_initiator=g.user @@ -967,7 +980,7 @@ def process_instance_list( # TODO: not sure if this is exactly what is wanted if report_filter.with_tasks_completed_by_me is True: process_instance_query = process_instance_query.filter( - ProcessInstanceModel.status.in_(["complete", "error", "terminated"]) # type: ignore + ProcessInstanceModel.status.in_(ProcessInstanceModel.terminal_statuses()) # type: ignore ) # process_instance_query = process_instance_query.join(UserModel, UserModel.id == ProcessInstanceModel.process_initiator_id) # process_instance_query = process_instance_query.add_columns(UserModel.username) @@ -996,7 +1009,7 @@ def process_instance_list( if report_filter.with_tasks_completed_by_my_group is True: process_instance_query = process_instance_query.filter( - ProcessInstanceModel.status.in_(["complete", "error", "terminated"]) # type: ignore + ProcessInstanceModel.status.in_(ProcessInstanceModel.terminal_statuses()) # type: ignore ) process_instance_query = process_instance_query.join( SpiffStepDetailsModel, @@ -1185,6 +1198,12 @@ def process_instance_delete( """Create_process_instance.""" process_instance = find_process_instance_by_id_or_raise(process_instance_id) + if not process_instance.has_terminal_status(): + raise ProcessInstanceCannotBeDeletedError( + f"Process instance ({process_instance.id}) cannot be deleted since it does not have a terminal status. " + f"Current status is {process_instance.status}." + ) + # (Pdb) db.session.delete # > db.session.query(SpiffLoggingModel).filter_by( @@ -1680,6 +1699,13 @@ def task_submit( """Task_submit_user_data.""" principal = find_principal_or_raise() process_instance = find_process_instance_by_id_or_raise(process_instance_id) + if not process_instance.can_submit_task(): + raise ApiError( + error_code="process_instance_not_runnable", + message=f"Process Instance ({process_instance.id}) has status " + f"{process_instance.status} which does not allow tasks to be submitted.", + status_code=400, + ) processor = ProcessInstanceProcessor(process_instance) spiff_task = get_spiff_task_from_process_instance( @@ -2141,6 +2167,11 @@ def update_task_data( ProcessInstanceModel.id == int(process_instance_id) ).first() if process_instance: + if process_instance.status != "suspended": + raise ProcessInstanceTaskDataCannotBeUpdatedError( + f"The process instance needs to be suspended to udpate the task-data. It is currently: {process_instance.status}" + ) + process_instance_bpmn_json_dict = json.loads(process_instance.bpmn_json) if "new_task_data" in body: new_task_data_str: str = body["new_task_data"] diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/git_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/git_service.py index 8ef952c3c..495603cf0 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/git_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/git_service.py @@ -100,6 +100,7 @@ class GitService: branch_name_to_use, git_username, git_email, + current_app.config["GIT_USER_PASSWORD"], ] return cls.run_shell_command_to_get_stdout(shell_command) diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py index 3bc21456e..1071ee259 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -1375,7 +1375,7 @@ class TestProcessApi(BaseTest): assert response.json is not None response = client.post( - f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/terminate", + f"/v1.0/process-instance-terminate/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}", headers=self.logged_in_headers(with_super_admin_user), ) assert response.status_code == 200 @@ -1396,15 +1396,13 @@ class TestProcessApi(BaseTest): ) -> None: """Test_process_instance_delete.""" process_group_id = "my_process_group" - process_model_id = "user_task" - bpmn_file_name = "user_task.bpmn" - bpmn_file_location = "user_task" + process_model_id = "sample" + bpmn_file_location = "sample" process_model_identifier = self.create_group_and_model_with_bpmn( client, with_super_admin_user, process_group_id=process_group_id, process_model_id=process_model_id, - bpmn_file_name=bpmn_file_name, bpmn_file_location=bpmn_file_location, ) @@ -1420,11 +1418,13 @@ class TestProcessApi(BaseTest): headers=self.logged_in_headers(with_super_admin_user), ) assert response.json is not None + assert response.status_code == 200 delete_response = client.delete( 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), ) + assert delete_response.json["ok"] is True assert delete_response.status_code == 200 def test_task_show( @@ -2421,7 +2421,7 @@ class TestProcessApi(BaseTest): assert process_instance.status == "user_input_required" client.post( - f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/suspend", + f"/v1.0/process-instance-suspend/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}", headers=self.logged_in_headers(with_super_admin_user), ) process_instance = ProcessInstanceService().get_process_instance( @@ -2429,15 +2429,25 @@ class TestProcessApi(BaseTest): ) assert process_instance.status == "suspended" - # TODO: Why can I run a suspended process instance? response = client.post( f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/run", headers=self.logged_in_headers(with_super_admin_user), ) + process_instance = ProcessInstanceService().get_process_instance( + process_instance_id + ) + assert process_instance.status == "suspended" + assert response.status_code == 400 - # task = response.json['next_task'] - - print("test_process_instance_suspend") + response = client.post( + f"/v1.0/process-instance-resume/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}", + headers=self.logged_in_headers(with_super_admin_user), + ) + assert response.status_code == 200 + process_instance = ProcessInstanceService().get_process_instance( + process_instance_id + ) + assert process_instance.status == "waiting" def test_script_unit_test_run( self, diff --git a/spiffworkflow-frontend/src/classes/ProcessInstanceClass.tsx b/spiffworkflow-frontend/src/classes/ProcessInstanceClass.tsx new file mode 100644 index 000000000..d44569cd4 --- /dev/null +++ b/spiffworkflow-frontend/src/classes/ProcessInstanceClass.tsx @@ -0,0 +1,5 @@ +export default class ProcessInstanceClass { + static terminalStatuses() { + return ['complete', 'error', 'terminated']; + } +} diff --git a/spiffworkflow-frontend/src/hooks/UriListForPermissions.tsx b/spiffworkflow-frontend/src/hooks/UriListForPermissions.tsx index 4ba04352b..a9895c71c 100644 --- a/spiffworkflow-frontend/src/hooks/UriListForPermissions.tsx +++ b/spiffworkflow-frontend/src/hooks/UriListForPermissions.tsx @@ -11,6 +11,9 @@ export const useUriListForPermissions = () => { processGroupShowPath: `/v1.0/process-groups/${params.process_group_id}`, processInstanceCreatePath: `/v1.0/process-instances/${params.process_model_id}`, processInstanceActionPath: `/v1.0/process-instances/${params.process_model_id}/${params.process_instance_id}`, + processInstanceResumePath: `/v1.0/process-instance-resume/${params.process_model_id}/${params.process_instance_id}`, + processInstanceSuspendPath: `/v1.0/process-instance-suspend/${params.process_model_id}/${params.process_instance_id}`, + processInstanceTerminatePath: `/v1.0/process-instance-terminate/${params.process_model_id}/${params.process_instance_id}`, processInstanceListPath: '/v1.0/process-instances', processInstanceLogListPath: `/v1.0/logs/${params.process_model_id}/${params.process_instance_id}`, processInstanceReportListPath: '/v1.0/process-instances/reports', diff --git a/spiffworkflow-frontend/src/interfaces.ts b/spiffworkflow-frontend/src/interfaces.ts index b0ab6208a..7805249be 100644 --- a/spiffworkflow-frontend/src/interfaces.ts +++ b/spiffworkflow-frontend/src/interfaces.ts @@ -52,6 +52,10 @@ export interface ProcessInstance { id: number; process_model_identifier: string; process_model_display_name: string; + status: string; + start_in_seconds: number | null; + end_in_seconds: number | null; + bpmn_xml_file_contents?: string; spiff_step?: number; } diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx index 88e5e3bb7..db89bee87 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx @@ -45,6 +45,7 @@ import { ProcessInstanceTask, } from '../interfaces'; import { usePermissionFetcher } from '../hooks/PermissionService'; +import ProcessInstanceClass from '../classes/ProcessInstanceClass'; export default function ProcessInstanceShow() { const navigate = useNavigate(); @@ -74,9 +75,9 @@ export default function ProcessInstanceShow() { [targetUris.processInstanceActionPath]: ['DELETE'], [targetUris.processInstanceLogListPath]: ['GET'], [targetUris.processModelShowPath]: ['PUT'], - [`${targetUris.processInstanceActionPath}/suspend`]: ['POST'], - [`${targetUris.processInstanceActionPath}/terminate`]: ['POST'], - [`${targetUris.processInstanceActionPath}/resume`]: ['POST'], + [`${targetUris.processInstanceResumePath}`]: ['POST'], + [`${targetUris.processInstanceSuspendPath}`]: ['POST'], + [`${targetUris.processInstanceTerminatePath}`]: ['POST'], }; const { ability, permissionsLoaded } = usePermissionFetcher( permissionRequestData @@ -146,7 +147,7 @@ export default function ProcessInstanceShow() { const terminateProcessInstance = () => { HttpService.makeCallToBackend({ - path: `${targetUris.processInstanceActionPath}/terminate`, + path: `${targetUris.processInstanceTerminatePath}`, successCallback: refreshPage, httpMethod: 'POST', }); @@ -154,7 +155,7 @@ export default function ProcessInstanceShow() { const suspendProcessInstance = () => { HttpService.makeCallToBackend({ - path: `${targetUris.processInstanceActionPath}/suspend`, + path: `${targetUris.processInstanceSuspendPath}`, successCallback: refreshPage, httpMethod: 'POST', }); @@ -162,7 +163,7 @@ export default function ProcessInstanceShow() { const resumeProcessInstance = () => { HttpService.makeCallToBackend({ - path: `${targetUris.processInstanceActionPath}/resume`, + path: `${targetUris.processInstanceResumePath}`, successCallback: refreshPage, httpMethod: 'POST', }); @@ -183,29 +184,23 @@ export default function ProcessInstanceShow() { return taskIds; }; - const currentSpiffStep = (processInstanceToUse: any) => { - if (typeof params.spiff_step === 'undefined') { - return processInstanceToUse.spiff_step; + const currentSpiffStep = () => { + if (processInstance && typeof params.spiff_step === 'undefined') { + return processInstance.spiff_step || 0; } return Number(params.spiff_step); }; - const showingFirstSpiffStep = (processInstanceToUse: any) => { - return currentSpiffStep(processInstanceToUse) === 1; + const showingFirstSpiffStep = () => { + return currentSpiffStep() === 1; }; - const showingLastSpiffStep = (processInstanceToUse: any) => { - return ( - currentSpiffStep(processInstanceToUse) === processInstanceToUse.spiff_step - ); + const showingLastSpiffStep = () => { + return processInstance && currentSpiffStep() === processInstance.spiff_step; }; - const spiffStepLink = ( - processInstanceToUse: any, - label: any, - distance: number - ) => { + const spiffStepLink = (label: any, distance: number) => { const processIdentifier = searchParams.get('process_identifier'); let queryParams = ''; if (processIdentifier) { @@ -217,32 +212,35 @@ export default function ProcessInstanceShow() { data-qa="process-instance-step-link" to={`/admin/process-instances/${params.process_model_id}/${ params.process_instance_id - }/${currentSpiffStep(processInstanceToUse) + distance}${queryParams}`} + }/${currentSpiffStep() + distance}${queryParams}`} > {label} ); }; - const previousStepLink = (processInstanceToUse: any) => { - if (showingFirstSpiffStep(processInstanceToUse)) { + const previousStepLink = () => { + if (showingFirstSpiffStep()) { return null; } - return spiffStepLink(processInstanceToUse, , -1); + return spiffStepLink(, -1); }; - const nextStepLink = (processInstanceToUse: any) => { - if (showingLastSpiffStep(processInstanceToUse)) { + const nextStepLink = () => { + if (showingLastSpiffStep()) { return null; } - return spiffStepLink(processInstanceToUse, , 1); + return spiffStepLink(, 1); }; - const getInfoTag = (processInstanceToUse: any) => { + const getInfoTag = () => { + if (!processInstance) { + return null; + } const currentEndDate = convertSecondsToFormattedDateTime( - processInstanceToUse.end_in_seconds + processInstance.end_in_seconds || 0 ); let currentEndDateTag; if (currentEndDate) { @@ -253,7 +251,7 @@ export default function ProcessInstanceShow() { {convertSecondsToFormattedDateTime( - processInstanceToUse.end_in_seconds + processInstance.end_in_seconds || 0 ) || 'N/A'} @@ -261,13 +259,13 @@ export default function ProcessInstanceShow() { } let statusIcon = ; - if (processInstanceToUse.status === 'suspended') { + if (processInstance.status === 'suspended') { statusIcon = ; - } else if (processInstanceToUse.status === 'complete') { + } else if (processInstance.status === 'complete') { statusIcon = ; - } else if (processInstanceToUse.status === 'terminated') { + } else if (processInstance.status === 'terminated') { statusIcon = ; - } else if (processInstanceToUse.status === 'error') { + } else if (processInstance.status === 'error') { statusIcon = ; } @@ -279,7 +277,7 @@ export default function ProcessInstanceShow() { {convertSecondsToFormattedDateTime( - processInstanceToUse.start_in_seconds + processInstance.start_in_seconds || 0 )} @@ -290,7 +288,7 @@ export default function ProcessInstanceShow() { - {processInstanceToUse.status} {statusIcon} + {processInstance.status} {statusIcon} @@ -333,11 +331,10 @@ export default function ProcessInstanceShow() { ); }; - const terminateButton = (processInstanceToUse: any) => { + const terminateButton = () => { if ( - ['complete', 'terminated', 'error'].indexOf( - processInstanceToUse.status - ) === -1 + processInstance && + !ProcessInstanceClass.terminalStatuses().includes(processInstance.status) ) { return ( @@ -354,11 +351,12 @@ export default function ProcessInstanceShow() { return
; }; - const suspendButton = (processInstanceToUse: any) => { + const suspendButton = () => { if ( - ['complete', 'terminated', 'error', 'suspended'].indexOf( - processInstanceToUse.status - ) === -1 + processInstance && + !ProcessInstanceClass.terminalStatuses() + .concat(['suspended']) + .includes(processInstance.status) ) { return (