diff --git a/packages/core/client/docs/zh-CN/core/block/collections.json b/packages/core/client/docs/zh-CN/core/block/collections.json deleted file mode 100644 index f37784bd11..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/collections.json +++ /dev/null @@ -1,486 +0,0 @@ -[ - { - "key": "h7b9i8khc3q", - "name": "users", - "inherit": false, - "hidden": false, - "description": null, - "category": [], - "namespace": "users.users", - "duplicator": { - "dumpable": "optional", - "with": "rolesUsers" - }, - "sortable": "sort", - "model": "UserModel", - "createdBy": true, - "updatedBy": true, - "logging": true, - "from": "db2cm", - "title": "{{t(\"Users\")}}", - "rawTitle": "{{t(\"Users\")}}", - "fields": [ - { - "uiSchema": { - "type": "number", - "title": "{{t(\"ID\")}}", - "x-component": "InputNumber", - "x-read-pretty": true, - "rawTitle": "{{t(\"ID\")}}" - }, - "key": "ffp1f2sula0", - "name": "id", - "type": "bigInt", - "interface": "id", - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "autoIncrement": true, - "primaryKey": true, - "allowNull": false - }, - { - "uiSchema": { - "type": "string", - "title": "{{t(\"Nickname\")}}", - "x-component": "Input", - "rawTitle": "{{t(\"Nickname\")}}" - }, - "key": "vrv7yjue90g", - "name": "nickname", - "type": "string", - "interface": "input", - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null - }, - { - "uiSchema": { - "type": "string", - "title": "{{t(\"Username\")}}", - "x-component": "Input", - "x-validator": { - "username": true - }, - "required": true, - "rawTitle": "{{t(\"Username\")}}" - }, - "key": "2ccs6evyrub", - "name": "username", - "type": "string", - "interface": "input", - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "unique": true - }, - { - "uiSchema": { - "type": "string", - "title": "{{t(\"Email\")}}", - "x-component": "Input", - "x-validator": "email", - "required": true, - "rawTitle": "{{t(\"Email\")}}" - }, - "key": "rrskwjl5wt1", - "name": "email", - "type": "string", - "interface": "email", - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "unique": true - }, - { - "uiSchema": { - "type": "string", - "title": "{{t(\"Phone\")}}", - "x-component": "Input", - "x-validator": "phone", - "required": true, - "rawTitle": "{{t(\"Phone\")}}" - }, - "key": "yzv4yjeg0pn", - "name": "phone", - "type": "string", - "interface": "phone", - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "unique": true - }, - { - "uiSchema": { - "type": "string", - "title": "{{t(\"Password\")}}", - "x-component": "Password", - "rawTitle": "{{t(\"Password\")}}" - }, - "key": "3pzwulm5o6b", - "name": "password", - "type": "password", - "interface": "password", - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "hidden": true - }, - { - "key": "q3is17d1abv", - "name": "appLang", - "type": "string", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null - }, - { - "key": "lhysy09i27u", - "name": "resetToken", - "type": "string", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "unique": true, - "hidden": true - }, - { - "key": "xlbup0n8dr5", - "name": "systemSettings", - "type": "json", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "defaultValue": {} - }, - { - "key": "w1vjr3cu2dk", - "name": "sort", - "type": "sort", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "hidden": true - }, - { - "key": "p3tw5siagb4", - "name": "createdById", - "type": "context", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "dataType": "bigInt", - "dataIndex": "state.currentUser.id", - "createOnly": true, - "visible": true, - "index": true - }, - { - "key": "1j6mx2762or", - "name": "createdBy", - "type": "belongsTo", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "target": "users", - "foreignKey": "createdById", - "targetKey": "id" - }, - { - "key": "k91xpvbvwle", - "name": "updatedById", - "type": "context", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "dataType": "bigInt", - "dataIndex": "state.currentUser.id", - "visible": true, - "index": true - }, - { - "key": "xfog81yb136", - "name": "updatedBy", - "type": "belongsTo", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "target": "users", - "foreignKey": "updatedById", - "targetKey": "id" - }, - { - "uiSchema": { - "type": "array", - "title": "{{t(\"Roles\")}}", - "x-component": "AssociationField", - "x-component-props": { - "multiple": true, - "fieldNames": { - "label": "title", - "value": "name" - } - }, - "rawTitle": "{{t(\"Roles\")}}" - }, - "key": "b7s9ywt6n06", - "name": "roles", - "type": "belongsToMany", - "interface": "m2m", - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "target": "roles", - "foreignKey": "userId", - "otherKey": "roleName", - "onDelete": "CASCADE", - "sourceKey": "id", - "targetKey": "name", - "through": "rolesUsers" - }, - { - "key": "0j83jlhhi9r", - "name": "jobs", - "type": "belongsToMany", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "through": "users_jobs", - "onDelete": "CASCADE", - "foreignKey": "userId", - "sourceKey": "id", - "otherKey": "jobId", - "targetKey": "id" - }, - { - "key": "h7s78jvbo89", - "name": "usersJobs", - "type": "hasMany", - "interface": null, - "description": null, - "collectionName": "users", - "parentKey": null, - "reverseKey": null, - "target": "users_jobs", - "foreignKey": "userId", - "sourceKey": "id", - "targetKey": "id" - } - ] - }, - { - "key": "pqnenvqrzxr", - "name": "roles", - "inherit": false, - "hidden": false, - "description": null, - "category": [], - "namespace": "acl.acl", - "duplicator": { - "dumpable": "required", - "with": "uiSchemas" - }, - "autoGenId": false, - "model": "RoleModel", - "filterTargetKey": "name", - "sortable": true, - "from": "db2cm", - "title": "{{t(\"Roles\")}}", - "rawTitle": "{{t(\"Roles\")}}", - "fields": [ - { - "uiSchema": { - "type": "string", - "title": "{{t(\"Role UID\")}}", - "x-component": "Input", - "rawTitle": "{{t(\"Role UID\")}}" - }, - "key": "jbz9m80bxmp", - "name": "name", - "type": "uid", - "interface": "input", - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "prefix": "r_", - "primaryKey": true - }, - { - "uiSchema": { - "type": "string", - "title": "{{t(\"Role name\")}}", - "x-component": "Input", - "rawTitle": "{{t(\"Role name\")}}" - }, - "key": "faywtz4sf3u", - "name": "title", - "type": "string", - "interface": "input", - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "unique": true, - "translation": true - }, - { - "key": "1enkovm9sye", - "name": "description", - "type": "string", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null - }, - { - "key": "wwoozt6911x", - "name": "strategy", - "type": "json", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null - }, - { - "key": "wupe6r46azg", - "name": "default", - "type": "boolean", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "defaultValue": false - }, - { - "key": "1wxu26hqcey", - "name": "hidden", - "type": "boolean", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "defaultValue": false - }, - { - "key": "krspuzq44fc", - "name": "allowConfigure", - "type": "boolean", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null - }, - { - "key": "mv8vmxdj2wd", - "name": "allowNewMenu", - "type": "boolean", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null - }, - { - "key": "c81x5luikwd", - "name": "menuUiSchemas", - "type": "belongsToMany", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "target": "uiSchemas", - "targetKey": "x-uid", - "onDelete": "CASCADE", - "foreignKey": "roleName", - "sourceKey": "name", - "otherKey": "uiSchemaXUid", - "through": "rolesUischemas" - }, - { - "key": "lm9x55l6gxm", - "name": "resources", - "type": "hasMany", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "target": "rolesResources", - "sourceKey": "name", - "targetKey": "name", - "foreignKey": "roleName" - }, - { - "key": "5dnal1v7se3", - "name": "snippets", - "type": "set", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "defaultValue": ["!ui.*", "!pm", "!pm.*"] - }, - { - "key": "foxkspl2zt7", - "name": "users", - "type": "belongsToMany", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "target": "users", - "foreignKey": "roleName", - "otherKey": "userId", - "onDelete": "CASCADE", - "sourceKey": "name", - "targetKey": "id", - "through": "rolesUsers" - }, - { - "key": "n3937y2slrt", - "name": "sort", - "type": "sort", - "interface": null, - "description": null, - "collectionName": "roles", - "parentKey": null, - "reverseKey": null, - "hidden": true - } - ] - } -] diff --git a/packages/core/client/docs/zh-CN/core/block/createApp.tsx b/packages/core/client/docs/zh-CN/core/block/createApp.tsx deleted file mode 100644 index ba99db85b7..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/createApp.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Application, ApplicationOptions, CollectionManagerProvider } from '@nocobase/client'; -import MockAdapter from 'axios-mock-adapter'; -import React, { ComponentType } from 'react'; -import collections from './collections.json'; - -export function createApp(Demo: ComponentType, options: ApplicationOptions, mocks: Record = {}) { - const Provider = () => { - return ( - - - - ); - }; - - const app = new Application({ - apiClient: { - baseURL: 'http://localhost:8000', - }, - providers: [Provider], - ...options, - }); - - const mock = new MockAdapter(app.apiClient.axios); - - Object.entries(mocks).forEach(([url, data]) => { - mock.onGet(url).reply(async (config) => { - const res = typeof data === 'function' ? data(config) : data; - return [200, res]; - }); - mock.onPost(url).reply(async (config) => { - const res = typeof data === 'function' ? data(config) : data; - return [200, res]; - }); - }); - - const Root = app.getRootComponent(); - return Root; -} diff --git a/packages/core/client/docs/zh-CN/core/block/demo1.tsx b/packages/core/client/docs/zh-CN/core/block/demo1.tsx deleted file mode 100644 index 23b370c7fd..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/demo1.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import React, { FC } from 'react'; -import { - SchemaComponent, - useDataBlockRequestV2, - useBlockSettingsV2, - withSchemaComponentProps, - UseDataBlockProps, -} from '@nocobase/client'; -import { createApp } from './createApp'; -import { Switch, Table, TableProps } from 'antd'; - -interface DemoTableRecordType { - name: string; -} -type DemoTableProps = TableProps; -const DemoTable: FC = withSchemaComponentProps((props) => { - const { dn } = useBlockSettingsV2(); - return ( - <> - { - dn.deepMerge({ - 'x-decorator-props': { - bordered: v, - }, - }); - }} - > -
- - ); -}); - -function useDemoTableProps(): DemoTableProps { - const { data, loading } = useDataBlockRequestV2<{ data: DemoTableRecordType[]; total: number }>(); - const { props, changeSchemaProps } = useBlockSettingsV2<{ - rowKey?: string; - params?: Record; - bordered?: boolean; - }>(); - const { rowKey, params, bordered } = props; - return { - columns: [ - { - title: 'ID', - dataIndex: 'id', - key: 'id', - }, - { - title: 'Name', - dataIndex: 'name', - key: 'name', - }, - { - title: 'Address', - dataIndex: 'address', - key: 'address', - }, - ], - loading, - dataSource: data?.data || [], - rowKey, - bordered, - pagination: { - pageSize: params.pageSize || 5, - current: params.page || 1, - total: data?.total, - onChange(page, pageSize) { - changeSchemaProps({ - params: { - pageSize, - page, - }, - }); - }, - }, - }; -} - -const collection = 'users'; -const action = 'list'; - -const useTableDataBlockDecoratorProps: UseDataBlockProps<'CollectionList'> = () => { - return { - params: { - address: 'New York', - }, - }; -}; - -const schema = { - type: 'void', - name: 'hello', - 'x-decorator': 'DataBlockProviderV2', - 'x-use-decorator-props': 'useTableDataBlockDecoratorProps', - 'x-component': 'DemoTable', - 'x-use-component-props': 'useDemoTableProps', - 'x-decorator-props': { - action: action, - collection: collection, - params: { - pageSize: 5, - page: 1, - }, - rowKey: 'id', - bordered: false, - }, -}; - -const Demo = () => { - return ; -}; - -const mocks = { - [`${collection}:${action}`]: function (config: any) { - console.log('请求结果'); - const { page = 1, pageSize, address } = config.params; - const fixedData = []; - for (let i = 0; i < pageSize; i += 1) { - fixedData.push({ - id: (page - 1) * pageSize + i + 1, - name: ['Light', 'Bamboo', 'Little'][i % 3], - address: `${address} No. ${i + 1} Lake Park`, - }); - } - return { - data: fixedData, - total: 200, - }; - }, -}; - -const Root = createApp( - Demo, - { components: { DemoTable }, scopes: { useDemoTableProps, useTableDataBlockDecoratorProps } }, - mocks, -); - -export default Root; diff --git a/packages/core/client/docs/zh-CN/core/block/demo3 copy.tsx b/packages/core/client/docs/zh-CN/core/block/demo3 copy.tsx deleted file mode 100644 index 85790d3f2b..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/demo3 copy.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import React, { FC } from 'react'; -import { - RecordV2, - RecordProviderV2, - SchemaComponent, - useDataBlockRequestV2, - useBlockSettingsV2, - withSchemaComponentProps, - useDesignable, -} from '@nocobase/client'; -import { createApp } from './createApp'; -import { Switch, Table, TableProps } from 'antd'; - -interface DemoTableRecordType { - name: string; -} -type DemoTableProps = TableProps; -const DemoTable: FC = withSchemaComponentProps((props) => { - const { dn } = useDesignable(); - return ( - <> - { - dn.deepMerge({ - 'x-decorator-props': { - bordered: v, - }, - }); - }} - > -
- - ); -}); - -function useDemoTableProps(): DemoTableProps { - const { data, loading } = useDataBlockRequestV2<{ data: DemoTableRecordType[]; total: number }>(); - const { rowKey, params, bordered } = useBlockSettingsV2<{ rowKey?: string; params?: Record }>(); - const { dn } = useDesignable(); - return { - columns: [ - { - title: 'ID', - dataIndex: 'id', - key: 'id', - }, - { - title: 'Name', - dataIndex: 'name', - key: 'name', - }, - { - title: 'Address', - dataIndex: 'address', - key: 'address', - }, - ], - loading, - dataSource: data?.data || [], - rowKey, - bordered, - pagination: { - pageSize: params.pageSize || 5, - current: params.page || 1, - total: data?.total, - onChange(page, pageSize) { - dn.deepMerge({ - 'x-decorator-props': { - params: { - pageSize, - page, - }, - }, - }); - }, - }, - }; -} - -const collection = 'users'; -const action = 'list'; -const associationA = 'a'; -const associationB = 'b'; -const association = `${associationA}.${associationB}`; - -const schema = { - type: 'void', - name: 'hello', - 'x-decorator': 'DataBlockProviderV2', - 'x-component': 'DemoTable', - 'x-use-component-props': 'useDemoTableProps', - 'x-decorator-props': { - action: action, - params: { - pageSize: 5, - page: 1, - }, - rowKey: 'id', - dragSort: false, - resource: collection, - showIndex: true, - collection: collection, - bordered: false, - association, - }, -}; - -const Demo = () => { - const record = new RecordV2({ current: { sourceId: 1 } }); - return ( - - - - ); -}; - -const mocks = { - [`${associationA}/1/${associationB}:${action}`]: function (config: any) { - console.log('请求结果'); - const { page = 1, pageSize } = config.params; - const fixedData = []; - for (let i = 0; i < pageSize; i += 1) { - fixedData.push({ - id: (page - 1) * pageSize + i + 1, - name: ['Light', 'Bamboo', 'Little'][i % 3], - address: `New York No. ${i + 1} Lake Park`, - }); - } - return { - data: fixedData, - total: 200, - }; - }, -}; - -const Root = createApp(Demo, { components: { DemoTable }, scopes: { useDemoTableProps } }, mocks); - -export default Root; diff --git a/packages/core/client/docs/zh-CN/core/block/index.md b/packages/core/client/docs/zh-CN/core/block/index.md deleted file mode 100644 index a96b4f7b36..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/index.md +++ /dev/null @@ -1,23 +0,0 @@ -# Block Provider - -## API - -- collection-list - - - -- collection-get - - - -- collection-create - - - -- collection-record - - - -## 综合示例 - - diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.column.decorator.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.column.decorator.tsx deleted file mode 100644 index ac23b121cd..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.column.decorator.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { useField, useFieldSchema } from '@formily/react'; -import { useCollection, useCollectionManager, useCompile, useSchemaToolbarRender } from '@nocobase/client'; -import React, { useLayoutEffect } from 'react'; -import { isCollectionFieldComponent } from './Table.useProps'; - -export const useColumnSchema = () => { - const { getField } = useCollection(); - const compile = useCompile(); - const columnSchema = useFieldSchema(); - const { getCollectionJoinField } = useCollectionManager(); - const fieldSchema = columnSchema.reduceProperties((buf, s) => { - if (isCollectionFieldComponent(s)) { - return s; - } - return buf; - }, null); - if (!fieldSchema) { - return {}; - } - - const collectionField = getField(fieldSchema.name) || getCollectionJoinField(fieldSchema?.['x-collection-field']); - return { columnSchema, fieldSchema, collectionField, uiSchema: compile(collectionField?.uiSchema) }; -}; - -export const TableColumnDecorator = () => { - const field = useField(); - const { fieldSchema, uiSchema } = useColumnSchema(); - const { render } = useSchemaToolbarRender(fieldSchema); - const compile = useCompile(); - useLayoutEffect(() => { - if (field.title) { - return; - } - if (!fieldSchema) { - return; - } - if (uiSchema?.title) { - field.title = uiSchema?.title; - } - }, [field, fieldSchema, uiSchema?.title]); - return ( - <> - {render()} -
{field?.title || compile(uiSchema?.title)}
- - ); -}; diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.column.initializer.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.column.initializer.tsx deleted file mode 100644 index b07e4a3829..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.column.initializer.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { Schema } from '@formily/json-schema'; -import { useFieldSchema, useForm } from '@formily/react'; -import { SchemaInitializer, SchemaInitializerItemType, useCollectionManager, useCollectionV2 } from '@nocobase/client'; - -const quickEditField = [ - 'attachment', - 'textarea', - 'markdown', - 'json', - 'richText', - 'polygon', - 'circle', - 'point', - 'lineString', -]; - -export const findTableColumn = (schema: Schema, key: string, action: string, deepth = 0) => { - return schema.reduceProperties((buf, s) => { - if (s[key] === action) { - return s; - } - const c = s.reduceProperties((buf, s) => { - if (s[key] === action) { - return s; - } - return buf; - }); - if (c) { - return c; - } - return buf; - }); -}; -export const removeTableColumn = (schema, cb) => { - cb(schema.parent); -}; -export const useTableColumnInitializerFields = () => { - const { name, fields = [] } = useCollectionV2(); - const { getInterface, getCollection } = useCollectionManager(); - const fieldSchema = useFieldSchema(); - const isSubTable = fieldSchema['x-component'] === 'AssociationField.SubTable'; - const form = useForm(); - const isReadPretty = isSubTable ? form.readPretty : true; - - return fields - .filter( - (field) => field?.interface && field?.interface !== 'subTable' && !field?.isForeignKey && !field?.treeChildren, - ) - .map((field) => { - const interfaceConfig = getInterface(field.interface); - const isFileCollection = field?.target && getCollection(field?.target)?.template === 'file'; - const schema = { - name: field.name, - 'x-collection-field': `${name}.${field.name}`, - 'x-component': 'CollectionField', - 'x-component-props': isFileCollection - ? { - fieldNames: { - label: 'preview', - value: 'id', - }, - } - : {}, - 'x-read-pretty': isReadPretty || field.uiSchema?.['x-read-pretty'], - 'x-decorator': isSubTable - ? quickEditField.includes(field.interface) || isFileCollection - ? 'QuickEdit' - : 'FormItem' - : null, - 'x-decorator-props': { - labelStyle: { - display: 'none', - }, - }, - }; - return { - type: 'item', - name: field.name, - title: field?.uiSchema?.title || field.name, - Component: 'TableCollectionFieldInitializer', - find: findTableColumn, - remove: removeTableColumn, - schemaInitialize: (s) => { - interfaceConfig?.schemaInitialize?.(s, { - field, - readPretty: isReadPretty, - block: 'Table', - targetCollection: getCollection(field.target), - }); - }, - field, - schema, - } as SchemaInitializerItemType; - }); -}; - -export const tableColumnInitializer = new SchemaInitializer({ - name: 'tableColumnInitializer', - insertPosition: 'beforeEnd', - icon: 'SettingOutlined', - title: 'Configure columns', - wrap: (s) => { - if (s['x-action-column']) { - return s; - } - return { - type: 'void', - 'x-decorator': 'TableColumnDecorator', - 'x-settings': 'tableColumnSettings', - 'x-component': 'TableColumn', - properties: { - [s.name]: { - ...s, - }, - }, - }; - }, - items: [ - { - name: 'displayFields', - type: 'itemGroup', - title: '{{t("Display fields")}}', - useChildren() { - const columns = useTableColumnInitializerFields(); - console.log('columns', columns); - return columns; - }, - }, - ], -}); diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.column.settings.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.column.settings.tsx deleted file mode 100644 index 6bb38e2e2c..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.column.settings.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { SchemaSettings } from '@nocobase/client'; - -export const tableColumnSettings = new SchemaSettings({ - name: 'tableColumnSettings', - items: [ - { - name: 'remove', - type: 'remove', - componentProps: { - removeParentsIfNoChildren: true, - breakRemoveOn: { - 'x-component': 'Grid', - }, - }, - }, - ], -}); diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.column.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.column.tsx deleted file mode 100644 index edb226751f..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.column.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { useField } from '@formily/react'; -import React from 'react'; - -export const TableColumn = () => { - const field = useField(); - return
{field.title}
; -}; diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.decoratorProps.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.decoratorProps.tsx deleted file mode 100644 index 515e8626fe..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.decoratorProps.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { useState } from 'react'; - -export const useTableDecoratorProps = ({ fieldNames }) => { - const [expandFlag, setExpandFlag] = useState(fieldNames ? true : false); - return { - expandFlag, - setExpandFlag, - }; -}; diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.plugin.ts b/packages/core/client/docs/zh-CN/core/block/table/Table.plugin.ts deleted file mode 100644 index 497fcda403..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.plugin.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Plugin } from '@nocobase/client'; - -import { tableSettings } from './Table.settings'; -import { TableToolbar } from './Table.toolbar'; -import { useTableProps } from './Table.useProps'; -import { useTableDecoratorProps } from './Table.decoratorProps'; -import { tableColumnInitializer } from './Table.column.initializer'; -import { NocoBaseTable } from './Table'; -import { tableColumnSettings } from './Table.column.settings'; -import { TableColumn } from './Table.column'; -import { TableColumnDecorator } from './Table.column.decorator'; - -export class TablePlugin extends Plugin { - async load() { - this.app.schemaSettingsManager.add(tableSettings, tableColumnSettings); - this.app.addComponents({ TableToolbar, NocoBaseTable, TableColumn, TableColumnDecorator }); - this.app.addScopes({ useTableProps, useTableDecoratorProps }); - this.app.schemaInitializerManager.add(tableColumnInitializer); - } -} diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.settings.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.settings.tsx deleted file mode 100644 index cb98d40fc5..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.settings.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { SchemaSettings, useBlockSettingsV2 } from '@nocobase/client'; - -export const tableSettings = new SchemaSettings({ - name: 'tableSettings', - items: [ - { - name: 'bordered', - type: 'switch', - useComponentProps() { - const { dn, props } = useBlockSettingsV2<{ bordered?: boolean }>(); - return { - title: 'Bordered', - checked: !!props.bordered, - onChange(v) { - dn.deepMerge({ - 'x-decorator-props': { - bordered: v, - }, - }); - }, - }; - }, - }, - { - name: 'remove', - type: 'remove', - componentProps: { - removeParentsIfNoChildren: true, - breakRemoveOn: { - 'x-component': 'Grid', - }, - }, - }, - ], -}); diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.toolbar.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.toolbar.tsx deleted file mode 100644 index de945e5722..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.toolbar.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; -import { SchemaToolbar, useCollectionV2 } from '@nocobase/client'; - -export const TableToolbar = () => { - const { name, title } = useCollectionV2(); - return ; -}; diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.tsx deleted file mode 100644 index acef10df4b..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { withSchemaComponentProps } from '@nocobase/client'; -import { Table } from 'antd'; - -export const NocoBaseTable = withSchemaComponentProps(Table); diff --git a/packages/core/client/docs/zh-CN/core/block/table/Table.useProps.tsx b/packages/core/client/docs/zh-CN/core/block/table/Table.useProps.tsx deleted file mode 100644 index 9bb98bbba9..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/Table.useProps.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import React from 'react'; -import { useDataBlockRequestV2, useBlockSettingsV2, useDesignable, useSchemaInitializerRender } from '@nocobase/client'; -import { ISchema, RecursionField, Schema, useFieldSchema } from '@formily/react'; -import { TableProps } from 'antd'; - -interface TableRequest { - data: any[]; - meta: { - count: number; - page: number; - pageSize: number; - totalPage: number; - }; -} - -export const isCollectionFieldComponent = (schema: ISchema) => { - return schema['x-component'] === 'CollectionField'; -}; - -export const isColumnComponent = (schema: Schema) => { - return schema['x-component']?.endsWith('.Column') > -1; -}; - -const useTableColumns = () => { - const schema = useFieldSchema(); - const { designable } = useDesignable(); - const { exists, render } = useSchemaInitializerRender(schema['x-initializer'], schema['x-initializer-props']); - const columns = schema - .reduceProperties((buf, s) => { - if (isColumnComponent(s)) { - return buf.concat([s]); - } - return buf; - }, []) - ?.map((s: Schema) => { - const collectionFields = s.reduceProperties((buf, s) => { - if (isCollectionFieldComponent(s)) { - return buf.concat([s]); - } - }, []); - const dataIndex = collectionFields?.length > 0 ? collectionFields[0].name : s.name; - return { - title: , - dataIndex, - key: s.name, - sorter: s['x-component-props']?.['sorter'], - width: 200, - ...s['x-component-props'], - render: (v, record) => { - return v; - }, - }; - }); - if (!exists) { - return columns; - } - - const tableColumns = columns.concat({ - title: render(), - dataIndex: 'TABLE_COLUMN_INITIALIZER', - key: 'TABLE_COLUMN_INITIALIZER', - render: designable ? () =>
: null, - }); - return tableColumns; -}; - -export function useTableProps(): TableProps { - const { data, loading } = useDataBlockRequestV2(); - const { props, dn } = useBlockSettingsV2<{ - rowKey?: string; - params?: Record; - bordered?: boolean; - }>(); - const { rowKey, params, bordered } = props; - const columns = useTableColumns(); - return { - columns, - loading, - dataSource: data?.data || [], - rowKey, - bordered, - pagination: { - pageSize: params.pageSize || 5, - current: params.page || 1, - total: data?.meta?.count, - onChange(page, pageSize) { - dn.deepMerge({ - 'x-decorator-props': { - params: { - pageSize, - page, - }, - }, - }); - }, - }, - components: { - body: { - row: ({ children, ...props }) => { - return {children}; - }, - }, - }, - }; -} diff --git a/packages/core/client/docs/zh-CN/core/block/table/index.tsx b/packages/core/client/docs/zh-CN/core/block/table/index.tsx deleted file mode 100644 index d596b0949d..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/index.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { - CardItem, - Application, - SchemaComponent, - DataBlockProviderV2, - TableCollectionFieldInitializer, - CollectionManagerProvider, -} from '@nocobase/client'; -import MockAdapter from 'axios-mock-adapter'; -import requestData from './requestData.json'; -import schema from './schema.json'; -import collections from '../collections.json'; - -import { TablePlugin } from './Table.plugin'; - -const Root = () => { - return ( - - - - ); -}; - -const app = new Application({ - apiClient: { - baseURL: 'http://localhost:8000/api', - }, - plugins: [TablePlugin], - providers: [Root], - components: { - CardItem, - DataBlockProviderV2, - TableCollectionFieldInitializer, - }, - designable: true, -}); - -const mock = new MockAdapter(app.apiClient.axios); -mock.onGet('users:list').reply(200, requestData); - -export default app.getRootComponent(); diff --git a/packages/core/client/docs/zh-CN/core/block/table/old-schema.json b/packages/core/client/docs/zh-CN/core/block/table/old-schema.json deleted file mode 100644 index 7f2091edde..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/old-schema.json +++ /dev/null @@ -1,264 +0,0 @@ -{ - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-decorator": "TableBlockProvider", - "x-acl-action": "users:list", - "x-decorator-props": { - "collection": "users", - "resource": "users", - "action": "list", - "params": { - "pageSize": 20 - }, - "rowKey": "id", - "showIndex": true, - "dragSort": false, - "disableTemplate": false - }, - "x-designer": "TableBlockDesigner", - "x-component": "CardItem", - "x-filter-targets": [], - "properties": { - "actions": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-initializer": "TableActionInitializers", - "x-component": "ActionBar", - "x-component-props": { - "style": { - "marginBottom": "var(--nb-spacing)" - } - }, - "properties": { - "a94r4fylw0f": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-action": "create", - "x-acl-action": "create", - "title": "{{t('Add new')}}", - "x-designer": "Action.Designer", - "x-component": "Action", - "x-decorator": "ACLActionProvider", - "x-component-props": { - "openMode": "drawer", - "type": "primary", - "component": "CreateRecordAction", - "icon": "PlusOutlined" - }, - "x-align": "right", - "x-acl-action-props": { - "skipScopeCheck": true - }, - "properties": { - "drawer": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "title": "{{ t(\"Add record\") }}", - "x-component": "Action.Container", - "x-component-props": { - "className": "nb-action-popup" - }, - "properties": { - "tabs": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-component": "Tabs", - "x-component-props": {}, - "x-initializer": "TabPaneInitializersForCreateFormBlock", - "properties": { - "tab1": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "title": "{{t(\"Add new\")}}", - "x-component": "Tabs.TabPane", - "x-designer": "Tabs.Designer", - "x-component-props": {}, - "properties": { - "grid": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-component": "Grid", - "x-initializer": "CreateFormBlockInitializers", - "x-uid": "rgh15rmpn51", - "x-async": false, - "x-index": 1 - } - }, - "x-uid": "xcmqqdez9up", - "x-async": false, - "x-index": 1 - } - }, - "x-uid": "b7zpfmevge2", - "x-async": false, - "x-index": 1 - } - }, - "x-uid": "dvp2ppiiol3", - "x-async": false, - "x-index": 1 - } - }, - "x-uid": "31ntpwf34wy", - "x-async": false, - "x-index": 2 - } - }, - "x-uid": "m58frw0kwnm", - "x-async": false, - "x-index": 1 - }, - "ve197icvkz4": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "array", - "x-initializer": "TableColumnInitializers", - "x-component": "TableV2", - "x-component-props": { - "rowKey": "id", - "rowSelection": { - "type": "checkbox" - }, - "useProps": "{{ useTableBlockProps }}" - }, - "properties": { - "actions": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "title": "{{ t(\"Actions\") }}", - "x-action-column": "actions", - "x-decorator": "TableV2.Column.ActionBar", - "x-component": "TableV2.Column", - "x-designer": "TableV2.ActionColumnDesigner", - "x-initializer": "TableActionColumnInitializers", - "properties": { - "actions": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-decorator": "DndContext", - "x-component": "Space", - "x-component-props": { - "split": "|" - }, - "x-uid": "yu3vl95pjxe", - "x-async": false, - "x-index": 1 - } - }, - "x-uid": "f174ti2ljhj", - "x-async": false, - "x-index": 1 - }, - "ptw1didvz8u": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-decorator": "TableV2.Column.Decorator", - "x-designer": "TableV2.Column.Designer", - "x-component": "TableV2.Column", - "properties": { - "id": { - "_isJSONSchemaObject": true, - "version": "2.0", - "x-collection-field": "users.id", - "x-component": "CollectionField", - "x-component-props": {}, - "x-read-pretty": true, - "x-decorator": null, - "x-decorator-props": { - "labelStyle": { - "display": "none" - } - }, - "x-uid": "btph12il4oe", - "x-async": false, - "x-index": 1 - } - }, - "x-uid": "gtkofwm9ge1", - "x-async": false, - "x-index": 2 - }, - "ayc1c6i8lo3": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-decorator": "TableV2.Column.Decorator", - "x-designer": "TableV2.Column.Designer", - "x-component": "TableV2.Column", - "properties": { - "nickname": { - "_isJSONSchemaObject": true, - "version": "2.0", - "x-collection-field": "users.nickname", - "x-component": "CollectionField", - "x-component-props": { - "ellipsis": true - }, - "x-read-pretty": true, - "x-decorator": null, - "x-decorator-props": { - "labelStyle": { - "display": "none" - } - }, - "x-uid": "nrc2to382kx", - "x-async": false, - "x-index": 1 - } - }, - "x-uid": "8ip9l7b0xfz", - "x-async": false, - "x-index": 3 - }, - "jg6znqow8ds": { - "_isJSONSchemaObject": true, - "version": "2.0", - "type": "void", - "x-decorator": "TableV2.Column.Decorator", - "x-designer": "TableV2.Column.Designer", - "x-component": "TableV2.Column", - "properties": { - "username": { - "_isJSONSchemaObject": true, - "version": "2.0", - "x-collection-field": "users.username", - "x-component": "CollectionField", - "x-component-props": { - "ellipsis": true - }, - "x-read-pretty": true, - "x-decorator": null, - "x-decorator-props": { - "labelStyle": { - "display": "none" - } - }, - "x-uid": "a4y8vhd49n2", - "x-async": false, - "x-index": 1 - } - }, - "x-uid": "yk1ydfk1gug", - "x-async": false, - "x-index": 4 - } - }, - "x-uid": "fmq2qd3uthy", - "x-async": false, - "x-index": 2 - } - }, - "x-uid": "mgsx7skkb50", - "x-async": false, - "x-index": 1 -} diff --git a/packages/core/client/docs/zh-CN/core/block/table/requestData.json b/packages/core/client/docs/zh-CN/core/block/table/requestData.json deleted file mode 100644 index 7ab3a61038..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/requestData.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "data": [ - { - "createdAt": "2023-12-04T09:42:52.953Z", - "updatedAt": "2023-12-04T09:42:52.953Z", - "appLang": null, - "createdById": null, - "email": "admin@nocobase.com", - "id": 1, - "nickname": "Super Admin", - "phone": null, - "systemSettings": {}, - "updatedById": null, - "username": "nocobase" - } - ], - "meta": { - "count": 1, - "page": 1, - "pageSize": 20, - "totalPage": 1, - "allowedActions": { - "view": [1], - "update": [1], - "destroy": [] - } - } -} diff --git a/packages/core/client/docs/zh-CN/core/block/table/schema.json b/packages/core/client/docs/zh-CN/core/block/table/schema.json deleted file mode 100644 index ff590acf43..0000000000 --- a/packages/core/client/docs/zh-CN/core/block/table/schema.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "type": "void", - "name": "root", - "x-decorator": "DataBlockProviderV2", - "x-use-decorator-props": "useTableDecoratorProps", - "x-decorator-props": { - "collection": "users", - "action": "list", - "params": { - "pageSize": 20 - }, - "rowKey": "id" - }, - "x-toolbar": "TableToolbar", - "x-settings": "tableSettings", - "x-component": "CardItem", - "properties": { - "ve197icvkz4": { - "type": "array", - "x-initializer": "tableColumnInitializer", - "x-component": "NocoBaseTable", - "x-use-component-props": "useTableProps", - "ptw1didvz8u": {} - } - } -} diff --git a/packages/core/client/docs/zh-CN/core/collection/demos/collections.json b/packages/core/client/docs/zh-CN/core/collection/demos/collections.json index fc0e05c3f9..4d3aa45f83 100644 --- a/packages/core/client/docs/zh-CN/core/collection/demos/collections.json +++ b/packages/core/client/docs/zh-CN/core/collection/demos/collections.json @@ -95,6 +95,35 @@ "parentKey": null, "reverseKey": null, "unique": true + }, + { + "key": "t09bauwm0wb", + "name": "roles", + "type": "belongsToMany", + "interface": "m2m", + "description": null, + "collectionName": "users", + "parentKey": null, + "reverseKey": null, + "target": "roles", + "foreignKey": "userId", + "otherKey": "roleName", + "onDelete": "CASCADE", + "sourceKey": "id", + "targetKey": "name", + "through": "rolesUsers", + "uiSchema": { + "type": "array", + "title": "{{t(\"Roles\")}}", + "x-component": "AssociationField", + "x-component-props": { + "multiple": true, + "fieldNames": { + "label": "title", + "value": "name" + } + } + } } ] }, diff --git a/packages/core/client/docs/zh-CN/core/data-block/data-block-provider.md b/packages/core/client/docs/zh-CN/core/data-block/data-block-provider.md index d205e5e724..41b1802e58 100644 --- a/packages/core/client/docs/zh-CN/core/data-block/data-block-provider.md +++ b/packages/core/client/docs/zh-CN/core/data-block/data-block-provider.md @@ -43,8 +43,9 @@ Table 中的字段信息及列表数据,都是存储在数据库中的。 ```tsx | pure const DataBlockProvider = (props) => { - return - / + return + + / {action !== 'list' && @@ -53,7 +54,8 @@ const DataBlockProvider = (props) => { / - + + } ``` @@ -71,6 +73,7 @@ const DataBlockProvider = (props) => { 'x-decorator': 'DataBlockProvider', 'x-decorator-props': { collection: 'users', + dataSource: 'main', action: 'list', tableProps: { bordered: true, @@ -82,7 +85,7 @@ const DataBlockProvider = (props) => { ### 完整示例 - + ## 属性 @@ -111,6 +114,7 @@ interface AllDataBlockProps { - collection(`x-decorator-props`):区块的 collection 表名,用于获取区块的字段信息和区块数据 - association(`x-decorator-props`):区块的关系字段名,用于获取区块的关系字段信息和关系字段数据 +- dataSource(`x-decorator-props`): 数据源,具体可参考 [Data Modeling](https://docs.nocobase.com/manual/data-modeling) - action(`x-decorator-props`):区块的请求类型,`list` 或 `get` - params(`x-decorator-props` 和 `x-use-decorator-props`):区块的请求参数,同时存在于 - filterByTk(`x-use-decorator-props`):相当于 `params.filterByTk`,可理解为 `id`,用于获取单条数据 @@ -120,16 +124,18 @@ interface AllDataBlockProps { ```tsx | pure const DataBlockProvider = (props) => { - return - / - - - {action !== 'list' && - {props.children} - } - - - + return + + / + + + {action !== 'list' && + {props.children} + } + + + + } ``` @@ -212,18 +218,29 @@ const checked = props.tableProps.bordered; -#### Form get +#### Form get & update + + #### Form create -#### Form record + + +#### Form record & update + + ### association -#### Table list +association 与 collection 类似,只是需要提供 `sourceId`,我们以 `Table list` 为例。 -#### Form get +#### Table list & sourceId -#### Form create + + +#### Table list & parentRecord + +如果不提供 `sourceId`,则需要提供 `parentRecord`,我们以 `Table list` 为例。 + + -#### Form record diff --git a/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/association-table-list-and-parent-record.tsx b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/association-table-list-and-parent-record.tsx new file mode 100644 index 0000000000..447ab29fbb --- /dev/null +++ b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/association-table-list-and-parent-record.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { Select, Table, TableProps } from 'antd'; +import { SchemaComponent, UseDataBlockProps, useDataBlockRequestV2, withDynamicSchemaProps } from '@nocobase/client'; +import { ISchema } from '@formily/json-schema'; + +import { createApp } from '../../../collection/demos/createApp'; +import useUrlState from '@ahooksjs/use-url-state'; + +const collection = 'users'; +const associationField = 'roles'; + +const association = `${collection}.${associationField}`; +const action = 'list'; + +const schema: ISchema = { + type: 'void', + name: 'root', + 'x-decorator': 'DataBlockProviderV2', + 'x-use-decorator-props': 'useBlockDecoratorProps', + 'x-decorator-props': { + association, + action, + }, + 'x-component': 'CardItem', + properties: { + demo: { + type: 'array', + 'x-component': 'MyTable', + 'x-use-component-props': 'useTableProps', + }, + }, +}; + +const MyTable = withDynamicSchemaProps(Table); + +function useTableProps(): TableProps { + const { data, loading } = useDataBlockRequestV2(); + return { + loading, + dataSource: data?.data || [], + columns: [ + { + title: 'Name', + dataIndex: 'name', + }, + { + title: 'Title', + dataIndex: 'title', + }, + { + title: 'Description', + dataIndex: 'description', + }, + ], + }; +} + +const useBlockDecoratorProps: UseDataBlockProps<'CollectionList'> = () => { + const parentRecord = { + id: 1, + username: 'Tom', + }; + return { + parentRecord, + }; +}; + +const Demo = () => { + return ; +}; + +const mocks = { + [`${collection}/1/${associationField}:${action}`]: { + data: [ + { + name: 'admin', + title: 'Admin', + description: 'Admin description', + }, + { + name: 'developer', + title: 'Developer', + description: 'Developer description', + }, + ], + }, +}; + +const Root = createApp( + Demo, + { + components: { MyTable }, + scopes: { useTableProps, useBlockDecoratorProps }, + }, + mocks, +); + +export default Root; diff --git a/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/association-table-list-and-source-id.tsx b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/association-table-list-and-source-id.tsx new file mode 100644 index 0000000000..87f46f7af2 --- /dev/null +++ b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/association-table-list-and-source-id.tsx @@ -0,0 +1,132 @@ +import React from 'react'; +import { Select, Table, TableProps } from 'antd'; +import { SchemaComponent, UseDataBlockProps, useDataBlockRequestV2, withDynamicSchemaProps } from '@nocobase/client'; +import { ISchema } from '@formily/json-schema'; + +import { createApp } from '../../../collection/demos/createApp'; +import useUrlState from '@ahooksjs/use-url-state'; + +const collection = 'users'; +const associationField = 'roles'; + +const association = `${collection}.${associationField}`; +const action = 'list'; + +const schema: ISchema = { + type: 'void', + name: 'root', + 'x-decorator': 'DataBlockProviderV2', + 'x-use-decorator-props': 'useBlockDecoratorProps', + 'x-decorator-props': { + association, + action, + }, + 'x-component': 'CardItem', + properties: { + demo: { + type: 'array', + 'x-component': 'MyTable', + 'x-use-component-props': 'useTableProps', + }, + }, +}; + +const MyTable = withDynamicSchemaProps(Table); + +function useTableProps(): TableProps { + const { data, loading } = useDataBlockRequestV2(); + return { + loading, + dataSource: data?.data || [], + columns: [ + { + title: 'Name', + dataIndex: 'name', + }, + { + title: 'Title', + dataIndex: 'title', + }, + { + title: 'Description', + dataIndex: 'description', + }, + ], + }; +} + +const useBlockDecoratorProps: UseDataBlockProps<'CollectionList'> = () => { + const [state] = useUrlState({ userId: '1' }); + return { + sourceId: state.userId, + }; +}; + +const Demo = () => { + const [state, setState] = useUrlState({ userId: '1' }); + return ( + <> + + + + ); +}; + +const mocks = { + [`${collection}/1/${associationField}:${action}`]: { + data: [ + { + name: 'admin', + title: 'Admin', + description: 'Admin description', + }, + { + name: 'developer', + title: 'Developer', + description: 'Developer description', + }, + ], + }, + [`${collection}/2/${associationField}:${action}`]: { + data: [ + { + name: 'developer', + title: 'Developer', + description: 'Developer description', + }, + { + name: 'tester', + title: 'Tester', + description: 'Tester description', + }, + ], + }, + [`${collection}:get/1`]: { + id: 1, + username: 'Tom', + }, + [`${collection}:get/2`]: { + id: 1, + username: 'Jack', + }, +}; + +const Root = createApp( + Demo, + { + components: { MyTable }, + scopes: { useTableProps, useBlockDecoratorProps }, + }, + mocks, +); + +export default Root; diff --git a/packages/core/client/docs/zh-CN/core/block/demo3.tsx b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-create.tsx similarity index 58% rename from packages/core/client/docs/zh-CN/core/block/demo3.tsx rename to packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-create.tsx index beeba57b70..7f9bb3de1d 100644 --- a/packages/core/client/docs/zh-CN/core/block/demo3.tsx +++ b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-create.tsx @@ -1,8 +1,9 @@ import React, { FC } from 'react'; -import { SchemaComponent, useDataBlockResourceV2, withSchemaComponentProps } from '@nocobase/client'; -import { createApp } from './createApp'; -import { Button, Form, Input, InputNumber } from 'antd'; -import { FormProps } from 'antd/lib'; +import { Button, Form, FormProps, Input, InputNumber, notification } from 'antd'; +import { SchemaComponent, useDataBlockResourceV2, withDynamicSchemaProps } from '@nocobase/client'; +import { ISchema } from '@formily/json-schema'; + +import { createApp } from '../../../collection/demos/createApp'; interface DemoFormFieldType { id: number; @@ -10,7 +11,7 @@ interface DemoFormFieldType { age: number; } type DemoFormProps = FormProps; -const DemoForm: FC = withSchemaComponentProps((props) => { +const DemoForm: FC = withDynamicSchemaProps((props) => { return (
@@ -38,24 +39,38 @@ const DemoForm: FC = withSchemaComponentProps((props) => { function useDemoFormProps(): DemoFormProps { const resource = useDataBlockResourceV2(); + const onFinish = async (values: DemoFormFieldType) => { + console.log('values', values); + await resource.create({ + values, + }); + notification.success({ + message: 'Save successfully!', + }); + }; + return { - onFinish: (values) => { - resource.create({ values }); - }, + onFinish, }; } const collection = 'users'; -const schema = { +const schema: ISchema = { type: 'void', - name: 'hello', + name: 'root', 'x-decorator': 'DataBlockProviderV2', - 'x-component': 'DemoForm', - 'x-use-component-props': 'useDemoFormProps', 'x-decorator-props': { collection: collection, }, + 'x-component': 'CardItem', + properties: { + demo: { + type: 'object', + 'x-component': 'DemoForm', + 'x-use-component-props': 'useDemoFormProps', + }, + }, }; const Demo = () => { @@ -64,11 +79,17 @@ const Demo = () => { const mocks = { [`${collection}:create`]: (config) => { - console.log('请求结果', config.data); + console.log('config.data', config.data); return [200, { msg: 'ok' }]; }, }; - -const Root = createApp(Demo, { components: { DemoForm }, scopes: { useDemoFormProps } }, mocks); +const Root = createApp( + Demo, + { + components: { DemoForm }, + scopes: { useDemoFormProps }, + }, + mocks, +); export default Root; diff --git a/packages/core/client/docs/zh-CN/core/block/demo2.tsx b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-get-and-update.tsx similarity index 55% rename from packages/core/client/docs/zh-CN/core/block/demo2.tsx rename to packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-get-and-update.tsx index c33fb3d719..034c32e365 100644 --- a/packages/core/client/docs/zh-CN/core/block/demo2.tsx +++ b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-get-and-update.tsx @@ -1,15 +1,16 @@ -import React, { FC, useEffect, useState } from 'react'; +import React, { FC, useEffect } from 'react'; +import { Button, Form, FormProps, Input, InputNumber, Select, notification } from 'antd'; import { - RecordProviderV2, SchemaComponent, - useDataBlockRequestV2, - withSchemaComponentProps, UseDataBlockProps, + useDataBlockResourceV2, useRecordDataV2, + withDynamicSchemaProps, } from '@nocobase/client'; -import { createApp } from './createApp'; -import { Button, Form, Input, InputNumber, Select } from 'antd'; -import { FormProps } from 'antd/lib'; +import { ISchema } from '@formily/json-schema'; +import useUrlState from '@ahooksjs/use-url-state'; + +import { createApp } from '../../../collection/demos/createApp'; interface DemoFormFieldType { id: number; @@ -17,7 +18,7 @@ interface DemoFormFieldType { age: number; } type DemoFormProps = FormProps; -const DemoForm: FC = withSchemaComponentProps((props) => { +const DemoForm: FC = withDynamicSchemaProps((props) => { return ( @@ -45,56 +46,78 @@ const DemoForm: FC = withSchemaComponentProps((props) => { function useDemoFormProps(): DemoFormProps { const data = useRecordDataV2(); + const resource = useDataBlockResourceV2(); + const [form] = Form.useForm(); + useEffect(() => { form.setFieldsValue(data); }, [data, form]); + + const onFinish = async (values: DemoFormFieldType) => { + console.log('values', values); + await resource.update({ + filterByTk: data.id, + values, + }); + notification.success({ + message: 'Save successfully!', + }); + }; + return { initialValues: data, preserve: true, + onFinish, form, }; } - -const useFormBlockDecoratorProps: UseDataBlockProps<'CollectionGet'> = () => { - const { filterByTk } = useRecordDataV2<{ filterByTk: number }>(); +const useBlockDecoratorProps: UseDataBlockProps<'CollectionGet'> = () => { + const [state] = useUrlState({ id: '1' }); return { - filterByTk, + filterByTk: state.id, }; }; const collection = 'users'; const action = 'get'; -const schema = { +const schema: ISchema = { type: 'void', - name: 'hello', + name: 'root', 'x-decorator': 'DataBlockProviderV2', - 'x-use-decorator-props': 'useFormBlockDecoratorProps', - 'x-component': 'DemoForm', - 'x-use-component-props': 'useDemoFormProps', + 'x-use-decorator-props': 'useBlockDecoratorProps', 'x-decorator-props': { collection: collection, action: action, }, + 'x-component': 'CardItem', + properties: { + demo: { + type: 'object', + 'x-component': 'DemoForm', + 'x-use-component-props': 'useDemoFormProps', + }, + }, }; const Demo = () => { - const [id, setId] = useState(1); + const [state, setState] = useUrlState({ id: '1' }); + return ( - + <> - + ); }; @@ -103,7 +126,7 @@ const mocks = { const { filterByTk } = config.params; return { data: - filterByTk === 1 + Number(filterByTk) === 1 ? { id: 1, username: 'Bamboo', @@ -116,11 +139,19 @@ const mocks = { }, }; }, + [`${collection}:update`]: function (config) { + console.log('config.data', config.data); + return { + data: 'ok', + }; + }, }; - const Root = createApp( Demo, - { components: { DemoForm }, scopes: { useDemoFormProps, useFormBlockDecoratorProps } }, + { + components: { DemoForm }, + scopes: { useDemoFormProps, useBlockDecoratorProps }, + }, mocks, ); diff --git a/packages/core/client/docs/zh-CN/core/block/demo4.tsx b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-record-and-update.tsx similarity index 52% rename from packages/core/client/docs/zh-CN/core/block/demo4.tsx rename to packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-record-and-update.tsx index 9a21638b27..40696d1b21 100644 --- a/packages/core/client/docs/zh-CN/core/block/demo4.tsx +++ b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/collection-form-record-and-update.tsx @@ -1,15 +1,16 @@ +import React, { FC, useEffect } from 'react'; +import { Button, Form, FormProps, Input, InputNumber, notification } from 'antd'; import { RecordProviderV2, SchemaComponent, UseDataBlockProps, + useDataBlockResourceV2, useRecordDataV2, - useRecordV2, - withSchemaComponentProps, + withDynamicSchemaProps, } from '@nocobase/client'; -import { Button, Form, Input, InputNumber } from 'antd'; -import { FormProps } from 'antd/lib'; -import React, { FC, useEffect } from 'react'; -import { createApp } from './createApp'; +import { ISchema } from '@formily/json-schema'; + +import { createApp } from '../../../collection/demos/createApp'; interface DemoFormFieldType { id: number; @@ -17,7 +18,7 @@ interface DemoFormFieldType { age: number; } type DemoFormProps = FormProps; -const DemoForm: FC = withSchemaComponentProps((props) => { +const DemoForm: FC = withDynamicSchemaProps((props) => { return ( @@ -45,51 +46,92 @@ const DemoForm: FC = withSchemaComponentProps((props) => { function useDemoFormProps(): DemoFormProps { const data = useRecordDataV2(); + const resource = useDataBlockResourceV2(); + const [form] = Form.useForm(); + useEffect(() => { form.setFieldsValue(data); }, [data, form]); + + const onFinish = async (values: DemoFormFieldType) => { + console.log('values', values); + await resource.update({ + filterByTk: data.id, + values, + }); + notification.success({ + message: 'Save successfully!', + }); + }; + return { + initialValues: data, preserve: true, + onFinish, form, }; } - const useFormBlockDecoratorProps: UseDataBlockProps<'CollectionRecord'> = () => { - const record = useRecordV2(); + const record = useRecordDataV2(); return { record, }; }; const collection = 'users'; +const action = 'get'; -const schema = { +const schema: ISchema = { type: 'void', - name: 'hello', + name: 'root', 'x-decorator': 'DataBlockProviderV2', 'x-use-decorator-props': 'useFormBlockDecoratorProps', - 'x-component': 'DemoForm', - 'x-use-component-props': 'useDemoFormProps', 'x-decorator-props': { collection: collection, + action: action, }, + 'x-component': 'CardItem', + properties: { + demo: { + type: 'object', + 'x-component': 'DemoForm', + 'x-use-component-props': 'useDemoFormProps', + }, + }, +}; + +const recordData = { + id: 1, + username: 'Bamboo', + age: 18, }; const Demo = () => { return ( - - - + <> + + + + ); }; -const Root = createApp(Demo, { components: { DemoForm }, scopes: { useDemoFormProps, useFormBlockDecoratorProps } }); +const mocks = { + [`${collection}:update`]: function (config) { + console.log('config.data', config.data); + return { + data: 'ok', + }; + }, +}; +const Root = createApp( + Demo, + { + components: { DemoForm }, + scopes: { useDemoFormProps, useFormBlockDecoratorProps }, + }, + mocks, +); export default Root; diff --git a/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/demo1.tsx b/packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/complete-demo.tsx similarity index 100% rename from packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/demo1.tsx rename to packages/core/client/docs/zh-CN/core/data-block/demos/data-block-provider/complete-demo.tsx diff --git a/packages/core/client/src/application/collection/Collection.tsx b/packages/core/client/src/application/collection/Collection.tsx index fce3772f44..0a2af9e2cd 100644 --- a/packages/core/client/src/application/collection/Collection.tsx +++ b/packages/core/client/src/application/collection/Collection.tsx @@ -221,7 +221,9 @@ export class CollectionV2 { } getField(name: SchemaKey) { const fieldsMap = this.getFieldsMap(); - + if (typeof name === 'string' && name.startsWith(`${this.name}.`)) { + name = name.replace(`${this.name}.`, ''); + } if (String(name).split('.').length > 1) { const [fieldName, ...others] = String(name).split('.'); const field = fieldsMap[fieldName]; diff --git a/packages/core/client/src/application/collection/RecordProvider.tsx b/packages/core/client/src/application/collection/RecordProvider.tsx index ab25994d79..2b19410140 100644 --- a/packages/core/client/src/application/collection/RecordProvider.tsx +++ b/packages/core/client/src/application/collection/RecordProvider.tsx @@ -61,7 +61,7 @@ export function useRecordV2( return context; } -export function useRecordDataV2(showErrorWhenNotExists = true): DataType { +export function useRecordDataV2(showErrorWhenNotExists = true): DataType { const record = useRecordV2(showErrorWhenNotExists); return record.data; } diff --git a/packages/core/client/src/application/data-block/DataBlockProvider.tsx b/packages/core/client/src/application/data-block/DataBlockProvider.tsx index 01560523ab..f2c3b80eca 100644 --- a/packages/core/client/src/application/data-block/DataBlockProvider.tsx +++ b/packages/core/client/src/application/data-block/DataBlockProvider.tsx @@ -12,7 +12,7 @@ export interface AllDataBlockProps { collection: string; association: string; dataSource?: string; - sourceId: string | number; + sourceId?: string | number; filterByTk: string | number; record: RecordV2; action?: 'list' | 'get'; diff --git a/packages/core/client/src/application/data-block/DataBlockRequestProvider.tsx b/packages/core/client/src/application/data-block/DataBlockRequestProvider.tsx index 443c087452..0e676345b5 100644 --- a/packages/core/client/src/application/data-block/DataBlockRequestProvider.tsx +++ b/packages/core/client/src/application/data-block/DataBlockRequestProvider.tsx @@ -1,5 +1,5 @@ import { useDeepCompareEffect } from 'ahooks'; -import React, { FC, createContext, useContext } from 'react'; +import React, { FC, createContext, useContext, useEffect } from 'react'; import { UseRequestResult, useAPIClient, useRequest } from '../../api-client'; import { useDataBlockResourceV2 } from './DataBlockResourceProvider'; @@ -35,25 +35,33 @@ function useCurrentRequest(options: Omit) { // 因为修改 Schema 会导致 params 对象发生变化,所以这里使用 `DeepCompare` useDeepCompareEffect(() => { - request.run(); + if (action) { + request.run(); + } }, [params, action, record]); + useEffect(() => { + if (action) { + request.run(); + } + }, [resource]); + return request; } function useParentRequest(options: Omit) { const { sourceId, association, parentRecord } = options; const api = useAPIClient(); - return useRequest( - () => { + async () => { if (parentRecord) return Promise.resolve({ data: parentRecord }); if (!association) return Promise.resolve({ data: undefined }); // "association": "Collection.Field" const arr = association.split('.'); // :get/ const url = `${arr[0]}:get/${sourceId}`; - return api.request({ url }).then((res) => res.data); + const res = await api.request({ url }); + return res.data; }, { refreshDeps: [association, parentRecord, sourceId], diff --git a/packages/core/client/src/application/data-block/DataBlockResourceProvider.tsx b/packages/core/client/src/application/data-block/DataBlockResourceProvider.tsx index 22a907fbea..e3d1b45e0e 100644 --- a/packages/core/client/src/application/data-block/DataBlockResourceProvider.tsx +++ b/packages/core/client/src/application/data-block/DataBlockResourceProvider.tsx @@ -3,7 +3,7 @@ import { IResource } from '@nocobase/sdk'; import { useAPIClient } from '../../api-client'; import { useDataBlockPropsV2 } from './DataBlockProvider'; -import { DEFAULT_DATA_SOURCE_NAME, useCollectionManagerV2 } from '../collection'; +import { DEFAULT_DATA_SOURCE_NAME, RecordV2, useCollectionManagerV2 } from '../collection'; export const DataBlockResourceContextV2 = createContext(null); DataBlockResourceContextV2.displayName = 'DataBlockResourceContextV2'; @@ -26,7 +26,8 @@ export const DataBlockResourceProviderV2: FC<{ children?: ReactNode }> = ({ chil if (association && parentRecord) { const associationCollection = cm.getCollection(association); if (associationCollection) { - return parentRecord.data[associationCollection.sourceKey || 'id']; + const parentRecordData = parentRecord instanceof RecordV2 ? parentRecord.data : parentRecord; + return parentRecordData[associationCollection.sourceKey || 'id']; } } }, [sourceId, parentRecord]);