Merge branch 'feat/tree-collection' into feat/gantt-block

This commit is contained in:
katherinehhh 2023-03-15 23:09:22 +08:00
commit a0120d4163
7 changed files with 153 additions and 121 deletions

View File

@ -7,6 +7,7 @@ import { useCollection } from '../collection-manager';
import { RecordProvider, useRecord } from '../record-provider'; import { RecordProvider, useRecord } from '../record-provider';
import { useDesignable } from '../schema-component'; import { useDesignable } from '../schema-component';
import { BlockProvider, useBlockRequestContext } from './BlockProvider'; import { BlockProvider, useBlockRequestContext } from './BlockProvider';
import { useActionContext } from '../schema-component';
export const FormBlockContext = createContext<any>({}); export const FormBlockContext = createContext<any>({});
@ -78,6 +79,18 @@ export const useFormBlockContext = () => {
export const useFormBlockProps = () => { export const useFormBlockProps = () => {
const ctx = useFormBlockContext(); const ctx = useFormBlockContext();
const record = useRecord();
const { fieldSchema } = useActionContext();
const { addChild } = fieldSchema['x-component-props'];
useEffect(() => {
if (addChild) {
ctx.form.query('parent').take((field) => {
field.disabled = true;
field.value = new Proxy({ ...record }, {});
});
}
});
useEffect(() => { useEffect(() => {
ctx.form.setInitialValues(ctx.service?.data?.data); ctx.form.setInitialValues(ctx.service?.data?.data);
}, []); }, []);

View File

@ -1,10 +1,11 @@
import { ArrayField, createForm } from '@formily/core'; import { ArrayField, createForm } from '@formily/core';
import { FormContext, Schema, useField, useFieldSchema } from '@formily/react'; import { FormContext, Schema, useField, useFieldSchema } from '@formily/react';
import uniq from 'lodash/uniq'; import uniq from 'lodash/uniq';
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react'; import React, { createContext, useMemo, useState, useContext,useEffect } from 'react';
import { useCollectionManager, useCollection } from '../collection-manager'; import { useCollectionManager } from '../collection-manager';
import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider'; import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider';
import { useFixedSchema } from '../schema-component'; import { useFixedSchema } from '../schema-component';
import { SchemaComponentOptions } from '../..';
export const TableBlockContext = createContext<any>({}); export const TableBlockContext = createContext<any>({});
@ -89,7 +90,7 @@ export const TableBlockProvider = (props) => {
const form = useMemo(() => createForm(), []); const form = useMemo(() => createForm(), []);
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const { getCollection } = useCollectionManager(); const { getCollection } = useCollectionManager();
const collection=getCollection(props.collection) const collection = getCollection(props.collection);
const { treeTable } = fieldSchema['x-decorator-props']; const { treeTable } = fieldSchema['x-decorator-props'];
if (props.dragSort) { if (props.dragSort) {
params['sort'] = ['sort']; params['sort'] = ['sort'];
@ -101,11 +102,13 @@ export const TableBlockProvider = (props) => {
params['appends'] = appends; params['appends'] = appends;
} }
return ( return (
<FormContext.Provider value={form}> <SchemaComponentOptions scope={{ treeTable }}>
<BlockProvider {...props} params={params}> <FormContext.Provider value={form}>
<InternalTableBlockProvider {...props} params={params} /> <BlockProvider {...props} params={params}>
</BlockProvider> <InternalTableBlockProvider {...props} params={params} />
</FormContext.Provider> </BlockProvider>
</FormContext.Provider>
</SchemaComponentOptions>
); );
}; };

View File

@ -50,6 +50,7 @@ export const ActionDesigner = (props) => {
const actionType = fieldSchema['x-action'] ?? ''; const actionType = fieldSchema['x-action'] ?? '';
const isLinkageAction = Object.keys(useFormBlockContext()).length > 0 && Object.keys(useRecord()).length > 0; const isLinkageAction = Object.keys(useFormBlockContext()).length > 0 && Object.keys(useRecord()).length > 0;
const isChildCollectionAction = getChildrenCollections(name).length > 0 && fieldSchema['x-action'] === 'create'; const isChildCollectionAction = getChildrenCollections(name).length > 0 && fieldSchema['x-action'] === 'create';
const isSupportEditButton = fieldSchema['x-action'] !== 'expandAll';
useEffect(() => { useEffect(() => {
const schemaUid = uid(); const schemaUid = uid();
const schema: ISchema = { const schema: ISchema = {
@ -85,6 +86,7 @@ export const ActionDesigner = (props) => {
title: t('Button title'), title: t('Button title'),
default: fieldSchema.title, default: fieldSchema.title,
'x-component-props': {}, 'x-component-props': {},
'x-visible': isSupportEditButton,
// description: `原字段标题:${collectionField?.uiSchema?.title}`, // description: `原字段标题:${collectionField?.uiSchema?.title}`,
}, },
icon: { icon: {
@ -93,6 +95,7 @@ export const ActionDesigner = (props) => {
title: t('Button icon'), title: t('Button icon'),
default: fieldSchema?.['x-component-props']?.icon, default: fieldSchema?.['x-component-props']?.icon,
'x-component-props': {}, 'x-component-props': {},
'x-visible': isSupportEditButton,
// description: `原字段标题:${collectionField?.uiSchema?.title}`, // description: `原字段标题:${collectionField?.uiSchema?.title}`,
}, },
type: { type: {
@ -114,27 +117,25 @@ export const ActionDesigner = (props) => {
} as ISchema } as ISchema
} }
onSubmit={({ title, icon, type }) => { onSubmit={({ title, icon, type }) => {
if (title) { fieldSchema.title = title;
fieldSchema.title = title; field.title = title;
field.title = title; field.componentProps.icon = icon;
field.componentProps.icon = icon; field.componentProps.danger = type === 'danger';
field.componentProps.danger = type === 'danger'; field.componentProps.type = type;
field.componentProps.type = type; fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; fieldSchema['x-component-props'].icon = icon;
fieldSchema['x-component-props'].icon = icon; fieldSchema['x-component-props'].danger = type === 'danger';
fieldSchema['x-component-props'].danger = type === 'danger'; fieldSchema['x-component-props'].type = type;
fieldSchema['x-component-props'].type = type; dn.emit('patch', {
dn.emit('patch', { schema: {
schema: { ['x-uid']: fieldSchema['x-uid'],
['x-uid']: fieldSchema['x-uid'], title,
title, 'x-component-props': {
'x-component-props': { ...fieldSchema['x-component-props'],
...fieldSchema['x-component-props'],
},
}, },
}); },
dn.refresh(); });
} dn.refresh();
}} }}
/> />
{isLinkageAction && <SchemaSettings.LinkageRules collectionName={name} />} {isLinkageAction && <SchemaSettings.LinkageRules collectionName={name} />}

View File

@ -10,13 +10,7 @@ import { default as classNames, default as cls } from 'classnames';
import React, { RefCallback, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import React, { RefCallback, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { DndContext, useDesignable } from '../..'; import { DndContext, useDesignable } from '../..';
import { import { RecordIndexProvider, RecordProvider, useSchemaInitializer, useTableBlockContext } from '../../../';
RecordIndexProvider,
RecordProvider,
useSchemaInitializer,
useTableBlockContext,
SchemaComponentOptions,
} from '../../../';
import { useACLFieldWhitelist } from '../../../acl/ACLProvider'; import { useACLFieldWhitelist } from '../../../acl/ACLProvider';
import { isCollectionFieldComponent, isColumnComponent, extractIndex, getIdsWithChildren } from './utils'; import { isCollectionFieldComponent, isColumnComponent, extractIndex, getIdsWithChildren } from './utils';
@ -418,57 +412,55 @@ export const Table: any = observer((props: any) => {
}; };
return ( return (
<SchemaComponentOptions scope={{ treeTable }}> <div
<div ref={mountedRef}
ref={mountedRef} className={css`
className={css` height: 100%;
overflow: hidden;
.ant-table-wrapper {
height: 100%; height: 100%;
overflow: hidden; }
.ant-table-wrapper { .ant-table {
height: 100%; overflow-x: auto;
} overflow-y: hidden;
.ant-table { }
overflow-x: auto; `}
overflow-y: hidden; >
} <SortableWrapper>
`} <AntdTable
> ref={(ref) => {
<SortableWrapper> const headerHeight = ref?.querySelector('.ant-table-header')?.getBoundingClientRect().height || 0;
<AntdTable const paginationHeight = ref?.querySelector('.ant-table-pagination')?.getBoundingClientRect().height || 0;
ref={(ref) => { setHeaderAndPaginationHeight(Math.ceil(headerHeight + paginationHeight + 16));
const headerHeight = ref?.querySelector('.ant-table-header')?.getBoundingClientRect().height || 0; }}
const paginationHeight = ref?.querySelector('.ant-table-pagination')?.getBoundingClientRect().height || 0; rowKey={rowKey ?? defaultRowKey}
setHeaderAndPaginationHeight(Math.ceil(headerHeight + paginationHeight + 16)); {...others}
}} {...restProps}
rowKey={rowKey ?? defaultRowKey} pagination={paginationProps}
{...others} components={components}
{...restProps} onChange={(pagination, filters, sorter, extra) => {
pagination={paginationProps} onTableChange?.(pagination, filters, sorter, extra);
components={components} }}
onChange={(pagination, filters, sorter, extra) => { tableLayout={'auto'}
onTableChange?.(pagination, filters, sorter, extra); scroll={scroll}
}} columns={columns}
tableLayout={'auto'} expandable={{
scroll={scroll} onExpand: (flag, record) => {
columns={columns} const newKeys = flag ? [...expandedKeys, record.id] : expandedKeys.filter((i) => record.id !== i);
expandable={{ setExpandesKeys(newKeys);
onExpand: (flag, record) => { },
const newKeys = flag ? [...expandedKeys, record.id] : expandedKeys.filter((i) => record.id !== i); expandedRowKeys: expandedKeys,
setExpandesKeys(newKeys); }}
}, dataSource={field?.value?.slice?.()}
expandedRowKeys: expandedKeys, />
}} </SortableWrapper>
dataSource={field?.value?.slice?.()} {field.errors.length > 0 && (
/> <div className="ant-formily-item-error-help ant-formily-item-help ant-formily-item-help-enter ant-formily-item-help-enter-active">
</SortableWrapper> {field.errors.map((error) => {
{field.errors.length > 0 && ( return error.messages.map((message) => <div>{message}</div>);
<div className="ant-formily-item-error-help ant-formily-item-help ant-formily-item-help-enter ant-formily-item-help-enter-active"> })}
{field.errors.map((error) => { </div>
return error.messages.map((message) => <div>{message}</div>); )}
})} </div>
</div>
)}
</div>
</SchemaComponentOptions>
); );
}); });

View File

@ -1,9 +1,7 @@
import React from 'react'; import React from 'react';
import { useFieldSchema } from '@formily/react';
import { SchemaComponentOptions } from '../../schema-component';
import { ActionInitializer } from './ActionInitializer'; import { ActionInitializer } from './ActionInitializer';
export const CreateChildInitializer = (props) => { export const CreateChildInitializer = (props) => {
const schema = { const schema = {
type: 'void', type: 'void',
title: '{{ t("Add Child") }}', title: '{{ t("Add Child") }}',
@ -55,10 +53,3 @@ export const CreateChildInitializer = (props) => {
}; };
return <ActionInitializer {...props} schema={schema} />; return <ActionInitializer {...props} schema={schema} />;
}; };
export const CreateChildProvider = (props) => {
const schema = useFieldSchema();
const { treeTable } = schema?.parent?.['x-decorator-props'];
console.log(props, schema);
return <SchemaComponentOptions>{props.children}</SchemaComponentOptions>;
};

View File

@ -16,18 +16,3 @@ export const CreateSubmitActionInitializer = (props) => {
}; };
return <ActionInitializer {...props} schema={schema} />; return <ActionInitializer {...props} schema={schema} />;
}; };
export const CreateChildSubmitActionInitializer = (props) => {
const schema = {
title: '{{ t("Submit") }}',
'x-action': 'submit',
'x-component': 'Action',
'x-designer': 'Action.Designer',
'x-component-props': {
type: 'primary',
htmlType: 'submit',
useProps: '{{ useCreateChildActionProps }}',
},
};
return <ActionInitializer {...props} schema={schema} />;
};

View File

@ -1,9 +1,11 @@
import React from 'react'; import React from 'react';
import { Button } from 'antd'; import { Button } from 'antd';
import { ActionInitializer } from './ActionInitializer'; import { css } from '@emotion/css';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ActionInitializer } from './ActionInitializer';
import { useTableBlockContext } from '../../'; import { useTableBlockContext } from '../../';
import { NodeCollapseOutlined, NodeExpandOutlined } from '@ant-design/icons'; import { NodeCollapseOutlined, NodeExpandOutlined } from '@ant-design/icons';
export const ExpandActionInitializer = (props) => { export const ExpandActionInitializer = (props) => {
const schema = { const schema = {
'x-action': 'expandAll', 'x-action': 'expandAll',
@ -23,17 +25,62 @@ export const ExpandActionInitializer = (props) => {
return <ActionInitializer {...props} schema={schema} />; return <ActionInitializer {...props} schema={schema} />;
}; };
export const ExpandActionComponent = () => { export const actionDesignerCss = css`
position: relative;
&:hover {
.general-schema-designer {
display: block;
}
}
.general-schema-designer {
position: absolute;
z-index: 999;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: none;
background: rgba(241, 139, 98, 0.06);
border: 0;
top: 0;
bottom: 0;
left: 0;
right: 0;
pointer-events: none;
> .general-schema-designer-icons {
position: absolute;
right: 2px;
top: 2px;
line-height: 16px;
pointer-events: all;
.ant-space-item {
background-color: #f18b62;
color: #fff;
line-height: 16px;
width: 16px;
padding-left: 1px;
}
}
}
`;
export const ExpandActionComponent = (props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const ctx = useTableBlockContext(); const ctx = useTableBlockContext();
return ( return (
<Button <div className={actionDesignerCss}>
onClick={() => { {ctx.params['tree'] && (
ctx?.setExpandFlag(); <Button
}} onClick={() => {
icon={ctx?.expandFlag ? <NodeCollapseOutlined /> : <NodeExpandOutlined />} ctx?.setExpandFlag();
> }}
{ctx?.expandFlag ? t('Collapse all') : t('Expand all')} icon={ctx?.expandFlag ? <NodeCollapseOutlined /> : <NodeExpandOutlined />}
</Button> type={props.type}
>
{props.children[1]}
<span style={{ marginLeft: 10 }}>{ctx?.expandFlag ? t('Collapse all') : t('Expand all')}</span>
</Button>
)}
</div>
); );
}; };