From 8c2a502eadb7055bad88af5a994065a4835f7f79 Mon Sep 17 00:00:00 2001 From: kwasniew Date: Tue, 9 Sep 2025 12:58:51 +0200 Subject: [PATCH] fix: limit and offset with non numbers --- .../component/events/EventLog/useEventLogSearch.ts | 12 ++++-------- .../FeatureToggleList/useGlobalFeatureSearch.ts | 12 ++++-------- .../useProjectFeatureSearch.ts | 6 +++--- frontend/src/utils/safeNumberParam.ts | 9 +++++++++ 4 files changed, 20 insertions(+), 19 deletions(-) create mode 100644 frontend/src/utils/safeNumberParam.ts diff --git a/frontend/src/component/events/EventLog/useEventLogSearch.ts b/frontend/src/component/events/EventLog/useEventLogSearch.ts index ce51ba35d9..efbebc2fd7 100644 --- a/frontend/src/component/events/EventLog/useEventLogSearch.ts +++ b/frontend/src/component/events/EventLog/useEventLogSearch.ts @@ -1,9 +1,4 @@ -import { - encodeQueryParams, - NumberParam, - StringParam, - withDefault, -} from 'use-query-params'; +import { encodeQueryParams, StringParam, withDefault } from 'use-query-params'; import { FilterItemParam } from 'utils/serializeQueryParams'; import { usePersistentTableState } from 'hooks/usePersistentTableState'; import mapValues from 'lodash.mapvalues'; @@ -11,6 +6,7 @@ import { useEventSearch } from 'hooks/api/getters/useEventSearch/useEventSearch' import type { SearchEventsParams } from 'openapi'; import type { FilterItemParamHolder } from 'component/filter/Filters/Filters'; import { format, subYears } from 'date-fns'; +import { SafeNumberParam } from 'utils/safeNumberParam'; type Log = | { type: 'global' } @@ -58,8 +54,8 @@ export const useEventLogSearch = ( refreshInterval = 15 * 1000, ) => { const stateConfig = { - offset: withDefault(NumberParam, 0), - limit: withDefault(NumberParam, DEFAULT_PAGE_SIZE), + offset: withDefault(SafeNumberParam, 0), + limit: withDefault(SafeNumberParam, DEFAULT_PAGE_SIZE), query: StringParam, from: withDefault(FilterItemParam, { values: [format(subYears(new Date(), 1), 'yyyy-MM-dd')], diff --git a/frontend/src/component/feature/FeatureToggleList/useGlobalFeatureSearch.ts b/frontend/src/component/feature/FeatureToggleList/useGlobalFeatureSearch.ts index 32b5a7cab7..4dbf56fbdf 100644 --- a/frontend/src/component/feature/FeatureToggleList/useGlobalFeatureSearch.ts +++ b/frontend/src/component/feature/FeatureToggleList/useGlobalFeatureSearch.ts @@ -1,10 +1,5 @@ import { useCallback } from 'react'; -import { - encodeQueryParams, - NumberParam, - StringParam, - withDefault, -} from 'use-query-params'; +import { encodeQueryParams, StringParam, withDefault } from 'use-query-params'; import { DEFAULT_PAGE_LIMIT, useFeatureSearch, @@ -16,12 +11,13 @@ import { import { usePersistentTableState } from 'hooks/usePersistentTableState'; import mapValues from 'lodash.mapvalues'; import type { SearchFeaturesParams } from 'openapi'; +import { SafeNumberParam } from 'utils/safeNumberParam'; export const useGlobalFeatureSearch = (pageLimit = DEFAULT_PAGE_LIMIT) => { const storageKey = 'features-list-table'; const stateConfig = { - offset: withDefault(NumberParam, 0), - limit: withDefault(NumberParam, pageLimit), + offset: withDefault(SafeNumberParam, 0), + limit: withDefault(SafeNumberParam, pageLimit), query: StringParam, favoritesFirst: withDefault(BooleansStringParam, true), sortBy: withDefault(StringParam, 'createdAt'), diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/useProjectFeatureSearch.ts b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/useProjectFeatureSearch.ts index 78c43401e0..20ebc83e82 100644 --- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/useProjectFeatureSearch.ts +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/useProjectFeatureSearch.ts @@ -1,7 +1,6 @@ import { ArrayParam, encodeQueryParams, - NumberParam, StringParam, withDefault, } from 'use-query-params'; @@ -16,6 +15,7 @@ import { import { usePersistentTableState } from 'hooks/usePersistentTableState'; import mapValues from 'lodash.mapvalues'; import type { SearchFeaturesParams } from 'openapi'; +import { SafeNumberParam } from 'utils/safeNumberParam'; type Attribute = | { key: 'tag'; operator: 'INCLUDE' } @@ -28,8 +28,8 @@ export const useProjectFeatureSearch = ( refreshInterval = 15 * 1000, ) => { const stateConfig = { - offset: withDefault(NumberParam, 0), - limit: withDefault(NumberParam, DEFAULT_PAGE_LIMIT), + offset: withDefault(SafeNumberParam, 0), + limit: withDefault(SafeNumberParam, DEFAULT_PAGE_LIMIT), query: StringParam, favoritesFirst: withDefault(BooleansStringParam, true), sortBy: withDefault(StringParam, 'createdAt'), diff --git a/frontend/src/utils/safeNumberParam.ts b/frontend/src/utils/safeNumberParam.ts new file mode 100644 index 0000000000..2f95c5475e --- /dev/null +++ b/frontend/src/utils/safeNumberParam.ts @@ -0,0 +1,9 @@ +import { encodeNumber, decodeNumber } from 'serialize-query-params'; + +export const SafeNumberParam = { + encode: encodeNumber, + decode: (input: any) => { + const result = decodeNumber(input); + return result == null ? result : Number.isNaN(result) ? null : result; + }, +};