From e9827d0d5e9351e4a5ddc21a9393859697770c74 Mon Sep 17 00:00:00 2001 From: jbirddog <100367399+jbirddog@users.noreply.github.com> Date: Mon, 1 May 2023 10:32:19 -0400 Subject: [PATCH] Stable last updated time for human tasks with timers (#231) --- .../migrations/versions/664bb2f00694_.py | 32 +++++++++++++++++++ .../models/process_instance.py | 2 ++ .../process_instance_report_service.py | 6 ++-- .../services/workflow_execution_service.py | 1 + .../components/ProcessInstanceListTable.tsx | 8 +++++ 5 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 spiffworkflow-backend/migrations/versions/664bb2f00694_.py diff --git a/spiffworkflow-backend/migrations/versions/664bb2f00694_.py b/spiffworkflow-backend/migrations/versions/664bb2f00694_.py new file mode 100644 index 00000000..6da1f539 --- /dev/null +++ b/spiffworkflow-backend/migrations/versions/664bb2f00694_.py @@ -0,0 +1,32 @@ +"""empty message + +Revision ID: 664bb2f00694 +Revises: 0c7428378d6e +Create Date: 2023-04-27 13:32:04.143969 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '664bb2f00694' +down_revision = '0c7428378d6e' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('process_instance', schema=None) as batch_op: + batch_op.add_column(sa.Column('task_updated_at_in_seconds', sa.Integer(), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('process_instance', schema=None) as batch_op: + batch_op.drop_column('task_updated_at_in_seconds') + + # ### end Alembic commands ### diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index 009a7486..61887102 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -95,6 +95,7 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): start_in_seconds: int | None = db.Column(db.Integer, index=True) end_in_seconds: int | None = db.Column(db.Integer, index=True) + task_updated_at_in_seconds: int = db.Column(db.Integer, nullable=True) updated_at_in_seconds: int = db.Column(db.Integer) created_at_in_seconds: int = db.Column(db.Integer) status: str = db.Column(db.String(50), index=True) @@ -122,6 +123,7 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): "bpmn_version_control_identifier": self.bpmn_version_control_identifier, "bpmn_version_control_type": self.bpmn_version_control_type, "process_initiator_username": self.process_initiator.username, + "task_updated_at_in_seconds": self.task_updated_at_in_seconds, } def serialized_with_metadata(self) -> dict[str, Any]: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py index 04510969..9a33dbc1 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py @@ -161,7 +161,7 @@ class ProcessInstanceReportService: {"Header": "Task", "accessor": "task_title"}, {"Header": "Waiting For", "accessor": "waiting_for"}, {"Header": "Started", "accessor": "start_in_seconds"}, - {"Header": "Last Updated", "accessor": "updated_at_in_seconds"}, + {"Header": "Last Updated", "accessor": "task_updated_at_in_seconds"}, {"Header": "status", "accessor": "status"}, ], "filter_by": [ @@ -186,7 +186,7 @@ class ProcessInstanceReportService: {"Header": "Task", "accessor": "task_title"}, {"Header": "Started By", "accessor": "process_initiator_username"}, {"Header": "Started", "accessor": "start_in_seconds"}, - {"Header": "Last Updated", "accessor": "updated_at_in_seconds"}, + {"Header": "Last Updated", "accessor": "task_updated_at_in_seconds"}, ], "filter_by": [ {"field_name": "with_tasks_i_can_complete", "field_value": "true"}, @@ -208,7 +208,7 @@ class ProcessInstanceReportService: {"Header": "Task", "accessor": "task_title"}, {"Header": "Started By", "accessor": "process_initiator_username"}, {"Header": "Started", "accessor": "start_in_seconds"}, - {"Header": "Last Updated", "accessor": "updated_at_in_seconds"}, + {"Header": "Last Updated", "accessor": "task_updated_at_in_seconds"}, ], "filter_by": [ { diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/workflow_execution_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/workflow_execution_service.py index db29f3ba..13ac5a7f 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/workflow_execution_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/workflow_execution_service.py @@ -157,6 +157,7 @@ class TaskModelSavingDelegate(EngineStepDelegate): # # self._add_parents(spiff_task) self.last_completed_spiff_task = spiff_task + self.process_instance.task_updated_at_in_seconds = round(time.time()) if self.secondary_engine_step_delegate: self.secondary_engine_step_delegate.did_complete_task(spiff_task) diff --git a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx index 778c1713..40e10ba7 100644 --- a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx +++ b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx @@ -1375,6 +1375,7 @@ export default function ProcessInstanceListTable({ start_in_seconds: formatSecondsForDisplay, end_in_seconds: formatSecondsForDisplay, updated_at_in_seconds: formatSecondsForDisplay, + task_updated_at_in_seconds: formatSecondsForDisplay, }; const formatter = reportColumnFormatters[column.accessor] ?? defaultFormatter; @@ -1400,6 +1401,13 @@ export default function ProcessInstanceListTable({ /> ); } + if (column.accessor === 'task_updated_at_in_seconds') { + return ( + + ); + } return ( // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions