From 6da22fca219cb2be4befd709d164f99ead69080c Mon Sep 17 00:00:00 2001 From: Regourd Colin Date: Mon, 1 Jul 2024 13:46:23 +0200 Subject: [PATCH] Revert "Revert "Add loader to select"" --- .changeset/strange-waves-rush.md | 5 + .github/workflows/reset-database.yml | 3 + .../[locale]/admin/[[...nextadmin]]/page.tsx | 2 +- apps/example/options.tsx | 4 + apps/example/pageRouterOptions.tsx | 9 +- apps/example/public/assets/logo.svg | 92 +++++++++++ packages/next-admin/src/components/Form.tsx | 1 + .../next-admin/src/components/LoaderRow.tsx | 7 +- .../inputs/MultiSelect/MultiSelectWidget.tsx | 147 +++++++++--------- .../src/components/inputs/SelectWidget.tsx | 21 ++- .../src/components/inputs/Selector.tsx | 44 ++---- .../src/hooks/useCloseOnOutsideClick.ts | 33 ++-- 12 files changed, 229 insertions(+), 139 deletions(-) create mode 100644 .changeset/strange-waves-rush.md create mode 100644 apps/example/public/assets/logo.svg diff --git a/.changeset/strange-waves-rush.md b/.changeset/strange-waves-rush.md new file mode 100644 index 00000000..c48a981d --- /dev/null +++ b/.changeset/strange-waves-rush.md @@ -0,0 +1,5 @@ +--- +"@premieroctet/next-admin": patch +--- + +Add loader on select diff --git a/.github/workflows/reset-database.yml b/.github/workflows/reset-database.yml index 6c086fba..e4b4074f 100644 --- a/.github/workflows/reset-database.yml +++ b/.github/workflows/reset-database.yml @@ -13,4 +13,7 @@ jobs: - name: Install dependencies run: yarn install - name: Reset database + env: + POSTGRES_URL_NON_POOLING: ${{ env.POSTGRES_URL_NON_POOLING }} + POSTGRES_URL: ${{ env.POSTGRES_URL }} run: yarn reset-database \ No newline at end of file diff --git a/apps/example/app/[locale]/admin/[[...nextadmin]]/page.tsx b/apps/example/app/[locale]/admin/[[...nextadmin]]/page.tsx index 9313f40f..3987db28 100644 --- a/apps/example/app/[locale]/admin/[[...nextadmin]]/page.tsx +++ b/apps/example/app/[locale]/admin/[[...nextadmin]]/page.tsx @@ -17,7 +17,7 @@ export const viewport: Viewport = { }; export const metadata: Metadata = { - icons: "/favicon.ico", + icons: "/assets/logo.svg", }; export default async function AdminPage({ diff --git a/apps/example/options.tsx b/apps/example/options.tsx index 1b459cfa..7797fa3a 100644 --- a/apps/example/options.tsx +++ b/apps/example/options.tsx @@ -228,6 +228,10 @@ export const options: NextAdminOptions = { label: "Documentation", url: "https://next-admin.js.org", }, + { + label: "Page Router", + url: "/pagerouter/admin", + }, ], defaultColorScheme: "dark", }; diff --git a/apps/example/pageRouterOptions.tsx b/apps/example/pageRouterOptions.tsx index 54699343..cf988246 100644 --- a/apps/example/pageRouterOptions.tsx +++ b/apps/example/pageRouterOptions.tsx @@ -3,7 +3,7 @@ import DatePicker from "./components/DatePicker"; export const options: NextAdminOptions = { basePath: "/pagerouter/admin", - title: "⚡️ My Admin", + title: "⚡️ My Admin Page Router", model: { User: { toString: (user) => `${user.name} (${user.email})`, @@ -22,7 +22,6 @@ export const options: NextAdminOptions = { }, }, }, - ], fields: { role: { @@ -157,6 +156,12 @@ export const options: NextAdminOptions = { icon: "AdjustmentsHorizontalIcon", }, }, + externalLinks: [ + { + label: "App Router", + url: "/ ", + }, + ], sidebar: { groups: [ { diff --git a/apps/example/public/assets/logo.svg b/apps/example/public/assets/logo.svg new file mode 100644 index 00000000..21a409c6 --- /dev/null +++ b/apps/example/public/assets/logo.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/next-admin/src/components/Form.tsx b/packages/next-admin/src/components/Form.tsx index 4f987519..2fb6c478 100644 --- a/packages/next-admin/src/components/Form.tsx +++ b/packages/next-admin/src/components/Form.tsx @@ -560,6 +560,7 @@ const Form = ({ onSubmit={(e) => console.log("onSubmit", e)} onError={(e) => console.log("onError", e)} ref={formRef} + className="relative" /> )} diff --git a/packages/next-admin/src/components/LoaderRow.tsx b/packages/next-admin/src/components/LoaderRow.tsx index 31230672..d389ac59 100644 --- a/packages/next-admin/src/components/LoaderRow.tsx +++ b/packages/next-admin/src/components/LoaderRow.tsx @@ -12,14 +12,15 @@ const LoadingRow = forwardRef< return (
- - {t("selector.loading")} + + {t("selector.loading")}
); }); diff --git a/packages/next-admin/src/components/inputs/MultiSelect/MultiSelectWidget.tsx b/packages/next-admin/src/components/inputs/MultiSelect/MultiSelectWidget.tsx index 12040131..7991a4f6 100644 --- a/packages/next-admin/src/components/inputs/MultiSelect/MultiSelectWidget.tsx +++ b/packages/next-admin/src/components/inputs/MultiSelect/MultiSelectWidget.tsx @@ -1,11 +1,8 @@ import { RJSFSchema } from "@rjsf/utils"; import clsx from "clsx"; -import { PropsWithChildren, useRef } from "react"; -import { twMerge } from "tailwind-merge"; import DoubleArrow from "../../../assets/icons/DoubleArrow"; import { useForm } from "../../../context/FormContext"; import { useI18n } from "../../../context/I18nContext"; -import useCloseOnOutsideClick from "../../../hooks/useCloseOnOutsideClick"; import { Enumeration, Field, ModelName } from "../../../types"; import Button from "../../radix/Button"; import { Selector } from "../Selector"; @@ -26,9 +23,7 @@ type Props = { const MultiSelectWidget = (props: Props) => { const formContext = useForm(); const { formData, onChange, options, name, schema } = props; - const containerRef = useRef(null); const { t } = useI18n(); - useCloseOnOutsideClick(containerRef, () => formContext.setOpen(false, name)); const fieldOptions = formContext.options?.model?.[formContext.resource!]?.edit?.fields?.[ name as Field @@ -53,65 +48,61 @@ const MultiSelectWidget = (props: Props) => { // @ts-expect-error const fieldSortable = displayMode === "list" && !!fieldOptions?.orderField; - const Select = ({ - children, - className, - }: PropsWithChildren>) => ( -
- - {children} -
+ const select = ( + ); return (
{displayMode === "select" && ( - +
+ {select} + {formData?.map( + (value: any, index: number) => + value && ( + onRemoveClick(value.value)} + deletable={!props.disabled} + /> + ) + )} + {!props.disabled && ( +
+ +
+ )} +
)} {displayMode === "list" && (
@@ -123,15 +114,16 @@ const MultiSelectWidget = (props: Props) => { sortable={fieldSortable} onUpdateFormData={onChange} /> - + +
)} {displayMode === "table" && ( @@ -142,15 +134,16 @@ const MultiSelectWidget = (props: Props) => { onRemoveClick={onRemoveClick} deletable={!props.disabled} /> - + +
)} diff --git a/packages/next-admin/src/components/inputs/SelectWidget.tsx b/packages/next-admin/src/components/inputs/SelectWidget.tsx index ac8a1b69..1933122a 100644 --- a/packages/next-admin/src/components/inputs/SelectWidget.tsx +++ b/packages/next-admin/src/components/inputs/SelectWidget.tsx @@ -5,11 +5,10 @@ import { import { WidgetProps } from "@rjsf/utils"; import clsx from "clsx"; import Link from "next/link"; -import { useMemo, useRef } from "react"; +import { useMemo } from "react"; import DoubleArrow from "../../assets/icons/DoubleArrow"; import { useConfig } from "../../context/ConfigContext"; import { useForm } from "../../context/FormContext"; -import useCloseOnOutsideClick from "../../hooks/useCloseOnOutsideClick"; import { Enumeration } from "../../types"; import { slugify } from "../../utils/tools"; import { Selector } from "./Selector"; @@ -28,8 +27,6 @@ const SelectWidget = ({ const enumOptions = options.enumOptions?.map( (option: any) => option.value as Enumeration ); - const containerRef = useRef(null); - useCloseOnOutsideClick(containerRef, () => formContext.setOpen(false, name)); const { basePath } = useConfig(); @@ -43,7 +40,7 @@ const SelectWidget = ({ }, [value]); return ( -
+
{ + e.stopPropagation(); + }} >
diff --git a/packages/next-admin/src/hooks/useCloseOnOutsideClick.ts b/packages/next-admin/src/hooks/useCloseOnOutsideClick.ts index c8037e7f..76b45cb9 100644 --- a/packages/next-admin/src/hooks/useCloseOnOutsideClick.ts +++ b/packages/next-admin/src/hooks/useCloseOnOutsideClick.ts @@ -1,24 +1,23 @@ -import { useEffect } from "react"; +import { useEffect, useRef } from "react"; -function useCloseOnOutsideClick( - ref: React.RefObject, +const useCloseOnOutsideClick = ( close: () => void -) { - function onWindowClick(event: MouseEvent) { +) => { + const ref: React.RefObject = useRef(null); + const onWindowClick = (event: MouseEvent) => { if (ref.current && !ref.current.contains(event.target as Node)) { close(); } - } - useEffect( - () => { - window.addEventListener("click", onWindowClick); - return () => { - window.removeEventListener("click", onWindowClick); - }; - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [] - ); -} + }; + + useEffect(() => { + window.addEventListener("click", onWindowClick); + return () => { + window.removeEventListener("click", onWindowClick); + }; + }, []); + + return ref; +}; export default useCloseOnOutsideClick;