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:
parent
6246d152b0
commit
f6769341bd
@ -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`
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
});
|
||||
|
@ -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 || [];
|
||||
},
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user