diff --git a/.changeset/quick-games-tease.md b/.changeset/quick-games-tease.md new file mode 100644 index 00000000..647da443 --- /dev/null +++ b/.changeset/quick-games-tease.md @@ -0,0 +1,5 @@ +--- +"@premieroctet/next-admin": patch +--- + +Possibility to not display search field on list if search option is an empty array. In case search options are not defined, all scalar fields are concerned diff --git a/packages/next-admin/src/components/List.tsx b/packages/next-admin/src/components/List.tsx index 982018e7..8f7315f8 100644 --- a/packages/next-admin/src/components/List.tsx +++ b/packages/next-admin/src/components/List.tsx @@ -3,12 +3,14 @@ import { ColumnDef, RowSelectionState } from "@tanstack/react-table"; import debounce from "lodash/debounce"; import { ChangeEvent, - useContext, useEffect, useState, - useTransition, + useTransition } from "react"; import { ITEMS_PER_PAGE } from "../config"; +import { useConfig } from "../context/ConfigContext"; +import { useDeleteAction } from "../hooks/useDeleteAction"; +import { useRouterInternal } from "../hooks/useRouterInternal"; import { ListData, ListDataFieldValue, @@ -31,9 +33,6 @@ import { SelectTrigger, SelectValue, } from "./radix/Select"; -import { useRouterInternal } from "../hooks/useRouterInternal"; -import { useConfig } from "../context/ConfigContext"; -import { useDeleteAction } from "../hooks/useDeleteAction"; export type ListProps = { resource: ModelName; @@ -66,67 +65,70 @@ function List({ const sortDirection = query.sortDirection as "asc" | "desc"; const { deleteItems } = useDeleteAction(resource, deleteAction); - const onSearchChange = debounce((e: ChangeEvent) => { - startTransition(() => { - router?.push({ - pathname: location.pathname, - query: { ...query, search: e.target.value }, + let onSearchChange; + if (!(options?.list?.search && options?.list?.search?.length === 0)) { + onSearchChange = debounce((e: ChangeEvent) => { + startTransition(() => { + router?.push({ + pathname: location.pathname, + query: { ...query, search: e.target.value }, + }); }); - }); - }, 300); + }, 300); + } const columns: ColumnDef>[] = data && data?.length > 0 ? Object.keys(data[0]).map((property) => { - return { - accessorKey: property, - header: () => { - return ( - { - router?.push({ - pathname: location.pathname, - query: { - ...query, - sortColumn: property, - sortDirection: - query.sortDirection === "asc" ? "desc" : "asc", - }, - }); - }} - /> - ); - }, - cell: ({ row }) => { - const modelData = row.original; - const cellData = modelData[ - property as keyof ListFieldsOptions - ] as unknown as ListDataFieldValue; + return { + accessorKey: property, + header: () => { + return ( + { + router?.push({ + pathname: location.pathname, + query: { + ...query, + sortColumn: property, + sortDirection: + query.sortDirection === "asc" ? "desc" : "asc", + }, + }); + }} + /> + ); + }, + cell: ({ row }) => { + const modelData = row.original; + const cellData = modelData[ + property as keyof ListFieldsOptions + ] as unknown as ListDataFieldValue; - const dataFormatter = - options?.list?.fields?.[ - property as keyof ListFieldsOptions - ]?.formatter || - ((cell: any) => { - if (typeof cell === "object") { - return cell[resourcesIdProperty[property as ModelName]]; - } else { - return cell; - } - }); + const dataFormatter = + options?.list?.fields?.[ + property as keyof ListFieldsOptions + ]?.formatter || + ((cell: any) => { + if (typeof cell === "object") { + return cell[resourcesIdProperty[property as ModelName]]; + } else { + return cell; + } + }); - return ( - - ); - }, - }; - }) + return ( + + ); + }, + }; + }) : []; useEffect(() => { diff --git a/packages/next-admin/src/components/ListHeader.tsx b/packages/next-admin/src/components/ListHeader.tsx index 06a9c270..8458fe13 100644 --- a/packages/next-admin/src/components/ListHeader.tsx +++ b/packages/next-admin/src/components/ListHeader.tsx @@ -5,15 +5,15 @@ import Link from "next/link"; import { ChangeEvent, useMemo } from "react"; import Loader from "../assets/icons/Loader"; import { useConfig } from "../context/ConfigContext"; +import { useI18n } from "../context/I18nContext"; import { ModelAction, ModelName } from "../types"; import ActionsDropdown from "./ActionsDropdown"; import { buttonVariants } from "./radix/Button"; -import { useI18n } from "../context/I18nContext"; type Props = { resource: ModelName; isPending: boolean; - onSearchChange: (e: ChangeEvent) => void; + onSearchChange?: (e: ChangeEvent) => void; search: string; actions?: ModelAction[]; selectedRows: RowSelectionState; @@ -53,7 +53,7 @@ export default function ListHeader({ return (
-
+ {onSearchChange &&
{isPending ? ( ) : ( @@ -70,7 +70,7 @@ export default function ListHeader({ className="px-3 py-1.5 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm focus-visible:outline focus-visible:outline-indigo-500 focus-visible:ring focus-visible:ring-indigo-500" placeholder={t("list.header.search.placeholder")} /> -
+
}
{!!selectedRowsCount && ( diff --git a/packages/next-admin/src/utils/props.ts b/packages/next-admin/src/utils/props.ts index 042af465..16e486bf 100644 --- a/packages/next-admin/src/utils/props.ts +++ b/packages/next-admin/src/utils/props.ts @@ -1,5 +1,6 @@ "use server"; import { Prisma, PrismaClient } from "@prisma/client"; +import { cloneDeep } from "lodash"; import qs from "querystring"; import { ActionParams, @@ -24,7 +25,6 @@ import { transformData, transformSchema, } from "./server"; -import { cloneDeep } from "lodash"; export type GetPropsFromParamsParams = { params?: string[]; @@ -99,6 +99,18 @@ export async function getPropsFromParams({ ); } + const clientOptions: NextAdminOptions = { + basePath: options.basePath, + model: { + [resource as ModelName]: { + list: { + display: options.model?.[resource as ModelName]?.list?.display, + search: options.model?.[resource as ModelName]?.list?.search, + }, + } + }, + } + let defaultProps: AdminComponentProps = { resources, basePath, @@ -112,6 +124,7 @@ export async function getPropsFromParams({ resourcesTitles, resourcesIdProperty, deleteAction, + options: clientOptions, }; if (!params) return defaultProps;