feat(client): improve the collection manager module
This commit is contained in:
parent
451f706b46
commit
fc1a65a2fb
@ -5,6 +5,7 @@ import {
|
|||||||
AntdSchemaComponentProvider,
|
AntdSchemaComponentProvider,
|
||||||
APIClientProvider,
|
APIClientProvider,
|
||||||
AuthLayout,
|
AuthLayout,
|
||||||
|
CollectionManagerProvider,
|
||||||
CollectionManagerShortcut,
|
CollectionManagerShortcut,
|
||||||
compose,
|
compose,
|
||||||
DesignableSwitch,
|
DesignableSwitch,
|
||||||
@ -40,6 +41,7 @@ const providers = [
|
|||||||
{ components: { ACLShortcut, DesignableSwitch, CollectionManagerShortcut, SystemSettingsShortcut } },
|
{ components: { ACLShortcut, DesignableSwitch, CollectionManagerShortcut, SystemSettingsShortcut } },
|
||||||
],
|
],
|
||||||
[SchemaComponentProvider, { components: { Link, NavLink } }],
|
[SchemaComponentProvider, { components: { Link, NavLink } }],
|
||||||
|
CollectionManagerProvider,
|
||||||
AntdSchemaComponentProvider,
|
AntdSchemaComponentProvider,
|
||||||
[DocumentTitleProvider, { addonAfter: 'NocoBase' }],
|
[DocumentTitleProvider, { addonAfter: 'NocoBase' }],
|
||||||
[RouteSwitchProvider, { components: { AuthLayout, AdminLayout, RouteSchemaComponent, SigninPage, SignupPage } }],
|
[RouteSwitchProvider, { components: { AuthLayout, AdminLayout, RouteSchemaComponent, SigninPage, SignupPage } }],
|
||||||
|
@ -3,6 +3,7 @@ import { Result } from 'ahooks/lib/useRequest/src/types';
|
|||||||
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
|
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||||
|
|
||||||
export interface ActionParams {
|
export interface ActionParams {
|
||||||
|
filterByTk?: any;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
AntdSchemaComponentProvider,
|
AntdSchemaComponentProvider,
|
||||||
APIClientProvider,
|
APIClientProvider,
|
||||||
AuthLayout,
|
AuthLayout,
|
||||||
|
CollectionManagerProvider,
|
||||||
CollectionManagerShortcut,
|
CollectionManagerShortcut,
|
||||||
compose,
|
compose,
|
||||||
DesignableSwitch,
|
DesignableSwitch,
|
||||||
@ -39,6 +40,7 @@ const providers = [
|
|||||||
{ components: { ACLShortcut, DesignableSwitch, CollectionManagerShortcut, SystemSettingsShortcut } },
|
{ components: { ACLShortcut, DesignableSwitch, CollectionManagerShortcut, SystemSettingsShortcut } },
|
||||||
],
|
],
|
||||||
[SchemaComponentProvider, { components: { Link, NavLink } }],
|
[SchemaComponentProvider, { components: { Link, NavLink } }],
|
||||||
|
CollectionManagerProvider,
|
||||||
AntdSchemaComponentProvider,
|
AntdSchemaComponentProvider,
|
||||||
[DocumentTitleProvider, { addonAfter: 'NocoBase' }],
|
[DocumentTitleProvider, { addonAfter: 'NocoBase' }],
|
||||||
[RouteSwitchProvider, { components: { AuthLayout, AdminLayout, RouteSchemaComponent, SigninPage, SignupPage } }],
|
[RouteSwitchProvider, { components: { AuthLayout, AdminLayout, RouteSchemaComponent, SigninPage, SignupPage } }],
|
||||||
|
@ -26,6 +26,8 @@ const InternalField: React.FC = (props) => {
|
|||||||
setFieldProps('description', uiSchema.description);
|
setFieldProps('description', uiSchema.description);
|
||||||
setFieldProps('initialValue', uiSchema.default);
|
setFieldProps('initialValue', uiSchema.default);
|
||||||
setRequired();
|
setRequired();
|
||||||
|
// @ts-ignore
|
||||||
|
field.dataSource = uiSchema.enum;
|
||||||
field.component = [component, uiSchema['x-component-props']];
|
field.component = [component, uiSchema['x-component-props']];
|
||||||
}, [uiSchema.title, uiSchema.description, uiSchema.required]);
|
}, [uiSchema.title, uiSchema.description, uiSchema.required]);
|
||||||
return React.createElement(component, props);
|
return React.createElement(component, props);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { CollectionContext } from './context';
|
||||||
import { useCollectionManager } from './hooks';
|
import { useCollectionManager } from './hooks';
|
||||||
import { CollectionOptions } from './types';
|
import { CollectionOptions } from './types';
|
||||||
import { CollectionContext } from './context';
|
|
||||||
|
|
||||||
export const CollectionProvider: React.FC<{ name?: string; collection: CollectionOptions }> = (props) => {
|
export const CollectionProvider: React.FC<{ name?: string; collection: CollectionOptions }> = (props) => {
|
||||||
const { name, collection, children } = props;
|
const { name, collection, children } = props;
|
||||||
|
@ -1,146 +0,0 @@
|
|||||||
import { Button, Divider, Drawer, Space, Table, Typography } from 'antd';
|
|
||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
export const ConfigurationTable = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Space style={{ justifyContent: 'flex-end', width: '100%', marginBottom: 16 }}>
|
|
||||||
<Button key="destroy">删除</Button>
|
|
||||||
<Button type={'primary'} key="create">
|
|
||||||
添加
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
<Table
|
|
||||||
rowSelection={{
|
|
||||||
type: 'checkbox',
|
|
||||||
}}
|
|
||||||
columns={[
|
|
||||||
{
|
|
||||||
title: '数据表名称',
|
|
||||||
dataIndex: 'title',
|
|
||||||
key: 'title',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '数据表标识',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
dataIndex: 'actions',
|
|
||||||
key: 'actions',
|
|
||||||
render: () => (
|
|
||||||
<Space split={<Divider type="vertical" />}>
|
|
||||||
<ConfigureFields />
|
|
||||||
<Typography.Link>Edit</Typography.Link>
|
|
||||||
<Typography.Link>Delete</Typography.Link>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
dataSource={[
|
|
||||||
{
|
|
||||||
name: 'users',
|
|
||||||
title: '用户',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConfigureFields = () => {
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography.Link onClick={() => setVisible(true)}>Configure</Typography.Link>
|
|
||||||
<Drawer width={800} title={'字段配置'} visible={visible} destroyOnClose onClose={() => setVisible(false)}>
|
|
||||||
<CollectionFieldList />
|
|
||||||
</Drawer>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CollectionFieldList = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Space style={{ justifyContent: 'flex-end', width: '100%', marginBottom: 16 }}>
|
|
||||||
<Button key="destroy">删除</Button>
|
|
||||||
<Button type={'primary'} key="create">
|
|
||||||
添加
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
<Table
|
|
||||||
rowSelection={{
|
|
||||||
type: 'checkbox',
|
|
||||||
}}
|
|
||||||
columns={[
|
|
||||||
{
|
|
||||||
title: '字段名称',
|
|
||||||
dataIndex: 'title',
|
|
||||||
key: 'title',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '字段标识',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
dataIndex: 'actions',
|
|
||||||
key: 'actions',
|
|
||||||
render: () => (
|
|
||||||
<Space split={<Divider type="vertical" />}>
|
|
||||||
<CollectionFieldEdit />
|
|
||||||
<Typography.Link>Delete</Typography.Link>
|
|
||||||
</Space>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
dataSource={[
|
|
||||||
{
|
|
||||||
name: 'title',
|
|
||||||
title: '标题',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CollectionFieldEdit = () => {
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Typography.Link onClick={() => setVisible(true)}>Edit</Typography.Link>
|
|
||||||
<Drawer
|
|
||||||
width={800}
|
|
||||||
title={'字段配置'}
|
|
||||||
visible={visible}
|
|
||||||
destroyOnClose
|
|
||||||
onClose={() => setVisible(false)}
|
|
||||||
footer={
|
|
||||||
<Space style={{ justifyContent: 'flex-end', width: '100%' }}>
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
setVisible(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type={'primary'}
|
|
||||||
onClick={() => {
|
|
||||||
setVisible(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
CollectionFieldEdit
|
|
||||||
</Drawer>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
@ -0,0 +1,82 @@
|
|||||||
|
import { useForm } from '@formily/react';
|
||||||
|
import React from 'react';
|
||||||
|
import { useResourceActionContext, useResourceContext } from '..';
|
||||||
|
import { useRequest } from '../../api-client';
|
||||||
|
import { useRecord } from '../../record-provider';
|
||||||
|
import { SchemaComponent, useActionContext } from '../../schema-component';
|
||||||
|
import { collectionSchema } from './schemas/collections';
|
||||||
|
|
||||||
|
const useCancelAction = () => {
|
||||||
|
const form = useForm();
|
||||||
|
const ctx = useActionContext();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
ctx.setVisible(false);
|
||||||
|
form.reset();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const useCreateAction = () => {
|
||||||
|
const form = useForm();
|
||||||
|
const ctx = useActionContext();
|
||||||
|
const { refresh } = useResourceActionContext();
|
||||||
|
const { resource } = useResourceContext();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
await form.submit();
|
||||||
|
await resource.create({ values: form.values });
|
||||||
|
ctx.setVisible(false);
|
||||||
|
await form.reset();
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const useUpdateAction = () => {
|
||||||
|
const form = useForm();
|
||||||
|
const ctx = useActionContext();
|
||||||
|
const { refresh } = useResourceActionContext();
|
||||||
|
const { resource, targetKey } = useResourceContext();
|
||||||
|
const { [targetKey]: filterByTk } = useRecord();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
await form.submit();
|
||||||
|
await resource.update({ filterByTk, values: form.values });
|
||||||
|
ctx.setVisible(false);
|
||||||
|
await form.reset();
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const useDestroyAction = () => {
|
||||||
|
const { refresh } = useResourceActionContext();
|
||||||
|
const { resource, targetKey } = useResourceContext();
|
||||||
|
const { [targetKey]: filterByTk } = useRecord();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
await resource.destroy({ filterByTk });
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const useValues = (options) => {
|
||||||
|
const record = useRecord();
|
||||||
|
return useRequest(() => Promise.resolve({ data: record }), {
|
||||||
|
...options,
|
||||||
|
refreshDeps: [record],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ConfigurationTable = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SchemaComponent
|
||||||
|
schema={collectionSchema}
|
||||||
|
scope={{ useCancelAction, useCreateAction, useUpdateAction, useDestroyAction, useValues }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1 @@
|
|||||||
|
export * from './ConfigurationTable';
|
@ -0,0 +1,249 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
|
|
||||||
|
const collection = {
|
||||||
|
name: 'fields',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'type',
|
||||||
|
interface: 'input',
|
||||||
|
uiSchema: {
|
||||||
|
title: '存储类型',
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'Select',
|
||||||
|
enum: [
|
||||||
|
{
|
||||||
|
label: 'String',
|
||||||
|
value: 'string',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
required: true,
|
||||||
|
} as ISchema,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'title',
|
||||||
|
interface: 'input',
|
||||||
|
uiSchema: {
|
||||||
|
title: '字段名称',
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'Input',
|
||||||
|
required: true,
|
||||||
|
} as ISchema,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'name',
|
||||||
|
interface: 'input',
|
||||||
|
uiSchema: {
|
||||||
|
title: '字段标识',
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'Input',
|
||||||
|
description: '使用英文',
|
||||||
|
} as ISchema,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const collectionFieldSchema: ISchema = {
|
||||||
|
type: 'void',
|
||||||
|
'x-collection-field': 'collections.fields',
|
||||||
|
'x-decorator': 'ResourceActionProvider',
|
||||||
|
'x-decorator-props': {
|
||||||
|
association: {
|
||||||
|
sourceKey: 'name',
|
||||||
|
targetKey: 'name',
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
resource: 'collections.fields',
|
||||||
|
action: 'list',
|
||||||
|
params: {
|
||||||
|
pageSize: 5,
|
||||||
|
filter: {},
|
||||||
|
sort: ['sort'],
|
||||||
|
appends: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-component': 'CollectionProvider',
|
||||||
|
'x-component-props': {
|
||||||
|
collection,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
properties: {
|
||||||
|
delete: {
|
||||||
|
type: 'void',
|
||||||
|
title: '删除',
|
||||||
|
'x-component': 'Action',
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
type: 'void',
|
||||||
|
title: '创建',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
drawer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer',
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
title: 'Drawer Title',
|
||||||
|
properties: {
|
||||||
|
type: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer.Footer',
|
||||||
|
properties: {
|
||||||
|
action1: {
|
||||||
|
title: 'Cancel',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useCancelAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
action2: {
|
||||||
|
title: 'Submit',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
useAction: '{{ useCreateAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
table1: {
|
||||||
|
type: 'void',
|
||||||
|
'x-uid': 'input',
|
||||||
|
'x-component': 'VoidTable',
|
||||||
|
'x-component-props': {
|
||||||
|
rowKey: 'id',
|
||||||
|
rowSelection: {
|
||||||
|
type: 'checkbox',
|
||||||
|
},
|
||||||
|
useDataSource: '{{ useDataSourceFromRAC }}',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
column1: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableColumnDecorator',
|
||||||
|
'x-component': 'VoidTable.Column',
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
type: 'number',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
column2: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableColumnDecorator',
|
||||||
|
'x-component': 'VoidTable.Column',
|
||||||
|
properties: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
column3: {
|
||||||
|
type: 'void',
|
||||||
|
title: 'Actions',
|
||||||
|
'x-component': 'VoidTable.Column',
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Space',
|
||||||
|
'x-component-props': {
|
||||||
|
split: '|',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
update: {
|
||||||
|
type: 'void',
|
||||||
|
title: '编辑',
|
||||||
|
'x-component': 'Action.Link',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
drawer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer',
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
'x-decorator-props': {
|
||||||
|
useValues: '{{ useValues }}',
|
||||||
|
},
|
||||||
|
title: 'Drawer Title',
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-disabled': true,
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer.Footer',
|
||||||
|
properties: {
|
||||||
|
action1: {
|
||||||
|
title: 'Cancel',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useCancelAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
action2: {
|
||||||
|
title: 'Submit',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
useAction: '{{ useUpdateAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
type: 'void',
|
||||||
|
title: '删除',
|
||||||
|
'x-component': 'Action.Link',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useDestroyAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
@ -0,0 +1,259 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
|
import { collectionFieldSchema } from './collectionFields';
|
||||||
|
|
||||||
|
const collection = {
|
||||||
|
name: 'collections',
|
||||||
|
filterTargetKey: 'name',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'integer',
|
||||||
|
name: 'title',
|
||||||
|
interface: 'input',
|
||||||
|
uiSchema: {
|
||||||
|
title: '数据表名称',
|
||||||
|
type: 'number',
|
||||||
|
'x-component': 'Input',
|
||||||
|
required: true,
|
||||||
|
} as ISchema,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'name',
|
||||||
|
interface: 'input',
|
||||||
|
uiSchema: {
|
||||||
|
title: '数据表标识',
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'Input',
|
||||||
|
description: '使用英文',
|
||||||
|
} as ISchema,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'hasMany',
|
||||||
|
name: 'fields',
|
||||||
|
target: 'fields',
|
||||||
|
collectionName: 'collections',
|
||||||
|
sourceKey: 'name',
|
||||||
|
targetKey: 'name',
|
||||||
|
uiSchema: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const collectionSchema: ISchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
block1: {
|
||||||
|
type: 'void',
|
||||||
|
'x-collection': 'collections',
|
||||||
|
'x-decorator': 'ResourceActionProvider',
|
||||||
|
'x-decorator-props': {
|
||||||
|
collection: {
|
||||||
|
targetKey: 'name',
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
resource: 'collections',
|
||||||
|
action: 'list',
|
||||||
|
params: {
|
||||||
|
pageSize: 5,
|
||||||
|
filter: {},
|
||||||
|
sort: ['sort'],
|
||||||
|
appends: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-component': 'CollectionProvider',
|
||||||
|
'x-component-props': {
|
||||||
|
collection,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
properties: {
|
||||||
|
delete: {
|
||||||
|
type: 'void',
|
||||||
|
title: '删除',
|
||||||
|
'x-component': 'Action',
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
type: 'void',
|
||||||
|
title: '创建',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
drawer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer',
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
title: 'Drawer Title',
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer.Footer',
|
||||||
|
properties: {
|
||||||
|
action1: {
|
||||||
|
title: 'Cancel',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useCancelAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
action2: {
|
||||||
|
title: 'Submit',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
useAction: '{{ useCreateAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
table1: {
|
||||||
|
type: 'void',
|
||||||
|
'x-uid': 'input',
|
||||||
|
'x-component': 'VoidTable',
|
||||||
|
'x-component-props': {
|
||||||
|
rowKey: 'id',
|
||||||
|
rowSelection: {
|
||||||
|
type: 'checkbox',
|
||||||
|
},
|
||||||
|
useDataSource: '{{ useDataSourceFromRAC }}',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
column1: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableColumnDecorator',
|
||||||
|
'x-component': 'VoidTable.Column',
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
type: 'number',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
column2: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableColumnDecorator',
|
||||||
|
'x-component': 'VoidTable.Column',
|
||||||
|
properties: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
column3: {
|
||||||
|
type: 'void',
|
||||||
|
title: 'Actions',
|
||||||
|
'x-component': 'VoidTable.Column',
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Space',
|
||||||
|
'x-component-props': {
|
||||||
|
split: '|',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
view: {
|
||||||
|
type: 'void',
|
||||||
|
title: '配置字段',
|
||||||
|
'x-component': 'Action.Link',
|
||||||
|
'x-component-props': {},
|
||||||
|
properties: {
|
||||||
|
drawer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer',
|
||||||
|
title: 'Drawer Title',
|
||||||
|
properties: {
|
||||||
|
collectionFieldSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
type: 'void',
|
||||||
|
title: '编辑',
|
||||||
|
'x-component': 'Action.Link',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
drawer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer',
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
'x-decorator-props': {
|
||||||
|
useValues: '{{ useValues }}',
|
||||||
|
},
|
||||||
|
title: 'Drawer Title',
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-disabled': true,
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action.Drawer.Footer',
|
||||||
|
properties: {
|
||||||
|
action1: {
|
||||||
|
title: 'Cancel',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useCancelAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
action2: {
|
||||||
|
title: 'Submit',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
useAction: '{{ useUpdateAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
type: 'void',
|
||||||
|
title: '删除',
|
||||||
|
'x-component': 'Action.Link',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useDestroyAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
@ -1,22 +1,59 @@
|
|||||||
import { Result } from 'ahooks/lib/useRequest/src/types';
|
import { Result } from 'ahooks/lib/useRequest/src/types';
|
||||||
import React, { createContext, useContext, useEffect } from 'react';
|
import React, { createContext, useContext, useEffect } from 'react';
|
||||||
import { useRequest } from '../api-client';
|
import { useRecord } from '..';
|
||||||
|
import { useAPIClient, useRequest } from '../api-client';
|
||||||
|
|
||||||
export const ResourceActionContext = createContext<Result<any, any>>(null);
|
export const ResourceActionContext = createContext<Result<any, any>>(null);
|
||||||
|
|
||||||
interface ResourceActionProviderProps {
|
interface ResourceActionProviderProps {
|
||||||
|
type?: 'association' | 'collection';
|
||||||
request?: any;
|
request?: any;
|
||||||
uid?: string;
|
uid?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ResourceActionProvider: React.FC<ResourceActionProviderProps> = (props) => {
|
const ResourceContext = createContext<any>(null);
|
||||||
const { request, uid } = props;
|
|
||||||
console.log(request);
|
const CollectionResourceActionProvider = (props) => {
|
||||||
|
const { collection, request, uid } = props;
|
||||||
|
const api = useAPIClient();
|
||||||
const service = useRequest(request, {
|
const service = useRequest(request, {
|
||||||
uid,
|
uid,
|
||||||
refreshDeps: [request],
|
refreshDeps: [request],
|
||||||
});
|
});
|
||||||
return <ResourceActionContext.Provider value={service}>{props.children}</ResourceActionContext.Provider>;
|
const resource = api.resource(request.resource);
|
||||||
|
return (
|
||||||
|
<ResourceContext.Provider value={{ type: 'collection', resource, collection }}>
|
||||||
|
<ResourceActionContext.Provider value={service}>{props.children}</ResourceActionContext.Provider>
|
||||||
|
</ResourceContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AssociationResourceActionProvider = (props) => {
|
||||||
|
const { association, request, uid } = props;
|
||||||
|
const api = useAPIClient();
|
||||||
|
const record = useRecord();
|
||||||
|
const resourceOf = record[association.sourceKey];
|
||||||
|
const service = useRequest(
|
||||||
|
{ resourceOf, ...request },
|
||||||
|
{
|
||||||
|
uid,
|
||||||
|
refreshDeps: [request, resourceOf],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const resource = api.resource(request.resource, resourceOf);
|
||||||
|
return (
|
||||||
|
<ResourceContext.Provider value={{ type: 'association', resource, association }}>
|
||||||
|
<ResourceActionContext.Provider value={service}>{props.children}</ResourceActionContext.Provider>
|
||||||
|
</ResourceContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ResourceActionProvider: React.FC<ResourceActionProviderProps> = (props) => {
|
||||||
|
const { request } = props;
|
||||||
|
if (request?.resource?.includes('.')) {
|
||||||
|
return <AssociationResourceActionProvider {...props} />;
|
||||||
|
}
|
||||||
|
return <CollectionResourceActionProvider {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useResourceActionContext = () => {
|
export const useResourceActionContext = () => {
|
||||||
@ -32,3 +69,8 @@ export const useDataSourceFromRAC = (options: any) => {
|
|||||||
}, [service.loading]);
|
}, [service.loading]);
|
||||||
return service;
|
return service;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useResourceContext = () => {
|
||||||
|
const { type, resource, collection, association } = useContext(ResourceContext);
|
||||||
|
return { type, resource, collection, association, targetKey: association?.targetKey || collection?.targetKey };
|
||||||
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from './useCollection';
|
export * from './useCollection';
|
||||||
export * from './useCollectionField';
|
export * from './useCollectionField';
|
||||||
export * from './useCollectionManager';
|
export * from './useCollectionManager';
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useContext } from 'react';
|
|
||||||
import { SchemaKey } from '@formily/react';
|
import { SchemaKey } from '@formily/react';
|
||||||
import { CollectionFieldOptions } from '../types';
|
import { useContext } from 'react';
|
||||||
import { CollectionContext } from '../context';
|
|
||||||
import { useAPIClient } from '../../api-client';
|
import { useAPIClient } from '../../api-client';
|
||||||
|
import { CollectionContext } from '../context';
|
||||||
|
import { CollectionFieldOptions } from '../types';
|
||||||
|
|
||||||
export const useCollection = () => {
|
export const useCollection = () => {
|
||||||
const collection = useContext(CollectionContext);
|
const collection = useContext(CollectionContext);
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { CollectionFieldContext } from '../context';
|
|
||||||
import { useRecord } from '../../record-provider';
|
|
||||||
import { useCollection } from './useCollection';
|
|
||||||
import { useAPIClient } from '../../api-client';
|
import { useAPIClient } from '../../api-client';
|
||||||
|
import { useRecord } from '../../record-provider';
|
||||||
|
import { CollectionFieldContext } from '../context';
|
||||||
|
import { useCollection } from './useCollection';
|
||||||
|
|
||||||
export const useCollectionField = () => {
|
export const useCollectionField = () => {
|
||||||
const collection = useCollection();
|
const collection = useCollection();
|
||||||
const record = useRecord();
|
const record = useRecord();
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const ctx = useContext(CollectionFieldContext);
|
const ctx = useContext(CollectionFieldContext);
|
||||||
const resource = api?.resource(`${collection?.name || ctx?.collectinName}.${ctx.name}`, record[ctx.sourceKey]);
|
const resourceName = `${ctx?.collectinName || collection?.name}.${ctx.name}`;
|
||||||
|
const resource = api?.resource(resourceName, record[ctx.sourceKey]);
|
||||||
|
console.log({ resourceName });
|
||||||
return {
|
return {
|
||||||
...ctx,
|
...ctx,
|
||||||
resource,
|
resource,
|
||||||
|
@ -7,6 +7,7 @@ export interface CollectionManagerOptions {
|
|||||||
|
|
||||||
export interface CollectionOptions {
|
export interface CollectionOptions {
|
||||||
name?: string;
|
name?: string;
|
||||||
|
filterTargetKey?: string;
|
||||||
fields?: any[];
|
fields?: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ export interface ICollectionProviderProps {
|
|||||||
export interface CollectionFieldOptions {
|
export interface CollectionFieldOptions {
|
||||||
name?: any;
|
name?: any;
|
||||||
collectinName?: string;
|
collectinName?: string;
|
||||||
|
targetKey?: string;
|
||||||
sourceKey?: string; // association field
|
sourceKey?: string; // association field
|
||||||
uiSchema?: ISchema;
|
uiSchema?: ISchema;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user