mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 13:37:37 +00:00
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 { 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`
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
});
|
});
|
||||||
|
@ -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 || [];
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user