From 003805deac940b81dcc2973436621edf55688933 Mon Sep 17 00:00:00 2001 From: Hugo FOYART <11079152+foyarash@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:31:23 +0200 Subject: [PATCH] fix: correctly display path in advanced search (#442) * fix: correctly display path in advanced search * fix display path * decrease dialog radius * use translated names in dropdown trigger --- .changeset/breezy-cups-call.md | 5 +++ .../AdvancedSearchDropdownItem.tsx | 9 +++- .../src/components/radix/Dialog.tsx | 4 +- .../next-admin/src/context/I18nContext.tsx | 14 ++++--- .../next-admin/src/hooks/useAdvancedSearch.ts | 11 ++++- .../src/utils/advancedSearch.test.ts | 13 ++++++ .../next-admin/src/utils/advancedSearch.ts | 42 +++++++++++++++---- 7 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 .changeset/breezy-cups-call.md diff --git a/.changeset/breezy-cups-call.md b/.changeset/breezy-cups-call.md new file mode 100644 index 00000000..eec079c2 --- /dev/null +++ b/.changeset/breezy-cups-call.md @@ -0,0 +1,5 @@ +--- +"@premieroctet/next-admin": patch +--- + +fix: correctly display path in advanced search diff --git a/packages/next-admin/src/components/advancedSearch/AdvancedSearchDropdownItem.tsx b/packages/next-admin/src/components/advancedSearch/AdvancedSearchDropdownItem.tsx index f48eaaeb..f18586af 100644 --- a/packages/next-admin/src/components/advancedSearch/AdvancedSearchDropdownItem.tsx +++ b/packages/next-admin/src/components/advancedSearch/AdvancedSearchDropdownItem.tsx @@ -10,6 +10,7 @@ import { UIQueryBlock, } from "../../utils/advancedSearch"; import { useConfig } from "../../context/ConfigContext"; +import { useI18n } from "../../context/I18nContext"; type Props = { property: string; @@ -29,6 +30,7 @@ const AdvancedSearchDropdownItem = ({ displayPath, }: Props) => { const { options } = useConfig(); + const { t } = useI18n(); const schemaDef = schema.definitions[resource]; const schemaProperty = schemaDef.properties[property as keyof typeof schemaDef.properties]; @@ -66,8 +68,11 @@ const AdvancedSearchDropdownItem = ({ }, [hasChildren, schemaProperty, schema]); const aliases = options?.model?.[resource]?.aliases; - const displayedProperty = - aliases?.[property as keyof typeof aliases] ?? property; + const displayedProperty = t( + `model.${resource}.fields.${property}`, + {}, + aliases?.[property as keyof typeof aliases] ?? property + ); const onClick = (evt: MouseEvent) => { if (hasChildren) { diff --git a/packages/next-admin/src/components/radix/Dialog.tsx b/packages/next-admin/src/components/radix/Dialog.tsx index 7156dea2..9924c633 100644 --- a/packages/next-admin/src/components/radix/Dialog.tsx +++ b/packages/next-admin/src/components/radix/Dialog.tsx @@ -15,7 +15,7 @@ export const DialogOverlay = forwardRef< string; + const I18nContext = createContext<{ - t: ( - key: string, - options?: { [key: string]: any }, - fallback?: string - ) => string; + t: TranslationFn; }>({ t: () => "", }); @@ -20,7 +22,7 @@ export const I18nProvider = ({ translations, children, }: PropsWithChildren) => { - const t = ( + const t: TranslationFn = ( key: string, options?: { [key: string]: any }, fallback?: string diff --git a/packages/next-admin/src/hooks/useAdvancedSearch.ts b/packages/next-admin/src/hooks/useAdvancedSearch.ts index 86d7199f..95ce1b74 100644 --- a/packages/next-admin/src/hooks/useAdvancedSearch.ts +++ b/packages/next-admin/src/hooks/useAdvancedSearch.ts @@ -6,6 +6,8 @@ import { } from "../utils/advancedSearch"; import { useRouterInternal } from "./useRouterInternal"; import { ModelName, Schema } from "../types"; +import { useConfig } from "../context/ConfigContext"; +import { useI18n } from "../context/I18nContext"; type UseAdvancedSearchParams = { resource: M; @@ -17,6 +19,8 @@ const useAdvancedSearch = ({ schema, }: UseAdvancedSearchParams) => { const { router, query } = useRouterInternal(); + const { options } = useConfig(); + const { t } = useI18n(); const [uiBlocks, setUiBlocks] = useState(() => { if (query.q) { const blocks = validateQuery(query.q); @@ -25,7 +29,12 @@ const useAdvancedSearch = ({ return null; } - return buildUIBlocks(blocks, { resource, schema }); + return buildUIBlocks(blocks, { + resource, + schema, + options: options?.model, + t, + }); } }); diff --git a/packages/next-admin/src/utils/advancedSearch.test.ts b/packages/next-admin/src/utils/advancedSearch.test.ts index d643be7c..80cbbb62 100644 --- a/packages/next-admin/src/utils/advancedSearch.test.ts +++ b/packages/next-admin/src/utils/advancedSearch.test.ts @@ -153,6 +153,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[0]", nullable: true, + displayPath: "test", }, { type: "filter", @@ -164,6 +165,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[1]", nullable: true, + displayPath: "test", }, { type: "filter", @@ -175,6 +177,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[2]", nullable: true, + displayPath: "test", }, { type: "filter", @@ -186,6 +189,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[3]", nullable: false, + displayPath: "test2", }, { type: "filter", @@ -197,6 +201,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[4]", nullable: false, + displayPath: "test5 → test6", }, { type: "filter", @@ -208,6 +213,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[5]", nullable: false, + displayPath: "test5 → some", }, { type: "and", @@ -224,6 +230,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[6].children[0]", nullable: false, + displayPath: "test3 → test", }, { type: "filter", @@ -235,6 +242,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[6].children[1]", nullable: false, + displayPath: "test3 → test2", }, { type: "or", @@ -251,6 +259,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[6].children[2].children[0]", nullable: false, + displayPath: "test5 → test6", }, ], }, @@ -266,6 +275,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[7]", nullable: false, + displayPath: "testBool", }, { type: "filter", @@ -277,6 +287,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[8]", nullable: true, + displayPath: "testNull", }, { type: "filter", @@ -288,6 +299,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[9]", nullable: false, + displayPath: "testArray", }, ]; @@ -322,6 +334,7 @@ describe("advancedSearch", () => { canHaveChildren: false, internalPath: "[0]", nullable: false, + displayPath: "test2", }, ]; diff --git a/packages/next-admin/src/utils/advancedSearch.ts b/packages/next-admin/src/utils/advancedSearch.ts index 36a9fdfa..4ee3e7ef 100644 --- a/packages/next-admin/src/utils/advancedSearch.ts +++ b/packages/next-admin/src/utils/advancedSearch.ts @@ -1,7 +1,8 @@ import z from "zod"; import set from "lodash.set"; import get from "lodash.get"; -import { ModelName, Schema, SchemaModel } from "../types"; +import { ModelName, ModelOptions, Schema, SchemaModel } from "../types"; +import { TranslationFn } from "../context/I18nContext"; export type QueryCondition = | "equals" @@ -234,8 +235,19 @@ const getQueryBlockValue = ( export const buildUIBlocks = ( blocks: QueryBlock | null, - { resource, schema }: { resource: M; schema: Schema }, - fields: string[] = [] + { + resource, + schema, + options, + t, + }: { + resource: M; + schema: Schema; + options?: ModelOptions; + t?: TranslationFn; + }, + fields: string[] = [], + displayFields: string[] = [] ): UIQueryBlock[] => { if (blocks) { const entries = Object.entries(blocks); @@ -247,7 +259,12 @@ export const buildUIBlocks = ( type: key === "AND" ? "and" : "or", id: crypto.randomUUID(), children: value.flatMap((block: QueryBlock) => { - return buildUIBlocks(block, { resource, schema }, fields); + return buildUIBlocks( + block, + { resource, schema, options }, + fields, + displayFields + ); }), }; } else { @@ -257,10 +274,14 @@ export const buildUIBlocks = ( key as keyof typeof resourceInSchema.properties ]; const conditions = Object.entries(value as Filter); + const displayKeyFallback = options?.[resource]?.aliases?.[key] ?? key; + const displayKey = + t?.(`model.${resource}.fields.${key}`, {}, displayKeyFallback) ?? + displayKeyFallback; if (schemaProperty) { // @ts-expect-error - return conditions.flatMap(([conditionKey, conditionValue]) => { + return conditions.flatMap(([conditionKey]) => { const queryCondition = getQueryCondition(conditionKey); if (queryCondition) { @@ -286,6 +307,7 @@ export const buildUIBlocks = ( contentType: contentType, canHaveChildren: false, nullable: isFieldNullable(schemaProperty.type), + displayPath: [...displayFields, displayKey].join(" → "), }; } else { let isArrayConditionKey = conditionKey === "some"; @@ -321,8 +343,9 @@ export const buildUIBlocks = ( .flatMap((block) => { return buildUIBlocks( block, - { resource: childResourceName, schema }, - [...fields, key] + { resource: childResourceName, schema, options }, + [...fields, key], + [...displayFields, displayKey] ); }) .filter(Boolean) as UIQueryBlock[], @@ -331,8 +354,9 @@ export const buildUIBlocks = ( return buildUIBlocks( { [childKey]: childValue } as Filter, - { resource: childResourceName, schema }, - [...fields, key] + { resource: childResourceName, schema, options }, + [...fields, key], + [...displayFields, displayKey] ); }) .flat();