fix: client docs (#2965)
* fix: application bug * fix: test error * feat: client doc * fix: delete it.only * fix: demos * fix: ci * fix: create index.md --------- Co-authored-by: dream2023 <1098626505@qq.com>
This commit is contained in:
parent
bafb03a228
commit
05040a1c5f
23
.github/workflows/deploy-client-docs.yml
vendored
Normal file
23
.github/workflows/deploy-client-docs.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
name: deploy client docs
|
||||||
|
on: [push]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "18"
|
||||||
|
- run: yarn install
|
||||||
|
- name: Build
|
||||||
|
run: yarn doc build core/client
|
||||||
|
- name: copy files via ssh
|
||||||
|
uses: appleboy/scp-action@v0.1.4
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.CN_CLIENT_HOST }}
|
||||||
|
username: ${{ secrets.CN_CLIENT_USERNAME }}
|
||||||
|
key: ${{ secrets.CN_CLIENT_KEY }}
|
||||||
|
port: ${{ secrets.CN_CLIENT_PORT }}
|
||||||
|
source: "packages/core/client/dist/*"
|
||||||
|
target: ${{ secrets.CN_CLIENT_TARGET }}/${{ github.ref_name }}
|
@ -1,18 +1,6 @@
|
|||||||
import { defineConfig } from 'dumi';
|
|
||||||
import { defineThemeConfig } from 'dumi-theme-nocobase'
|
|
||||||
import { getUmiConfig } from '@nocobase/devtools/umiConfig';
|
import { getUmiConfig } from '@nocobase/devtools/umiConfig';
|
||||||
import fs from 'fs';
|
import { defineConfig } from 'dumi';
|
||||||
import path from 'path';
|
import { defineThemeConfig } from 'dumi-theme-nocobase';
|
||||||
|
|
||||||
const contributingPath = path.resolve(__dirname, './contributing.md');
|
|
||||||
const docsContributingPath = path.resolve(__dirname, './docs/contributing.md');
|
|
||||||
|
|
||||||
// check if the target path already exists, and remove it if it does
|
|
||||||
if (fs.existsSync(docsContributingPath)) {
|
|
||||||
fs.unlinkSync(docsContributingPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.copyFileSync(contributingPath, docsContributingPath);
|
|
||||||
|
|
||||||
const umiConfig = getUmiConfig();
|
const umiConfig = getUmiConfig();
|
||||||
|
|
||||||
@ -23,34 +11,106 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
atomDirs: [
|
atomDirs: [
|
||||||
{ type: 'component', dir: 'src' },
|
{ type: 'api', dir: 'src' },
|
||||||
{ type: 'component', dir: 'src/schema-component/antd' },
|
{ type: 'api', dir: 'src/schema-component/antd' },
|
||||||
{ type: 'component', dir: 'src/route-switch/antd' },
|
{ type: 'api', dir: 'src/route-switch/antd' },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
themeConfig: defineThemeConfig({
|
themeConfig: defineThemeConfig({
|
||||||
title: 'NocoBase',
|
title: 'NocoBase',
|
||||||
logo: 'https://www.nocobase.com/images/logo.png',
|
logo: 'https://www.nocobase.com/images/logo.png',
|
||||||
github: 'https://github.com/nocobase/nocobase',
|
github: 'https://github.com/nocobase/nocobase',
|
||||||
footer: 'nocobase | Copyright © 2022',
|
footer: 'nocobase | Copyright © 2022',
|
||||||
sidebarGroupModePath: ['/components'],
|
// sidebarGroupModePath: ['/components'],
|
||||||
nav: [
|
nav: [
|
||||||
{
|
{
|
||||||
title: 'Intro',
|
title: 'API',
|
||||||
link: '/intro',
|
link: '/apis/application',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
sidebarEnhance: {
|
||||||
|
'/apis': [
|
||||||
|
{
|
||||||
|
title: 'Core',
|
||||||
|
type: 'group',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Application',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Application',
|
||||||
|
link: '/apis/application',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Client',
|
title: 'APIClient',
|
||||||
link: '/components/acl',
|
link: '/apis/api-client',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Develop',
|
title: 'SettingsCenter',
|
||||||
link: '/develop',
|
link: '#',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Contributing',
|
title: 'UI schema designer',
|
||||||
link: '/contributing',
|
children: [
|
||||||
}
|
{
|
||||||
]
|
title: 'SchemaComponent',
|
||||||
})
|
link: '#',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'SchemaInitializer',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'SchemaSettings',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'DNDContext & DragHandler',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Collection Manager',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'BlockProvider',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'RecordProvider',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'React components',
|
||||||
|
type: 'group',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Board',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Icon',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Schema components',
|
||||||
|
type: 'group',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: 'Input',
|
||||||
|
link: '#',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
---
|
|
||||||
toc: menu
|
|
||||||
---
|
|
||||||
|
|
||||||
# 参与贡献
|
|
||||||
|
|
||||||
客户端的模块都在 `src` 目录下,各自模块独立。
|
|
||||||
|
|
||||||
## 客户端模块
|
|
||||||
|
|
||||||
最小单元模块化,一个完整的模块包含:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
|- /__tests__/ # 测试文件目录
|
|
||||||
|- /demos/ # demo 目录
|
|
||||||
|- index.ts # 最好不要直接在 index.ts 文件里写代码,index 文件只负责 export
|
|
||||||
|- index.md # 文档,默认为英文
|
|
||||||
|- index.zh-CN.md # 中文文档,可缺失,可以先都写到 index.md 里
|
|
||||||
```
|
|
||||||
|
|
||||||
## 测试
|
|
||||||
|
|
||||||
详细文档见 [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/)
|
|
||||||
|
|
||||||
```tsx | pure
|
|
||||||
import React from 'react';
|
|
||||||
import { render } from '@testing-library/react';
|
|
||||||
import { compose } from '../';
|
|
||||||
|
|
||||||
describe('compose', () => {
|
|
||||||
it('case 1', () => {
|
|
||||||
const A: React.FC = (props) => (
|
|
||||||
<div>
|
|
||||||
<h1>A</h1>
|
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
const App = compose(A)();
|
|
||||||
const { container } = render(<App />);
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Demo
|
|
||||||
|
|
||||||
组件 Demo 见 [dumi](https://d.umijs.org/guide/basic#write-component-demo),可以直接写在文档里,如:
|
|
||||||
|
|
||||||
<pre lang="markdown">
|
|
||||||
```jsx
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default () => <h1>Hello NocoBase!</h1>;
|
|
||||||
```
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
也可以引用 demo 文件
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
<code src="./demos/dmeo1.tsx"></code>
|
|
||||||
```
|
|
1
packages/core/client/docs/index.md
Normal file
1
packages/core/client/docs/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
<Navigate replace to="/apis/application"></Navigate>
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Client
|
|
||||||
order: 1
|
|
||||||
---
|
|
||||||
|
|
||||||
# ACL
|
|
||||||
|
|
||||||
访问控制列表,plugin-acl 的前端模块,详细文档待补充。
|
|
@ -1,25 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Table } from 'antd';
|
|
||||||
import { i18n, compose, APIClient, APIClientProvider, AntdConfigProvider } from '@nocobase/client';
|
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
|
||||||
import { I18nextProvider } from 'react-i18next';
|
|
||||||
|
|
||||||
const apiClient = new APIClient({
|
|
||||||
baseURL: `${location.protocol}//${location.host}/api/`,
|
|
||||||
});
|
|
||||||
|
|
||||||
const mock = new MockAdapter(apiClient.axios);
|
|
||||||
|
|
||||||
mock.onGet('/app:getLang').reply(200, {
|
|
||||||
data: { lang: 'zh-CN' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const providers = [
|
|
||||||
[APIClientProvider, { apiClient }],
|
|
||||||
[I18nextProvider, { i18n }],
|
|
||||||
[AntdConfigProvider, { remoteLocale: true }],
|
|
||||||
];
|
|
||||||
|
|
||||||
export default compose(...providers)(() => {
|
|
||||||
return <Table />;
|
|
||||||
});
|
|
@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Client
|
|
||||||
order: 1
|
|
||||||
---
|
|
||||||
|
|
||||||
# AntdConfigProvider
|
|
||||||
|
|
||||||
为 antd 组件提供统一的全局化配置
|
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"></code>
|
|
1
packages/core/client/src/appInfo/index.md
Normal file
1
packages/core/client/src/appInfo/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# AppInfo
|
@ -1,7 +1,6 @@
|
|||||||
|
import { Application, Plugin } from '@nocobase/client';
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { Link, Outlet, useLocation } from 'react-router-dom';
|
import { Link, Outlet, useLocation } from 'react-router-dom';
|
||||||
import { Application } from '../Application';
|
|
||||||
import { Plugin } from '../Plugin';
|
|
||||||
|
|
||||||
const Root = () => {
|
const Root = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
|
import { Application, Plugin, RouterManager, useApp } from '@nocobase/client';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Link, Navigate, Outlet, useParams } from 'react-router-dom';
|
import { Link, Navigate, Outlet, useParams } from 'react-router-dom';
|
||||||
import { Application } from '../Application';
|
|
||||||
import { useApp } from '../hooks';
|
|
||||||
import { Plugin } from '../Plugin';
|
|
||||||
import { RouterManager } from '../RouterManager';
|
|
||||||
|
|
||||||
const Root = () => {
|
const Root = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
group:
|
group:
|
||||||
title: Client
|
title: core
|
||||||
order: 1
|
order: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
import React, { createContext, useContext } from 'react';
|
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
|
||||||
import { APIClient, APIClientProvider, compose, AsyncDataProvider, useAsyncData } from '@nocobase/client';
|
|
||||||
|
|
||||||
const apiClient = new APIClient();
|
|
||||||
|
|
||||||
const mock = new MockAdapter(apiClient.axios);
|
|
||||||
|
|
||||||
mock.onGet('/users/1').reply(200, {
|
|
||||||
data: { id: 1, name: 'John Smith' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const providers = [
|
|
||||||
[APIClientProvider, { apiClient }],
|
|
||||||
[AsyncDataProvider, { request: { url: '/users/1' } }],
|
|
||||||
];
|
|
||||||
|
|
||||||
export default compose(...providers)(() => {
|
|
||||||
const { data } = useAsyncData();
|
|
||||||
console.log(data);
|
|
||||||
return <div>{data?.data?.name}</div>;
|
|
||||||
});
|
|
@ -1,51 +0,0 @@
|
|||||||
import { APIClient, APIClientProvider, SchemaComponent, SchemaComponentProvider, useRequest } from '@nocobase/client';
|
|
||||||
import { Table } from 'antd';
|
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const apiClient = new APIClient();
|
|
||||||
|
|
||||||
const mock = new MockAdapter(apiClient.axios);
|
|
||||||
|
|
||||||
mock.onGet('/users').reply(200, {
|
|
||||||
data: [
|
|
||||||
{ id: 1, name: 'John Smith' },
|
|
||||||
{ id: 2, name: 'Mike' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const TableView = (props) => {
|
|
||||||
const { request, ...others } = props;
|
|
||||||
const callback = () => props.dataSource || [];
|
|
||||||
const { data, loading } = useRequest<{
|
|
||||||
data: any;
|
|
||||||
}>(props.request || callback);
|
|
||||||
return <Table {...others} dataSource={data?.data} loading={loading} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<APIClientProvider apiClient={apiClient}>
|
|
||||||
<SchemaComponentProvider components={{ TableView }}>
|
|
||||||
<SchemaComponent
|
|
||||||
schema={{
|
|
||||||
type: 'void',
|
|
||||||
name: 'tableView',
|
|
||||||
'x-component': 'TableView',
|
|
||||||
'x-component-props': {
|
|
||||||
request: { url: '/users' },
|
|
||||||
rowKey: 'id',
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
title: 'Name',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
</APIClientProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,84 +0,0 @@
|
|||||||
import {
|
|
||||||
APIClient,
|
|
||||||
APIClientProvider,
|
|
||||||
AsyncDataProvider,
|
|
||||||
SchemaComponent,
|
|
||||||
SchemaComponentProvider,
|
|
||||||
useAsyncData,
|
|
||||||
} from '@nocobase/client';
|
|
||||||
import { Table } from 'antd';
|
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const apiClient = new APIClient();
|
|
||||||
|
|
||||||
const mock = new MockAdapter(apiClient.axios);
|
|
||||||
|
|
||||||
mock.onGet('/users').reply(200, {
|
|
||||||
data: [
|
|
||||||
{ id: 1, name: 'John Smith' },
|
|
||||||
{ id: 2, name: 'Mike' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const TableView = (props) => {
|
|
||||||
const { data, loading } = useAsyncData();
|
|
||||||
return <Table {...props} dataSource={data?.data} loading={loading} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
const AsyncDataTableView = (props) => {
|
|
||||||
const { request, ...others } = props;
|
|
||||||
return (
|
|
||||||
<AsyncDataProvider request={request}>
|
|
||||||
<TableView {...others} />
|
|
||||||
</AsyncDataProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<APIClientProvider apiClient={apiClient}>
|
|
||||||
<SchemaComponentProvider components={{ TableView, AsyncDataTableView, AsyncDataProvider }}>
|
|
||||||
<SchemaComponent
|
|
||||||
schema={{
|
|
||||||
properties: {
|
|
||||||
table1: {
|
|
||||||
type: 'void',
|
|
||||||
'x-decorator': 'AsyncDataProvider',
|
|
||||||
'x-decorator-props': {
|
|
||||||
request: { url: '/users' },
|
|
||||||
},
|
|
||||||
'x-component': 'TableView',
|
|
||||||
'x-component-props': {
|
|
||||||
rowKey: 'id',
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
title: 'Name',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
table2: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'AsyncDataTableView',
|
|
||||||
'x-component-props': {
|
|
||||||
request: { url: '/users' },
|
|
||||||
rowKey: 'id',
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
title: 'Name',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
</APIClientProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,154 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Client
|
|
||||||
order: 1
|
|
||||||
---
|
|
||||||
|
|
||||||
# AsyncDataProvider
|
|
||||||
|
|
||||||
利用 Formily 提供的 [Effect Hooks](https://core.formilyjs.org/zh-CN/api/entry/form-effect-hooks) 或 [x-reactions](https://react.formilyjs.org/zh-CN/api/shared/schema#schemareactions) 协议能一定程度的解决某些场景的异步数据源问题,但是如果只用来处理异步请求,并不会很好用,而且局限于 Formily 体系内。为了更灵活的处理异步请求的各种需求,NocoBase 提供了非常好用的可配置化的 [useRequest()](api-client#userequest),用于配置各种异步请求。与此同时,又提供了 `<AsyncDataProvider/>` 组件,可以将请求结果共享给子组件,方便处理其他更复杂的需求。以平时最常见,但却可能非常复杂的表格为例。表格的使用场景有:
|
|
||||||
|
|
||||||
- TableView 只作为表格视图
|
|
||||||
- RowSelection 动态数据的勾选项
|
|
||||||
- TableField 表格字段
|
|
||||||
|
|
||||||
各自的 schema 可以这么表示:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// 表格视图,type 为 void,无 default 默认值,无 field.value,
|
|
||||||
// dataSource 直接写在组件的 props 里
|
|
||||||
{
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'TableView',
|
|
||||||
'x-component-props': {
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
title: 'Name',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
dataSource: [
|
|
||||||
{ id: 1, name: 'Name1' },
|
|
||||||
{ id: 2, name: 'Name2' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 单选(表格视图),类似于 Radio.Group 字段,可选项由表格视图提供
|
|
||||||
{
|
|
||||||
type: 'number',
|
|
||||||
'x-component': 'RowSelection',
|
|
||||||
'x-component-props': {
|
|
||||||
rowSelection: {
|
|
||||||
type: 'radio',
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
title: 'Name',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
dataSource: [
|
|
||||||
{ id: 1, name: 'Name1' },
|
|
||||||
{ id: 2, name: 'Name2' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
default: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 多选(表格视图),类似于 Checkbox.Group 字段,可选项由表格视图提供
|
|
||||||
{
|
|
||||||
type: 'array',
|
|
||||||
'x-component': 'RowSelection',
|
|
||||||
'x-component-props': {
|
|
||||||
rowSelection: {
|
|
||||||
type: 'checkbox',
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
title: 'Name',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
dataSource: [
|
|
||||||
{ id: 1, name: 'Name1' },
|
|
||||||
{ id: 2, name: 'Name2' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
default: [1],
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格字段,数据由表单提供,schema 层面可以配置默认值
|
|
||||||
// 与表格视图的方式不同,dataSource 和 columns 不适合直接配置在 x-component-props 里,怎么处理先忽略。
|
|
||||||
{
|
|
||||||
type: 'array',
|
|
||||||
'x-component': 'TableField',
|
|
||||||
'x-component-props': {},
|
|
||||||
default: [
|
|
||||||
{ id: 1, name: 'Name1' },
|
|
||||||
{ id: 2, name: 'Name2' },
|
|
||||||
],
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
大多数实际应用中,表格视图的 dataSource 是异步获取的,可能也需要过滤和分页,这样一来直接在 x-component-props 里写 dataSource 并不合适。为了解决这个问题,可以给组件扩展一个 request 属性,用于请求远程数据,例子如下:
|
|
||||||
|
|
||||||
<code src="./demos/demo2.tsx"></code>
|
|
||||||
|
|
||||||
上述例子的 `<TableView/>` 组件就是一个 React Component,可以正常使用,而不局限于 SchemaComponent 场景。更进一步,为了处理过滤表单、分页等问题,建议将 request 通过 `<AsyncDataProvider/>` 共享给 `<TableView/>` 组件。
|
|
||||||
|
|
||||||
```tsx | pure
|
|
||||||
const result = useRequest(props.request);
|
|
||||||
<AsyncDataProvider value={result}>
|
|
||||||
<TableView/>
|
|
||||||
</AsyncDataProvider>
|
|
||||||
```
|
|
||||||
|
|
||||||
或者直接将 request 交给 AsyncDataProvider
|
|
||||||
|
|
||||||
```tsx | pure
|
|
||||||
<AsyncDataProvider request={props.request}>
|
|
||||||
<TableView/>
|
|
||||||
</AsyncDataProvider>
|
|
||||||
```
|
|
||||||
|
|
||||||
在 `<AsyncDataProvider/>` 的子组件里就可以通过 `useAsyncData()` 来获取 result,可用于处理过滤、分页等。
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const { data, loading, params, run, refresh, parent } = useAsyncData();
|
|
||||||
```
|
|
||||||
|
|
||||||
转化为 Schema 时,可以将 AsyncDataProvider 放在 `x-decorator` 里,也可以将重新组合的 AsyncDataProvider + TableView,放在 `x-component` 里。
|
|
||||||
|
|
||||||
<code src="./demos/demo3.tsx"></code>
|
|
||||||
|
|
||||||
将 AsyncDataProvider 独立出来,放到 x-decorator 里的另一个好处,例子如下:
|
|
||||||
|
|
||||||
```tsx | pure
|
|
||||||
<CollectionProvider>
|
|
||||||
{/* 从 CollectionProvider 里获取资源请求参数,并将请求结果同时共享给 DesignableBar 和 TableView */}
|
|
||||||
<AsyncDataProvider>
|
|
||||||
<DesignableBar/>
|
|
||||||
<TableView>
|
|
||||||
<RecordProvider>
|
|
||||||
<CollectionFieldProvider>
|
|
||||||
{/* 从 CollectionFieldProvider 里获取关系资源请求参数,并将请求结果同时共享给子组件 */}
|
|
||||||
<AsyncDataProvider>
|
|
||||||
{/* 组件 */}
|
|
||||||
</AsyncDataProvider>
|
|
||||||
</CollectionFieldProvider>
|
|
||||||
</RecordProvider>
|
|
||||||
</TableView>
|
|
||||||
</AsyncDataProvider>
|
|
||||||
</CollectionProvider>
|
|
||||||
```
|
|
||||||
|
|
||||||
上面例子嵌套了两层 AsyncDataProvider,在子 AsyncDataProvider 里,也可以获取到更上一级的请求结果,如:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const { parent } = useAsyncData();
|
|
||||||
parent.refresh();
|
|
||||||
```
|
|
1
packages/core/client/src/block-provider/index.md
Normal file
1
packages/core/client/src/block-provider/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# BlockProvider
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Client
|
|
||||||
order: 1
|
|
||||||
---
|
|
||||||
|
|
||||||
# I18n
|
|
||||||
|
|
||||||
提供国际化解决方案。
|
|
@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Route Components
|
|
||||||
order: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
# AdminLayout <Badge>待定</Badge>
|
|
||||||
|
|
||||||
结构
|
|
||||||
|
|
||||||
- Layout
|
|
||||||
- Layout.Header
|
|
||||||
- SiteTitle
|
|
||||||
- Menu(SchemaComponent)
|
|
||||||
- PluginManager.Toolbar
|
|
||||||
- DesignableAction
|
|
||||||
- CollectionManager.Action
|
|
||||||
- ACL.Action
|
|
||||||
- SystemSettings.Action
|
|
||||||
- CurrentUser.Dropdown
|
|
||||||
- Layout.Sider
|
|
||||||
- SideMenu(随 Menu 联动的)
|
|
||||||
- Layout.Content
|
|
||||||
- PageTitle
|
|
||||||
- SchemaComponent
|
|
@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Route Components
|
|
||||||
order: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
# AuthLayout
|
|
||||||
|
|
1
packages/core/client/src/schema-settings/index.md
Normal file
1
packages/core/client/src/schema-settings/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# SchemaSettings
|
@ -1,44 +0,0 @@
|
|||||||
import {
|
|
||||||
AntdSchemaComponentProvider,
|
|
||||||
APIClient,
|
|
||||||
APIClientProvider,
|
|
||||||
SchemaComponentProvider,
|
|
||||||
SystemSettingsProvider,
|
|
||||||
useSystemSettings,
|
|
||||||
} from '@nocobase/client';
|
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const apiClient = new APIClient();
|
|
||||||
|
|
||||||
const mock = new MockAdapter(apiClient.axios);
|
|
||||||
|
|
||||||
mock.onGet('/systemSettings:get/1').reply(200, {
|
|
||||||
data: {
|
|
||||||
title: 'NocoBase',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const Demo = () => {
|
|
||||||
const { data } = useSystemSettings();
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h3>以下为测试内容</h3>
|
|
||||||
System title: {data?.data?.title}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<APIClientProvider apiClient={apiClient}>
|
|
||||||
<SystemSettingsProvider>
|
|
||||||
<SchemaComponentProvider>
|
|
||||||
<AntdSchemaComponentProvider>
|
|
||||||
<Demo />
|
|
||||||
</AntdSchemaComponentProvider>
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
</SystemSettingsProvider>
|
|
||||||
</APIClientProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,21 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Client
|
|
||||||
order: 1
|
|
||||||
---
|
|
||||||
|
|
||||||
# SystemSettings
|
|
||||||
|
|
||||||
## SystemSettingsProvider
|
|
||||||
|
|
||||||
## SystemSettingsShortcut
|
|
||||||
|
|
||||||
## useSystemSettings
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const { data, loading, refresh } = useSystemSettings();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"></code>
|
|
Loading…
Reference in New Issue
Block a user