diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/QueryEditor/index.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/QueryEditor/index.tsx index 630f92c30b2..682e6869e9a 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/QueryEditor/index.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/QueryEditor/index.tsx @@ -125,13 +125,18 @@ export default function QueryEditor() { const domApi = useDomApi(); const [dialogState, setDialogState] = React.useState(null); + const isDraft = dialogState?.isDraft || false; const page = appDom.getNode(dom, state.nodeId, 'page'); const { queries = [] } = appDom.getChildNodes(dom, page) ?? []; const handleEditStateDialogClose = React.useCallback(() => { - appStateApi.setView({ kind: 'page', nodeId: page.id }); - }, [appStateApi, page.id]); + if (isDraft) { + setDialogState(null); + } else { + appStateApi.setView({ kind: 'page', nodeId: page.id }); + } + }, [appStateApi, isDraft, page.id]); const handleCreated = React.useCallback((node: appDom.QueryNode) => { setDialogState({ node, isDraft: true }); @@ -142,11 +147,7 @@ export default function QueryEditor() { if (appDom.nodeExists(dom, node.id)) { domApi.saveNode(node); } else { - appStateApi.update((draft) => appDom.addNode(draft, node, page, 'queries'), { - kind: 'page', - nodeId: page.id, - view: { kind: 'query', nodeId: node.id }, - }); + appStateApi.update((draft) => appDom.addNode(draft, node, page, 'queries')); } }, [dom, domApi, appStateApi, page], @@ -184,15 +185,19 @@ export default function QueryEditor() { ); React.useEffect(() => { - setDialogState(() => { + setDialogState((previousState) => { if (currentView.kind === 'page' && currentView.view?.kind === 'query') { const node = appDom.getNode(dom, currentView.view?.nodeId, 'query'); return { node, isDraft: false }; } + if (isDraft) { + return previousState; + } + return null; }); - }, [dom, currentView]); + }, [currentView, dom, isDraft]); const [anchorEl, setAnchorEl] = React.useState(null); @@ -297,7 +302,7 @@ export default function QueryEditor() { (style === 'auto' ? 0 : parseFloat(style)); + + let offsetLeft = parseMarginStyle(styles.marginLeft); + let offsetRight = parseMarginStyle(styles.marginRight); + let offsetTop = parseMarginStyle(styles.marginTop); + let offsetBottom = parseMarginStyle(styles.marginBottom); if (styles.boxSizing === 'content-box') { offsetLeft += parseFloat(styles.paddingLeft) + parseFloat(styles.borderLeftWidth); diff --git a/test/integration/rest-basic/index.spec.ts b/test/integration/rest-basic/index.spec.ts index 75da332e48e..6c26f1c9e69 100644 --- a/test/integration/rest-basic/index.spec.ts +++ b/test/integration/rest-basic/index.spec.ts @@ -23,7 +23,7 @@ test.use({ }, }); -test('rest basics', async ({ page, localApp }) => { +test('rest basics', async ({ page, context, localApp }) => { const queriesFilePath = path.resolve(localApp.dir, './toolpad.yml'); await fileReplaceAll(queriesFilePath, HTTPBIN_SOURCE_URL, HTTPBIN_TARGET_URL); @@ -37,9 +37,32 @@ test('rest basics', async ({ page, localApp }) => { const editorModel = new ToolpadEditor(page); await editorModel.goto(); + await editorModel.componentEditor.getByRole('button', { name: 'Add query' }).click(); + await page.getByRole('button', { name: 'serverside HTTP request' }).click(); + + const newQueryEditor = page.getByRole('dialog', { name: 'query' }); + + await expect(newQueryEditor).toBeVisible(); + + // Make sure switching tabs does not close query editor + const newTab = await context.newPage(); + await newTab.bringToFront(); + await page.bringToFront(); + await expect(newQueryEditor).toBeVisible(); + + await newQueryEditor.getByRole('button', { name: 'Save' }).click(); + await expect(newQueryEditor).not.toBeVisible(); + await editorModel.componentEditor.getByRole('button', { name: 'query1' }).click(); - const queryEditor = page.getByRole('dialog', { name: 'query1' }); - await queryEditor.getByRole('button', { name: 'Preview' }).click(); - const networkTab = queryEditor.getByRole('tabpanel', { name: 'Network' }); + + const existingQueryEditor = page.getByRole('dialog', { name: 'query1' }); + + await expect(existingQueryEditor).toBeVisible(); + + await existingQueryEditor.getByRole('button', { name: 'Preview' }).click(); + const networkTab = existingQueryEditor.getByRole('tabpanel', { name: 'Network' }); await expect(networkTab.getByText('/get?query1_param1=query1_value')).not.toBeEmpty(); + + await existingQueryEditor.getByRole('button', { name: 'Cancel' }).click(); + await expect(existingQueryEditor).not.toBeVisible(); });