diff --git a/.github/workflows/deploy-client-docs.yml b/.github/workflows/deploy-client-docs.yml new file mode 100644 index 000000000..cb1a4991f --- /dev/null +++ b/.github/workflows/deploy-client-docs.yml @@ -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 }} diff --git a/packages/core/client/.dumirc.ts b/packages/core/client/.dumirc.ts index 18cf515ab..7be56e346 100644 --- a/packages/core/client/.dumirc.ts +++ b/packages/core/client/.dumirc.ts @@ -1,18 +1,6 @@ -import { defineConfig } from 'dumi'; -import { defineThemeConfig } from 'dumi-theme-nocobase' import { getUmiConfig } from '@nocobase/devtools/umiConfig'; -import fs from 'fs'; -import path from 'path'; - -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); +import { defineConfig } from 'dumi'; +import { defineThemeConfig } from 'dumi-theme-nocobase'; const umiConfig = getUmiConfig(); @@ -23,34 +11,106 @@ export default defineConfig({ }, resolve: { atomDirs: [ - { type: 'component', dir: 'src' }, - { type: 'component', dir: 'src/schema-component/antd' }, - { type: 'component', dir: 'src/route-switch/antd' }, - ] + { type: 'api', dir: 'src' }, + { type: 'api', dir: 'src/schema-component/antd' }, + { type: 'api', dir: 'src/route-switch/antd' }, + ], }, themeConfig: defineThemeConfig({ title: 'NocoBase', logo: 'https://www.nocobase.com/images/logo.png', github: 'https://github.com/nocobase/nocobase', footer: 'nocobase | Copyright © 2022', - sidebarGroupModePath: ['/components'], + // sidebarGroupModePath: ['/components'], nav: [ { - title: 'Intro', - link: '/intro', + title: 'API', + link: '/apis/application', }, - { - title: 'Client', - link: '/components/acl', - }, - { - title: 'Develop', - link: '/develop', - }, - { - title: 'Contributing', - link: '/contributing', - } - ] - }) + ], + sidebarEnhance: { + '/apis': [ + { + title: 'Core', + type: 'group', + children: [ + { + title: 'Application', + children: [ + { + title: 'Application', + link: '/apis/application', + }, + { + title: 'APIClient', + link: '/apis/api-client', + }, + { + title: 'SettingsCenter', + link: '#', + }, + ], + }, + { + title: 'UI schema designer', + 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: '#', + }, + ], + }, + ], + }, + }), }); diff --git a/packages/core/client/contributing.md b/packages/core/client/contributing.md deleted file mode 100644 index 1f4f1b8a1..000000000 --- a/packages/core/client/contributing.md +++ /dev/null @@ -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) => ( -
-

A

- {props.children} -
- ); - const App = compose(A)(); - const { container } = render(); - expect(container).toMatchSnapshot(); - }); -}); -``` - -## Demo - -组件 Demo 见 [dumi](https://d.umijs.org/guide/basic#write-component-demo),可以直接写在文档里,如: - -
-```jsx
-import React from 'react';
-
-export default () => 

Hello NocoBase!

; -``` -
- -也可以引用 demo 文件 - -```markdown - -``` diff --git a/packages/core/client/docs/index.md b/packages/core/client/docs/index.md new file mode 100644 index 000000000..bc0930d2d --- /dev/null +++ b/packages/core/client/docs/index.md @@ -0,0 +1 @@ + diff --git a/packages/core/client/src/acl/index.md b/packages/core/client/src/acl/index.md deleted file mode 100644 index 4de99929a..000000000 --- a/packages/core/client/src/acl/index.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -group: - title: Client - order: 1 ---- - -# ACL - -访问控制列表,plugin-acl 的前端模块,详细文档待补充。 diff --git a/packages/core/client/src/antd-config-provider/demos/demo1.tsx b/packages/core/client/src/antd-config-provider/demos/demo1.tsx deleted file mode 100644 index dd79a424e..000000000 --- a/packages/core/client/src/antd-config-provider/demos/demo1.tsx +++ /dev/null @@ -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 ; -}); diff --git a/packages/core/client/src/antd-config-provider/index.md b/packages/core/client/src/antd-config-provider/index.md deleted file mode 100644 index f773165e6..000000000 --- a/packages/core/client/src/antd-config-provider/index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -group: - title: Client - order: 1 ---- - -# AntdConfigProvider - -为 antd 组件提供统一的全局化配置 - - diff --git a/packages/core/client/src/appInfo/index.md b/packages/core/client/src/appInfo/index.md new file mode 100644 index 000000000..4f297ea84 --- /dev/null +++ b/packages/core/client/src/appInfo/index.md @@ -0,0 +1 @@ +# AppInfo \ No newline at end of file diff --git a/packages/core/client/src/application/demos/demo1.tsx b/packages/core/client/src/application/demos/demo1.tsx index 722e5f9d2..e724d1201 100644 --- a/packages/core/client/src/application/demos/demo1.tsx +++ b/packages/core/client/src/application/demos/demo1.tsx @@ -1,7 +1,6 @@ +import { Application, Plugin } from '@nocobase/client'; import React, { FC } from 'react'; import { Link, Outlet, useLocation } from 'react-router-dom'; -import { Application } from '../Application'; -import { Plugin } from '../Plugin'; const Root = () => { return ( diff --git a/packages/core/client/src/application/demos/demo2.tsx b/packages/core/client/src/application/demos/demo2.tsx index e68cac3f3..50f7a816b 100644 --- a/packages/core/client/src/application/demos/demo2.tsx +++ b/packages/core/client/src/application/demos/demo2.tsx @@ -1,9 +1,6 @@ +import { Application, Plugin, RouterManager, useApp } from '@nocobase/client'; import React, { useMemo } from 'react'; 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 = () => { return ( diff --git a/packages/core/client/src/application/index.md b/packages/core/client/src/application/index.md index 27f9d321f..b6677d9e3 100644 --- a/packages/core/client/src/application/index.md +++ b/packages/core/client/src/application/index.md @@ -1,6 +1,6 @@ --- group: - title: Client + title: core order: 1 --- diff --git a/packages/core/client/src/async-data-provider/demos/demo1.tsx b/packages/core/client/src/async-data-provider/demos/demo1.tsx deleted file mode 100644 index f8c2dc224..000000000 --- a/packages/core/client/src/async-data-provider/demos/demo1.tsx +++ /dev/null @@ -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
{data?.data?.name}
; -}); diff --git a/packages/core/client/src/async-data-provider/demos/demo2.tsx b/packages/core/client/src/async-data-provider/demos/demo2.tsx deleted file mode 100644 index 7e1938e19..000000000 --- a/packages/core/client/src/async-data-provider/demos/demo2.tsx +++ /dev/null @@ -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
; -}; - -export default () => { - return ( - - - - - - ); -}; diff --git a/packages/core/client/src/async-data-provider/demos/demo3.tsx b/packages/core/client/src/async-data-provider/demos/demo3.tsx deleted file mode 100644 index b35ad6ba0..000000000 --- a/packages/core/client/src/async-data-provider/demos/demo3.tsx +++ /dev/null @@ -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
; -}; - -const AsyncDataTableView = (props) => { - const { request, ...others } = props; - return ( - - - - ); -}; - -export default () => { - return ( - - - - - - ); -}; diff --git a/packages/core/client/src/async-data-provider/index.md b/packages/core/client/src/async-data-provider/index.md deleted file mode 100644 index 1b10926d5..000000000 --- a/packages/core/client/src/async-data-provider/index.md +++ /dev/null @@ -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),用于配置各种异步请求。与此同时,又提供了 `` 组件,可以将请求结果共享给子组件,方便处理其他更复杂的需求。以平时最常见,但却可能非常复杂的表格为例。表格的使用场景有: - -- 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 属性,用于请求远程数据,例子如下: - - - -上述例子的 `` 组件就是一个 React Component,可以正常使用,而不局限于 SchemaComponent 场景。更进一步,为了处理过滤表单、分页等问题,建议将 request 通过 `` 共享给 `` 组件。 - -```tsx | pure -const result = useRequest(props.request); - - - -``` - -或者直接将 request 交给 AsyncDataProvider - -```tsx | pure - - - -``` - -在 `` 的子组件里就可以通过 `useAsyncData()` 来获取 result,可用于处理过滤、分页等。 - -```ts -const { data, loading, params, run, refresh, parent } = useAsyncData(); -``` - -转化为 Schema 时,可以将 AsyncDataProvider 放在 `x-decorator` 里,也可以将重新组合的 AsyncDataProvider + TableView,放在 `x-component` 里。 - - - -将 AsyncDataProvider 独立出来,放到 x-decorator 里的另一个好处,例子如下: - -```tsx | pure - - {/* 从 CollectionProvider 里获取资源请求参数,并将请求结果同时共享给 DesignableBar 和 TableView */} - - - - - - {/* 从 CollectionFieldProvider 里获取关系资源请求参数,并将请求结果同时共享给子组件 */} - - {/* 组件 */} - - - - - - -``` - -上面例子嵌套了两层 AsyncDataProvider,在子 AsyncDataProvider 里,也可以获取到更上一级的请求结果,如: - -```ts -const { parent } = useAsyncData(); -parent.refresh(); -``` diff --git a/packages/core/client/src/block-provider/index.md b/packages/core/client/src/block-provider/index.md new file mode 100644 index 000000000..a277e3d54 --- /dev/null +++ b/packages/core/client/src/block-provider/index.md @@ -0,0 +1 @@ +# BlockProvider \ No newline at end of file diff --git a/packages/core/client/src/i18n/index.md b/packages/core/client/src/i18n/index.md deleted file mode 100644 index d2fc8b50c..000000000 --- a/packages/core/client/src/i18n/index.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -group: - title: Client - order: 1 ---- - -# I18n - -提供国际化解决方案。 diff --git a/packages/core/client/src/route-switch/antd/admin-layout/index.md b/packages/core/client/src/route-switch/antd/admin-layout/index.md deleted file mode 100644 index 9f7fbeb31..000000000 --- a/packages/core/client/src/route-switch/antd/admin-layout/index.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -group: - title: Route Components - order: 2 ---- - -# AdminLayout 待定 - -结构 - -- 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 diff --git a/packages/core/client/src/route-switch/antd/auth-layout/index.md b/packages/core/client/src/route-switch/antd/auth-layout/index.md deleted file mode 100644 index ddbd32856..000000000 --- a/packages/core/client/src/route-switch/antd/auth-layout/index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -group: - title: Route Components - order: 2 ---- - -# AuthLayout - diff --git a/packages/core/client/src/schema-settings/index.md b/packages/core/client/src/schema-settings/index.md new file mode 100644 index 000000000..a7700ee3c --- /dev/null +++ b/packages/core/client/src/schema-settings/index.md @@ -0,0 +1 @@ +# SchemaSettings \ No newline at end of file diff --git a/packages/core/client/src/system-settings/demos/demo1.tsx b/packages/core/client/src/system-settings/demos/demo1.tsx deleted file mode 100644 index a4bec09ff..000000000 --- a/packages/core/client/src/system-settings/demos/demo1.tsx +++ /dev/null @@ -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 ( -
-

以下为测试内容

- System title: {data?.data?.title} -
- ); -}; - -export default () => { - return ( - - - - - - - - - - ); -}; diff --git a/packages/core/client/src/system-settings/index.md b/packages/core/client/src/system-settings/index.md deleted file mode 100644 index bca6a4e9b..000000000 --- a/packages/core/client/src/system-settings/index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -group: - title: Client - order: 1 ---- - -# SystemSettings - -## SystemSettingsProvider - -## SystemSettingsShortcut - -## useSystemSettings - -```ts -const { data, loading, refresh } = useSystemSettings(); -``` - -## Examples - -