fix: FixedBlock does not disappear when the current tab is deleted (#1324)

* fix: fixed block does not disappear when the current tab is deleted

* fix: using template and fixedBlock together causes props to conflict

* fix: reference templates do not work properly
This commit is contained in:
Dunqing 2023-01-07 23:31:09 +08:00 committed by GitHub
parent 6246d152b0
commit f6769341bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 46 deletions

View File

@ -4,32 +4,37 @@ import { css } from '@emotion/css';
import { SchemaSettings } from '../../../schema-settings'; import { SchemaSettings } from '../../../schema-settings';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDesignable } from '../../hooks'; import { useDesignable } from '../../hooks';
import { useGridContext } from '../grid';
import { useRecord } from '../../../record-provider'; import { useRecord } from '../../../record-provider';
import { useBlockTemplateContext } from '../../../schema-templates/BlockTemplate';
const FixedBlockContext = React.createContext({ const FixedBlockContext = React.createContext({
setFixedSchema: (schema: Schema) => {}, setFixedSchema: (schema: Schema) => {},
height: 0, height: 0,
schema: {} as unknown as Schema, fixedSchemaRef: {} as unknown as React.MutableRefObject<Schema>,
}); });
export const useFixedSchema = () => { export const useFixedSchema = () => {
const field = useField(); const field = useField();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const { setFixedSchema } = useFixedBlock(); const { setFixedSchema, fixedSchemaRef } = useFixedBlock();
const { fieldSchema: templateFieldSchema } = useBlockTemplateContext();
const hasSet = useRef(false); const hasSet = useRef(false);
useEffect(() => { useEffect(() => {
if (fieldSchema?.['x-decorator-props']?.fixedBlock) { if (fieldSchema?.['x-decorator-props']?.fixedBlock) {
setFixedSchema(fieldSchema); const nextSchema = templateFieldSchema || fieldSchema;
setFixedSchema(nextSchema);
hasSet.current = true; hasSet.current = true;
} else if (hasSet.current) {
setFixedSchema(null);
} }
}, [field?.decoratorProps?.fixedBlock, fieldSchema?.['x-decorator-props']?.fixedBlock]); }, [field?.decoratorProps?.fixedBlock, fieldSchema?.['x-decorator-props']?.fixedBlock]);
useEffect( useEffect(
() => () => { () => () => {
if (hasSet.current) { if (hasSet.current && fixedSchemaRef.current) {
setFixedSchema(null); setFixedSchema(null);
fixedSchemaRef.current = null;
} }
}, },
[], [],
@ -55,15 +60,18 @@ export const useFixedBlockDesignerSetting = () => {
<SchemaSettings.SwitchItem <SchemaSettings.SwitchItem
title={t('Fix block')} title={t('Fix block')}
checked={fieldSchema['x-decorator-props']['fixedBlock']} checked={fieldSchema['x-decorator-props']['fixedBlock']}
onChange={(fixedBlock) => { onChange={async (fixedBlock) => {
field.decoratorProps.fixedBlock = fixedBlock; const decoratorProps = {
fieldSchema['x-decorator-props'].fixedBlock = fixedBlock; ...fieldSchema['x-decorator-props'],
dn.emit('patch', { fixedBlock,
};
await dn.emit('patch', {
schema: { schema: {
['x-uid']: fieldSchema['x-uid'], ['x-uid']: fieldSchema['x-uid'],
'x-decorator-props': fieldSchema['x-decorator-props'], 'x-decorator-props': decoratorProps,
}, },
}); });
field.decoratorProps = fieldSchema['x-decorator-props'] = decoratorProps;
}} }}
/> />
); );
@ -76,14 +84,22 @@ interface FixedBlockProps {
const FixedBlock: React.FC<FixedBlockProps> = (props) => { const FixedBlock: React.FC<FixedBlockProps> = (props) => {
const { height } = props; const { height } = props;
const [fixedSchema, setFixedSchema] = useState<Schema>(); const [fixedSchema, _setFixedSchema] = useState<Schema>();
const fixedSchemaRef = useRef(fixedSchema);
const setFixedSchema = (next) => {
if (fixedSchema && next) {
fixedSchemaRef.current = next;
}
_setFixedSchema(next);
};
const schema = useMemo<Schema>(() => { const schema = useMemo<Schema>(() => {
if (!fixedSchema || fixedSchema['x-decorator-props']?.fixedBlock !== true) return; return fixedSchema?.parent;
return fixedSchema.parent; }, [fixedSchema]);
}, [fixedSchema, fixedSchema?.['x-decorator-props']['fixedBlock']]);
return ( return (
<FixedBlockContext.Provider value={{ schema: fixedSchema, height, setFixedSchema }}> <FixedBlockContext.Provider value={{ height, setFixedSchema, fixedSchemaRef }}>
{schema ? ( {schema ? (
<div <div
className={css` className={css`

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { FormDialog, FormLayout } from '@formily/antd'; import { FormDialog, FormLayout } from '@formily/antd';
import { RecursionField, SchemaOptionsContext, useField, useFieldSchema } from '@formily/react'; import { RecursionField, Schema, SchemaOptionsContext, useField, useFieldSchema } from '@formily/react';
import { Button, PageHeader as AntdPageHeader, Spin, Tabs } from 'antd'; import { Button, PageHeader as AntdPageHeader, Spin, Tabs } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
@ -246,6 +246,29 @@ export const Page = (props) => {
<div style={{ margin: 24 }}> <div style={{ margin: 24 }}>
{loading ? ( {loading ? (
<Spin /> <Spin />
) : !disablePageHeader && enablePageTabs ? (
fieldSchema.mapProperties((schema) => {
if (schema.name !== activeKey) return null;
return (
<FixedBlock
key={schema.name}
height={
// header 46 margin 48
height + 46 + 48
}
>
<SchemaComponent
schema={
new Schema({
properties: {
[schema.name]: schema,
},
})
}
/>
</FixedBlock>
);
})
) : ( ) : (
<FixedBlock <FixedBlock
height={ height={
@ -253,15 +276,6 @@ export const Page = (props) => {
height + 46 + 48 height + 46 + 48
} }
> >
{!disablePageHeader && enablePageTabs ? (
<RecursionField
schema={fieldSchema}
onlyRenderProperties
filterProperties={(s) => {
return s.name === activeKey;
}}
/>
) : (
<div <div
className={css` className={css`
> .nb-grid:not(:last-child) { > .nb-grid:not(:last-child) {
@ -273,7 +287,6 @@ export const Page = (props) => {
> >
{props.children} {props.children}
</div> </div>
)}
</FixedBlock> </FixedBlock>
)} )}
</div> </div>

View File

@ -239,12 +239,12 @@ export class Designable {
this.events[name].push(listener); this.events[name].push(listener);
} }
emit(name: 'insertAdjacent' | 'remove' | 'error' | 'patch' | 'batchPatch', ...args) { async emit(name: 'insertAdjacent' | 'remove' | 'error' | 'patch' | 'batchPatch', ...args) {
if (!this.events[name]) { if (!this.events[name]) {
return; return;
} }
const [opts, ...others] = args; const [opts, ...others] = args;
this.events[name].forEach((fn) => fn.bind(this)({ current: this.current, ...opts }, ...others)); return Promise.all(this.events[name].map((fn) => fn.bind(this)({ current: this.current, ...opts }, ...others)));
} }
parentsIn(schema: Schema) { parentsIn(schema: Schema) {

View File

@ -19,10 +19,8 @@ export const BlockTemplate = observer((props: any) => {
const { t } = useTranslation(); const { t } = useTranslation();
const template = useMemo(() => getTemplateById(templateId), [templateId]); const template = useMemo(() => getTemplateById(templateId), [templateId]);
return template ? ( return template ? (
<div>
<BlockTemplateContext.Provider value={{ dn, field, fieldSchema, template }}> <BlockTemplateContext.Provider value={{ dn, field, fieldSchema, template }}>
<RemoteSchemaComponent noForm uid={template?.uid} /> <RemoteSchemaComponent noForm uid={template?.uid} />
</BlockTemplateContext.Provider> </BlockTemplateContext.Provider>
</div>
) : null; ) : null;
}); });

View File

@ -39,7 +39,7 @@ export const SchemaTemplateManagerProvider: React.FC<any> = (props) => {
}; };
const regenerateUid = (s: ISchema) => { const regenerateUid = (s: ISchema) => {
s['x-uid'] = uid(); s['name'] = s['x-uid'] = uid();
Object.keys(s.properties || {}).forEach((key) => { Object.keys(s.properties || {}).forEach((key) => {
regenerateUid(s.properties[key]); regenerateUid(s.properties[key]);
}); });
@ -120,10 +120,9 @@ export const useSchemaTemplateManager = () => {
return templates?.find((template) => template.key === key); return templates?.find((template) => template.key === key);
}, },
getTemplatesByCollection(collectionName: string, resourceName: string = null) { getTemplatesByCollection(collectionName: string, resourceName: string = null) {
const items = templates?.filter?.((template) => (template.collectionName === collectionName)); const items = templates?.filter?.((template) => template.collectionName === collectionName);
return items || []; return items || [];
}, },
}; };
}; };