fix: fix e2e error

This commit is contained in:
Zeke Zhang 2024-11-03 08:23:34 +08:00
parent b3a4201a82
commit ca4ad2877b
2 changed files with 55 additions and 28 deletions

View File

@ -12,7 +12,7 @@ import { css } from '@emotion/css';
import { useField, useFieldSchema } from '@formily/react';
import { Space } from 'antd';
import classNames from 'classnames';
import React, { FC, useEffect, useMemo, useRef } from 'react';
import React, { createContext, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaInitializer, SchemaSettings, SchemaToolbarProvider, useSchemaInitializerRender } from '../application';
import { useSchemaSettingsRender } from '../application/schema-settings/hooks/useSchemaSettingsRender';
@ -195,6 +195,7 @@ export interface SchemaToolbarProps {
spaceWrapperStyle?: React.CSSProperties;
spaceClassName?: string;
spaceStyle?: React.CSSProperties;
onVisibleChange?: (nextVisible: boolean) => void;
}
const InternalSchemaToolbar: FC<SchemaToolbarProps> = (props) => {
@ -283,6 +284,7 @@ const InternalSchemaToolbar: FC<SchemaToolbarProps> = (props) => {
return settings !== false && schemaSettingsExists ? schemaSettingsRender() : null;
}, [schemaSettingsExists, schemaSettingsRender, settings]);
const toolbarRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const toolbarElement = toolbarRef.current;
let parentElement = toolbarElement?.parentElement;
@ -296,12 +298,14 @@ const InternalSchemaToolbar: FC<SchemaToolbarProps> = (props) => {
function show() {
if (toolbarElement) {
toolbarElement.style.display = 'block';
props.onVisibleChange?.(true);
}
}
function hide() {
if (toolbarElement) {
toolbarElement.style.display = 'none';
props.onVisibleChange?.(false);
}
}
@ -316,7 +320,7 @@ const InternalSchemaToolbar: FC<SchemaToolbarProps> = (props) => {
parentElement.removeEventListener('mouseenter', show);
parentElement.removeEventListener('mouseleave', hide);
};
}, []);
}, [props.onVisibleChange]);
return (
<div
@ -349,14 +353,28 @@ const InternalSchemaToolbar: FC<SchemaToolbarProps> = (props) => {
);
};
/**
* @internal
*/
export const SchemaToolbarVisibleContext = createContext(false);
export const SchemaToolbar: FC<SchemaToolbarProps> = React.memo((props) => {
const { designable } = useDesignable();
const [visible, setVisible] = useState(false);
const onVisibleChange = useCallback((nextVisible: boolean) => {
setVisible(nextVisible);
}, []);
if (!designable) {
return null;
}
return <InternalSchemaToolbar {...props} />;
return (
<SchemaToolbarVisibleContext.Provider value={visible}>
<InternalSchemaToolbar {...props} onVisibleChange={onVisibleChange} />
</SchemaToolbarVisibleContext.Provider>
);
});
SchemaToolbar.displayName = 'SchemaToolbar';

View File

@ -38,12 +38,19 @@ import React, {
useCallback,
useContext,
useEffect,
useLayoutEffect,
useMemo,
useState,
} from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { SchemaSettingsItemType, VariablesContext } from '../';
import {
SchemaSettingsItemType,
SchemaToolbarVisibleContext,
VariablesContext,
useCollection,
useCollectionManager,
} from '../';
import { APIClientProvider } from '../api-client/APIClientProvider';
import { useAPIClient } from '../api-client/hooks/useAPIClient';
import { ApplicationContext, LocationSearchContext, useApp, useLocationSearch } from '../application';
@ -63,7 +70,6 @@ import {
import { FormActiveFieldsProvider, useFormActiveFields } from '../block-provider/hooks';
import { useLinkageCollectionFilterOptions, useSortFields } from '../collection-manager/action-hooks';
import { useCollectionManager_deprecated } from '../collection-manager/hooks/useCollectionManager_deprecated';
import { useCollection_deprecated } from '../collection-manager/hooks/useCollection_deprecated';
import { CollectionFieldOptions_deprecated } from '../collection-manager/types';
import { SelectWithTitle, SelectWithTitleProps } from '../common/SelectWithTitle';
import { useNiceDropdownMaxHeight } from '../common/useNiceDropdownHeight';
@ -142,15 +148,20 @@ interface SchemaSettingsProviderProps {
}
export const SchemaSettingsProvider: React.FC<SchemaSettingsProviderProps> = (props) => {
const { children, fieldSchema, ...others } = props;
const { children, fieldSchema } = props;
const { getTemplateBySchema } = useSchemaTemplateManager();
const { name } = useCollection_deprecated();
const collection = useCollection();
const template = getTemplateBySchema(fieldSchema);
return (
<SchemaSettingsContext.Provider value={{ collectionName: name, template, fieldSchema, ...others }}>
{children}
</SchemaSettingsContext.Provider>
const value = useMemo(
() => ({
...props,
collectionName: collection?.name,
template,
fieldSchema,
}),
[collection?.name, fieldSchema, props, template],
);
return <SchemaSettingsContext.Provider value={value}>{children}</SchemaSettingsContext.Provider>;
};
export const SchemaSettingsDropdown: React.FC<SchemaSettingsProps> = React.memo((props) => {
@ -159,26 +170,24 @@ export const SchemaSettingsDropdown: React.FC<SchemaSettingsProps> = React.memo(
const { Component, getMenuItems } = useMenuItem();
const dropdownMaxHeight = useNiceDropdownMaxHeight([visible]);
const [openDropdown, setOpenDropdown] = useState(false);
const toolbarVisible = useContext(SchemaToolbarVisibleContext);
const setDropdownVisible = (visible: boolean) => {
setVisible(visible);
// 延迟 300ms 是为了避免对动画造成影响
setTimeout(() => {
setOpenDropdown(visible);
}, 300);
};
useLayoutEffect(() => {
if (toolbarVisible) {
setOpenDropdown(false);
}
}, [toolbarVisible]);
const changeMenu: DropdownProps['onOpenChange'] = (nextOpen: boolean, info) => {
if (info.source === 'trigger' || nextOpen) {
// 当鼠标快速滑过时,终止菜单的渲染,防止卡顿
startTransition(() => {
setDropdownVisible(nextOpen);
setVisible(nextOpen);
});
}
};
// 从这里截断,可以保证每次显示时都是最新的菜单列表
// 从这里截断,可以保证每次显示时都是最新状态的菜单列表
if (!openDropdown) {
return (
<div onMouseEnter={() => setOpenDropdown(true)} data-testid={props['data-testid']}>
@ -190,7 +199,7 @@ export const SchemaSettingsDropdown: React.FC<SchemaSettingsProps> = React.memo(
const items = getMenuItems(() => props.children);
return (
<SchemaSettingsProvider visible={visible} setVisible={setDropdownVisible} dn={dn} {...others}>
<SchemaSettingsProvider visible={visible} setVisible={setVisible} dn={dn} {...others}>
<Component />
<Dropdown
open={visible}
@ -255,7 +264,7 @@ export const SchemaSettingsFormItemTemplate = function FormItemTemplate(props) {
const { insertAdjacentPosition = 'afterBegin', componentName, collectionName, resourceName } = props;
const { t } = useTranslation();
const compile = useCompile();
const { getCollection } = useCollectionManager_deprecated();
const cm = useCollectionManager();
const { dn, setVisible, template, fieldSchema } = useSchemaSettings();
const api = useAPIClient();
const { saveAsTemplate, copyTemplateSchema } = useSchemaTemplateManager();
@ -307,7 +316,7 @@ export const SchemaSettingsFormItemTemplate = function FormItemTemplate(props) {
title="Save as block template"
onClick={async () => {
setVisible(false);
const collection = collectionName && getCollection(collectionName);
const collection = collectionName && cm?.getCollection(collectionName);
const gridSchema = findGridSchema(fieldSchema);
const values = await FormDialog(
t('Save as template'),
@ -785,7 +794,7 @@ export const SchemaSettingsModalItem: FC<SchemaSettingsModalItemProps> = (props)
...others
} = props;
const options = useContext(SchemaOptionsContext);
const collection = useCollection_deprecated();
const collection = useCollection();
const apiClient = useAPIClient();
const app = useApp();
const { theme } = useGlobalTheme();
@ -848,7 +857,7 @@ export const SchemaSettingsModalItem: FC<SchemaSettingsModalItemProps> = (props)
<DataSourceApplicationProvider dataSourceManager={dm} dataSource={dataSourceKey}>
<AssociationOrCollectionProvider
allowNull
collection={collection.name}
collection={collection?.name}
association={association}
>
<SchemaComponentOptions scope={options.scope} components={options.components}>
@ -922,7 +931,7 @@ export const SchemaSettingsDefaultSortingRules = function DefaultSortingRules(pr
const fieldSchema = useFieldSchema();
const field = useField();
const title = props.title || t('Set default sorting rules');
const { name } = useCollection_deprecated();
const collection = useCollection();
const defaultSort = get(fieldSchema, path) || [];
const sort = defaultSort?.map((item: string) => {
return item.startsWith('-')
@ -935,7 +944,7 @@ export const SchemaSettingsDefaultSortingRules = function DefaultSortingRules(pr
direction: 'asc',
};
});
const sortFields = useSortFields(props.name || name);
const sortFields = useSortFields(props.name || collection?.name);
const onSubmit = async ({ sort }) => {
if (props?.onSubmit) {