diff --git a/.changeset/nine-cougars-kneel.md b/.changeset/nine-cougars-kneel.md new file mode 100644 index 0000000000..acafb614cd --- /dev/null +++ b/.changeset/nine-cougars-kneel.md @@ -0,0 +1,7 @@ +--- +"@cloudoperators/juno-app-doop": patch +"@cloudoperators/juno-app-heureka": patch +"@cloudoperators/juno-app-supernova": patch +--- + +fix(heureka): correct numeric searchTerm URL param to string in search box diff --git a/apps/doop/src/lib/helpers.ts b/apps/doop/src/lib/helpers.ts index 6d3a1443f2..57673926b5 100644 --- a/apps/doop/src/lib/helpers.ts +++ b/apps/doop/src/lib/helpers.ts @@ -3,6 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { z } from "zod" + +/** Zod schema for optional URL search params that may be parsed as numbers by TanStack Router. */ +export const optionalStringSchema = z.preprocess( + (val) => + val === undefined || val === null ? undefined : typeof val === "string" ? val : String(val as number | boolean), + z.string().optional() +) + export const parseError = (error: any) => { if (!error || (typeof error === "object" && Object.keys(error).length === 0)) return "An error occurred. There is no further information" diff --git a/apps/doop/src/routes/violations.tsx b/apps/doop/src/routes/violations.tsx index a77359f553..664e19dd8e 100644 --- a/apps/doop/src/routes/violations.tsx +++ b/apps/doop/src/routes/violations.tsx @@ -17,13 +17,13 @@ import { } from "../components/StoreProvider" import { parseInitialFilters } from "../lib/store/createFiltersSlice" import { isObjectWithKeys } from "../lib/helpers" -import { filterSearchParamsByPrefix } from "../lib/helpers" +import { filterSearchParamsByPrefix, optionalStringSchema } from "../lib/helpers" const filterValueSchema = z.union([z.string(), z.array(z.string()), z.undefined()]) const searchSchema = z .object({ - searchTerm: z.string().optional(), + searchTerm: optionalStringSchema, violationGroup: z.string().optional(), }) .catchall(filterValueSchema) diff --git a/apps/heureka/src/routes/services/index.tsx b/apps/heureka/src/routes/services/index.tsx index 6209eefd39..1705cd4bcf 100644 --- a/apps/heureka/src/routes/services/index.tsx +++ b/apps/heureka/src/routes/services/index.tsx @@ -13,14 +13,14 @@ import { SELECTED_FILTER_PREFIX } from "../../constants" import { fetchServices } from "../../api/fetchServices" import { fetchServicesFilters } from "../../api/fetchServicesFilters" import { extractFilterSettingsFromSearchParams } from "../../components/Services/utils" -import { filterSearchParamsByPrefix } from "../../utils" +import { filterSearchParamsByPrefix, optionalStringSchema } from "../../utils" const filterValueSchema = z.union([z.string(), z.array(z.string()), z.undefined()]) const servicesSearchSchema = z .object({ service: z.string().optional(), - searchTerm: z.string().optional(), + searchTerm: optionalStringSchema, }) .catchall(filterValueSchema) diff --git a/apps/heureka/src/routes/vulnerabilities/index.tsx b/apps/heureka/src/routes/vulnerabilities/index.tsx index e39330b1bb..c4f0a09fd3 100644 --- a/apps/heureka/src/routes/vulnerabilities/index.tsx +++ b/apps/heureka/src/routes/vulnerabilities/index.tsx @@ -10,14 +10,14 @@ import { SELECTED_FILTER_PREFIX } from "../../constants" import { fetchVulnerabilities } from "../../api/fetchVulnerabilities" import { fetchVulnerabilityFilters } from "../../api/fetchVulnerabilityFilters" import { extractFilterSettingsFromSearchParams } from "../../components/Vulnerabilities/utils" -import { filterSearchParamsByPrefix } from "../../utils" +import { filterSearchParamsByPrefix, optionalStringSchema } from "../../utils" const filterValueSchema = z.union([z.string(), z.array(z.string()), z.undefined()]) const vulnerabilitiesSearchSchema = z .object({ vulnerability: z.string().optional(), - searchTerm: z.preprocess((val) => (typeof val === "number" ? val.toString() : val), z.string().optional()), + searchTerm: optionalStringSchema, }) .catchall(filterValueSchema) diff --git a/apps/heureka/src/utils.ts b/apps/heureka/src/utils.ts index 94e9e35bbd..34766f6c52 100644 --- a/apps/heureka/src/utils.ts +++ b/apps/heureka/src/utils.ts @@ -5,6 +5,14 @@ import { useState, useRef, useEffect, Dispatch, SetStateAction } from "react" import { KnownIcons } from "@cloudoperators/juno-ui-components" +import { z } from "zod" + +/** Zod schema for optional URL search params that may be parsed as numbers by TanStack Router. */ +export const optionalStringSchema = z.preprocess( + (val) => + val === undefined || val === null ? undefined : typeof val === "string" ? val : String(val as number | boolean), + z.string().optional() +) export const capitalizeFirstLetter = (str: string): string => { return str.charAt(0).toUpperCase() + str.slice(1) diff --git a/apps/supernova/src/lib/utils.ts b/apps/supernova/src/lib/utils.ts index cb9c9e850b..7e119c216e 100644 --- a/apps/supernova/src/lib/utils.ts +++ b/apps/supernova/src/lib/utils.ts @@ -3,6 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { z } from "zod" + +/** Zod schema for optional URL search params that may be parsed as numbers by TanStack Router. */ +export const optionalStringSchema = z.preprocess( + (val) => + val === undefined || val === null ? undefined : typeof val === "string" ? val : String(val as number | boolean), + z.string().optional() +) + import { AlertItem, SeverityCounts } from "./createAlertsSlice" export const severityToSemanticName = (severity: any) => { diff --git a/apps/supernova/src/routes/alerts.tsx b/apps/supernova/src/routes/alerts.tsx index 4bf24e57cc..f37e04118d 100644 --- a/apps/supernova/src/routes/alerts.tsx +++ b/apps/supernova/src/routes/alerts.tsx @@ -13,14 +13,13 @@ import AlertsTab from "../components/alerts/AlertsTab" import { ACTIVE_FILTERS_PREFIX, PAUSED_FILTERS_PREFIX } from "../constants" import { convertUrlStateToAppState, getFiltersForUrl } from "../lib/urlStateUtils" import { useGlobalsActions, useFilterActions, useGlobalsInitialFiltersApplied } from "../components/StoreProvider" -import { isObjectWithKeys } from "../lib/utils" -import { filterSearchParamsByPrefix } from "../lib/utils" +import { isObjectWithKeys, filterSearchParamsByPrefix, optionalStringSchema } from "../lib/utils" const filterValueSchema = z.union([z.string(), z.array(z.string()), z.undefined()]) const searchSchema = z .object({ - searchTerm: z.string().optional(), + searchTerm: optionalStringSchema, showDetailsFor: z.string().optional(), predefinedFilter: z.string().optional(), })