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

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css';
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 classNames from 'classnames';
import React, { useContext, useEffect, useState } from 'react';
@ -246,6 +246,29 @@ export const Page = (props) => {
<div style={{ margin: 24 }}>
{loading ? (
<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
height={
@ -253,15 +276,6 @@ export const Page = (props) => {
height + 46 + 48
}
>
{!disablePageHeader && enablePageTabs ? (
<RecursionField
schema={fieldSchema}
onlyRenderProperties
filterProperties={(s) => {
return s.name === activeKey;
}}
/>
) : (
<div
className={css`
> .nb-grid:not(:last-child) {
@ -273,7 +287,6 @@ export const Page = (props) => {
>
{props.children}
</div>
)}
</FixedBlock>
)}
</div>

View File

@ -239,12 +239,12 @@ export class Designable {
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]) {
return;
}
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) {

View File

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

View File

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