diff --git a/spiffworkflow-backend/migrations/env.py b/spiffworkflow-backend/migrations/env.py
index 68feded2a..630e381ad 100644
--- a/spiffworkflow-backend/migrations/env.py
+++ b/spiffworkflow-backend/migrations/env.py
@@ -1,5 +1,3 @@
-from __future__ import with_statement
-
import logging
from logging.config import fileConfig
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py
index 3bba5aed6..e00e7cacf 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py
@@ -2,10 +2,9 @@
from dataclasses import dataclass
from typing import Optional
-from sqlalchemy import ForeignKey
-
from flask_bpmn.models.db import db
from flask_bpmn.models.db import SpiffworkflowBaseDBModel
+from sqlalchemy import ForeignKey
from sqlalchemy.orm import deferred
from spiffworkflow_backend.models.group import GroupModel
@@ -22,4 +21,6 @@ class SpiffStepDetailsModel(SpiffworkflowBaseDBModel):
task_json: str = deferred(db.Column(db.JSON, nullable=False)) # type: ignore
timestamp: float = db.Column(db.DECIMAL(17, 6), nullable=False)
completed_by_user_id: int = db.Column(db.Integer, nullable=True)
- lane_assignment_id: Optional[int] = db.Column(ForeignKey(GroupModel.id), nullable=True)
+ lane_assignment_id: Optional[int] = db.Column(
+ ForeignKey(GroupModel.id), nullable=True
+ )
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 c4044b2a2..67f91ab19 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py
@@ -1264,7 +1264,9 @@ def task_submit(
if terminate_loop and spiff_task.is_looping():
spiff_task.terminate_loop()
- active_task = ActiveTaskModel.query.filter_by(process_instance_id=process_instance_id, task_id=task_id).first()
+ active_task = ActiveTaskModel.query.filter_by(
+ process_instance_id=process_instance_id, task_id=task_id
+ ).first()
if active_task is None:
raise (
ApiError(
@@ -1274,7 +1276,13 @@ def task_submit(
)
)
- ProcessInstanceService.complete_form_task(processor=processor, spiff_task=spiff_task, data=body, user=g.user, active_task=active_task)
+ ProcessInstanceService.complete_form_task(
+ processor=processor,
+ spiff_task=spiff_task,
+ data=body,
+ user=g.user,
+ active_task=active_task,
+ )
# If we need to update all tasks, then get the next ready task and if it a multi-instance with the same
# task spec, complete that form as well.
diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py
index ccf362ab7..aac9b1760 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py
@@ -6,9 +6,9 @@ from typing import List
from flask import current_app
from flask_bpmn.api.api_error import ApiError
from flask_bpmn.models.db import db
-from SpiffWorkflow.task import Task as SpiffTask
-from spiffworkflow_backend.models.active_task import ActiveTaskModel # type: ignore
+from SpiffWorkflow.task import Task as SpiffTask # type: ignore
+from spiffworkflow_backend.models.active_task import ActiveTaskModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceApi
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
@@ -189,7 +189,7 @@ class ProcessInstanceService:
spiff_task: SpiffTask,
data: dict[str, Any],
user: UserModel,
- active_task: ActiveTaskModel
+ active_task: ActiveTaskModel,
) -> None:
"""All the things that need to happen when we complete a form.
diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py
index 9e65b9707..f1834ab3a 100644
--- a/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py
+++ b/spiffworkflow-backend/tests/spiffworkflow_backend/scripts/test_get_localtime.py
@@ -74,7 +74,11 @@ class TestGetLocaltime(BaseTest):
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {"timezone": "US/Pacific"}, initiator_user
+ processor,
+ spiff_task,
+ {"timezone": "US/Pacific"},
+ initiator_user,
+ active_task,
)
active_task = process_instance.active_tasks[0]
diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py
index 916347b35..36f077435 100644
--- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py
+++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_authorization_service.py
@@ -126,7 +126,7 @@ class TestAuthorizationService(BaseTest):
active_task.task_name, processor.bpmn_process_instance
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
active_task = process_instance.active_tasks[0]
@@ -137,5 +137,5 @@ class TestAuthorizationService(BaseTest):
{"username": "testuser2", "sub": "open_id"}
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, finance_user
+ processor, spiff_task, {}, finance_user, active_task
)
diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py
index 6bd1cca6d..18c115617 100644
--- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py
+++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_dot_notation.py
@@ -44,6 +44,7 @@ class TestDotNotation(BaseTest):
process_instance = ProcessInstanceService().get_process_instance(
process_instance_id
)
+ active_task = process_instance.active_tasks[0]
processor = ProcessInstanceProcessor(process_instance)
processor.do_engine_steps(save=True)
@@ -57,7 +58,7 @@ class TestDotNotation(BaseTest):
"invoice.dueDate": "09/30/2022",
}
ProcessInstanceService.complete_form_task(
- processor, user_task, form_data, with_super_admin_user
+ processor, user_task, form_data, with_super_admin_user, active_task
)
expected = {
diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py
index ad7aefe34..f0de77aa7 100644
--- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py
+++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py
@@ -91,10 +91,10 @@ class TestProcessInstanceProcessor(BaseTest):
)
with pytest.raises(UserDoesNotHaveAccessToTaskError):
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, finance_user
+ processor, spiff_task, {}, finance_user, active_task
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
assert len(process_instance.active_tasks) == 1
@@ -108,11 +108,11 @@ class TestProcessInstanceProcessor(BaseTest):
)
with pytest.raises(UserDoesNotHaveAccessToTaskError):
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, finance_user
+ processor, spiff_task, {}, finance_user, active_task
)
assert len(process_instance.active_tasks) == 1
active_task = process_instance.active_tasks[0]
@@ -124,7 +124,7 @@ class TestProcessInstanceProcessor(BaseTest):
active_task.task_name, processor.bpmn_process_instance
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
assert process_instance.status == ProcessInstanceStatus.complete.value
@@ -173,10 +173,10 @@ class TestProcessInstanceProcessor(BaseTest):
)
with pytest.raises(UserDoesNotHaveAccessToTaskError):
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, finance_user_three
+ processor, spiff_task, {}, finance_user_three, active_task
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
assert len(process_instance.active_tasks) == 1
@@ -190,12 +190,12 @@ class TestProcessInstanceProcessor(BaseTest):
)
with pytest.raises(UserDoesNotHaveAccessToTaskError):
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
g.user = finance_user_three
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, finance_user_three
+ processor, spiff_task, {}, finance_user_three, active_task
)
assert len(process_instance.active_tasks) == 1
active_task = process_instance.active_tasks[0]
@@ -208,11 +208,11 @@ class TestProcessInstanceProcessor(BaseTest):
)
with pytest.raises(UserDoesNotHaveAccessToTaskError):
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, finance_user_four
+ processor, spiff_task, {}, finance_user_four, active_task
)
assert len(process_instance.active_tasks) == 1
active_task = process_instance.active_tasks[0]
@@ -224,7 +224,7 @@ class TestProcessInstanceProcessor(BaseTest):
active_task.task_name, processor.bpmn_process_instance
)
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
assert len(process_instance.active_tasks) == 1
@@ -234,8 +234,10 @@ class TestProcessInstanceProcessor(BaseTest):
)
with pytest.raises(UserDoesNotHaveAccessToTaskError):
ProcessInstanceService.complete_form_task(
- processor, spiff_task, {}, initiator_user
+ processor, spiff_task, {}, initiator_user, active_task
)
- ProcessInstanceService.complete_form_task(processor, spiff_task, {}, testadmin1)
+ ProcessInstanceService.complete_form_task(
+ processor, spiff_task, {}, testadmin1, active_task
+ )
assert process_instance.status == ProcessInstanceStatus.complete.value
diff --git a/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx b/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx
new file mode 100644
index 000000000..fe6652951
--- /dev/null
+++ b/spiffworkflow-frontend/src/components/MyCompletedInstances.tsx
@@ -0,0 +1,13 @@
+import ProcessInstanceListTable from './ProcessInstanceListTable';
+
+const paginationQueryParamPrefix = 'my_completed_instances';
+
+export default function MyCompletedInstances() {
+ return (
+
+ );
+}
diff --git a/spiffworkflow-frontend/src/components/PaginationForTable.tsx b/spiffworkflow-frontend/src/components/PaginationForTable.tsx
index 19d098ffd..70da531d9 100644
--- a/spiffworkflow-frontend/src/components/PaginationForTable.tsx
+++ b/spiffworkflow-frontend/src/components/PaginationForTable.tsx
@@ -13,7 +13,6 @@ type OwnProps = {
perPageOptions?: number[];
pagination: PaginationObject | null;
tableToDisplay: any;
- queryParamString?: string;
paginationQueryParamPrefix?: string;
};
diff --git a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx
index 81a416f30..ceb0e997a 100644
--- a/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx
+++ b/spiffworkflow-frontend/src/components/ProcessInstanceListTable.tsx
@@ -46,12 +46,14 @@ type OwnProps = {
filtersEnabled?: boolean;
processModelFullIdentifier?: string;
paginationQueryParamPrefix?: string;
+ perPageOptions?: number[];
};
export default function ProcessInstanceListTable({
filtersEnabled = true,
processModelFullIdentifier,
paginationQueryParamPrefix,
+ perPageOptions,
}: OwnProps) {
const params = useParams();
const [searchParams] = useSearchParams();
@@ -108,12 +110,17 @@ export default function ProcessInstanceListTable({
setPagination(result.pagination);
}
function getProcessInstances() {
- const { page, perPage } = getPageInfoFromSearchParams(
+ // eslint-disable-next-line prefer-const
+ let { page, perPage } = getPageInfoFromSearchParams(
searchParams,
undefined,
undefined,
paginationQueryParamPrefix
);
+ if (perPageOptions && !perPageOptions.includes(perPage)) {
+ // eslint-disable-next-line prefer-destructuring
+ perPage = perPageOptions[1];
+ }
let queryParamString = `per_page=${perPage}&page=${page}`;
Object.keys(parametersToAlwaysFilterBy).forEach((paramName: string) => {
@@ -200,6 +207,9 @@ export default function ProcessInstanceListTable({
parametersToAlwaysFilterBy,
parametersToGetFromSearchParams,
filtersEnabled,
+ paginationQueryParamPrefix,
+ processModelFullIdentifier,
+ perPageOptions,
]);
// does the comparison, but also returns false if either argument
@@ -307,25 +317,6 @@ export default function ProcessInstanceListTable({
);
};
- const getSearchParamsAsQueryString = () => {
- let queryParamString = '';
- Object.keys(parametersToAlwaysFilterBy).forEach((paramName) => {
- const searchParamValue = searchParams.get(paramName);
- if (searchParamValue) {
- queryParamString += `&${paramName}=${searchParamValue}`;
- }
- });
-
- Object.keys(parametersToGetFromSearchParams).forEach(
- (paramName: string) => {
- if (searchParams.get(paramName)) {
- queryParamString += `&${paramName}=${searchParams.get(paramName)}`;
- }
- }
- );
- return queryParamString;
- };
-
const processStatusSearch = () => {
return (
{filterComponent()}
@@ -550,8 +546,8 @@ export default function ProcessInstanceListTable({
perPage={perPage}
pagination={pagination}
tableToDisplay={buildTable()}
- queryParamString={getSearchParamsAsQueryString()}
paginationQueryParamPrefix={paginationQueryParamPrefix}
+ perPageOptions={perPageOptions}
/>
>
);
diff --git a/spiffworkflow-frontend/src/routes/CompletedInstances.tsx b/spiffworkflow-frontend/src/routes/CompletedInstances.tsx
index 8b5dbcac7..237c21f3b 100644
--- a/spiffworkflow-frontend/src/routes/CompletedInstances.tsx
+++ b/spiffworkflow-frontend/src/routes/CompletedInstances.tsx
@@ -1,3 +1,5 @@
+import MyCompletedInstances from '../components/MyCompletedInstances';
+
export default function CompletedInstances() {
- return <>>;
+ return ;
}
diff --git a/spiffworkflow-frontend/src/routes/MessageInstanceList.tsx b/spiffworkflow-frontend/src/routes/MessageInstanceList.tsx
index 62e189b6c..09d283167 100644
--- a/spiffworkflow-frontend/src/routes/MessageInstanceList.tsx
+++ b/spiffworkflow-frontend/src/routes/MessageInstanceList.tsx
@@ -94,14 +94,8 @@ export default function MessageInstanceList() {
if (pagination) {
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
- let queryParamString = '';
let breadcrumbElement = null;
if (searchParams.get('process_instance_id')) {
- queryParamString += `&process_group_id=${searchParams.get(
- 'process_group_id'
- )}&process_model_id=${searchParams.get(
- 'process_model_id'
- )}&process_instance_id=${searchParams.get('process_instance_id')}`;
breadcrumbElement = (
>
);