From 1fc2f388e33830f9cbdb4618d0335e0d66b4cd40 Mon Sep 17 00:00:00 2001 From: Zeke Zhang <958414905@qq.com> Date: Wed, 9 Oct 2024 10:33:29 +0800 Subject: [PATCH] fix(popup): z-index (#5373) * fix(popup): z-index * test: add e2e test * chore: fix build error * Revert "chore: fix build error" This reverts commit d0fe9ba217d2991a290f7fdd6bf5282c9bd9f71a. * refactor: avoid build error * chore: make e2e more stable --- .../src/modules/popup/__e2e__/zIndex.test.ts | 22 +++ .../antd/action/Action.Drawer.tsx | 81 +++++----- .../antd/action/Action.Modal.tsx | 149 +++++++++--------- .../antd/action/Action.Page.tsx | 11 +- .../src/schema-component/antd/action/utils.ts | 2 - .../antd/action/zIndexContext.tsx | 16 ++ 6 files changed, 165 insertions(+), 116 deletions(-) create mode 100644 packages/core/client/src/schema-component/antd/action/zIndexContext.tsx diff --git a/packages/core/client/src/modules/popup/__e2e__/zIndex.test.ts b/packages/core/client/src/modules/popup/__e2e__/zIndex.test.ts index 00c6eac6c1..3d05489c24 100644 --- a/packages/core/client/src/modules/popup/__e2e__/zIndex.test.ts +++ b/packages/core/client/src/modules/popup/__e2e__/zIndex.test.ts @@ -51,4 +51,26 @@ test.describe('z-index of dialog', () => { await page.getByRole('button', { name: 'Cancel' }).click({ timeout: 1000 }); await expect(page.getByRole('dialog').getByText('Assign field values')).not.toBeVisible(); }); + + test('Users & Permissions', async ({ page }) => { + await page.goto('/admin/settings/users-permissions/roles'); + + // Data source + await page.getByRole('tab', { name: 'Data sources' }).click(); + await page.getByLabel('action-Action.Link-Configure-').click(); + await page.getByRole('tab', { name: 'Action permissions', exact: true }).click(); + await page.getByLabel('action-Action.Link-Configure-dataSourcesCollections-users', { exact: true }).click(); + await page.getByLabel('Individual').check(); + await page + .getByTestId('drawer-Action.Drawer-dataSourcesCollections-Configure permission') + .getByRole('cell') + .locator('.ant-select-selector') + .first() + .click(); + await page + .getByTestId('drawer-RecordPicker.Selector-dataSourcesCollections-Select record') + .getByLabel('action-Action-Add new-create-') + .click(); + await expect(page.getByText('Add condition', { exact: true })).toBeVisible(); + }); }); diff --git a/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx b/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx index 0def3b4d0e..4a1c7da78f 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx @@ -19,7 +19,7 @@ import { useStyles } from './Action.Drawer.style'; import { useActionContext } from './hooks'; import { useSetAriaLabelForDrawer } from './hooks/useSetAriaLabelForDrawer'; import { ActionDrawerProps, ComposedActionDrawer, OpenSize } from './types'; -import { antdDrawerZIndex } from './utils'; +import { useZIndexContext, zIndexContext } from './zIndexContext'; const DrawerErrorFallback: React.FC = (props) => { const { visible, setVisible } = useActionContext(); @@ -43,6 +43,7 @@ export const InternalActionDrawer: React.FC = observer( const field = useField(); const { componentCls, hashId } = useStyles(); const tabContext = useTabsContext(); + const parentZIndex = useZIndexContext(); const footerSchema = schema.reduceProperties((buf, s) => { if (s['x-component'] === footerNodeName) { return s; @@ -62,44 +63,48 @@ export const InternalActionDrawer: React.FC = observer( useSetAriaLabelForDrawer(visible); } + const zIndex = parentZIndex + (props.level || 0); + return ( - - setVisible(false, true)} - rootClassName={classNames(componentCls, hashId, drawerProps?.className, others.className, 'reset')} - footer={ - footerSchema && ( -
- { - return s['x-component'] === footerNodeName; - }} - /> -
- ) - } - > - { - return s['x-component'] !== footerNodeName; - }} - /> -
-
+ + + setVisible(false, true)} + rootClassName={classNames(componentCls, hashId, drawerProps?.className, others.className, 'reset')} + footer={ + footerSchema && ( +
+ { + return s['x-component'] === footerNodeName; + }} + /> +
+ ) + } + > + { + return s['x-component'] !== footerNodeName; + }} + /> +
+
+
); }, { displayName: 'ActionDrawer' }, diff --git a/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx b/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx index fe24d02381..bf054edf25 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx @@ -20,7 +20,7 @@ import { TabsContextProvider, useTabsContext } from '../tabs/context'; import { useActionContext } from './hooks'; import { useSetAriaLabelForModal } from './hooks/useSetAriaLabelForModal'; import { ActionDrawerProps, ComposedActionDrawer, OpenSize } from './types'; -import { antdDrawerZIndex } from './utils'; +import { useZIndexContext, zIndexContext } from './zIndexContext'; const ModalErrorFallback: React.FC = (props) => { const { visible, setVisible } = useActionContext(); @@ -47,6 +47,7 @@ export const InternalActionModal: React.FC> = obse const field = useField(); const { token } = useToken(); const tabContext = useTabsContext(); + const parentZIndex = useZIndexContext(); const footerSchema = schema.reduceProperties((buf, s) => { if (s['x-component'] === footerNodeName) { return s; @@ -70,79 +71,83 @@ export const InternalActionModal: React.FC> = obse useSetAriaLabelForModal(visible); } + const zIndex = parentZIndex + (props.level || 0); + return ( - - { - setVisible(false, true); - form.reset(); - }} - className={classNames( - others.className, - modalProps?.className, - css` - &.nb-action-popup { - .ant-modal-header { - display: none; - } - - .ant-modal-content { - background: var(--nb-box-bg); - border: 1px solid rgba(255, 255, 255, 0.1); - padding-bottom: 0; - } - - // 这里的样式是为了保证页面 tabs 标签下面的分割线和页面内容对齐(页面内边距可以通过主题编辑器调节) - .ant-tabs-nav { - padding-left: ${token.paddingLG - token.paddingPageHorizontal}px; - padding-right: ${token.paddingLG - token.paddingPageHorizontal}px; - margin-left: ${token.paddingPageHorizontal - token.paddingLG}px; - margin-right: ${token.paddingPageHorizontal - token.paddingLG}px; - } - - .ant-modal-footer { - display: ${showFooter ? 'block' : 'none'}; - } - } - `, - )} - footer={ - showFooter ? ( - { - return s['x-component'] === footerNodeName; - }} - /> - ) : ( - false - ) - } - > - { - return s['x-component'] !== footerNodeName; + + + - - + destroyOnClose + open={visible} + onCancel={() => { + setVisible(false, true); + form.reset(); + }} + className={classNames( + others.className, + modalProps?.className, + css` + &.nb-action-popup { + .ant-modal-header { + display: none; + } + + .ant-modal-content { + background: var(--nb-box-bg); + border: 1px solid rgba(255, 255, 255, 0.1); + padding-bottom: 0; + } + + // 这里的样式是为了保证页面 tabs 标签下面的分割线和页面内容对齐(页面内边距可以通过主题编辑器调节) + .ant-tabs-nav { + padding-left: ${token.paddingLG - token.paddingPageHorizontal}px; + padding-right: ${token.paddingLG - token.paddingPageHorizontal}px; + margin-left: ${token.paddingPageHorizontal - token.paddingLG}px; + margin-right: ${token.paddingPageHorizontal - token.paddingLG}px; + } + + .ant-modal-footer { + display: ${showFooter ? 'block' : 'none'}; + } + } + `, + )} + footer={ + showFooter ? ( + { + return s['x-component'] === footerNodeName; + }} + /> + ) : ( + false + ) + } + > + { + return s['x-component'] !== footerNodeName; + }} + /> + + + ); }, { displayName: 'ActionModal' }, diff --git a/packages/core/client/src/schema-component/antd/action/Action.Page.tsx b/packages/core/client/src/schema-component/antd/action/Action.Page.tsx index 1fc433f79a..427accb25c 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Page.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Page.tsx @@ -15,7 +15,7 @@ import { BackButtonUsedInSubPage } from '../page/BackButtonUsedInSubPage'; import { TabsContextProvider, useTabsContext } from '../tabs/context'; import { useActionPageStyle } from './Action.Page.style'; import { usePopupOrSubpagesContainerDOM } from './hooks/usePopupSlotDOM'; -import { antdDrawerZIndex } from './utils'; +import { useZIndexContext, zIndexContext } from './zIndexContext'; export function ActionPage({ level }) { const filedSchema = useFieldSchema(); @@ -23,12 +23,13 @@ export function ActionPage({ level }) { const { getContainerDOM } = usePopupOrSubpagesContainerDOM(); const { styles } = useActionPageStyle(); const tabContext = useTabsContext(); + const parentZIndex = useZIndexContext(); const style = useMemo(() => { return { - zIndex: antdDrawerZIndex + level, + zIndex: parentZIndex + (level || 0), }; - }, [level]); + }, [parentZIndex, level]); if (!ctx.visible) { return null; @@ -37,7 +38,9 @@ export function ActionPage({ level }) { const actionPageNode = (
}> - + + +
); diff --git a/packages/core/client/src/schema-component/antd/action/utils.ts b/packages/core/client/src/schema-component/antd/action/utils.ts index 574d92c69e..372a70023b 100644 --- a/packages/core/client/src/schema-component/antd/action/utils.ts +++ b/packages/core/client/src/schema-component/antd/action/utils.ts @@ -154,5 +154,3 @@ export const setInitialActionState = (field) => { field.data.hidden = false; field.componentProps['disabled'] = false; }; - -export const antdDrawerZIndex = 100; diff --git a/packages/core/client/src/schema-component/antd/action/zIndexContext.tsx b/packages/core/client/src/schema-component/antd/action/zIndexContext.tsx new file mode 100644 index 0000000000..76721e13a3 --- /dev/null +++ b/packages/core/client/src/schema-component/antd/action/zIndexContext.tsx @@ -0,0 +1,16 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import React from 'react'; + +export const zIndexContext = React.createContext(100); + +export const useZIndexContext = () => { + return React.useContext(zIndexContext); +};