From 3cf7eb8603d0d304d24daa4a83fcdd9fba9c15a5 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Fri, 7 Feb 2025 13:53:23 +0000 Subject: [PATCH] Make dialogs work in iframes --- .../toolpad/core/components/crud/CRUDBasic.js | 28 ++++++++++++++++--- .../core/components/crud/CRUDBasic.tsx | 2 +- .../components/crud/CRUDBasic.tsx.preview | 3 +- .../src/useDialogs/useDialogs.tsx | 24 ++++++++++++++-- 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/docs/data/toolpad/core/components/crud/CRUDBasic.js b/docs/data/toolpad/core/components/crud/CRUDBasic.js index c120e526dbb..14db1d8a6a2 100644 --- a/docs/data/toolpad/core/components/crud/CRUDBasic.js +++ b/docs/data/toolpad/core/components/crud/CRUDBasic.js @@ -33,7 +33,10 @@ const demoTheme = createTheme({ }, }); -let notesStore = []; +let notesStore = [ + { id: 1, title: 'Grocery List Item', text: 'Buy more coffee.' }, + { id: 2, title: 'Personal Goal', text: 'Finish reading the book.' }, +]; export const notesDataSource = { fields: [ @@ -180,6 +183,12 @@ export const notesDataSource = { }, }; +function matchPath(pattern, pathname) { + const regex = new RegExp(`^${pattern.replace(/:[^/]+/g, '([^/]+)')}$`); + const match = pathname.match(regex); + return match ? match[1] : null; +} + function CRUDBasic(props) { const { window } = props; @@ -189,8 +198,20 @@ function CRUDBasic(props) { const demoWindow = window !== undefined ? window() : undefined; const title = React.useMemo(() => { + if (router.pathname === '/notes/new') { + return 'New Note'; + } + const editNoteId = matchPath('/notes/:noteId/edit', router.pathname); + if (editNoteId) { + return `Note ${editNoteId} - Edit`; + } + const showNoteId = matchPath('/notes/:noteId', router.pathname); + if (showNoteId) { + return `Note ${showNoteId}`; + } + return undefined; - }, []); + }, [router.pathname]); return ( {/* preview-end */} diff --git a/docs/data/toolpad/core/components/crud/CRUDBasic.tsx b/docs/data/toolpad/core/components/crud/CRUDBasic.tsx index 450471fb8a3..0f549f70f1c 100644 --- a/docs/data/toolpad/core/components/crud/CRUDBasic.tsx +++ b/docs/data/toolpad/core/components/crud/CRUDBasic.tsx @@ -181,7 +181,7 @@ export const notesDataSource: DataSource = { errors.title = 'Title must be at least 3 characters long'; } if (!formValues.text) { - errors.status = 'Text is required'; + errors.text = 'Text is required'; } return errors; diff --git a/docs/data/toolpad/core/components/crud/CRUDBasic.tsx.preview b/docs/data/toolpad/core/components/crud/CRUDBasic.tsx.preview index 58fbd4030eb..a5ae2974706 100644 --- a/docs/data/toolpad/core/components/crud/CRUDBasic.tsx.preview +++ b/docs/data/toolpad/core/components/crud/CRUDBasic.tsx.preview @@ -1,6 +1,5 @@ dataSource={notesDataSource} rootPath="/notes" - initialPageSize={25} - defaultValues={{ itemCount: 1 }} + initialPageSize={10} /> \ No newline at end of file diff --git a/packages/toolpad-core/src/useDialogs/useDialogs.tsx b/packages/toolpad-core/src/useDialogs/useDialogs.tsx index 192b20aac0a..ed5b2598ac7 100644 --- a/packages/toolpad-core/src/useDialogs/useDialogs.tsx +++ b/packages/toolpad-core/src/useDialogs/useDialogs.tsx @@ -11,6 +11,7 @@ import { useNonNullableContext } from '@toolpad/utils/react'; import invariant from 'invariant'; import * as React from 'react'; import { DialogsContext } from './DialogsContext'; +import { WindowContext } from '../shared/context'; export interface OpenDialogOptions { /** @@ -192,9 +193,17 @@ export interface AlertDialogPayload extends AlertOptions { export interface AlertDialogProps extends DialogProps {} export function AlertDialog({ open, payload, onClose }: AlertDialogProps) { + const appWindowContext = React.useContext(WindowContext); + const okButtonProps = useDialogLoadingButton(() => onClose()); return ( - onClose()}> + onClose()} + container={appWindowContext?.document.body} + > {payload.title ?? 'Alert'} {payload.msg} @@ -213,10 +222,18 @@ export interface ConfirmDialogPayload extends ConfirmOptions { export interface ConfirmDialogProps extends DialogProps {} export function ConfirmDialog({ open, payload, onClose }: ConfirmDialogProps) { + const appWindowContext = React.useContext(WindowContext); + const cancelButtonProps = useDialogLoadingButton(() => onClose(false)); const okButtonProps = useDialogLoadingButton(() => onClose(true)); return ( - onClose(false)}> + onClose(false)} + container={appWindowContext?.document.body} + > {payload.title ?? 'Confirm'} {payload.msg} @@ -238,6 +255,8 @@ export interface PromptDialogPayload extends PromptOptions { export interface PromptDialogProps extends DialogProps {} export function PromptDialog({ open, payload, onClose }: PromptDialogProps) { + const appWindowContext = React.useContext(WindowContext); + const [input, setInput] = React.useState(''); const cancelButtonProps = useDialogLoadingButton(() => onClose(null)); @@ -265,6 +284,7 @@ export function PromptDialog({ open, payload, onClose }: PromptDialogProps) { } }, }} + container={appWindowContext?.document.body} > {payload.title ?? 'Confirm'}