From fcccbdc845f2d466ef7cf8a793afa7c9d666d38a Mon Sep 17 00:00:00 2001 From: jasquat Date: Mon, 14 Nov 2022 12:06:39 -0500 Subject: [PATCH] added remaining task tables w/ burnettk --- .../src/spiffworkflow_backend/api.yml | 33 ++++- .../routes/process_api_blueprint.py | 49 +++++- .../components/TasksForMyOpenProcesses.tsx | 2 +- ...rtedByOthers.tsx => TasksWaitingForMe.tsx} | 6 +- .../components/TasksWaitingForMyGroups.tsx | 139 ++++++++++++++++++ .../src/routes/GroupedTasks.tsx | 7 +- 6 files changed, 221 insertions(+), 15 deletions(-) rename spiffworkflow-frontend/src/components/{MyTasksForProcessesStartedByOthers.tsx => TasksWaitingForMe.tsx} (95%) create mode 100644 spiffworkflow-frontend/src/components/TasksWaitingForMyGroups.tsx diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index a87d5a2f..f2135cb3 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -901,7 +901,7 @@ paths: items: $ref: "#/components/schemas/Task" - /tasks/for-processes-started-by-others: + /tasks/for-me: parameters: - name: page in: query @@ -918,7 +918,36 @@ paths: get: tags: - Process Instances - operationId: spiffworkflow_backend.routes.process_api_blueprint.task_list_for_processes_started_by_others + operationId: spiffworkflow_backend.routes.process_api_blueprint.task_list_for_me + summary: returns the list of tasks for given user's open process instances + responses: + "200": + description: list of tasks + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Task" + + /tasks/for-my-groups: + parameters: + - name: page + in: query + required: false + description: The page number to return. Defaults to page 1. + schema: + type: integer + - name: per_page + in: query + required: false + description: The page number to return. Defaults to page 1. + schema: + type: integer + get: + tags: + - Process Instances + operationId: spiffworkflow_backend.routes.process_api_blueprint.task_list_for_my_groups summary: returns the list of tasks for given user's open process instances responses: "200": 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 98f8abce..d3f5c274 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -1029,7 +1029,17 @@ def task_list_for_my_open_processes( return get_tasks(page=page, per_page=per_page) -def task_list_for_processes_started_by_others( +def task_list_for_me(page: int = 1, per_page: int = 100) -> flask.wrappers.Response: + """Task_list_for_processes_started_by_others.""" + return get_tasks( + processes_started_by_user=False, + has_lane_assignment_id=False, + page=page, + per_page=per_page, + ) + + +def task_list_for_my_groups( page: int = 1, per_page: int = 100 ) -> flask.wrappers.Response: """Task_list_for_processes_started_by_others.""" @@ -1037,14 +1047,21 @@ def task_list_for_processes_started_by_others( def get_tasks( - processes_started_by_user: bool = True, page: int = 1, per_page: int = 100 + processes_started_by_user: bool = True, + has_lane_assignment_id: bool = True, + page: int = 1, + per_page: int = 100, ) -> flask.wrappers.Response: """Get_tasks.""" user_id = g.user.id + + # use distinct to ensure we only get one row per active task otherwise + # we can get back multiple for the same active task row which throws off + # pagination later on + # https://stackoverflow.com/q/34582014/6090676 active_tasks_query = ( - ActiveTaskModel.query.outerjoin( - GroupModel, GroupModel.id == ActiveTaskModel.lane_assignment_id - ) + ActiveTaskModel.query.distinct() + .outerjoin(GroupModel, GroupModel.id == ActiveTaskModel.lane_assignment_id) .join(ProcessInstanceModel) .join(UserModel, UserModel.id == ProcessInstanceModel.process_initiator_id) ) @@ -1052,11 +1069,29 @@ def get_tasks( if processes_started_by_user: active_tasks_query = active_tasks_query.filter( ProcessInstanceModel.process_initiator_id == user_id - ).outerjoin(ActiveTaskUserModel, and_(ActiveTaskUserModel.user_id == user_id)) + ).outerjoin( + ActiveTaskUserModel, + and_( + ActiveTaskUserModel.user_id == user_id, + ActiveTaskModel.id == ActiveTaskUserModel.active_task_id, + ), + ) else: active_tasks_query = active_tasks_query.filter( ProcessInstanceModel.process_initiator_id != user_id - ).join(ActiveTaskUserModel, and_(ActiveTaskUserModel.user_id == user_id)) + ).join( + ActiveTaskUserModel, + and_( + ActiveTaskUserModel.user_id == user_id, + ActiveTaskModel.id == ActiveTaskUserModel.active_task_id, + ), + ) + if has_lane_assignment_id: + active_tasks_query = active_tasks_query.filter( + ActiveTaskModel.lane_assignment_id.is_not(None) # type: ignore + ) + else: + active_tasks_query = active_tasks_query.filter(ActiveTaskModel.lane_assignment_id.is_(None)) # type: ignore active_tasks = active_tasks_query.add_columns( ProcessInstanceModel.process_model_identifier, diff --git a/spiffworkflow-frontend/src/components/TasksForMyOpenProcesses.tsx b/spiffworkflow-frontend/src/components/TasksForMyOpenProcesses.tsx index 8a2f0bdd..5c3a0ec6 100644 --- a/spiffworkflow-frontend/src/components/TasksForMyOpenProcesses.tsx +++ b/spiffworkflow-frontend/src/components/TasksForMyOpenProcesses.tsx @@ -124,7 +124,7 @@ export default function MyOpenProcesses() { perPageOptions={[2, PER_PAGE_FOR_TASKS_ON_HOME_PAGE, 25]} pagination={pagination} tableToDisplay={buildTable()} - path="/tasks/for-my-open-processes" + path="/tasks/grouped" /> ); diff --git a/spiffworkflow-frontend/src/components/MyTasksForProcessesStartedByOthers.tsx b/spiffworkflow-frontend/src/components/TasksWaitingForMe.tsx similarity index 95% rename from spiffworkflow-frontend/src/components/MyTasksForProcessesStartedByOthers.tsx rename to spiffworkflow-frontend/src/components/TasksWaitingForMe.tsx index d1fafd39..a24eeb8c 100644 --- a/spiffworkflow-frontend/src/components/MyTasksForProcessesStartedByOthers.tsx +++ b/spiffworkflow-frontend/src/components/TasksWaitingForMe.tsx @@ -13,7 +13,7 @@ import { PaginationObject } from '../interfaces'; const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5; -export default function MyTasksForProcessesStartedByOthers() { +export default function TasksWaitingForMe() { const [searchParams] = useSearchParams(); const [tasks, setTasks] = useState([]); const [pagination, setPagination] = useState(null); @@ -28,7 +28,7 @@ export default function MyTasksForProcessesStartedByOthers() { setPagination(result.pagination); }; HttpService.makeCallToBackend({ - path: `/tasks/for-processes-started-by-others?per_page=${perPage}&page=${page}`, + path: `/tasks/for-me?per_page=${perPage}&page=${page}`, successCallback: setTasksFromResult, }); }, [searchParams]); @@ -126,7 +126,7 @@ export default function MyTasksForProcessesStartedByOthers() { perPageOptions={[2, PER_PAGE_FOR_TASKS_ON_HOME_PAGE, 25]} pagination={pagination} tableToDisplay={buildTable()} - path="/tasks/for-my-open-processes" + path="/tasks/grouped" /> ); diff --git a/spiffworkflow-frontend/src/components/TasksWaitingForMyGroups.tsx b/spiffworkflow-frontend/src/components/TasksWaitingForMyGroups.tsx new file mode 100644 index 00000000..6190e0e8 --- /dev/null +++ b/spiffworkflow-frontend/src/components/TasksWaitingForMyGroups.tsx @@ -0,0 +1,139 @@ +import { useEffect, useState } from 'react'; +// @ts-ignore +import { Button, Table } from '@carbon/react'; +import { Link, useSearchParams } from 'react-router-dom'; +import PaginationForTable from './PaginationForTable'; +import { + convertSecondsToFormattedDateTime, + getPageInfoFromSearchParams, + modifyProcessModelPath, +} from '../helpers'; +import HttpService from '../services/HttpService'; +import { PaginationObject } from '../interfaces'; + +const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5; + +export default function TasksForWaitingForMyGroups() { + const [searchParams] = useSearchParams(); + const [tasks, setTasks] = useState([]); + const [pagination, setPagination] = useState(null); + + useEffect(() => { + const { page, perPage } = getPageInfoFromSearchParams( + searchParams, + PER_PAGE_FOR_TASKS_ON_HOME_PAGE + ); + const setTasksFromResult = (result: any) => { + setTasks(result.results); + setPagination(result.pagination); + }; + HttpService.makeCallToBackend({ + path: `/tasks/for-my-groups?per_page=${perPage}&page=${page}`, + successCallback: setTasksFromResult, + }); + }, [searchParams]); + + const buildTable = () => { + const rows = tasks.map((row) => { + const rowToUse = row as any; + const taskUrl = `/tasks/${rowToUse.process_instance_id}/${rowToUse.task_id}`; + const modifiedProcessModelIdentifier = modifyProcessModelPath( + rowToUse.process_model_identifier + ); + return ( + + + + {rowToUse.process_model_display_name} + + + + + View {rowToUse.process_instance_id} + + + + {rowToUse.task_title} + + {rowToUse.username} + {rowToUse.process_instance_status} + {rowToUse.group_identifier || '-'} + + {convertSecondsToFormattedDateTime( + rowToUse.created_at_in_seconds + ) || '-'} + + + {convertSecondsToFormattedDateTime( + rowToUse.updated_at_in_seconds + ) || '-'} + + + + + + ); + }); + return ( + + + + + + + + + + + + + + + {rows} +
Process ModelProcess InstanceTask NameProcess Started ByProcess Instance StatusAssigned GroupProcess StartedProcess UpdatedActions
+ ); + }; + + const tasksComponent = () => { + if (pagination && pagination.total < 1) { + return null; + } + const { page, perPage } = getPageInfoFromSearchParams( + searchParams, + PER_PAGE_FOR_TASKS_ON_HOME_PAGE + ); + return ( + <> +

Tasks waiting for my groups

+ + + ); + }; + + if (pagination) { + return tasksComponent(); + } + return null; +} diff --git a/spiffworkflow-frontend/src/routes/GroupedTasks.tsx b/spiffworkflow-frontend/src/routes/GroupedTasks.tsx index 7312bc55..a08959c5 100644 --- a/spiffworkflow-frontend/src/routes/GroupedTasks.tsx +++ b/spiffworkflow-frontend/src/routes/GroupedTasks.tsx @@ -1,12 +1,15 @@ -import MyTasksForProcessesStartedByOthers from '../components/MyTasksForProcessesStartedByOthers'; import TasksForMyOpenProcesses from '../components/TasksForMyOpenProcesses'; +import TasksWaitingForMe from '../components/TasksWaitingForMe'; +import TasksForWaitingForMyGroups from '../components/TasksWaitingForMyGroups'; export default function GroupedTasks() { return ( <>
- + +
+ ); }