feat(client): improve code
This commit is contained in:
parent
054a73d576
commit
022c173f7e
@ -1,14 +1,15 @@
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { connect, SchemaOptionsContext, useField, useFieldSchema, useForm } from '@formily/react';
|
||||
import { useCollectionField } from './hooks';
|
||||
import { CollectionFieldProvider } from './CollectionFieldProvider';
|
||||
import { Field, FormPath } from '@formily/core';
|
||||
import { connect, SchemaOptionsContext, useField, useFieldSchema } from '@formily/react';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { CollectionFieldProvider } from './CollectionFieldProvider';
|
||||
import { useCollectionField } from './hooks';
|
||||
|
||||
// TODO: 初步适配
|
||||
const InternalField: React.FC = (props) => {
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const { uiSchema } = useCollectionField();
|
||||
console.log('uiSchema', uiSchema);
|
||||
const options = useContext(SchemaOptionsContext);
|
||||
const component = FormPath.getIn(options?.components, uiSchema['x-component']);
|
||||
const setFieldProps = (key, value) => {
|
||||
|
@ -1,12 +1,15 @@
|
||||
import React from 'react';
|
||||
import { CollectionManagerOptions } from './types';
|
||||
import { CollectionManagerSchemaComponentProvider } from './CollectionManagerSchemaComponentProvider';
|
||||
import { CollectionManagerContext } from './context';
|
||||
import { CollectionManagerOptions } from './types';
|
||||
|
||||
export const CollectionManagerProvider: React.FC<CollectionManagerOptions> = (props) => {
|
||||
const { interfaces, collections } = props;
|
||||
return (
|
||||
<CollectionManagerContext.Provider value={{ interfaces, collections }}>
|
||||
<CollectionManagerSchemaComponentProvider>
|
||||
{props.children}
|
||||
</CollectionManagerSchemaComponentProvider>
|
||||
</CollectionManagerContext.Provider>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import { SchemaComponentOptions } from '../';
|
||||
import {
|
||||
CollectionField,
|
||||
CollectionFieldProvider,
|
||||
CollectionProvider,
|
||||
ResourceActionProvider,
|
||||
useDataSourceFromRAC
|
||||
} from './';
|
||||
|
||||
export const CollectionManagerSchemaComponentProvider: React.FC = (props) => {
|
||||
return (
|
||||
<SchemaComponentOptions
|
||||
scope={{ useDataSourceFromRAC }}
|
||||
components={{ CollectionField, CollectionFieldProvider, CollectionProvider, ResourceActionProvider }}
|
||||
>
|
||||
{props.children}
|
||||
</SchemaComponentOptions>
|
||||
);
|
||||
};
|
@ -0,0 +1,34 @@
|
||||
import { Result } from 'ahooks/lib/useRequest/src/types';
|
||||
import React, { createContext, useContext, useEffect } from 'react';
|
||||
import { useRequest } from '../api-client';
|
||||
|
||||
export const ResourceActionContext = createContext<Result<any, any>>(null);
|
||||
|
||||
interface ResourceActionProviderProps {
|
||||
request?: any;
|
||||
uid?: string;
|
||||
}
|
||||
|
||||
export const ResourceActionProvider: React.FC<ResourceActionProviderProps> = (props) => {
|
||||
const { request, uid } = props;
|
||||
console.log(request);
|
||||
const service = useRequest(request, {
|
||||
uid,
|
||||
refreshDeps: [request],
|
||||
});
|
||||
return <ResourceActionContext.Provider value={service}>{props.children}</ResourceActionContext.Provider>;
|
||||
};
|
||||
|
||||
export const useResourceActionContext = () => {
|
||||
return useContext(ResourceActionContext);
|
||||
};
|
||||
|
||||
export const useDataSourceFromRAC = (options: any) => {
|
||||
const service = useContext(ResourceActionContext);
|
||||
useEffect(() => {
|
||||
if (!service.loading) {
|
||||
options?.onSuccess(service.data);
|
||||
}
|
||||
}, [service.loading]);
|
||||
return service;
|
||||
};
|
163
packages/client/src/collection-manager/demos/demo4.tsx
Normal file
163
packages/client/src/collection-manager/demos/demo4.tsx
Normal file
@ -0,0 +1,163 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import {
|
||||
AntdSchemaComponentProvider, CollectionManagerProvider,
|
||||
SchemaComponent,
|
||||
SchemaComponentProvider
|
||||
} from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
const schema: ISchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
block1: {
|
||||
type: 'void',
|
||||
'x-decorator': 'CollectionProvider',
|
||||
'x-decorator-props': {
|
||||
name: 'posts',
|
||||
},
|
||||
properties: {
|
||||
createdBy: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-read-pretty': true,
|
||||
properties: {
|
||||
rowSelection: {
|
||||
'x-component': 'RowSelection',
|
||||
'x-component-props': {
|
||||
rowKey: 'id',
|
||||
objectValue: true,
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
},
|
||||
dataSource: [
|
||||
{ id: 1, name: 'Name1' },
|
||||
{ id: 2, name: 'Name2' },
|
||||
{ id: 3, name: 'Name3' },
|
||||
],
|
||||
},
|
||||
properties: {
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: 'Name',
|
||||
'x-component': 'RowSelection.Column',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
item: {
|
||||
'x-component': 'RecordPicker.SelectedItem',
|
||||
properties: {
|
||||
drawer1: {
|
||||
'x-component': 'Action.Drawer',
|
||||
type: 'void',
|
||||
title: 'Drawer Title',
|
||||
properties: {
|
||||
hello1: {
|
||||
'x-content': 'Hello',
|
||||
title: 'T1',
|
||||
},
|
||||
footer1: {
|
||||
'x-component': 'Action.Drawer.Footer',
|
||||
type: 'void',
|
||||
properties: {
|
||||
close1: {
|
||||
type: 'void',
|
||||
title: 'Close',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
// useAction: '{{ useCloseAction }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const collections = [
|
||||
{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'integer',
|
||||
name: 'id',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: 'ID1',
|
||||
type: 'number',
|
||||
'x-component': 'InputNumber',
|
||||
required: true,
|
||||
description: 'description1',
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: 'Name1',
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
description: 'description1',
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'date',
|
||||
interface: 'datetime',
|
||||
uiSchema: {
|
||||
type: 'boolean',
|
||||
title: `Date1`,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {
|
||||
dateFormat: 'YYYY/MM/DD',
|
||||
// showTime: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'belongsToMany',
|
||||
name: 'createdBy',
|
||||
target: 'users',
|
||||
foreignKey: 'createdById',
|
||||
uiSchema: {
|
||||
type: 'array',
|
||||
title: `创建人`,
|
||||
default: [
|
||||
{ id: 1, name: 'name1' },
|
||||
{ id: 2, name: 'name2' },
|
||||
],
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'RecordPicker',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<SchemaComponentProvider>
|
||||
<AntdSchemaComponentProvider>
|
||||
<CollectionManagerProvider collections={collections}>
|
||||
<SchemaComponent schema={schema} />
|
||||
</CollectionManagerProvider>
|
||||
</AntdSchemaComponentProvider>
|
||||
</SchemaComponentProvider>
|
||||
);
|
||||
};
|
@ -142,3 +142,4 @@ const { name, uiSchema, resource } = useCollectionField();
|
||||
resource 需要与 `<RecordProvider/>` 搭配使用,用于提供当前数据表行记录的上下文。如:
|
||||
|
||||
<code src="./demos/demo3.tsx"/>
|
||||
<code src="./demos/demo4.tsx"/>
|
||||
|
@ -1,8 +1,11 @@
|
||||
export * from './CollectionField';
|
||||
export * from './CollectionFieldProvider';
|
||||
export * from './CollectionManagerProvider';
|
||||
export * from './CollectionManagerSchemaComponentProvider';
|
||||
export * from './CollectionManagerShortcut';
|
||||
export * from './CollectionProvider';
|
||||
export * from './context';
|
||||
export * from './hooks';
|
||||
export * from './ResourceActionProvider';
|
||||
export * from './types';
|
||||
export * from './CollectionField';
|
||||
export * from './CollectionManagerShortcut';
|
||||
|
||||
|
@ -0,0 +1,54 @@
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useCollection, useDesignable } from '../../../';
|
||||
|
||||
export const useColumnSchema = () => {
|
||||
const { getField } = useCollection();
|
||||
const columnSchema = useFieldSchema();
|
||||
const fieldSchema = columnSchema.reduceProperties((buf, s) => {
|
||||
if (s['x-component'] === 'CollectionField') {
|
||||
return s;
|
||||
}
|
||||
return buf;
|
||||
}, null);
|
||||
if (!fieldSchema) {
|
||||
return;
|
||||
}
|
||||
const collectionField = getField(fieldSchema.name);
|
||||
return { columnSchema, fieldSchema, collectionField };
|
||||
};
|
||||
|
||||
export const TableColumnDecorator = (props) => {
|
||||
const field = useField();
|
||||
const { columnSchema, fieldSchema, collectionField } = useColumnSchema();
|
||||
const { refresh } = useDesignable();
|
||||
useEffect(() => {
|
||||
if (field.title) {
|
||||
return;
|
||||
}
|
||||
if (!fieldSchema) {
|
||||
return;
|
||||
}
|
||||
if (collectionField?.uiSchema?.title) {
|
||||
field.title = collectionField?.uiSchema?.title;
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<div
|
||||
onClick={() => {
|
||||
field.title = uid();
|
||||
columnSchema.title = field.title = field.title;
|
||||
refresh();
|
||||
field.query(`.*.${fieldSchema.name}`).take((f) => {
|
||||
f.componentProps.dateFormat = 'YYYY-MM-DD';
|
||||
});
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
export * from './ArrayTable';
|
||||
export * from './Initializer';
|
||||
export * from './TableColumnDecorator';
|
||||
|
||||
|
@ -22,7 +22,10 @@ mock.onGet('/posts:list').reply(async (config) => {
|
||||
return {
|
||||
id: v + (page - 1) * pageSize,
|
||||
name: uid(),
|
||||
date: '2022-01-02 22:22:22'
|
||||
date: '2022-01-02 22:22:22',
|
||||
createdBy: [
|
||||
{ id: 1, name: 'name1' },
|
||||
],
|
||||
};
|
||||
}),
|
||||
meta: {
|
||||
|
@ -1,18 +1,13 @@
|
||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import { ISchema, observer, useField, useFieldSchema } from '@formily/react';
|
||||
import {
|
||||
AntdSchemaComponentProvider,
|
||||
APIClientProvider,
|
||||
CollectionField,
|
||||
CollectionManagerProvider,
|
||||
CollectionProvider,
|
||||
SchemaComponent,
|
||||
SchemaComponentProvider,
|
||||
useCollection,
|
||||
useDesignable,
|
||||
useRequest
|
||||
SchemaComponentProvider
|
||||
} from '@nocobase/client';
|
||||
import React, { createContext, useContext, useEffect } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import React from 'react';
|
||||
import { apiClient } from './apiClient';
|
||||
|
||||
const schema: ISchema = {
|
||||
@ -30,6 +25,7 @@ const schema: ISchema = {
|
||||
resource: 'posts',
|
||||
action: 'list',
|
||||
params: {
|
||||
pageSize: 5,
|
||||
filter: {},
|
||||
sort: [],
|
||||
appends: [],
|
||||
@ -37,6 +33,9 @@ const schema: ISchema = {
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
settings: {
|
||||
'x-component': 'SimpleSettingsForm',
|
||||
},
|
||||
table1: {
|
||||
type: 'void',
|
||||
'x-uid': 'input',
|
||||
@ -88,6 +87,50 @@ const schema: ISchema = {
|
||||
},
|
||||
},
|
||||
},
|
||||
column4: {
|
||||
type: 'void',
|
||||
// title: 'Name',
|
||||
'x-decorator': 'TableColumnDecorator',
|
||||
'x-component': 'VoidTable.Column',
|
||||
properties: {
|
||||
createdBy: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-read-pretty': true,
|
||||
properties: {
|
||||
item: {
|
||||
'x-component': 'RecordPicker.SelectedItem',
|
||||
properties: {
|
||||
drawer1: {
|
||||
'x-component': 'Action.Drawer',
|
||||
type: 'void',
|
||||
title: 'Drawer Title',
|
||||
properties: {
|
||||
hello1: {
|
||||
'x-content': 'Hello',
|
||||
title: 'T1',
|
||||
},
|
||||
footer1: {
|
||||
'x-component': 'Action.Drawer.Footer',
|
||||
type: 'void',
|
||||
properties: {
|
||||
close1: {
|
||||
type: 'void',
|
||||
title: 'Close',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
// useAction: '{{ useCloseAction }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -95,56 +138,6 @@ const schema: ISchema = {
|
||||
},
|
||||
};
|
||||
|
||||
const useColumnSchema = () => {
|
||||
const { getField } = useCollection();
|
||||
const columnSchema = useFieldSchema();
|
||||
const fieldSchema = columnSchema.reduceProperties((buf, s) => {
|
||||
if (s['x-component'] === 'CollectionField') {
|
||||
return s;
|
||||
}
|
||||
return buf;
|
||||
}, null);
|
||||
if (!fieldSchema) {
|
||||
return;
|
||||
}
|
||||
const collectionField = getField(fieldSchema.name);
|
||||
return { columnSchema, fieldSchema, collectionField };
|
||||
};
|
||||
|
||||
const TableColumnDecorator = (props) => {
|
||||
const field = useField();
|
||||
const { columnSchema, fieldSchema, collectionField } = useColumnSchema();
|
||||
const { refresh } = useDesignable();
|
||||
useEffect(() => {
|
||||
if (field.title) {
|
||||
return;
|
||||
}
|
||||
if (!fieldSchema) {
|
||||
return;
|
||||
}
|
||||
if (collectionField?.uiSchema?.title) {
|
||||
field.title = collectionField?.uiSchema?.title;
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
{props.children}
|
||||
<div
|
||||
onClick={() => {
|
||||
field.title = uid();
|
||||
columnSchema.title = field.title = field.title;
|
||||
refresh();
|
||||
field.query(`.*.${fieldSchema.name}`).take((f) => {
|
||||
f.componentProps.dateFormat = 'YYYY-MM-DD';
|
||||
});
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const collections = [
|
||||
{
|
||||
name: 'posts',
|
||||
@ -189,41 +182,57 @@ const collections = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'belongsToMany',
|
||||
name: 'createdBy',
|
||||
target: 'users',
|
||||
foreignKey: 'createdById',
|
||||
uiSchema: {
|
||||
type: 'array',
|
||||
title: `创建人`,
|
||||
// default: [
|
||||
// { id: 1, name: 'name1' },
|
||||
// { id: 2, name: 'name2' },
|
||||
// ],
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'RecordPicker',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const ResourceActionContext = createContext(null);
|
||||
|
||||
const ResourceActionProvider = (props) => {
|
||||
const { name } = useCollection();
|
||||
const { request } = props;
|
||||
const service = useRequest(request);
|
||||
return <ResourceActionContext.Provider value={{ service }}>{props.children}</ResourceActionContext.Provider>;
|
||||
};
|
||||
|
||||
const useDataSourceFromRAC = (options: any) => {
|
||||
const { service } = useContext(ResourceActionContext);
|
||||
useEffect(() => {
|
||||
if (!service.loading) {
|
||||
options?.onSuccess(service.data);
|
||||
}
|
||||
}, [service.loading]);
|
||||
return service;
|
||||
};
|
||||
|
||||
const componets = { CollectionProvider, TableColumnDecorator, ResourceActionProvider, CollectionField };
|
||||
const SimpleSettingsForm = observer(() => {
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
fieldSchema.parent['x-component-props']['request']['params']['pageSize'] = 20;
|
||||
field.query('.').take((f) => {
|
||||
f.componentProps.request.params.pageSize = 20;
|
||||
});
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<APIClientProvider apiClient={apiClient}>
|
||||
<CollectionManagerProvider collections={collections}>
|
||||
<SchemaComponentProvider components={componets}>
|
||||
<AntdSchemaComponentProvider>
|
||||
<SchemaComponent schema={schema} scope={{ useDataSourceFromRAC }} />
|
||||
</AntdSchemaComponentProvider>
|
||||
</SchemaComponentProvider>
|
||||
</CollectionManagerProvider>
|
||||
<SchemaComponentProvider>
|
||||
<AntdSchemaComponentProvider>
|
||||
<CollectionManagerProvider collections={collections}>
|
||||
<SchemaComponent schema={schema} components={{ SimpleSettingsForm }} />
|
||||
</CollectionManagerProvider>
|
||||
</AntdSchemaComponentProvider>
|
||||
</SchemaComponentProvider>
|
||||
</APIClientProvider>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user