From 74976ec6df57086773679bf92bc4541eab714ce0 Mon Sep 17 00:00:00 2001 From: jasquat Date: Wed, 2 Nov 2022 12:42:49 -0400 Subject: [PATCH] add date ranges for process instances search w/ burnettk --- .../src/spiffworkflow_backend/api.yml | 4 +- .../routes/process_api_blueprint.py | 12 +- spiffworkflow-frontend/src/config.tsx | 4 +- spiffworkflow-frontend/src/helpers.tsx | 25 ++- .../src/routes/ProcessInstanceList.tsx | 191 ++++++++---------- 5 files changed, 110 insertions(+), 126 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index 614d4f26c..de10f598c 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -429,7 +429,7 @@ paths: description: For filtering - beginning of start window - in seconds since epoch schema: type: integer - - name: start_till + - name: start_to in: query required: false description: For filtering - end of start window - in seconds since epoch @@ -441,7 +441,7 @@ paths: description: For filtering - beginning of end window - in seconds since epoch schema: type: integer - - name: end_till + - name: end_to in: query required: false description: For filtering - end of end window - in seconds since epoch 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 f2ffec20f..012cb52fe 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -651,9 +651,9 @@ def process_instance_list( page: int = 1, per_page: int = 100, start_from: Optional[int] = None, - start_till: Optional[int] = None, + start_to: Optional[int] = None, end_from: Optional[int] = None, - end_till: Optional[int] = None, + end_to: Optional[int] = None, process_status: Optional[str] = None, ) -> flask.wrappers.Response: """Process_instance_list.""" @@ -684,17 +684,17 @@ def process_instance_list( process_instance_query = process_instance_query.filter( ProcessInstanceModel.start_in_seconds >= start_from ) - if start_till is not None: + if start_to is not None: process_instance_query = process_instance_query.filter( - ProcessInstanceModel.start_in_seconds <= start_till + ProcessInstanceModel.start_in_seconds <= start_to ) if end_from is not None: process_instance_query = process_instance_query.filter( ProcessInstanceModel.end_in_seconds >= end_from ) - if end_till is not None: + if end_to is not None: process_instance_query = process_instance_query.filter( - ProcessInstanceModel.end_in_seconds <= end_till + ProcessInstanceModel.end_in_seconds <= end_to ) if process_status is not None: process_status_array = process_status.split(",") diff --git a/spiffworkflow-frontend/src/config.tsx b/spiffworkflow-frontend/src/config.tsx index 573e96bf5..c9e94eb06 100644 --- a/spiffworkflow-frontend/src/config.tsx +++ b/spiffworkflow-frontend/src/config.tsx @@ -16,4 +16,6 @@ export const PROCESS_STATUSES = [ 'suspended', ]; -export const DATE_FORMAT = 'Y-m-d'; +// with time: yyyy-MM-dd HH:mm:ss +export const DATE_FORMAT = 'yyyy-MM-dd'; +export const DATE_FORMAT_CARBON = 'Y-m-d'; diff --git a/spiffworkflow-frontend/src/helpers.tsx b/spiffworkflow-frontend/src/helpers.tsx index e9bb100ae..6b27fb4ca 100644 --- a/spiffworkflow-frontend/src/helpers.tsx +++ b/spiffworkflow-frontend/src/helpers.tsx @@ -20,7 +20,10 @@ export const capitalizeFirstLetter = (string: any) => { return string.charAt(0).toUpperCase() + string.slice(1); }; -export const convertDateToSeconds = (date: any, onChangeFunction: any) => { +export const convertDateToSeconds = ( + date: any, + onChangeFunction: any = null +) => { let dateInSeconds = date; if (date !== null) { let dateInMilliseconds = date; @@ -39,14 +42,26 @@ export const convertDateToSeconds = (date: any, onChangeFunction: any) => { return null; }; -export const convertSecondsToFormattedDate = (seconds: number) => { - if (seconds) { - const startDate = new Date(seconds * 1000); - return format(startDate, DATE_FORMAT); +export const convertStringToDate = (dateString: string) => { + if (dateString) { + return new Date(dateString); } return null; }; +export const convertSecondsToFormattedDate = (seconds: number) => { + if (seconds) { + const dateObject = new Date(seconds * 1000); + return format(dateObject, DATE_FORMAT); + } + return null; +}; + +export const convertDateStringToSeconds = (dateString: string) => { + const dateObject = convertStringToDate(dateString); + return convertDateToSeconds(dateObject); +}; + export const objectIsEmpty = (obj: object) => { return Object.keys(obj).length === 0; }; diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx index 214ab9369..63ee7a2fa 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx @@ -24,9 +24,9 @@ import { } from '@carbon/react'; import { InputGroup } from 'react-bootstrap'; import { Typeahead } from 'react-bootstrap-typeahead'; -import { PROCESS_STATUSES, DATE_FORMAT } from '../config'; +import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config'; import { - convertDateToSeconds, + convertDateStringToSeconds, convertSecondsToFormattedDate, getPageInfoFromSearchParams, getProcessModelFullIdentifierFromSearchParams, @@ -53,10 +53,10 @@ export default function ProcessInstanceList() { const oneHourInSeconds = 3600; const oneMonthInSeconds = oneHourInSeconds * 24 * 30; - const [startFrom, setStartFrom] = useState(null); - const [startTill, setStartTill] = useState(null); - const [endFrom, setEndFrom] = useState(null); - const [endTill, setEndTill] = useState(null); + const [startFrom, setStartFrom] = useState(''); + const [startTo, setStartTo] = useState(''); + const [endFrom, setEndFrom] = useState(''); + const [endTo, setEndTo] = useState(''); const setErrorMessage = (useContext as any)(ErrorContext)[1]; @@ -69,20 +69,17 @@ export default function ProcessInstanceList() { const [processModelAvailableItems, setProcessModelAvailableItems] = useState< ProcessModel[] >([]); - const [processModelFilteredItems, setProcessModelFilteredItems] = useState< - ProcessModel[] - >([]); const [processModelSelection, setProcessModelSelection] = useState(null); const parametersToAlwaysFilterBy = useMemo(() => { return { start_from: setStartFrom, - start_till: setStartTill, + start_to: setStartTo, end_from: setEndFrom, - end_till: setEndTill, + end_to: setEndTo, }; - }, [setStartFrom, setStartTill, setEndFrom, setEndTill]); + }, [setStartFrom, setStartTo, setEndFrom, setEndTo]); const parametersToGetFromSearchParams = useMemo(() => { return { @@ -109,7 +106,10 @@ export default function ProcessInstanceList() { const searchParamValue = searchParams.get(paramName); if (searchParamValue) { queryParamString += `&${paramName}=${searchParamValue}`; - functionToCall(searchParamValue); + const dateString = convertSecondsToFormattedDate( + searchParamValue as any + ); + functionToCall(dateString); } }); @@ -142,7 +142,6 @@ export default function ProcessInstanceList() { return item; }); setProcessModelAvailableItems(selectionArray); - setProcessModelFilteredItems(selectionArray); const processStatusSelectedArray: string[] = []; const processStatusAllOptionsArray = PROCESS_STATUSES.map( @@ -195,34 +194,46 @@ export default function ProcessInstanceList() { const { page, perPage } = getPageInfoFromSearchParams(searchParams); let queryParamString = `per_page=${perPage}&page=${page}`; - if (isTrueComparison(startFrom, '>', startTill)) { - setErrorMessage({ message: 'startFrom cannot be after startTill' }); + const startFromSeconds = convertDateStringToSeconds(startFrom); + const endFromSeconds = convertDateStringToSeconds(endFrom); + const startToSeconds = convertDateStringToSeconds(startTo); + const endToSeconds = convertDateStringToSeconds(endTo); + if (isTrueComparison(startFromSeconds, '>', startToSeconds)) { + setErrorMessage({ + message: '"Start date from" cannot be after "start date to"', + }); return; } - if (isTrueComparison(endFrom, '>', endTill)) { - setErrorMessage({ message: 'endFrom cannot be after endTill' }); + if (isTrueComparison(endFromSeconds, '>', endToSeconds)) { + setErrorMessage({ + message: '"End date from" cannot be after "end date to"', + }); return; } - if (isTrueComparison(startFrom, '>', endFrom)) { - setErrorMessage({ message: 'startFrom cannot be after endFrom' }); + if (isTrueComparison(startFromSeconds, '>', endFromSeconds)) { + setErrorMessage({ + message: '"Start date from" cannot be after "end date from"', + }); return; } - if (isTrueComparison(startTill, '>', endTill)) { - setErrorMessage({ message: 'startTill cannot be after endTill' }); + if (isTrueComparison(startToSeconds, '>', endToSeconds)) { + setErrorMessage({ + message: '"Start date to" cannot be after "end date to"', + }); return; } - if (startFrom) { - queryParamString += `&start_from=${startFrom}`; + if (startFromSeconds) { + queryParamString += `&start_from=${startFromSeconds}`; } - if (startTill) { - queryParamString += `&start_till=${startTill}`; + if (startToSeconds) { + queryParamString += `&start_to=${startToSeconds}`; } - if (endFrom) { - queryParamString += `&end_from=${endFrom}`; + if (endFromSeconds) { + queryParamString += `&end_from=${endFromSeconds}`; } - if (endTill) { - queryParamString += `&end_till=${endTill}`; + if (endToSeconds) { + queryParamString += `&end_to=${endToSeconds}`; } if (processStatusSelection.length > 0) { queryParamString += `&process_status=${processStatusSelection}`; @@ -242,30 +253,22 @@ export default function ProcessInstanceList() { initialDate: any, onChangeFunction: any ) => { - let selectedDate = null; - if (initialDate) { - selectedDate = new Date(initialDate * 1000); - } return ( - - - - - {labelString} - {'\u00A0'} - - - convertDateToSeconds(date, onChangeFunction) - } - showTimeSelect - dateFormat={DATE_FORMAT} - /> - - - + + { + onChangeFunction(dateChangeEvent.srcElement.value); + }} + value={initialDate} + /> + ); }; @@ -291,10 +294,8 @@ export default function ProcessInstanceList() { const shouldFilterProcessModel = (options: any) => { const processModel: ProcessModel = options.item; const { inputValue } = options; - return ( - processModel.process_group_id.match(inputValue) || - processModel.id.match(inputValue) || - processModel.display_name.match(inputValue) + return `${processModel.process_group_id}/${processModel.id} (${processModel.display_name})`.includes( + inputValue ); }; @@ -305,7 +306,7 @@ export default function ProcessInstanceList() { setProcessModelSelection(selection.selectedItem) } id="process-model-select" - items={processModelFilteredItems} + items={processModelAvailableItems} itemToString={(processModel: ProcessModel) => { if (processModel) { return `${processModel.process_group_id}/${ @@ -344,53 +345,14 @@ export default function ProcessInstanceList() { const clearFilters = () => { setProcessModelSelection(null); setProcessStatusSelection([]); + setStartFrom(''); + setStartTo(''); + setEndFrom(''); + setEndTo(''); }; const filterOptions = () => { const { page, perPage } = getPageInfoFromSearchParams(searchParams); - // return ( - //
- //
- //
- //
- // - // {processModelSearch()} - // - //
- // - // {dateComponent( - // 'Start Range: ', - // 'start-from', - // startFrom, - // setStartFrom - // )} - // {dateComponent('-', 'start-till', startTill, setStartTill)} - // - //
- // - // {dateComponent( - // 'End Range: \u00A0\u00A0', - // 'end-from', - // endFrom, - // setEndFrom - // )} - // {dateComponent('-', 'end-till', endTill, setEndTill)} - // - //
- // - // {processStatusSearch()} - // - // - // - // - //
- //
- //
- //
- //
- // ); return ( <> @@ -398,17 +360,22 @@ export default function ProcessInstanceList() { {processStatusSearch()} - - {' '} - - - + + {dateComponent( + 'Start date from', + 'start-from', + startFrom, + setStartFrom + )} + + + {dateComponent('Start date to', 'start-to', startTo, setStartTo)} + + + {dateComponent('End date from', 'end-from', endFrom, setEndFrom)} + + + {dateComponent('End date to', 'end-to', endTo, setEndTo)}