From 639bd80bfee9e0014b3d92b4a8e174eaf4f69cb1 Mon Sep 17 00:00:00 2001 From: Sina Javaheri Date: Thu, 7 Dec 2023 13:01:37 +0100 Subject: [PATCH] fix(inventory-string-values): fix remove unnecessary connection requests --- .../inventory/InventoryAdvanceSearch.tsx | 28 +------------ src/pages/panel/inventory/InventoryForm.tsx | 3 +- .../inventory/InventoryFormFilterRow.tsx | 3 +- .../InventoryFormFilterRowStringValue.tsx | 23 +++++++++-- .../InventoryFormFilterRowValues.tsx | 39 ++++++++++++++++++- src/pages/panel/inventory/utils/index.ts | 2 + .../inventoryAdvanceSearchConfigToString.ts | 27 +++++++++++++ 7 files changed, 90 insertions(+), 35 deletions(-) create mode 100644 src/pages/panel/inventory/utils/inventoryAdvanceSearchConfigToString.ts diff --git a/src/pages/panel/inventory/InventoryAdvanceSearch.tsx b/src/pages/panel/inventory/InventoryAdvanceSearch.tsx index 8ed5c581..81446437 100644 --- a/src/pages/panel/inventory/InventoryAdvanceSearch.tsx +++ b/src/pages/panel/inventory/InventoryAdvanceSearch.tsx @@ -4,22 +4,12 @@ import SearchIcon from '@mui/icons-material/Search' import { Box, Collapse, Divider, FormHelperText, IconButton, TextField, Typography, styled } from '@mui/material' import { ChangeEvent, Suspense, useCallback, useEffect, useRef, useState } from 'react' import { useSearchParams } from 'react-router-dom' -import { OPType, stringSimpleTypes } from 'src/pages/panel/shared/constants' import { panelUI } from 'src/shared/constants' import { ErrorBoundaryFallback, NetworkErrorBoundary } from 'src/shared/error-boundary-fallback' -import { ResourceComplexKindSimpleTypeDefinitions } from 'src/shared/types/server' import { shouldForwardProp } from 'src/shared/utils/shouldForwardProp' import { InventoryForm } from './InventoryForm' import { InventoryFormsSkeleton } from './InventoryForms.skeleton' -import { getArrayFromInOP } from './utils' - -export interface InventoryAdvanceSearchConfig { - id: number - property: string | null - op: OPType | null - value: string | null - fqn: ResourceComplexKindSimpleTypeDefinitions | null -} +import { InventoryAdvanceSearchConfig, inventoryAdvanceSearchConfigToString } from './utils' interface InventoryAdvanceSearchProps { value: string @@ -76,21 +66,7 @@ export const InventoryAdvanceSearch = ({ value: searchCrit, onChange, hasError } useEffect(() => { if (initializedRef.current) { const configJoined = config - .map((item) => { - if (typeof item === 'string' || !item) { - return item - } - if (item.property && item.op && item.value && item.fqn) { - const value = - stringSimpleTypes.includes(item.fqn as (typeof stringSimpleTypes)[number]) && item.value !== 'null' - ? item.op === 'in' || item.op === 'not in' - ? JSON.stringify(getArrayFromInOP(item.value, true)) - : `"${item.value}"` - : item.value - return `${item.property} ${item.op} ${value}` - } - return null - }) + .map(inventoryAdvanceSearchConfigToString) .filter((filter) => filter) .join(' and ') const result = (kind ? `is(${kind})${configJoined ? ' and ' : ''}` : '') + configJoined diff --git a/src/pages/panel/inventory/InventoryForm.tsx b/src/pages/panel/inventory/InventoryForm.tsx index 3f582993..990c59ea 100644 --- a/src/pages/panel/inventory/InventoryForm.tsx +++ b/src/pages/panel/inventory/InventoryForm.tsx @@ -7,10 +7,9 @@ import { DefaultPropertiesKeys } from 'src/pages/panel/shared/constants' import { getWorkspaceInventorySearchStartQuery } from 'src/pages/panel/shared/queries' import { isValidProp } from 'src/pages/panel/shared/utils' import { ErrorBoundaryFallback, NetworkErrorBoundary } from 'src/shared/error-boundary-fallback' -import { InventoryAdvanceSearchConfig } from './InventoryAdvanceSearch' import { InventoryFormFilterRow } from './InventoryFormFilterRow' import { InventoryFormTemplateObject, InventoryFormTemplates } from './InventoryFormTemplates' -import { getArrayFromInOP } from './utils' +import { InventoryAdvanceSearchConfig, getArrayFromInOP } from './utils' interface InventoryFormProps { setConfig: Dispatch> diff --git a/src/pages/panel/inventory/InventoryFormFilterRow.tsx b/src/pages/panel/inventory/InventoryFormFilterRow.tsx index cb0e92ec..7b3e2e39 100644 --- a/src/pages/panel/inventory/InventoryFormFilterRow.tsx +++ b/src/pages/panel/inventory/InventoryFormFilterRow.tsx @@ -13,10 +13,9 @@ import { stringOPTypes, } from 'src/pages/panel/shared/constants' import { ResourceComplexKindSimpleTypeDefinitions } from 'src/shared/types/server' -import { InventoryAdvanceSearchConfig } from './InventoryAdvanceSearch' import { InventoryFormFilterRowProperty } from './InventoryFormFilterRowProperty' import { InventoryFormFilterRowValues } from './InventoryFormFilterRowValues' -import { AutoCompletePreDefinedItems, getArrayFromInOP } from './utils' +import { AutoCompletePreDefinedItems, InventoryAdvanceSearchConfig, getArrayFromInOP } from './utils' interface InventoryFormFilterRowProps { item: InventoryAdvanceSearchConfig diff --git a/src/pages/panel/inventory/InventoryFormFilterRowStringValue.tsx b/src/pages/panel/inventory/InventoryFormFilterRowStringValue.tsx index 2e77a9bf..3178ab44 100644 --- a/src/pages/panel/inventory/InventoryFormFilterRowStringValue.tsx +++ b/src/pages/panel/inventory/InventoryFormFilterRowStringValue.tsx @@ -1,7 +1,7 @@ import { t } from '@lingui/macro' import { Autocomplete, AutocompleteProps, CircularProgress, TextField, TypographyProps } from '@mui/material' import { useInfiniteQuery } from '@tanstack/react-query' -import { ChangeEvent, ReactNode, UIEvent as ReactUIEvent, useMemo, useState } from 'react' +import { ChangeEvent, ReactNode, UIEvent as ReactUIEvent, useMemo, useRef, useState } from 'react' import { useUserProfile } from 'src/core/auth' import { getWorkspaceInventoryPropertyValuesQuery } from 'src/pages/panel/shared/queries' import { panelUI } from 'src/shared/constants' @@ -37,6 +37,7 @@ export function InventoryFormFilterRowStringValue i.label === typed) : value.label !== typed)) + ? `${searchCrit} and ${propertyName} ~ ".*${typed}.*"` + : searchCrit, propertyName, ] as const, initialPageParam: { @@ -112,7 +117,9 @@ export function InventoryFormFilterRowStringValue { - setTyped(typeof option === 'string' ? option : !Array.isArray(option) ? option?.label ?? '' : '') + const newTyped = typeof option === 'string' ? option : !Array.isArray(option) ? option?.label ?? '' : '' + setTyped(newTyped) + slectedTyped.current = newTyped const newOption = (typeof option === 'string' ? options.find((i) => i.label === option) @@ -121,6 +128,9 @@ export function InventoryFormFilterRowStringValue (typeof i === 'string' ? options.find((j) => j.label === i) : i)) .filter((i) => i) as AutoCompleteValue[]) : option) || null + if (!Array.isArray(option)) { + setHasFocus(false) + } onChange( (props.multiple ? Array.isArray(newOption) @@ -133,10 +143,12 @@ export function InventoryFormFilterRowStringValue option.value === value.value} ListboxComponent={ListboxComponent} ListboxProps={{ onScroll: handleScroll, }} + loading={isLoading} options={options} filterOptions={ networkDisabled @@ -159,6 +171,7 @@ export function InventoryFormFilterRowStringValue i.label === e.currentTarget.innerText) if (found) { + slectedTyped.current = e.currentTarget.innerText onChange(found as typeof value) } } @@ -179,6 +192,7 @@ export function InventoryFormFilterRowStringValue setHasFocus(true), @@ -186,6 +200,7 @@ export function InventoryFormFilterRowStringValue i.label === typed) if (found) { + slectedTyped.current = typed onChange(found as typeof value) } } @@ -202,7 +217,9 @@ export function InventoryFormFilterRowStringValue ), }} + onClick={() => setHasFocus(true)} onChange={(e) => { + slectedTyped.current = '' if (isNumber) { const curValue = e.currentTarget.value const num = Number(curValue) diff --git a/src/pages/panel/inventory/InventoryFormFilterRowValues.tsx b/src/pages/panel/inventory/InventoryFormFilterRowValues.tsx index b82dd471..4f7c73f1 100644 --- a/src/pages/panel/inventory/InventoryFormFilterRowValues.tsx +++ b/src/pages/panel/inventory/InventoryFormFilterRowValues.tsx @@ -2,17 +2,19 @@ import { Trans } from '@lingui/macro' import { MenuItem, Select, TextField } from '@mui/material' import { DatePicker, DateTimePicker } from '@mui/x-date-pickers' import dayjs from 'dayjs' +import { useRef } from 'react' import { OPType } from 'src/pages/panel/shared/constants' import { DurationPicker } from 'src/shared/duration-picker' import { ResourceComplexKindSimpleTypeDefinitions } from 'src/shared/types/server' -import { InventoryAdvanceSearchConfig } from './InventoryAdvanceSearch' import { InventoryFormFilterRowStringValue } from './InventoryFormFilterRowStringValue' import { AutoCompletePreDefinedItems, + InventoryAdvanceSearchConfig, getArrayFromInOP, getAutoCompletePropsFromKey, getAutocompleteDataFromKey, getAutocompleteValueFromKey, + inventoryAdvanceSearchConfigToString, } from './utils' interface InventoryFormFilterRowValuesProps { @@ -28,6 +30,16 @@ interface InventoryFormFilterRowValuesProps { + let crit = currentSearchCrit ? searchCrit.replace(currentSearchCrit, '').replace('and and', 'and') || 'all' : searchCrit + if (crit.endsWith(' and ')) { + crit = crit.substring(0, crit.length - 5) + } else if (crit.startsWith(' and ')) { + crit = crit.substring(5) + } + return crit +} + export function InventoryFormFilterRowValues({ data, hasDefaultProperties, @@ -35,9 +47,32 @@ export function InventoryFormFilterRowValues) { + const prev = useRef([data, searchCrit] as const) + const { + current: [prevData, prevSearchCrit], + } = prev const multiple = data.op === 'in' || data.op === 'not in' const currentValue = (data.value?.[0] === '[' ? getArrayFromInOP(data.value) : data.value) || (multiple ? ([] as string[]) : null) + let dataToProcess = data + + if ( + prevData.fqn === data.fqn && + prevData.id === data.id && + prevData.op === data.op && + prevData.property === data.property && + prevData.value !== data.value && + prevSearchCrit === searchCrit + ) { + dataToProcess = prevData + } else { + prev.current = [data, searchCrit] + } + + const currentSearchCrit = inventoryAdvanceSearchConfigToString(dataToProcess) + + const crit = removeCurrectSearchCrit(currentSearchCrit, searchCrit) + let isDouble = false let isNumber = false switch (data.fqn) { @@ -75,7 +110,7 @@ export function InventoryFormFilterRowValues ({ label: value, value }))) || null } defaultOptions={hasDefaultProperties ? getAutocompleteDataFromKey(data.property || '', preItems) : undefined} - searchCrit={searchCrit} + searchCrit={crit} propertyName={data.property || ''} autoFocus={!data.value} {...(hasDefaultProperties ? getAutoCompletePropsFromKey(data.property || '') : {})} diff --git a/src/pages/panel/inventory/utils/index.ts b/src/pages/panel/inventory/utils/index.ts index e7e3bef2..e296275e 100644 --- a/src/pages/panel/inventory/utils/index.ts +++ b/src/pages/panel/inventory/utils/index.ts @@ -2,4 +2,6 @@ export { getArrayFromInOP } from './getArrayFromInOP' export { getAutoCompletePropsFromKey, getAutocompleteDataFromKey, getAutocompleteValueFromKey } from './getAutoCompleteFromKey' export type { AutoCompletePreDefinedItems } from './getAutoCompleteFromKey' export { getCustomedWorkspaceInventoryPropertyAttributesQuery } from './getCustomedWorkspaceInventoryPropertyAttributes.query' +export { inventoryAdvanceSearchConfigToString } from './inventoryAdvanceSearchConfigToString' +export type { InventoryAdvanceSearchConfig } from './inventoryAdvanceSearchConfigToString' export { rowStrFromColumnKind } from './rowStrFromColumnKind' diff --git a/src/pages/panel/inventory/utils/inventoryAdvanceSearchConfigToString.ts b/src/pages/panel/inventory/utils/inventoryAdvanceSearchConfigToString.ts new file mode 100644 index 00000000..2adb5aca --- /dev/null +++ b/src/pages/panel/inventory/utils/inventoryAdvanceSearchConfigToString.ts @@ -0,0 +1,27 @@ +import { OPType, stringSimpleTypes } from 'src/pages/panel/shared/constants' +import { ResourceComplexKindSimpleTypeDefinitions } from 'src/shared/types/server' +import { getArrayFromInOP } from './getArrayFromInOP' + +export interface InventoryAdvanceSearchConfig { + id: number + property: string | null + op: OPType | null + value: string | null + fqn: ResourceComplexKindSimpleTypeDefinitions | null +} + +export const inventoryAdvanceSearchConfigToString = (config: InventoryAdvanceSearchConfig | string | null) => { + if (typeof config === 'string' || !config) { + return config + } + if (config.property && config.op && config.value && config.fqn) { + const value = + stringSimpleTypes.includes(config.fqn as (typeof stringSimpleTypes)[number]) && config.value !== 'null' + ? config.op === 'in' || config.op === 'not in' + ? JSON.stringify(getArrayFromInOP(config.value, true)) + : `"${config.value}"` + : config.value + return `${config.property} ${config.op} ${value}` + } + return null +}