diff --git a/packages/client/src/collection-manager/CollectionManagerSchemaComponentProvider.tsx b/packages/client/src/collection-manager/CollectionManagerSchemaComponentProvider.tsx
index e60f245ae..e481aaca3 100644
--- a/packages/client/src/collection-manager/CollectionManagerSchemaComponentProvider.tsx
+++ b/packages/client/src/collection-manager/CollectionManagerSchemaComponentProvider.tsx
@@ -8,12 +8,19 @@ import {
useDataSourceFromRAC
} from './';
import * as hooks from './action-hooks';
+import { DataSourceProvider, ds } from './sub-table';
export const CollectionManagerSchemaComponentProvider: React.FC = (props) => {
return (
{props.children}
diff --git a/packages/client/src/collection-manager/Configuration/AddSubFieldAction.tsx b/packages/client/src/collection-manager/Configuration/AddSubFieldAction.tsx
index 719d70003..e32747446 100644
--- a/packages/client/src/collection-manager/Configuration/AddSubFieldAction.tsx
+++ b/packages/client/src/collection-manager/Configuration/AddSubFieldAction.tsx
@@ -6,7 +6,8 @@ import { Button, Dropdown, Menu } from 'antd';
import { cloneDeep } from 'lodash';
import React, { useState } from 'react';
import { useRequest } from '../../api-client';
-import { ActionContext, SchemaComponent, useActionContext, useCompile, useFormBlockContext } from '../../schema-component';
+import { RecordProvider } from '../../record-provider';
+import { ActionContext, SchemaComponent, useActionContext, useCompile } from '../../schema-component';
import { useCollectionManager } from '../hooks';
import { IField } from '../interfaces/types';
import { options } from './interfaces';
@@ -61,7 +62,7 @@ const getSchema = (schema: IField): ISchema => {
'x-component': 'Action',
'x-component-props': {
type: 'primary',
- useAction: '{{ useCreateSubField }}',
+ useAction: '{{ ds.useCreateAction }}',
},
},
},
@@ -73,17 +74,9 @@ const getSchema = (schema: IField): ISchema => {
};
const useCreateSubField = () => {
- // const form = useForm();
- const { form, parent } = useFormBlockContext();
const ctx = useActionContext();
return {
async run() {
- await form.submit();
- const children = parent.form.values?.children?.slice?.();
- children.push(cloneDeep(form.values));
- console.log('form.values', form.values, children);
- parent.form.setValuesIn('children', children);
- ctx.setVisible(false);
// const options = form?.values?.uiSchema?.enum?.slice() || [];
// form.setValuesIn(
// 'uiSchema.enum',
@@ -132,7 +125,9 @@ export const AddSubFieldAction = () => {
添加字段
-
+
+
+
);
};
diff --git a/packages/client/src/collection-manager/Configuration/EditSubFieldAction.tsx b/packages/client/src/collection-manager/Configuration/EditSubFieldAction.tsx
index 825afed67..80c8e1a99 100644
--- a/packages/client/src/collection-manager/Configuration/EditSubFieldAction.tsx
+++ b/packages/client/src/collection-manager/Configuration/EditSubFieldAction.tsx
@@ -1,12 +1,13 @@
import { ArrayTable } from '@formily/antd';
-import { ISchema } from '@formily/react';
+import { ISchema, useForm } from '@formily/react';
import { uid } from '@formily/shared';
import cloneDeep from 'lodash/cloneDeep';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useAPIClient, useRequest } from '../../api-client';
import { useRecord } from '../../record-provider';
-import { ActionContext, SchemaComponent, useActionContext, useFormBlockContext } from '../../schema-component';
+import { ActionContext, SchemaComponent } from '../../schema-component';
+import { useUpdateAction } from '../action-hooks';
import { useCollectionManager } from '../hooks';
import { IField } from '../interfaces/types';
@@ -54,7 +55,7 @@ const getSchema = (schema: IField): ISchema => {
'x-component': 'Action',
'x-component-props': {
type: 'primary',
- useAction: '{{ useUpdateSubField }}',
+ useAction: '{{ ds.useUpdateAction }}',
},
},
},
@@ -65,23 +66,25 @@ const getSchema = (schema: IField): ISchema => {
};
};
-const useUpdateSubField = () => {
- const { form, parent } = useFormBlockContext();
- const ctx = useActionContext();
+const useUpdateCollectionField = () => {
+ const form = useForm();
+ const { run } = useUpdateAction();
+ const { refreshCM } = useCollectionManager();
return {
async run() {
await form.submit();
- const children = parent.form.values?.children?.slice?.();
- parent.form.setValuesIn(
- 'children',
- children.map((child) => {
- if (child.name === form.values.name) {
- return cloneDeep(form.values);
- }
- return child;
+ const options = form?.values?.uiSchema?.enum?.slice() || [];
+ form.setValuesIn(
+ 'uiSchema.enum',
+ options.map((option) => {
+ return {
+ value: uid(),
+ ...option,
+ };
}),
);
- ctx.setVisible(false);
+ await run();
+ await refreshCM();
},
};
};
@@ -97,15 +100,13 @@ export const EditSubFieldAction = (props) => {
{
- // const { data } = await api.resource('fields.children', record.key).get({
+ // const { data } = await api.resource('collections.fields', record.collectionName).get({
// filterByTk: record.name,
- // appends: ['uiSchema'],
+ // appends: record.interface === 'subTable' ? ['uiSchema', 'children'] : ['uiSchema'],
// });
const schema = getSchema({
...getInterface(record.interface),
- default: {
- ...record,
- },
+ default: record,
});
setSchema(schema);
setVisible(true);
@@ -113,7 +114,7 @@ export const EditSubFieldAction = (props) => {
>
{t('Edit')}
-
+
);
};
diff --git a/packages/client/src/collection-manager/interfaces/subTable.ts b/packages/client/src/collection-manager/interfaces/subTable.ts
index 1efb2e35e..6a16bc2e4 100644
--- a/packages/client/src/collection-manager/interfaces/subTable.ts
+++ b/packages/client/src/collection-manager/interfaces/subTable.ts
@@ -33,15 +33,15 @@ export const subTable: IField = {
...defaultProps,
subtable: {
type: 'void',
- 'x-component': 'div',
+ 'x-component': 'DataSourceProvider',
properties: {
actions: {
type: 'void',
'x-component': 'ActionBar',
'x-component-props': {
- style: {
- marginBottom: 16,
- },
+ // style: {
+ // marginBottom: 16,
+ // },
},
properties: {
delete: {
@@ -49,7 +49,7 @@ export const subTable: IField = {
title: '{{ t("Delete") }}',
'x-component': 'Action',
'x-component-props': {
- useAction: '{{ useBulkDestroySubField }}',
+ useAction: '{{ ds.useBulkDestroyAction }}',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
@@ -73,11 +73,15 @@ export const subTable: IField = {
'x-component': 'Table.Array',
'x-component-props': {
pagination: false,
+ expandable: {
+ childrenColumnName: '__nochildren__',
+ },
rowKey: 'name',
rowSelection: {
type: 'checkbox',
},
- useSelectedRowKeys: '{{ useSelectedRowKeys }}',
+ useSelectedRowKeys: '{{ ds.useSelectedRowKeys }}',
+ useDataSource: '{{ ds.useDataSource }}',
// scroll: { x: '100%' },
},
properties: {
@@ -96,7 +100,6 @@ export const subTable: IField = {
column2: {
type: 'void',
title: '{{ t("Field name") }}',
- 'x-decorator': 'Table.Column.Decorator',
'x-component': 'Table.Column',
properties: {
name: {
@@ -108,7 +111,6 @@ export const subTable: IField = {
column3: {
type: 'void',
title: '{{ t("Field interface") }}',
- 'x-decorator': 'Table.Column.Decorator',
'x-component': 'Table.Column',
properties: {
interface: {
@@ -134,7 +136,7 @@ export const subTable: IField = {
title: '{{ t("Edit") }}',
'x-component': 'EditSubFieldAction',
'x-component-props': {
- type: 'primary',
+ // useAction: '{{ ds.useUpdateAction }}',
},
},
delete: {
@@ -142,7 +144,7 @@ export const subTable: IField = {
title: '{{ t("Delete") }}',
'x-component': 'Action.Link',
'x-component-props': {
- useAction: '{{ useDestroySubField }}',
+ useAction: '{{ ds.useDestroyAction }}',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
diff --git a/packages/client/src/collection-manager/sub-table.tsx b/packages/client/src/collection-manager/sub-table.tsx
new file mode 100644
index 000000000..32e7ae133
--- /dev/null
+++ b/packages/client/src/collection-manager/sub-table.tsx
@@ -0,0 +1,214 @@
+import { observer, useForm } from '@formily/react';
+import React, { createContext, useContext, useState } from 'react';
+import { CollectionOptions, CollectionProvider, useActionContext, useRecord, useRequest } from '../';
+import { useAPIClient } from '../api-client';
+import { options } from './Configuration/interfaces';
+
+const collection: CollectionOptions = {
+ name: 'fields',
+ targetKey: 'name',
+ fields: [
+ {
+ type: 'string',
+ name: 'type',
+ interface: 'input',
+ uiSchema: {
+ title: '{{ t("Storage type") }}',
+ type: 'string',
+ 'x-component': 'Select',
+ enum: [
+ {
+ label: 'String',
+ value: 'string',
+ },
+ ],
+ required: true,
+ },
+ },
+ {
+ type: 'string',
+ name: 'interface',
+ interface: 'input',
+ uiSchema: {
+ title: '{{ t("Field interface") }}',
+ type: 'string',
+ 'x-component': 'Select',
+ enum: options as any,
+ },
+ },
+ {
+ type: 'string',
+ name: 'title',
+ interface: 'input',
+ uiSchema: {
+ title: '{{ t("Field display name") }}',
+ type: 'string',
+ 'x-component': 'Input',
+ required: true,
+ },
+ },
+ {
+ type: 'string',
+ name: 'name',
+ interface: 'input',
+ uiSchema: {
+ title: '{{ t("Field name") }}',
+ type: 'string',
+ 'x-component': 'Input',
+ },
+ },
+ ],
+};
+
+export const DataSourceContext = createContext(null);
+
+const useSelectedRowKeys = () => {
+ const ctx = useContext(DataSourceContext);
+ return [ctx.selectedRowKeys, ctx.setSelectedRowKeys];
+};
+
+const useDataSource = (options) => {
+ const ctx = useContext(DataSourceContext);
+ return useRequest(
+ () => {
+ return Promise.resolve({
+ data: ctx.dataSource,
+ });
+ },
+ {
+ ...options,
+ refreshDeps: [JSON.stringify(ctx.dataSource)],
+ },
+ );
+};
+
+const useCreateAction = () => {
+ const ctx = useContext(DataSourceContext);
+ const form = useForm();
+ const { setVisible } = useActionContext();
+ return {
+ async run() {
+ // console.log(ctx.dataSource);
+ const dataSource = ctx.dataSource || [];
+ dataSource.push(form.values);
+ ctx.setDataSource([...dataSource]);
+ setVisible(false);
+ },
+ };
+};
+
+const useBulkDestroyAction = () => {
+ const ctx = useContext(DataSourceContext);
+ const { selectedRowKeys, setSelectedRowKeys } = ctx;
+ return {
+ async run() {
+ const dataSource = ctx.dataSource || [];
+ ctx.setDataSource(
+ dataSource.filter((item) => {
+ return !selectedRowKeys.includes(item[ctx.rowKey]);
+ }),
+ );
+ setSelectedRowKeys([]);
+ },
+ };
+};
+
+const useUpdateAction = () => {
+ const record = useRecord();
+ const form = useForm();
+ const { setVisible } = useActionContext();
+ const ctx = useContext(DataSourceContext);
+ return {
+ async run() {
+ const dataSource = ctx?.dataSource || [];
+ const rowKey = ctx?.rowKey;
+ const values = dataSource.map((item) => {
+ if (record[rowKey] === item[rowKey]) {
+ return { ...form.values };
+ }
+ return item;
+ });
+ ctx.setDataSource([...values]);
+ setVisible(false);
+ },
+ };
+};
+
+const useDestroyAction = () => {
+ const record = useRecord();
+ const ctx = useContext(DataSourceContext);
+ return {
+ async run() {
+ const rowKey = ctx.rowKey;
+ const dataSource = ctx.dataSource || [];
+ ctx.setDataSource(
+ dataSource.filter((item) => {
+ return record[rowKey] !== item[rowKey];
+ }),
+ );
+ },
+ };
+};
+
+export const ds = {
+ useSelectedRowKeys,
+ useDataSource,
+ useCreateAction,
+ useBulkDestroyAction,
+ useUpdateAction,
+ useDestroyAction,
+};
+
+export const DataSourceProvider = observer((props) => {
+ const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+ const [dataSource, setDataSource] = useState([]);
+ const record = useRecord();
+ const api = useAPIClient();
+ const service = useRequest(
+ () => {
+ if (record.interface === 'subTable') {
+ if (record?.children?.length) {
+ return Promise.resolve({
+ data: record?.children || [],
+ });
+ }
+ return api
+ .resource('fields')
+ .list({
+ paginate: false,
+ appends: ['uiSchema'],
+ sort: 'sort',
+ filter: {
+ parentKey: record.key,
+ },
+ })
+ .then((res) => res?.data);
+ }
+ return Promise.resolve({
+ data: [],
+ });
+ },
+ {
+ onSuccess(data) {
+ console.log('dataSource1', data?.data);
+ setDataSource(data?.data);
+ },
+ },
+ );
+ return (
+
+
+ {props.children}
+
+
+ );
+});
diff --git a/packages/client/src/schema-component/antd/table/Table.Array.tsx b/packages/client/src/schema-component/antd/table/Table.Array.tsx
index 01e8c6438..e47d4c6ab 100644
--- a/packages/client/src/schema-component/antd/table/Table.Array.tsx
+++ b/packages/client/src/schema-component/antd/table/Table.Array.tsx
@@ -121,7 +121,13 @@ export const TableArray: React.FC = observer((props) => {
};
return (
);
});
diff --git a/packages/client/src/schema-component/antd/table/demos/demo4.tsx b/packages/client/src/schema-component/antd/table/demos/demo4.tsx
index 9efb03ea0..789058c40 100644
--- a/packages/client/src/schema-component/antd/table/demos/demo4.tsx
+++ b/packages/client/src/schema-component/antd/table/demos/demo4.tsx
@@ -13,52 +13,121 @@ import React, { createContext, useContext, useState } from 'react';
const DataSourceContext = createContext(null);
+const useSelectedRowKeys = () => {
+ const ctx = useContext(DataSourceContext);
+ return [ctx.selectedRowKeys, ctx.setSelectedRowKeys];
+};
+
+const useDataSource = (options) => {
+ const ctx = useContext(DataSourceContext);
+ return useRequest(
+ () => {
+ console.log('ctx.dataSource', ctx.dataSource);
+ return Promise.resolve({
+ data: ctx.dataSource,
+ });
+ },
+ {
+ ...options,
+ refreshDeps: [JSON.stringify(ctx.dataSource)],
+ },
+ );
+};
+
+const useCreateAction = () => {
+ const ctx = useContext(DataSourceContext);
+ return {
+ async run() {
+ console.log(ctx.dataSource);
+ const dataSource = ctx.dataSource || [];
+ dataSource.push({
+ id: uid(),
+ name: uid(),
+ });
+ ctx.setDataSource([...dataSource]);
+ },
+ };
+};
+
+const useBulkDestroyAction = () => {
+ const ctx = useContext(DataSourceContext);
+ const { selectedRowKeys, setSelectedRowKeys } = ctx;
+ return {
+ async run() {
+ const dataSource = ctx.dataSource || [];
+ ctx.setDataSource(
+ dataSource.filter((item) => {
+ return !selectedRowKeys.includes(item.id);
+ }),
+ );
+ setSelectedRowKeys([]);
+ },
+ };
+};
+
+const useUpdateAction = () => {
+ const record = useRecord();
+ // const form = useForm();
+ const ctx = useContext(DataSourceContext);
+ return {
+ async run() {
+ const dataSource = ctx.dataSource || [];
+ ctx.setDataSource([
+ ...dataSource.map((item) => {
+ if (record.id === item.id) {
+ record.name = uid();
+ return record;
+ }
+ return item;
+ }),
+ ]);
+ },
+ };
+};
+
+const useDestroyAction = () => {
+ const record = useRecord();
+ const ctx = useContext(DataSourceContext);
+ return {
+ async run() {
+ const dataSource = ctx.dataSource || [];
+ ctx.setDataSource(
+ dataSource.filter((item) => {
+ return record.id !== item.id;
+ }),
+ );
+ },
+ };
+};
+
+const ds = {
+ useSelectedRowKeys,
+ useDataSource,
+ useCreateAction,
+ useBulkDestroyAction,
+ useUpdateAction,
+ useDestroyAction,
+};
+
const schema: ISchema = {
type: 'object',
properties: {
context: {
type: 'void',
- 'x-component': 'Context',
+ 'x-component': 'DataSourceProvider',
properties: {
action1: {
- title: '提交',
+ title: '添加',
'x-component': 'Action',
'x-component-props': {
- useAction() {
- const ctx = useContext(DataSourceContext);
- return {
- async run() {
- console.log(ctx.dataSource);
- const dataSource = ctx.dataSource || [];
- dataSource.push({
- id: uid(),
- name: uid(),
- });
- ctx.setDataSource([...dataSource]);
- },
- };
- },
+ useAction: '{{ ds.useCreateAction }}',
},
},
action2: {
title: '删除',
'x-component': 'Action',
'x-component-props': {
- useAction() {
- const ctx = useContext(DataSourceContext);
- const { selectedRowKeys, setSelectedRowKeys } = ctx;
- return {
- async run() {
- const dataSource = ctx.dataSource || [];
- ctx.setDataSource(
- dataSource.filter((item) => {
- return !selectedRowKeys.includes(item.id);
- }),
- );
- setSelectedRowKeys([]);
- },
- };
- },
+ useAction: '{{ ds.useBulkDestroyAction }}',
},
},
input: {
@@ -67,28 +136,12 @@ const schema: ISchema = {
'x-component': 'Table.Array',
'x-component-props': {
rowKey: 'id',
+ pagination: false,
rowSelection: {
type: 'checkbox',
},
- useSelectedRowKeys() {
- const ctx = useContext(DataSourceContext);
- return [ctx.selectedRowKeys, ctx.setSelectedRowKeys];
- },
- useDataSource(options) {
- const ctx = useContext(DataSourceContext);
- return useRequest(
- () => {
- console.log('ctx.dataSource', ctx.dataSource);
- return Promise.resolve({
- data: ctx.dataSource,
- });
- },
- {
- ...options,
- refreshDeps: [JSON.stringify(ctx.dataSource)],
- },
- );
- },
+ useSelectedRowKeys: '{{ ds.useSelectedRowKeys }}',
+ useDataSource: '{{ ds.useDataSource }}',
},
properties: {
column1: {
@@ -108,24 +161,18 @@ const schema: ISchema = {
title: 'Actions',
'x-component': 'Table.Column',
properties: {
- action: {
+ action1: {
+ title: '编辑',
+ 'x-component': 'Action',
+ 'x-component-props': {
+ useAction: '{{ ds.useUpdateAction }}',
+ },
+ },
+ action2: {
title: '删除',
'x-component': 'Action',
'x-component-props': {
- useAction() {
- const record = useRecord();
- const ctx = useContext(DataSourceContext);
- return {
- async run() {
- const dataSource = ctx.dataSource || [];
- ctx.setDataSource(
- dataSource.filter((item) => {
- return record.id !== item.id;
- }),
- );
- },
- };
- },
+ useAction: '{{ ds.useDestroyAction }}',
},
},
},
@@ -137,7 +184,7 @@ const schema: ISchema = {
},
};
-const Context = observer((props) => {
+const DataSourceProvider = observer((props) => {
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [dataSource, setDataSource] = useState([]);
const service = useRequest(
@@ -174,7 +221,7 @@ const Context = observer((props) => {
export default () => {
return (
-
+
);
diff --git a/packages/database/src/magic-attribute-model.ts b/packages/database/src/magic-attribute-model.ts
index bcc338d66..958d7fb9a 100644
--- a/packages/database/src/magic-attribute-model.ts
+++ b/packages/database/src/magic-attribute-model.ts
@@ -25,6 +25,9 @@ export class MagicAttributeModel extends Model {
}
return super.set(`${this.magicAttribute}.${key}`, value, options);
} else {
+ if (!key) {
+ return;
+ }
Object.keys(key).forEach((k) => {
this.set(k, key[k], options);
});