diff --git a/packages/core/client/src/modules/popup/PopupContextProvider.tsx b/packages/core/client/src/modules/popup/PopupContextProvider.tsx index 488aa5abdc..55b69ee1f7 100644 --- a/packages/core/client/src/modules/popup/PopupContextProvider.tsx +++ b/packages/core/client/src/modules/popup/PopupContextProvider.tsx @@ -21,6 +21,7 @@ export const PopupContextProvider: React.FC<{ visible?: boolean; setVisible?: (visible: boolean) => void; }> = (props) => { + const { visible: visibleFromProps, setVisible: setVisibleFromProps } = props; const [visible, setVisible] = useState(false); const { visible: visibleWithURL, setVisible: setVisibleWithURL } = useContext(PopupVisibleProviderContext) || { visible: false, @@ -29,11 +30,11 @@ export const PopupContextProvider: React.FC<{ const fieldSchema = useFieldSchema(); const _setVisible = useCallback( (value: boolean): void => { - props.setVisible?.(value); + setVisibleFromProps?.(value); setVisible?.(value); setVisibleWithURL?.(value); }, - [props, setVisibleWithURL], + [setVisibleFromProps, setVisibleWithURL], ); const openMode = fieldSchema['x-component-props']?.['openMode'] || 'drawer'; const openSize = fieldSchema['x-component-props']?.['openSize']; @@ -41,7 +42,7 @@ export const PopupContextProvider: React.FC<{ return ( { + test('clicking and closing nested popups', async ({ page, mockPage }) => { + await mockPage(clickingAndClosingNestedPopups).goto(); + + // 1. 打开第一层弹窗 + await page.getByLabel('action-Action.Link-View-view-').click(); + + // 2. 打开第二层弹窗 + await page.getByLabel('block-item-CardItem-users-calendar').getByText('Super Admin').click(); + await expect(page.getByLabel('block-item-Markdown.Void-').getByText('Calendar popup.')).toBeVisible(); + + // 3. 关闭第二层弹窗后,第一层弹窗应仍然存在 + await page.getByLabel('drawer-Action.Container-users').nth(2).click(); + await expect(page.getByLabel('block-item-CardItem-users-calendar').getByText('Super Admin')).toBeVisible(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-calendar/src/client/__e2e__/templates.ts b/packages/plugins/@nocobase/plugin-calendar/src/client/__e2e__/templates.ts index 2167d0b5f9..b1887ababe 100644 --- a/packages/plugins/@nocobase/plugin-calendar/src/client/__e2e__/templates.ts +++ b/packages/plugins/@nocobase/plugin-calendar/src/client/__e2e__/templates.ts @@ -489,3 +489,466 @@ export const backgroundColorFieldBasic = { 'x-index': 1, }, }; +export const clickingAndClosingNestedPopups = { + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + 'x-app-version': '1.4.2', + properties: { + gu3lh4ohfmv: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + 'x-app-version': '1.4.2', + properties: { + '0k716vx55jw': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '1.4.2', + properties: { + '071seig43nq': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + 'x-app-version': '1.4.2', + properties: { + '27bjkk814v0': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableBlockProvider', + 'x-acl-action': 'users:list', + 'x-use-decorator-props': 'useTableBlockDecoratorProps', + 'x-decorator-props': { + collection: 'users', + dataSource: 'main', + action: 'list', + params: { + pageSize: 20, + }, + rowKey: 'id', + showIndex: true, + dragSort: false, + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:table', + 'x-component': 'CardItem', + 'x-filter-targets': [], + 'x-app-version': '1.4.2', + properties: { + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'table:configureActions', + 'x-component': 'ActionBar', + 'x-component-props': { + style: { + marginBottom: 'var(--nb-spacing)', + }, + }, + 'x-app-version': '1.4.2', + 'x-uid': 'bpji6jn3v1f', + 'x-async': false, + 'x-index': 1, + }, + nzjfwy6u3xz: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'array', + 'x-initializer': 'table:configureColumns', + 'x-component': 'TableV2', + 'x-use-component-props': 'useTableBlockProps', + 'x-component-props': { + rowKey: 'id', + rowSelection: { + type: 'checkbox', + }, + }, + 'x-app-version': '1.4.2', + properties: { + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("Actions") }}', + 'x-action-column': 'actions', + 'x-decorator': 'TableV2.Column.ActionBar', + 'x-component': 'TableV2.Column', + 'x-toolbar': 'TableColumnSchemaToolbar', + 'x-initializer': 'table:configureItemActions', + 'x-settings': 'fieldSettings:TableColumn', + 'x-toolbar-props': { + initializer: 'table:configureItemActions', + }, + 'x-app-version': '1.4.2', + properties: { + t1guxxh00u2: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + 'x-app-version': '1.4.2', + properties: { + ibdtt3wddl1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View") }}', + 'x-action': 'view', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:view', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + }, + 'x-action-context': { + dataSource: 'main', + collection: 'users', + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'popup:addTab', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:common:addBlock', + properties: { + j42bnb1n6yi: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '1.4.2', + properties: { + wg7hugxuf56: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + 'x-app-version': '1.4.2', + properties: { + '2hp241xeuef': { + 'x-uid': '0y9z2g6e5ea', + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-acl-action': 'users:list', + 'x-decorator': 'CalendarBlockProvider', + 'x-use-decorator-props': + 'useCalendarBlockDecoratorProps', + 'x-decorator-props': { + collection: 'users', + dataSource: 'main', + action: 'list', + fieldNames: { + id: 'id', + start: 'createdAt', + title: 'nickname', + end: ['updatedAt'], + }, + params: { + paginate: false, + }, + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:calendar', + 'x-component': 'CardItem', + 'x-app-version': '1.4.2', + 'x-component-props': { + title: 'Calendar block', + }, + properties: { + '57jxlpnfu9t': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'CalendarV2', + 'x-use-component-props': 'useCalendarBlockProps', + 'x-app-version': '1.4.2', + properties: { + toolBar: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'CalendarV2.ActionBar', + 'x-component-props': { + style: { + marginBottom: 24, + }, + }, + 'x-initializer': 'calendar:configureActions', + 'x-app-version': '1.4.2', + 'x-uid': 'ia38586h8fo', + 'x-async': false, + 'x-index': 1, + }, + event: { + 'x-uid': 'e8svncxqkp7', + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'CalendarV2.Event', + 'x-app-version': '1.4.2', + 'x-action-context': { + dataSource: 'main', + collection: 'users', + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + title: + "{{t('View record', { ns: 'calendar' })}}", + 'x-app-version': '1.4.2', + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'popup:addTab', + 'x-initializer-props': { + gridInitializer: + 'popup:common:addBlock', + }, + 'x-app-version': '1.4.2', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: + "{{t('Details', { ns: 'calendar' })}}", + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + 'x-app-version': '1.4.2', + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer-props': { + actionInitializers: + 'details:configureActions', + }, + 'x-initializer': + 'popup:common:addBlock', + 'x-app-version': '1.4.2', + properties: { + bh4zvrtn09t: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '1.4.2', + properties: { + '0lh42pfh3ph': { + _isJSONSchemaObject: + true, + version: '2.0', + type: 'void', + 'x-component': + 'Grid.Col', + 'x-app-version': + '1.4.2', + properties: { + '2kq6pr243vl': { + 'x-uid': + '21wdilxulem', + _isJSONSchemaObject: + true, + version: '2.0', + type: 'void', + 'x-settings': + 'blockSettings:markdown', + 'x-decorator': + 'CardItem', + 'x-decorator-props': + { + name: 'markdown', + engine: + 'handlebars', + }, + 'x-component': + 'Markdown.Void', + 'x-editable': false, + 'x-component-props': + { + content: + 'Calendar popup.', + }, + 'x-app-version': + '1.4.2', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'z94z356ifbk', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'xwmfjtwnihr', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'cmn694oblps', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'mgj91lvgxfh', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'felpqurn0fk', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'qc3g6z67zut', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'j1cysoi2ifz', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '45q1me8jji6', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'uq380f0t9p7', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 's9r0d0qwkyl', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ne2ocpkouz7', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'tkavcfe78kj', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'iz6ogq6s0mi', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '9i1fmjqbp2k', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '7o9hpj80o2d', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'c04kw7704np', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'na4gq4s5he9', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'jxwnopamkgz', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '413e4dqcg8x', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'q8teoqpn6st', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'r0kszo8gmy6', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'srs7hnvxpoa', + 'x-async': true, + 'x-index': 1, + }, +}; diff --git a/packages/plugins/@nocobase/plugin-calendar/src/client/calendar/Event.tsx b/packages/plugins/@nocobase/plugin-calendar/src/client/calendar/Event.tsx index a5f1b54171..c8ab8fe15b 100644 --- a/packages/plugins/@nocobase/plugin-calendar/src/client/calendar/Event.tsx +++ b/packages/plugins/@nocobase/plugin-calendar/src/client/calendar/Event.tsx @@ -13,6 +13,7 @@ import { useActionContext, useCollection, useCollectionRecordData, + usePopupSettings, VariablePopupRecordProvider, } from '@nocobase/client'; import React, { useCallback } from 'react'; @@ -23,12 +24,16 @@ export const Event = observer( const { visible, setVisible } = useActionContext(); const recordData = useCollectionRecordData(); const collection = useCollection(); + const { isPopupVisibleControlledByURL } = usePopupSettings(); + + // Fix the issue where closing a popup opened through the 'Calendar Block' causes all popups to close + const _setVisible = isPopupVisibleControlledByURL() ? null : setVisible; const close = useCallback(() => { setVisible(false); }, [setVisible]); return ( - + {props.children}