From d747af2d7a88421e98ecaab2ccb357bb89178fe6 Mon Sep 17 00:00:00 2001 From: jasquat Date: Fri, 15 Sep 2023 12:29:07 -0400 Subject: [PATCH] fixed process instance event table on the show page to work a little more intuitively w/ burnettk --- .../services/task_service.py | 1 + .../src/components/ProcessInstanceLogList.tsx | 46 +++++---- .../src/routes/ProcessInstanceShow.tsx | 96 ++++++++++++------- 3 files changed, 91 insertions(+), 52 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py index 97977b20..55497376 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py @@ -385,6 +385,7 @@ class TaskService: subprocesses = spiff_workflow.top_workflow.subprocesses direct_bpmn_process_parent = top_level_process + # BpmnWorkflows do not know their own guid so we have to cycle through subprocesses to find the guid that matches # calling list(subprocesses) to make a copy of the keys so we can change subprocesses while iterating # changing subprocesses happens when running parallel tests # for reasons we do not understand. https://stackoverflow.com/a/11941855/6090676 diff --git a/spiffworkflow-frontend/src/components/ProcessInstanceLogList.tsx b/spiffworkflow-frontend/src/components/ProcessInstanceLogList.tsx index 579bde76..c5dd0e81 100644 --- a/spiffworkflow-frontend/src/components/ProcessInstanceLogList.tsx +++ b/spiffworkflow-frontend/src/components/ProcessInstanceLogList.tsx @@ -21,6 +21,7 @@ import { import HttpService from '../services/HttpService'; import { useUriListForPermissions } from '../hooks/UriListForPermissions'; import { + ObjectWithStringKeysAndValues, PermissionsToCheck, ProcessInstanceEventErrorDetail, ProcessInstanceLogEntry, @@ -71,8 +72,6 @@ export default function ProcessInstanceLogList({ const [showFilterOptions, setShowFilterOptions] = useState(false); const randomNumberBetween0and1 = Math.random(); - searchParams.set('events', isEventsView ? 'true' : 'false'); - let shouldDisplayClearButton = false; if (randomNumberBetween0and1 < 0.05) { // 5% chance of being here @@ -87,20 +86,29 @@ export default function ProcessInstanceLogList({ const tableType = isEventsView ? 'events' : 'milestones'; const paginationQueryParamPrefix = `log-list-${tableType}`; - const updateSearchParams = (value: string, key: string) => { - if (value) { - searchParams.set(key, value); - } else { - searchParams.delete(key); - } + const updateSearchParams = (newValues: ObjectWithStringKeysAndValues) => { + Object.keys(newValues).forEach((key: string) => { + const value = newValues[key]; + if (value === undefined || value === null) { + searchParams.delete(key); + } else { + searchParams.set(key, value); + } + }); setSearchParams(searchParams); }; + const updateFilterValue = (value: string, key: string) => { + const newValues: ObjectWithStringKeysAndValues = {}; + newValues[`${paginationQueryParamPrefix}_page`] = '1'; + newValues[key] = value; + updateSearchParams(newValues); + }; + useEffect(() => { // Clear out any previous results to avoid a "flicker" effect where columns // are updated above the incorrect data. setProcessInstanceLogs([]); - // setPagination(null); const setProcessInstanceLogListFromResult = (result: any) => { setProcessInstanceLogs(result.results); @@ -108,7 +116,6 @@ export default function ProcessInstanceLogList({ }; const searchParamsToInclude = [ - 'events', 'bpmn_name', 'bpmn_identifier', 'task_type', @@ -126,10 +133,12 @@ export default function ProcessInstanceLogList({ paginationQueryParamPrefix ); + const eventsQueryParam = isEventsView ? 'true' : 'false'; + HttpService.makeCallToBackend({ path: `${targetUris.processInstanceLogListPath}?${createSearchParams( pickedSearchParams - )}&page=${page}&per_page=${perPage}`, + )}&page=${page}&per_page=${perPage}&events=${eventsQueryParam}`, successCallback: setProcessInstanceLogListFromResult, }); @@ -393,7 +402,7 @@ export default function ProcessInstanceLogList({ { - updateSearchParams(value.selectedItem, 'bpmn_name'); + updateFilterValue(value.selectedItem, 'bpmn_name'); }} id="task-name-filter" data-qa="task-type-select" @@ -415,7 +424,7 @@ export default function ProcessInstanceLogList({ { - updateSearchParams(value.selectedItem, 'bpmn_identifier'); + updateFilterValue(value.selectedItem, 'bpmn_identifier'); }} id="task-identifier-filter" data-qa="task-type-select" @@ -432,7 +441,7 @@ export default function ProcessInstanceLogList({ { - updateSearchParams(value.selectedItem, 'task_type'); + updateFilterValue(value.selectedItem, 'task_type'); }} id="task-type-select" data-qa="task-type-select" @@ -449,7 +458,7 @@ export default function ProcessInstanceLogList({ { - updateSearchParams(value.selectedItem, 'event_type'); + updateFilterValue(value.selectedItem, 'event_type'); }} id="event-type-select" data-qa="event-type-select" @@ -498,7 +507,12 @@ export default function ProcessInstanceLogList({ ); }; - const { page, perPage } = getPageInfoFromSearchParams(searchParams); + const { page, perPage } = getPageInfoFromSearchParams( + searchParams, + undefined, + undefined, + paginationQueryParamPrefix + ); if (clearAll) { return

Page cleared 👍

; } diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx index f2b7e70b..e6d60e18 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceShow.tsx @@ -85,7 +85,7 @@ type OwnProps = { export default function ProcessInstanceShow({ variant }: OwnProps) { const navigate = useNavigate(); const params = useParams(); - const [searchParams] = useSearchParams(); + const [searchParams, setSearchParams] = useSearchParams(); const eventsThatNeedPayload = ['MessageEventDefinition']; @@ -166,20 +166,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useEffect(() => { - if (processInstance) { - setPageTitle([ - processInstance.process_model_display_name, - `Process Instance ${processInstance.id}`, - ]); - } - return undefined; - }, [processInstance]); - - useEffect(() => { - if (!permissionsLoaded) { - return undefined; - } + const getActionableTaskList = useCallback(() => { const processTaskFailure = (result: any) => { setTasksCallHadError(true); handleAddErrorInUseEffect(result); @@ -195,19 +182,6 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { } setTasks(results); }; - let queryParams = ''; - const processIdentifier = searchParams.get('process_identifier'); - if (processIdentifier) { - queryParams = `?process_identifier=${processIdentifier}`; - } - let apiPath = '/process-instances/for-me'; - if (variant === 'all') { - apiPath = '/process-instances'; - } - HttpService.makeCallToBackend({ - path: `${apiPath}/${modifiedProcessModelId}/${params.process_instance_id}${queryParams}`, - successCallback: setProcessInstance, - }); let taskParams = '?most_recent_tasks_only=true'; if (typeof params.to_task_guid !== 'undefined') { taskParams = `${taskParams}&to_task_guid=${params.to_task_guid}`; @@ -229,19 +203,67 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { } else { setTasksCallHadError(true); } - return undefined; }, [ - targetUris, - params, - modifiedProcessModelId, - permissionsLoaded, ability, + handleAddErrorInUseEffect, + params.to_task_guid, searchParams, taskListPath, - variant, - handleAddErrorInUseEffect, ]); + const getProcessInstance = useCallback(() => { + let queryParams = ''; + const processIdentifier = searchParams.get('process_identifier'); + if (processIdentifier) { + queryParams = `?process_identifier=${processIdentifier}`; + } + let apiPath = '/process-instances/for-me'; + if (variant === 'all') { + apiPath = '/process-instances'; + } + HttpService.makeCallToBackend({ + path: `${apiPath}/${modifiedProcessModelId}/${params.process_instance_id}${queryParams}`, + successCallback: setProcessInstance, + }); + }, [params, modifiedProcessModelId, searchParams, variant]); + + useEffect(() => { + if (processInstance) { + setPageTitle([ + processInstance.process_model_display_name, + `Process Instance ${processInstance.id}`, + ]); + } + return undefined; + }, [processInstance]); + + useEffect(() => { + if (!permissionsLoaded) { + return undefined; + } + getProcessInstance(); + getActionableTaskList(); + + if (searchParams.get('tab')) { + setSelectedTabIndex(parseInt(searchParams.get('tab') || '0', 10)); + } + return undefined; + }, [ + permissionsLoaded, + getActionableTaskList, + getProcessInstance, + searchParams, + ]); + + const updateSearchParams = (value: string, key: string) => { + if (value !== undefined) { + searchParams.set(key, value); + } else { + searchParams.delete(key); + } + setSearchParams(searchParams); + }; + const deleteProcessInstance = () => { HttpService.makeCallToBackend({ path: targetUris.processInstanceActionPath, @@ -1378,7 +1400,9 @@ export default function ProcessInstanceShow({ variant }: OwnProps) { }; const updateSelectedTab = (newTabIndex: any) => { - setSelectedTabIndex(newTabIndex.selectedIndex); + // this causes the process instance and task list to render again as well + // it'd be nice if we could find a way to avoid that + updateSearchParams(newTabIndex.selectedIndex, 'tab'); }; if (processInstance && (tasks || tasksCallHadError) && permissionsLoaded) {