{
{tabs &&
}
- {searchStore.isSearching && (
+ {searchCtx.isSearching && (
<>
diff --git a/interface/app/route-schemas.ts b/interface/app/route-schemas.ts
index 0def66d28578..c00e0ee796c6 100644
--- a/interface/app/route-schemas.ts
+++ b/interface/app/route-schemas.ts
@@ -24,14 +24,14 @@ export const SearchIdParamsSchema = z.object({ id: z.coerce.number() });
export type SearchIdParams = z.infer
;
export const SearchParamsSchema = PathParamsSchema.extend({
- take: z.coerce.number().default(100),
- order: z
- .union([
- z.object({ field: z.literal('name'), value: SortOrderSchema }),
- z.object({ field: z.literal('dateCreated'), value: SortOrderSchema })
- // z.object({ field: z.literal('sizeInBytes'), value: SortOrderSchema })
- ])
- .optional(),
+ // take: z.coerce.number().default(100),
+ // order: z
+ // .union([
+ // z.object({ field: z.literal('name'), value: SortOrderSchema }),
+ // z.object({ field: z.literal('dateCreated'), value: SortOrderSchema })
+ // // z.object({ field: z.literal('sizeInBytes'), value: SortOrderSchema })
+ // ])
+ // .optional(),
search: z.string().optional()
});
export type SearchParams = z.infer;
diff --git a/interface/hooks/useZodSearchParams.ts b/interface/hooks/useZodSearchParams.ts
index 5f26f4108b37..7592e215076c 100644
--- a/interface/hooks/useZodSearchParams.ts
+++ b/interface/hooks/useZodSearchParams.ts
@@ -1,7 +1,6 @@
import { useCallback, useMemo } from 'react';
import { NavigateOptions, useSearchParams } from 'react-router-dom';
-import { getParams } from 'remix-params-helper';
-import type { z } from 'zod';
+import { z } from 'zod';
export function useZodSearchParams(schema: Z) {
// eslint-disable-next-line no-restricted-syntax
@@ -36,3 +35,136 @@ export function useZodSearchParams(schema: Z) {
)
] as const;
}
+
+// from https://github.com/kiliman/remix-params-helper/blob/main/src/helper.ts
+// original skips empty strings but empty strings are useful sometimes
+
+export function getParams>(
+ params: URLSearchParams | FormData | Record,
+ schema: T
+) {
+ type ParamsType = z.infer;
+ return getParamsInternal(params, schema);
+}
+
+function isIterable(maybeIterable: unknown): maybeIterable is Iterable {
+ return Symbol.iterator in Object(maybeIterable);
+}
+
+function getParamsInternal(
+ params: URLSearchParams | FormData | Record,
+ schema: any
+):
+ | { success: true; data: T; errors: undefined }
+ | { success: false; data: undefined; errors: { [key: string]: string } } {
+ const o: any = {};
+ let entries: [string, unknown][] = [];
+ if (isIterable(params)) {
+ entries = Array.from(params);
+ } else {
+ entries = Object.entries(params);
+ }
+ for (const [key, value] of entries) {
+ parseParams(o, schema, key, value);
+ }
+
+ const result = schema.safeParse(o);
+ if (result.success) {
+ return { success: true, data: result.data as T, errors: undefined };
+ } else {
+ const errors: Record = {};
+ const addError = (key: string, message: string) => {
+ if (!Object.prototype.hasOwnProperty.call(errors, key)) {
+ errors[key] = message;
+ } else {
+ if (!Array.isArray(errors[key])) {
+ errors[key] = [errors[key]];
+ }
+ errors[key].push(message);
+ }
+ };
+ for (const issue of result.error.issues) {
+ const { message, path, code, expected, received } = issue;
+ const [key, index] = path;
+ let value = o[key];
+ let prop = key;
+ if (index !== undefined) {
+ value = value[index];
+ prop = `${key}[${index}]`;
+ }
+ addError(key, message);
+ }
+ return { success: false, data: undefined, errors };
+ }
+}
+
+function parseParams(o: any, schema: any, key: string, value: any) {
+ // find actual shape definition for this key
+ let shape = schema;
+ while (shape instanceof z.ZodObject || shape instanceof z.ZodEffects) {
+ shape =
+ shape instanceof z.ZodObject
+ ? shape.shape
+ : shape instanceof z.ZodEffects
+ ? shape._def.schema
+ : null;
+ if (shape === null) {
+ throw new Error(`Could not find shape for key ${key}`);
+ }
+ }
+
+ if (key.includes('.')) {
+ const [parentProp, ...rest] = key.split('.') as [string, ...string[]];
+ o[parentProp!] = o[parentProp] ?? {};
+ parseParams(o[parentProp], shape[parentProp], rest.join('.'), value);
+ return;
+ }
+ let isArray = false;
+ if (key.includes('[]')) {
+ isArray = true;
+ key = key.replace('[]', '');
+ }
+ const def = shape[key];
+ if (def) {
+ processDef(def, o, key, value as string);
+ }
+}
+
+function processDef(def: z.ZodTypeAny, o: any, key: string, value: string) {
+ let parsedValue: any;
+ if (def instanceof z.ZodString || def instanceof z.ZodLiteral) {
+ parsedValue = value;
+ } else if (def instanceof z.ZodNumber) {
+ const num = Number(value);
+ parsedValue = isNaN(num) ? value : num;
+ } else if (def instanceof z.ZodDate) {
+ const date = Date.parse(value);
+ parsedValue = isNaN(date) ? value : new Date(date);
+ } else if (def instanceof z.ZodBoolean) {
+ parsedValue = value === 'true' ? true : value === 'false' ? false : Boolean(value);
+ } else if (def instanceof z.ZodNativeEnum || def instanceof z.ZodEnum) {
+ parsedValue = value;
+ } else if (def instanceof z.ZodOptional || def instanceof z.ZodDefault) {
+ // def._def.innerType is the same as ZodOptional's .unwrap(), which unfortunately doesn't exist on ZodDefault
+ processDef(def._def.innerType, o, key, value);
+ // return here to prevent overwriting the result of the recursive call
+ return;
+ } else if (def instanceof z.ZodArray) {
+ if (o[key] === undefined) {
+ o[key] = [];
+ }
+ processDef(def.element, o, key, value);
+ // return here since recursive call will add to array
+ return;
+ } else if (def instanceof z.ZodEffects) {
+ processDef(def._def.schema, o, key, value);
+ return;
+ } else {
+ throw new Error(`Unexpected type ${def._def.typeName} for key ${key}`);
+ }
+ if (Array.isArray(o[key])) {
+ o[key].push(parsedValue);
+ } else {
+ o[key] = parsedValue;
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 46c46045bedd..b59c2caa7d65 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -46,7 +46,7 @@ importers:
version: 5.2.2
vite:
specifier: ^4.5.0
- version: 4.5.0(@types/node@18.17.19)
+ version: 4.5.0(less@4.2.0)
.github/actions/publish-artifacts:
dependencies:
@@ -615,7 +615,7 @@ importers:
version: 5.2.2
vite:
specifier: ^4.5.0
- version: 4.5.0(@types/node@18.17.19)
+ version: 4.5.0(less@4.2.0)
vite-plugin-html:
specifier: ^3.2.0
version: 3.2.0(vite@4.5.0)
@@ -8952,7 +8952,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.2)
'@types/babel__core': 7.20.3
react-refresh: 0.14.0
- vite: 4.5.0(sass@1.69.5)
+ vite: 4.5.0(@types/node@18.17.19)
transitivePeerDependencies:
- supports-color
dev: true
@@ -21004,7 +21004,7 @@ packages:
'@rollup/pluginutils': 5.0.5
'@svgr/core': 8.1.0(typescript@5.2.2)
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0)
- vite: 4.5.0(sass@1.69.5)
+ vite: 4.5.0(@types/node@18.17.19)
transitivePeerDependencies:
- rollup
- supports-color