From 2caa42700cdfcb3a54f85f5aefefea790078ba68 Mon Sep 17 00:00:00 2001 From: jasquat Date: Mon, 17 Apr 2023 11:08:00 -0400 Subject: [PATCH] some more log stuff using debounce w/ burnettk --- .../helpers/spiff_enum.py | 4 - .../process_instance_events_controller.py | 58 + .../routes/process_instances_controller.py | 57 - spiffworkflow-frontend/package-lock.json | 40 + spiffworkflow-frontend/package.json | 2 + .../src/components/Filters.tsx | 1058 +---------------- .../components/ProcessInstanceListTable.tsx | 943 ++++++++++++++- .../src/routes/ProcessInstanceLogList.tsx | 166 ++- 8 files changed, 1243 insertions(+), 1085 deletions(-) create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instance_events_controller.py diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/helpers/spiff_enum.py b/spiffworkflow-backend/src/spiffworkflow_backend/helpers/spiff_enum.py index e3f65215..0fe75b0c 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/helpers/spiff_enum.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/helpers/spiff_enum.py @@ -1,11 +1,7 @@ -"""Spiff_enum.""" import enum class SpiffEnum(enum.Enum): - """SpiffEnum.""" - @classmethod def list(cls) -> list[str]: - """List.""" return [el.value for el in cls] diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instance_events_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instance_events_controller.py new file mode 100644 index 00000000..daf2780a --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instance_events_controller.py @@ -0,0 +1,58 @@ + + + +def process_instance_log_list( + modified_process_model_identifier: str, + process_instance_id: int, + page: int = 1, + per_page: int = 100, + detailed: bool = False, +) -> flask.wrappers.Response: + """Process_instance_log_list.""" + # to make sure the process instance exists + process_instance = _find_process_instance_by_id_or_raise(process_instance_id) + + log_query = ( + ProcessInstanceEventModel.query.filter_by(process_instance_id=process_instance.id) + .outerjoin(TaskModel, TaskModel.guid == ProcessInstanceEventModel.task_guid) + .outerjoin(TaskDefinitionModel, TaskDefinitionModel.id == TaskModel.task_definition_id) + .outerjoin( + BpmnProcessDefinitionModel, + BpmnProcessDefinitionModel.id == TaskDefinitionModel.bpmn_process_definition_id, + ) + ) + if not detailed: + log_query = log_query.filter( + and_( + TaskModel.state.in_(["COMPLETED"]), # type: ignore + TaskDefinitionModel.typename.in_(["IntermediateThrowEvent"]), # type: ignore + ) + ) + + logs = ( + log_query.order_by( + ProcessInstanceEventModel.timestamp.desc(), ProcessInstanceEventModel.id.desc() # type: ignore + ) + .outerjoin(UserModel, UserModel.id == ProcessInstanceEventModel.user_id) + .add_columns( + TaskModel.guid.label("spiff_task_guid"), # type: ignore + UserModel.username, + BpmnProcessDefinitionModel.bpmn_identifier.label("bpmn_process_definition_identifier"), # type: ignore + BpmnProcessDefinitionModel.bpmn_name.label("bpmn_process_definition_name"), # type: ignore + TaskDefinitionModel.bpmn_identifier.label("task_definition_identifier"), # type: ignore + TaskDefinitionModel.bpmn_name.label("task_definition_name"), # type: ignore + TaskDefinitionModel.typename.label("bpmn_task_type"), # type: ignore + ) + .paginate(page=page, per_page=per_page, error_out=False) + ) + + response_json = { + "results": logs.items, + "pagination": { + "count": len(logs.items), + "total": logs.total, + "pages": logs.pages, + }, + } + + return make_response(jsonify(response_json), 200) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py index 37fa778b..4f56de35 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py @@ -224,63 +224,6 @@ def process_instance_resume( return Response(json.dumps({"ok": True}), status=200, mimetype="application/json") -def process_instance_log_list( - modified_process_model_identifier: str, - process_instance_id: int, - page: int = 1, - per_page: int = 100, - detailed: bool = False, -) -> flask.wrappers.Response: - """Process_instance_log_list.""" - # to make sure the process instance exists - process_instance = _find_process_instance_by_id_or_raise(process_instance_id) - - log_query = ( - ProcessInstanceEventModel.query.filter_by(process_instance_id=process_instance.id) - .outerjoin(TaskModel, TaskModel.guid == ProcessInstanceEventModel.task_guid) - .outerjoin(TaskDefinitionModel, TaskDefinitionModel.id == TaskModel.task_definition_id) - .outerjoin( - BpmnProcessDefinitionModel, - BpmnProcessDefinitionModel.id == TaskDefinitionModel.bpmn_process_definition_id, - ) - ) - if not detailed: - log_query = log_query.filter( - and_( - TaskModel.state.in_(["COMPLETED"]), # type: ignore - TaskDefinitionModel.typename.in_(["IntermediateThrowEvent"]), # type: ignore - ) - ) - - logs = ( - log_query.order_by( - ProcessInstanceEventModel.timestamp.desc(), ProcessInstanceEventModel.id.desc() # type: ignore - ) - .outerjoin(UserModel, UserModel.id == ProcessInstanceEventModel.user_id) - .add_columns( - TaskModel.guid.label("spiff_task_guid"), # type: ignore - UserModel.username, - BpmnProcessDefinitionModel.bpmn_identifier.label("bpmn_process_definition_identifier"), # type: ignore - BpmnProcessDefinitionModel.bpmn_name.label("bpmn_process_definition_name"), # type: ignore - TaskDefinitionModel.bpmn_identifier.label("task_definition_identifier"), # type: ignore - TaskDefinitionModel.bpmn_name.label("task_definition_name"), # type: ignore - TaskDefinitionModel.typename.label("bpmn_task_type"), # type: ignore - ) - .paginate(page=page, per_page=per_page, error_out=False) - ) - - response_json = { - "results": logs.items, - "pagination": { - "count": len(logs.items), - "total": logs.total, - "pages": logs.pages, - }, - } - - return make_response(jsonify(response_json), 200) - - def process_instance_list_for_me( process_model_identifier: Optional[str] = None, page: int = 1, diff --git a/spiffworkflow-frontend/package-lock.json b/spiffworkflow-frontend/package-lock.json index a578aa3a..40c9b374 100644 --- a/spiffworkflow-frontend/package-lock.json +++ b/spiffworkflow-frontend/package-lock.json @@ -54,6 +54,7 @@ "react-bootstrap": "^2.5.0", "react-bootstrap-typeahead": "^6.0.0", "react-datepicker": "^4.8.0", + "react-debounce-input": "^3.3.0", "react-devtools": "^4.27.1", "react-dom": "^18.2.0", "react-icons": "^4.4.0", @@ -64,6 +65,7 @@ "serve": "^14.0.0", "timepicker": "^1.13.18", "typescript": "^4.7.4", + "use-debounce": "^9.0.4", "web-vitals": "^3.0.2" }, "devDependencies": { @@ -24152,6 +24154,18 @@ "react-dom": "^16.9.0 || ^17 || ^18" } }, + "node_modules/react-debounce-input": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.3.0.tgz", + "integrity": "sha512-VEqkvs8JvY/IIZvh71Z0TC+mdbxERvYF33RcebnodlsUZ8RSgyKe2VWaHXv4+/8aoOgXLxWrdsYs2hDhcwbUgA==", + "dependencies": { + "lodash.debounce": "^4", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -30689,6 +30703,17 @@ "node": ">=0.10.0" } }, + "node_modules/use-debounce": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.4.tgz", + "integrity": "sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ==", + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/use-memo-one": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz", @@ -50123,6 +50148,15 @@ "react-popper": "^2.2.5" } }, + "react-debounce-input": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.3.0.tgz", + "integrity": "sha512-VEqkvs8JvY/IIZvh71Z0TC+mdbxERvYF33RcebnodlsUZ8RSgyKe2VWaHXv4+/8aoOgXLxWrdsYs2hDhcwbUgA==", + "requires": { + "lodash.debounce": "^4", + "prop-types": "^15.8.1" + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -55104,6 +55138,12 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, + "use-debounce": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.4.tgz", + "integrity": "sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ==", + "requires": {} + }, "use-memo-one": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz", diff --git a/spiffworkflow-frontend/package.json b/spiffworkflow-frontend/package.json index 5294eff1..511e43ca 100644 --- a/spiffworkflow-frontend/package.json +++ b/spiffworkflow-frontend/package.json @@ -49,6 +49,7 @@ "react-bootstrap": "^2.5.0", "react-bootstrap-typeahead": "^6.0.0", "react-datepicker": "^4.8.0", + "react-debounce-input": "^3.3.0", "react-devtools": "^4.27.1", "react-dom": "^18.2.0", "react-icons": "^4.4.0", @@ -59,6 +60,7 @@ "serve": "^14.0.0", "timepicker": "^1.13.18", "typescript": "^4.7.4", + "use-debounce": "^9.0.4", "web-vitals": "^3.0.2" }, "overrides": { diff --git a/spiffworkflow-frontend/src/components/Filters.tsx b/spiffworkflow-frontend/src/components/Filters.tsx index 926d559b..9aa0c59c 100644 --- a/spiffworkflow-frontend/src/components/Filters.tsx +++ b/spiffworkflow-frontend/src/components/Filters.tsx @@ -1,995 +1,63 @@ -// // @ts-ignore -// import { Filter } from '@carbon/icons-react'; -// import { -// Button, -// Grid, -// Column, -// // @ts-ignore -// } from '@carbon/react'; -// import useAPIError from '../hooks/UseApiError'; -// -// type OwnProps = { -// showFilterOptions: boolean; -// setShowFilterOptions: Function; -// filtersEnabled?: boolean; -// }; -// -// export default function Filters({ -// showFilterOptions, -// setShowFilterOptions, -// filtersEnabled = true, -// }: OwnProps) { -// const { addError, removeError } = useAPIError(); -// -// const toggleShowFilterOptions = () => { -// setShowFilterOptions(!showFilterOptions); -// }; -// const reportFilterBy = () => { -// return (reportMetadata as any).filter_by; -// }; -// const reportColumns = () => { -// return (reportMetadata as any).columns; -// }; -// -// const navigateToNewReport = (queryParamString: string) => { -// removeError(); -// setProcessInstanceReportJustSaved(null); -// setProcessInstanceFilters({}); -// navigate(`${processInstanceListPathPrefix}?${queryParamString}`); -// }; -// -// const applyFilter = (event: any) => { -// event.preventDefault(); -// setProcessInitiatorNotFoundErrorText(''); -// -// const { page, perPage } = getPageInfoFromSearchParams( -// searchParams, -// undefined, -// undefined, -// paginationQueryParamPrefix -// ); -// let queryParamString = `per_page=${perPage}&page=${page}&user_filter=true`; -// const { -// valid, -// startFromSeconds, -// startToSeconds, -// endFromSeconds, -// endToSeconds, -// } = calculateStartAndEndSeconds(); -// -// if (!valid) { -// return; -// } -// -// if (startFromSeconds) { -// queryParamString += `&start_from=${startFromSeconds}`; -// } -// if (startToSeconds) { -// queryParamString += `&start_to=${startToSeconds}`; -// } -// if (endFromSeconds) { -// queryParamString += `&end_from=${endFromSeconds}`; -// } -// if (endToSeconds) { -// queryParamString += `&end_to=${endToSeconds}`; -// } -// if (processStatusSelection.length > 0) { -// queryParamString += `&process_status=${processStatusSelection}`; -// } -// -// if (processModelSelection) { -// queryParamString += `&process_model_identifier=${processModelSelection.id}`; -// } -// -// if (processInstanceReportSelection) { -// queryParamString += `&report_id=${processInstanceReportSelection.id}`; -// } -// -// const reportColumnsBase64 = encodeBase64(JSON.stringify(reportColumns())); -// queryParamString += `&report_columns=${reportColumnsBase64}`; -// const reportFilterByBase64 = encodeBase64(JSON.stringify(reportFilterBy())); -// queryParamString += `&report_filter_by=${reportFilterByBase64}`; -// -// if (processInitiatorSelection) { -// queryParamString += `&process_initiator_username=${processInitiatorSelection.username}`; -// navigateToNewReport(queryParamString); -// } else if (processInitiatorText) { -// HttpService.makeCallToBackend({ -// path: targetUris.userExists, -// httpMethod: 'POST', -// postBody: { username: processInitiatorText }, -// successCallback: (result: any) => { -// if (result.user_found) { -// queryParamString += `&process_initiator_username=${processInitiatorText}`; -// navigateToNewReport(queryParamString); -// } else { -// setProcessInitiatorNotFoundErrorText( -// `The provided username is invalid. Please type the exact username.` -// ); -// } -// }, -// }); -// } else { -// navigateToNewReport(queryParamString); -// } -// }; -// -// const dateComponent = ( -// labelString: any, -// name: any, -// initialDate: any, -// initialTime: string, -// onChangeDateFunction: any, -// onChangeTimeFunction: any, -// timeInvalid: boolean, -// setTimeInvalid: any -// ) => { -// return ( -// <> -// -// { -// if (!initialDate && !initialTime) { -// onChangeTimeFunction( -// convertDateObjectToFormattedHoursMinutes(new Date()) -// ); -// } -// onChangeDateFunction(dateChangeEvent.srcElement.value); -// }} -// value={initialDate} -// /> -// -// { -// if (event.srcElement.validity.valid) { -// setTimeInvalid(false); -// } else { -// setTimeInvalid(true); -// } -// onChangeTimeFunction(event.srcElement.value); -// }} -// /> -// -// ); -// }; -// -// const processStatusSearch = () => { -// return ( -// { -// setProcessStatusSelection(selection.selectedItems); -// setRequiresRefilter(true); -// }} -// itemToString={(item: any) => { -// return item || ''; -// }} -// selectionFeedback="top-after-reopen" -// selectedItems={processStatusSelection} -// /> -// ); -// }; -// -// const clearFilters = () => { -// setProcessModelSelection(null); -// setProcessStatusSelection([]); -// setStartFromDate(''); -// setStartFromTime(''); -// setStartToDate(''); -// setStartToTime(''); -// setEndFromDate(''); -// setEndFromTime(''); -// setEndToDate(''); -// setEndToTime(''); -// setProcessInitiatorSelection(null); -// setProcessInitiatorText(''); -// setRequiresRefilter(true); -// if (reportMetadata) { -// reportMetadata.filter_by = []; -// } -// }; -// -// const processInstanceReportDidChange = (selection: any, mode?: string) => { -// clearFilters(); -// const selectedReport = selection.selectedItem; -// setProcessInstanceReportSelection(selectedReport); -// -// let queryParamString = ''; -// if (selectedReport) { -// queryParamString = `?report_id=${selectedReport.id}`; -// } -// -// removeError(); -// setProcessInstanceReportJustSaved(mode || null); -// navigate(`${processInstanceListPathPrefix}${queryParamString}`); -// }; -// -// const reportColumnAccessors = () => { -// return reportColumns().map((reportColumn: ReportColumn) => { -// return reportColumn.accessor; -// }); -// }; -// -// // TODO onSuccess reload/select the new report in the report search -// const onSaveReportSuccess = (result: any, mode: string) => { -// processInstanceReportDidChange( -// { -// selectedItem: result, -// }, -// mode -// ); -// }; -// -// const saveAsReportComponent = () => { -// const { -// valid, -// startFromSeconds, -// startToSeconds, -// endFromSeconds, -// endToSeconds, -// } = calculateStartAndEndSeconds(false); -// -// if (!valid || !reportMetadata) { -// return null; -// } -// return ( -// -// ); -// }; -// -// const onDeleteReportSuccess = () => { -// processInstanceReportDidChange({ selectedItem: null }); -// }; -// -// const deleteReportComponent = () => { -// return processInstanceReportSelection ? ( -// -// ) : null; -// }; -// -// const removeColumn = (reportColumn: ReportColumn) => { -// if (reportMetadata) { -// const reportMetadataCopy = { ...reportMetadata }; -// const newColumns = reportColumns().filter( -// (rc: ReportColumn) => rc.accessor !== reportColumn.accessor -// ); -// Object.assign(reportMetadataCopy, { columns: newColumns }); -// setReportMetadata(reportMetadataCopy); -// setRequiresRefilter(true); -// } -// }; -// -// const handleColumnFormClose = () => { -// setShowReportColumnForm(false); -// setReportColumnFormMode(''); -// setReportColumnToOperateOn(null); -// }; -// -// const getFilterByFromReportMetadata = (reportColumnAccessor: string) => { -// if (reportMetadata) { -// return reportMetadata.filter_by.find((reportFilter: ReportFilter) => { -// return reportColumnAccessor === reportFilter.field_name; -// }); -// } -// return null; -// }; -// -// const getNewFiltersFromReportForEditing = ( -// reportColumnForEditing: ReportColumnForEditing -// ) => { -// if (!reportMetadata) { -// return null; -// } -// const reportMetadataCopy = { ...reportMetadata }; -// let newReportFilters = reportMetadataCopy.filter_by; -// if (reportColumnForEditing.filterable) { -// const newReportFilter: ReportFilter = { -// field_name: reportColumnForEditing.accessor, -// field_value: reportColumnForEditing.filter_field_value, -// operator: reportColumnForEditing.filter_operator || 'equals', -// }; -// const existingReportFilter = getFilterByFromReportMetadata( -// reportColumnForEditing.accessor -// ); -// if (existingReportFilter) { -// const existingReportFilterIndex = -// reportMetadataCopy.filter_by.indexOf(existingReportFilter); -// if (reportColumnForEditing.filter_field_value) { -// newReportFilters[existingReportFilterIndex] = newReportFilter; -// } else { -// newReportFilters.splice(existingReportFilterIndex, 1); -// } -// } else if (reportColumnForEditing.filter_field_value) { -// newReportFilters = newReportFilters.concat([newReportFilter]); -// } -// } -// return newReportFilters; -// }; -// -// const handleUpdateReportColumn = () => { -// if (reportColumnToOperateOn && reportMetadata) { -// const reportMetadataCopy = { ...reportMetadata }; -// let newReportColumns = null; -// if (reportColumnFormMode === 'new') { -// newReportColumns = reportColumns().concat([reportColumnToOperateOn]); -// } else { -// newReportColumns = reportColumns().map((rc: ReportColumn) => { -// if (rc.accessor === reportColumnToOperateOn.accessor) { -// return reportColumnToOperateOn; -// } -// return rc; -// }); -// } -// Object.assign(reportMetadataCopy, { -// columns: newReportColumns, -// filter_by: getNewFiltersFromReportForEditing(reportColumnToOperateOn), -// }); -// setReportMetadata(reportMetadataCopy); -// setReportColumnToOperateOn(null); -// setShowReportColumnForm(false); -// setRequiresRefilter(true); -// } -// }; -// -// const reportColumnToReportColumnForEditing = (reportColumn: ReportColumn) => { -// const reportColumnForEditing: ReportColumnForEditing = Object.assign( -// reportColumn, -// { filter_field_value: '', filter_operator: '' } -// ); -// const reportFilter = getFilterByFromReportMetadata( -// reportColumnForEditing.accessor -// ); -// if (reportFilter) { -// reportColumnForEditing.filter_field_value = reportFilter.field_value; -// reportColumnForEditing.filter_operator = -// reportFilter.operator || 'equals'; -// } -// return reportColumnForEditing; -// }; -// -// const updateReportColumn = (event: any) => { -// let reportColumnForEditing = null; -// if (event.selectedItem) { -// reportColumnForEditing = reportColumnToReportColumnForEditing( -// event.selectedItem -// ); -// } -// setReportColumnToOperateOn(reportColumnForEditing); -// setRequiresRefilter(true); -// }; -// -// // options includes item and inputValue -// const shouldFilterReportColumn = (options: any) => { -// const reportColumn: ReportColumn = options.item; -// const { inputValue } = options; -// return ( -// !reportColumnAccessors().includes(reportColumn.accessor) && -// (reportColumn.accessor || '') -// .toLowerCase() -// .includes((inputValue || '').toLowerCase()) -// ); -// }; -// -// const setReportColumnConditionValue = (event: any) => { -// if (reportColumnToOperateOn) { -// const reportColumnToOperateOnCopy = { -// ...reportColumnToOperateOn, -// }; -// reportColumnToOperateOnCopy.filter_field_value = event.target.value; -// setReportColumnToOperateOn(reportColumnToOperateOnCopy); -// setRequiresRefilter(true); -// } -// }; -// -// const reportColumnForm = () => { -// if (reportColumnFormMode === '') { -// return null; -// } -// const formElements = []; -// if (reportColumnFormMode === 'new') { -// formElements.push( -// { -// if (reportColumn) { -// return reportColumn.accessor; -// } -// return null; -// }} -// shouldFilterItem={shouldFilterReportColumn} -// placeholder="Choose a column to show" -// titleText="Column" -// selectedItem={reportColumnToOperateOn} -// /> -// ); -// } -// formElements.push([ -// { -// if (reportColumnToOperateOn) { -// setRequiresRefilter(true); -// const reportColumnToOperateOnCopy = { -// ...reportColumnToOperateOn, -// }; -// reportColumnToOperateOnCopy.Header = event.target.value; -// setReportColumnToOperateOn(reportColumnToOperateOnCopy); -// } -// }} -// />, -// ]); -// if (reportColumnToOperateOn && reportColumnToOperateOn.filterable) { -// formElements.push( -// -// ); -// } -// formElements.push( -//
-// ); -// const modalHeading = -// reportColumnFormMode === 'new' -// ? 'Add Column' -// : `Edit ${ -// reportColumnToOperateOn ? reportColumnToOperateOn.accessor : '' -// } column`; -// return ( -// -// {formElements} -// -// ); -// }; -// -// const columnSelections = () => { -// if (reportColumns()) { -// const tags: any = []; -// -// (reportColumns() as any).forEach((reportColumn: ReportColumn) => { -// const reportColumnForEditing = -// reportColumnToReportColumnForEditing(reportColumn); -// -// let tagType = 'cool-gray'; -// let tagTypeClass = ''; -// if (reportColumnForEditing.filterable) { -// tagType = 'green'; -// tagTypeClass = 'tag-type-green'; -// } -// let reportColumnLabel = reportColumnForEditing.Header; -// if (reportColumnForEditing.filter_field_value) { -// reportColumnLabel = `${reportColumnLabel}=${reportColumnForEditing.filter_field_value}`; -// } -// tags.push( -// -// -// -// -// -// -// -// {saveAsReportComponent()} -// {deleteReportComponent()} -// -// -// -// ); -// }; -// -// const getWaitingForTableCellComponent = (processInstanceTask: any) => { -// let fullUsernameString = ''; -// let shortUsernameString = ''; -// if (processInstanceTask.potential_owner_usernames) { -// fullUsernameString = processInstanceTask.potential_owner_usernames; -// const usernames = -// processInstanceTask.potential_owner_usernames.split(','); -// const firstTwoUsernames = usernames.slice(0, 2); -// if (usernames.length > 2) { -// firstTwoUsernames.push('...'); -// } -// shortUsernameString = firstTwoUsernames.join(','); -// } -// if (processInstanceTask.assigned_user_group_identifier) { -// fullUsernameString = processInstanceTask.assigned_user_group_identifier; -// shortUsernameString = processInstanceTask.assigned_user_group_identifier; -// } -// return {shortUsernameString}; -// }; -// const formatProcessInstanceId = (row: ProcessInstance, id: number) => { -// return {id}; -// }; -// const formatProcessModelIdentifier = (_row: any, identifier: any) => { -// return {identifier}; -// }; -// const formatProcessModelDisplayName = (_row: any, identifier: any) => { -// return {identifier}; -// }; -// -// const formatSecondsForDisplay = (_row: any, seconds: any) => { -// return convertSecondsToFormattedDateTime(seconds) || '-'; -// }; -// const defaultFormatter = (_row: any, value: any) => { -// return value; -// }; -// -// const formattedColumn = (row: any, column: any) => { -// const reportColumnFormatters: Record = { -// id: formatProcessInstanceId, -// process_model_identifier: formatProcessModelIdentifier, -// process_model_display_name: formatProcessModelDisplayName, -// start_in_seconds: formatSecondsForDisplay, -// end_in_seconds: formatSecondsForDisplay, -// updated_at_in_seconds: formatSecondsForDisplay, -// }; -// const formatter = -// reportColumnFormatters[column.accessor] ?? defaultFormatter; -// const value = row[column.accessor]; -// const modifiedModelId = modifyProcessIdentifierForPathParam( -// row.process_model_identifier -// ); -// const navigateToProcessInstance = () => { -// navigate(`${processInstanceShowPathPrefix}/${modifiedModelId}/${row.id}`); -// }; -// const navigateToProcessModel = () => { -// navigate(`/admin/process-models/${modifiedModelId}`); -// }; -// -// if (column.accessor === 'status') { -// return ( -// // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -// -// {formatter(row, value)} -// -// ); -// } -// if (column.accessor === 'process_model_display_name') { -// const pmStyle = { background: 'rgba(0, 0, 0, .02)' }; -// return ( -// // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -// -// {formatter(row, value)} -// -// ); -// } -// if (column.accessor === 'waiting_for') { -// return {getWaitingForTableCellComponent(row)}; -// } -// if (column.accessor === 'updated_at_in_seconds') { -// return ( -// -// ); -// } -// return ( -// // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -// -// {formatter(row, value)} -// -// ); -// }; -// -// const buildTable = () => { -// const headerLabels: Record = { -// id: 'Id', -// process_model_identifier: 'Process', -// process_model_display_name: 'Process', -// start_in_seconds: 'Start Time', -// end_in_seconds: 'End Time', -// status: 'Status', -// process_initiator_username: 'Started By', -// }; -// const getHeaderLabel = (header: string) => { -// return headerLabels[header] ?? header; -// }; -// const headers = reportColumns().map((column: any) => { -// return getHeaderLabel((column as any).Header); -// }); -// if (showActionsColumn) { -// headers.push('Actions'); -// } -// -// const rows = processInstances.map((row: any) => { -// const currentRow = reportColumns().map((column: any) => { -// return formattedColumn(row, column); -// }); -// if (showActionsColumn) { -// let buttonElement = null; -// if (row.task_id) { -// const taskUrl = `/tasks/${row.id}/${row.task_id}`; -// const regex = new RegExp(`\\b(${preferredUsername}|${userEmail})\\b`); -// let hasAccessToCompleteTask = false; -// if ( -// canCompleteAllTasks || -// (row.potential_owner_usernames || '').match(regex) -// ) { -// hasAccessToCompleteTask = true; -// } -// buttonElement = ( -// -// ); -// } -// -// currentRow.push({buttonElement}); -// } -// -// const rowStyle = { cursor: 'pointer' }; -// -// return ( -// -// {currentRow} -// -// ); -// }); -// -// return ( -// -// -// -// {headers.map((header: any) => ( -// -// {header} -// -// ))} -// -// -// {rows} -//
-// ); -// }; -// -// const reportSearchComponent = () => { -// if (showReports) { -// const columns = [ -// -// -// , -// ]; -// return ( -// -// {columns} -// -// ); -// } -// return null; -// }; -// -// if (filtersEnabled) { -// return ( -// <> -// -// -// {reportSearchComponent()} -// -// -// + + + + + + {saveAsReportComponent()} + {deleteReportComponent()} + + + + ); + }; + + const getWaitingForTableCellComponent = (processInstanceTask: any) => { + let fullUsernameString = ''; + let shortUsernameString = ''; + if (processInstanceTask.potential_owner_usernames) { + fullUsernameString = processInstanceTask.potential_owner_usernames; + const usernames = + processInstanceTask.potential_owner_usernames.split(','); + const firstTwoUsernames = usernames.slice(0, 2); + if (usernames.length > 2) { + firstTwoUsernames.push('...'); + } + shortUsernameString = firstTwoUsernames.join(','); + } + if (processInstanceTask.assigned_user_group_identifier) { + fullUsernameString = processInstanceTask.assigned_user_group_identifier; + shortUsernameString = processInstanceTask.assigned_user_group_identifier; + } + return {shortUsernameString}; + }; + const formatProcessInstanceId = (row: ProcessInstance, id: number) => { + return {id}; + }; + const formatProcessModelIdentifier = (_row: any, identifier: any) => { + return {identifier}; + }; + const formatProcessModelDisplayName = (_row: any, identifier: any) => { + return {identifier}; + }; + + const formatSecondsForDisplay = (_row: any, seconds: any) => { + return convertSecondsToFormattedDateTime(seconds) || '-'; + }; + const defaultFormatter = (_row: any, value: any) => { + return value; + }; + + const formattedColumn = (row: any, column: any) => { + const reportColumnFormatters: Record = { + id: formatProcessInstanceId, + process_model_identifier: formatProcessModelIdentifier, + process_model_display_name: formatProcessModelDisplayName, + start_in_seconds: formatSecondsForDisplay, + end_in_seconds: formatSecondsForDisplay, + updated_at_in_seconds: formatSecondsForDisplay, + }; + const formatter = + reportColumnFormatters[column.accessor] ?? defaultFormatter; + const value = row[column.accessor]; + const modifiedModelId = modifyProcessIdentifierForPathParam( + row.process_model_identifier + ); + const navigateToProcessInstance = () => { + navigate(`${processInstanceShowPathPrefix}/${modifiedModelId}/${row.id}`); + }; + const navigateToProcessModel = () => { + navigate(`/admin/process-models/${modifiedModelId}`); + }; + + if (column.accessor === 'status') { + return ( + // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions + + {formatter(row, value)} + + ); + } + if (column.accessor === 'process_model_display_name') { + const pmStyle = { background: 'rgba(0, 0, 0, .02)' }; + return ( + // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions + + {formatter(row, value)} + + ); + } + if (column.accessor === 'waiting_for') { + return {getWaitingForTableCellComponent(row)}; + } + if (column.accessor === 'updated_at_in_seconds') { + return ( + + ); + } + return ( + // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions + + {formatter(row, value)} + + ); + }; + + const buildTable = () => { + const headerLabels: Record = { + id: 'Id', + process_model_identifier: 'Process', + process_model_display_name: 'Process', + start_in_seconds: 'Start Time', + end_in_seconds: 'End Time', + status: 'Status', + process_initiator_username: 'Started By', + }; + const getHeaderLabel = (header: string) => { + return headerLabels[header] ?? header; + }; + const headers = reportColumns().map((column: any) => { + return getHeaderLabel((column as any).Header); + }); + if (showActionsColumn) { + headers.push('Actions'); + } + + const rows = processInstances.map((row: any) => { + const currentRow = reportColumns().map((column: any) => { + return formattedColumn(row, column); + }); + if (showActionsColumn) { + let buttonElement = null; + if (row.task_id) { + const taskUrl = `/tasks/${row.id}/${row.task_id}`; + const regex = new RegExp(`\\b(${preferredUsername}|${userEmail})\\b`); + let hasAccessToCompleteTask = false; + if ( + canCompleteAllTasks || + (row.potential_owner_usernames || '').match(regex) + ) { + hasAccessToCompleteTask = true; + } + buttonElement = ( + + ); + } + + currentRow.push({buttonElement}); + } + + const rowStyle = { cursor: 'pointer' }; + + return ( + + {currentRow} + + ); + }); + + return ( + + + + {headers.map((header: any) => ( + + {header} + + ))} + + + {rows} +
+ ); + }; + + const reportSearchComponent = () => { + if (showReports) { + const columns = [ + + + , + ]; + return ( + + {columns} + + ); + } + return null; + }; + if (pagination && (!textToShowIfEmpty || pagination.total > 0)) { // eslint-disable-next-line prefer-const let { page, perPage } = getPageInfoFromSearchParams( @@ -615,7 +1556,7 @@ export default function ProcessInstanceListTable({ {reportColumnForm()} {processInstanceReportSaveTag()} (''); + const [taskIdentifier, setTaskIdentifier] = useState(''); + const { targetUris } = useUriListForPermissions(); const isDetailedView = searchParams.get('detailed') === 'true'; + const [showFilterOptions, setShowFilterOptions] = useState(false); + let processInstanceShowPageBaseUrl = `/admin/process-instances/for-me/${params.process_model_id}`; if (variant === 'all') { processInstanceShowPageBaseUrl = `/admin/process-instances/${params.process_model_id}`; } + const addDebouncedSearchParams = useDebouncedCallback( + (value, key) => { + if (value) { + searchParams.set(key, value); + } else { + searchParams.delete(key); + } + setSearchParams(searchParams); + }, + // delay in ms + 1000 + ); + useEffect(() => { // Clear out any previous results to avoid a "flicker" effect where columns // are updated above the incorrect data. @@ -160,7 +198,96 @@ export default function ProcessInstanceLogList({ variant }: OwnProps) { ); }; - const selectedTabIndex = isDetailedView ? 1 : 0; + + const resetFilters = () => { + setTaskIdentifier(''); + setTaskName(''); + + searchParams.delete(taskName); + searchParams.delete(taskIdentifier); + + setSearchParams(searchParams); + }; + + const filterOptions = () => { + if (!showFilterOptions) { + return null; + } + + return ( + <> + + + { + const newValue = event.target.value; + setTaskName(newValue); + addDebouncedSearchParams(newValue, 'bpmn_name'); + }} + /> + + + { + const newValue = event.target.value; + setTaskIdentifier(newValue); + addDebouncedSearchParams(newValue, 'bpmn_identifier'); + }} + /> + + + + + + + + + + + ); + }; + + const tabs = () => { + const selectedTabIndex = isDetailedView ? 1 : 0; + return ( + + + { + searchParams.set('detailed', 'false'); + setSearchParams(searchParams); + }} + > + Milestones + + { + searchParams.set('detailed', 'true'); + setSearchParams(searchParams); + }} + > + Events + + + + ); + }; if (pagination) { const { page, perPage } = getPageInfoFromSearchParams(searchParams); @@ -181,30 +308,13 @@ export default function ProcessInstanceLogList({ variant }: OwnProps) { ['Logs'], ]} /> - - - { - searchParams.set('detailed', 'false'); - setSearchParams(searchParams); - }} - > - Milestones - - { - searchParams.set('detailed', 'true'); - setSearchParams(searchParams); - }} - > - Events - - - + {tabs()} +