diff --git a/docs/en-US/plugin-samples/schema-initializer/action-simple.md b/docs/en-US/plugin-samples/schema-initializer/action-simple.md index bd99ff142c..e4d1571c6f 100644 --- a/docs/en-US/plugin-samples/schema-initializer/action-simple.md +++ b/docs/en-US/plugin-samples/schema-initializer/action-simple.md @@ -129,7 +129,7 @@ The `createDocumentActionSchema` component takes a `blockComponent` parameter an - `x-component: 'Action'`: [Action Component](https://client.docs.nocobase.com/components/action) used to create a button. - `title: 'Document'`: Button title. - `x-doc-url`: A custom schema property representing the documentation URL. -- `x-use-component-props: 'useDocumentActionProps'`: Dynamic properties, more details can be found in [the documentation](/development/client/ui-schema/what-is-ui-schema#x-component-props-和-x-use-component-props). +- `x-use-component-props: 'useDocumentActionProps'`: Dynamic properties, more details can be found in [the documentation](/development/client/ui-schema/what-is-ui-schema#x-component-props-and-x-use-component-props). `useDocumentActionProps()`: - [useFieldSchema()](https://client.docs.nocobase.com/core/ui-schema/designable#usefieldschema): Retrieves the schema of the current node. @@ -263,7 +263,7 @@ You can add multiple languages via [http://localhost:13000/admin/settings/system ### Packaging and Uploading to the Production Environment -Following the [Build and Package Plugin](/development/your-fisrt-plugin#构建并打包插件) guide, we can package the plugin and upload it to the production environment. +Following the [Build and Package Plugin](/development/your-fisrt-plugin#build-and-package-the-plugin) guide, we can package the plugin and upload it to the production environment. If the source code was cloned, a full build is needed first to construct the plugin dependencies. diff --git a/docs/en-US/plugin-samples/schema-initializer/block-data-modal.md b/docs/en-US/plugin-samples/schema-initializer/block-data-modal.md index 797c80a90b..ec38a84221 100644 --- a/docs/en-US/plugin-samples/schema-initializer/block-data-modal.md +++ b/docs/en-US/plugin-samples/schema-initializer/block-data-modal.md @@ -1,11 +1,11 @@ -# 添加带弹窗的数据区块 Data Block Modal +# Adding Data Blocks with Modal -## 场景说明 +## Scenario Description -很多情况下在点击创建区块之前,我们需要先选择配置信息。例如: -- `Kanban` 区块点击后需要先选择 `Grouping field` 和 `Sorting field` -- `Calendar` 区块需要先选择 `Title field`、`Start date field`、`End date field` -- `Chart` 区块需要先配置图标相关信息 +In many cases, before clicking to create a block, we need to select configuration information first. For example: +- The `Kanban` block requires selecting a `Grouping field` and `Sorting field` first +- The `Calendar` block requires selecting a `Title field`, `Start date field`, and `End date field` first +- The `Chart` block requires configuring chart-related information first
@@ -13,21 +13,21 @@ -## 示例说明 +## Example Explanation -本实例会基于 ant-design [Timeline 组件](https://ant.design/components/timeline) 创建一个 `Timeline` 区块,并且在区块创建前选择 `Time Field` 和 `Title Field`。 +This example will create a `Timeline` block based on the ant-design [Timeline component](https://ant.design/components/timeline), and select a `Time Field` and `Title Field` before creating the block. -本实例主要为了演示 initializer 的使用,更多关于区块扩展可以查看 [区块扩展](/plugin-samples/block) 文档。 +This example mainly demonstrates the usage of the initializer. For more information on block extensions, refer to the [Block Extension](/plugin-samples/block) documentation. -本文档完整的示例代码可以在 [plugin-samples](https://github.com/nocobase/plugin-samples/tree/main/packages/plugins/%40nocobase-sample/plugin-initializer-block-data-modal) 中查看。 +The complete sample code for this document can be found in [plugin-samples](https://github.com/nocobase/plugin-samples/tree/main/packages/plugins/%40nocobase-sample/plugin-initializer-block-data-modal). -## 初始化插件 +## Initializing the Plugin -我们按照 [编写第一个插件](/development/your-fisrt-plugin) 文档说明,如果没有一个项目,可以先创建一个项目,如果已经有了或者是 clone 的源码,则跳过这一步。 +Following the instructions in the [Creating Your First Plugin](/development/your-fisrt-plugin) document, if you don't have a project yet, you can create one first. If you already have a project or have cloned the source code, skip this step. ```bash yarn create nocobase-app my-nocobase-app -d postgres @@ -36,66 +36,66 @@ yarn install yarn nocobase install ``` -然后初始化一个插件,并添加到系统中: +Next, initialize a plugin and add it to the system: ```bash yarn pm create @nocobase-sample/plugin-initializer-block-data-modal yarn pm enable @nocobase-sample/plugin-initializer-block-data-modal ``` -然后启动项目即可: +Then, start the project: ```bash yarn dev ``` -然后登录后访问 [http://localhost:13000/admin/pm/list/local/](http://localhost:13000/admin/pm/list/local/) 就可以看到插件已经安装并启用了。 +After logging in, visit [http://localhost:13000/admin/pm/list/local/](http://localhost:13000/admin/pm/list/local/) to see that the plugin has been installed and enabled. -## 功能实现 +## Feature Implementation -在实现本示例之前,我们需要先了解一些基础知识: +Before implementing this example, we need to understand some basic concepts: -- ant-design [Timeline 组件](https://ant.design/components/timeline) -- [SchemaInitializer 教程](/development/client/ui-schema/initializer):用于向界面内添加各种区块、字段、操作等 -- [SchemaInitializer API](https://client.docs.nocobase.com/core/ui-schema/schema-initializer):用于向界面内添加各种区块、字段、操作等 -- [UI Schema](/development/client/ui-schema/what-is-ui-schema):用于定义界面的结构和样式 -- [Designable 设计器](/development/client/ui-schema/designable):用于修改 Schema +- ant-design [Timeline component](https://ant.design/components/timeline) +- [SchemaInitializer Tutorial](/development/client/ui-schema/initializer): Used to add various blocks, fields, operations, etc., to the interface +- [SchemaInitializer API](https://client.docs.nocobase.com/core/ui-schema/schema-initializer): Provides an API for adding various blocks, fields, operations, etc., to the interface +- [UI Schema](/development/client/ui-schema/what-is-ui-schema): Used for defining the structure and style of the interface +- [Designable Designer](/development/client/ui-schema/designable): Used for modifying Schema ```bash . -├── client # 客户端插件 -│ ├── initializer # 初始化器 -│ ├── component # 区块组件 -│ ├── index.tsx # 客户端插件入口 -│ ├── locale.ts # 多语言工具函数 -│ ├── constants.ts # 常量 +├── client # Client-side plugin +│ ├── initializer # Initializer +│ ├── component # Block components +│ ├── index.tsx # Entry point for the client-side plugin +│ ├── locale.ts # Multi-language utility functions +│ ├── constants.ts # Constants │ ├── schema # Schema │ └── settings # Schema Settings -├── locale # 多语言文件 -│ ├── en-US.json # 英语 -│ └── zh-CN.json # 中文 -├── index.ts # 服务端插件入口 -└── server # 服务端插件 +├── locale # Multi-language files +│ ├── en-US.json # English +│ └── zh-CN.json # Chinese +├── index.ts # Server-side plugin entry point +└── server # Server-side plugin ``` -### 1. 定义名称 +### 1. Defining Names -我们首先需要定义区块名称,它将会使用在各个地方。 +First, we need to define the block's name, which will be used in various places. -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/constants.ts`: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/constants.ts`: ```ts export const BlockName = 'Timeline'; export const BlockNameLowercase = BlockName.toLowerCase(); ``` -### 2. 实现区块组件 +### 2. Implementing Block Components -#### 2.1 定义区块组件 +#### 2.1 Defining the Block Component -本示例要做的是一个 `Timeline` 区块组件,其具体的需求是: +In this example, we want to create a `Timeline` block component with the following requirements: -首先我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/component/Timeline.tsx` 文件,其内容如下: +First, create `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/component/Timeline.tsx` with the following content: ```tsx | pure import React, { FC } from 'react'; @@ -115,16 +115,16 @@ export const Timeline: FC = withDynamicSchemaProps((props) => { }, { displayName: BlockName }); ``` -`Timeline` 组件整体来说是一个被 `withDynamicSchemaProps` 包裹的组件,其接受 2 个参数: +The `Timeline` component is essentially a component wrapped by `withDynamicSchemaProps`, which accepts 2 parameters: -- `loading`:数据加载状态 -- `data`:`Timeline` 组件的 `items` 属性 +- `loading`: Data loading status +- `data`: The `items` property of the `Timeline` component -[withDynamicSchemaProps](/development/client/ui-schema/what-is-ui-schema#x-component-props-和-x-use-component-props) 是一个高阶组件,用于处理 Schema 中的的动态属性。 +[withDynamicSchemaProps](/development/client/ui-schema/what-is-ui-schema#x-component-props-and-x-use-component-props) is a higher-order component used to handle dynamic properties in Schema. -#### 2.2 注册区块组件 +#### 2.2 Registering the Block Component -我们需要将 `Timeline` 通过插件注册到系统中。 +We need to register the `Timeline` component in the system via the plugin. ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -139,14 +139,14 @@ export class PluginInitializerBlockDataModalClient extends Plugin { export default PluginInitializerBlockDataModalClient; ``` -#### 2.3 验证区块组件 +#### 2.3 Verifying the Block Component -组件验证方式有 2 种: +There are two ways to verify the component: -- 临时页面验证:我们可以临时建一个页面,然后渲染 `Timeline` 组件,查看是否符合需求 -- 文档示例验证:可以启动文档 `yarn doc plugins/@nocobase-sample/plugin-initializer-block-data-modal`,通过写文档示例的方式验证是否符合需求(TODO) +- Temporary page verification: You can create a temporary page, render the `Timeline` component, and check if it meets the requirements +- Documentation example verification: You can start the documentation with `yarn doc plugins/@nocobase-sample/plugin-initializer-block-data-modal` and verify the component through a documentation example (TODO) -我们以 `临时页面验证` 为例,我们新建一个页面,根据属性参数添加一个或者多个 `Timeline` 组件,查看是否符合需求。 +For this example, we'll use **Temporary Page Verification**. Create a page and add one or more `Timeline` components based on the parameters, then check if it meets the requirements. ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -190,26 +190,26 @@ export class PluginInitializerBlockDataModalClient extends Plugin { export default PluginInitializerBlockDataModalClient; ``` -然后访问 `http://localhost:13000/admin/timeline-block-component` 就可以看到对应测试页面的内容了。 +Then visit `http://localhost:13000/admin/timeline-block-component` to see the corresponding content on the test page. ![20240529210122](https://static-docs.nocobase.com/20240529210122.png) -验证完毕后需要删除测试页面。 +After verification, delete the test page. -### 3. 定义配置表单 +### 3. Defining the Configuration Form -根据需求,我们需要在选择数据表后配置 `Time Field` 和 `Title Field`,所以我们需要定义一个配置表单,取名为 `TimelineInitializerConfigForm`。 +According to the requirements, we need to configure `Time Field` and `Title Field` after selecting a data table, so we need to define a configuration form named `TimelineInitializerConfigForm`. -#### 3.1 定义配置表单组件 +#### 3.1 Defining the Configuration Form Component -我们需要先了解以下知识: +We need to understand the following knowledge first: - [Action](https://client.docs.nocobase.com/components/action) -- [Action.Modal](https://client.docs.nocobase.com/components/action#actionmodal):弹窗 -- [ActionContextProvider](https://client.docs.nocobase.com/components/action#actioncontext):`Action` 上下文 -- [SchemaComponent](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponent-1):用于渲染 Schema +- [Action.Modal](https://client.docs.nocobase.com/components/action#actionmodal): Modal popup +- [ActionContextProvider](https://client.docs.nocobase.com/components/action#actioncontext): `Action` context +- [SchemaComponent](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponent-1): Used to render Schema -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/initializer/ConfigForm.tsx` 文件,其内容如下: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/initializer/ConfigForm.tsx` with the following content: ```tsx | pure import React, { FC, useMemo } from "react"; @@ -246,29 +246,29 @@ export const TimelineInitializerConfigForm: FC = ({ vis } ``` -`TimelineInitializerConfigForm` 组件接受 4 个参数: +The `TimelineInitializerConfigForm` component accepts 4 parameters: -- `visible`:是否显示 -- `setVisible`:设置是否显示 -- `collection`:数据表名称 -- `dataSource`:数据源名称 -- `onSubmit`:表单提交回调 +- `visible`: Whether to display +- `setVisible`: Set whether to display +- `collection`: Data table name +- `dataSource`: Data source name +- `onSubmit`: Form submission callback -其中 `collection` 和 `dataSource` 是通过点击数据表后获取的,所以这里是动态的。 +The `collection` and `dataSource` are obtained after clicking the data table, so they are dynamic. -- [app](https://client.docs.nocobase.com/core/application/application):通过 [useApp()](https://client.docs.nocobase.com/core/application/application#useapp) 获取应用实例 -- [app.getCollectionManager](https://client.docs.nocobase.com/core/application/application##appgetcollectionmanager):获取 [CollectionManager](https://client.docs.nocobase.com/core/data-source/collection-manager) 实例 -- [getCollection](https://client.docs.nocobase.com/core/data-source/collection-manager#getcollectionpath):获取数据表 -- [getFields](https://client.docs.nocobase.com/core/data-source/collection#collectiongetfieldspredicate):获取数据表字段 +- [app](https://client.docs.nocobase.com/core/application/application): Get the application instance via [useApp()](https://client.docs.nocobase.com/core/application/application#useapp) +- [app.getCollectionManager](https://client.docs.nocobase.com/core/application/application##appgetcollectionmanager): Get the [CollectionManager](https://client.docs.nocobase.com/core/data-source/collection-manager) instance +- [getCollection](https://client.docs.nocobase.com/core/data-source/collection-manager#getcollectionpath): Get the data table +- [getFields](https://client.docs.nocobase.com/core/data-source/collection#collectiongetfieldspredicate): Get the data table fields -[ActionContextProvider](https://client.docs.nocobase.com/components/action#actioncontext) 用于传递 `visible` 和 `setVisible` 给子节点,`SchemaComponent` 用于渲染 Schema。 +[ActionContextProvider](https://client.docs.nocobase.com/components/action#actioncontext) is used to pass `visible` and `setVisible` to child nodes, and `SchemaComponent` is used to render the Schema. -#### 3.2 实现配置表单 Schema +#### 3.2 Implementing the Configuration Form Schema -我们需要先了解以下知识: +We need to understand the following knowledge first: -- [FormV2](https://client.docs.nocobase.com/components/form-v2):表单组件 -- [Select](https://client.docs.nocobase.com/components/action#select):选择器 +- [FormV2](https://client.docs.nocobase.com/components/form-v2): Form component +- [Select](https://client.docs.nocobase.com/components/action#select): Selector ```tsx | pure const useCloseActionProps = () => { @@ -346,22 +346,22 @@ const createSchema = (fields: CollectionFieldOptions[]): ISchema => { } ``` -我们定义了一个 `createSchema` 函数,用于生成配置表单的 Schema,其接受一个 `fields` 参数,这个参数是数据表的字段。 +We defined a `createSchema` function to generate the configuration form Schema, which accepts a `fields` parameter representing the data table fields. -上述的效果是弹窗内有一个表单,表单内有 2 个选择器,一个是 `Title Field`,一个是 `Time Field`,并且有一个 `Close` 和 `Submit` 按钮。 +The above effect is a modal with a form containing 2 selectors, one for `Title Field` and one for `Time Field`, plus `Close` and `Submit` buttons. -- `Close` 和 `Submit` 按钮因为要使用 Hooks,所以我们使用了 [x-use-component-props](/development/client/ui-schema/what-is-ui-schema#x-component-props-和-x-use-component-props) -- `Title Field`:所有字段都可以选择 -- `Time Field`:只有 `date` 类型的字段可以选择 +- The `Close` and `Submit` buttons use Hooks, so we use [x-use-component-props](/development/client/ui-schema/what-is-ui-schema#x-component-props-and-x-use-component-props) +- `Title Field`: All fields can be selected +- `Time Field`: Only `date` type fields can be selected -然后我们还需要修改 `TimelineInitializerConfigForm`,将 `useSubmitActionProps` 和 `useCloseActionProps` 注册到 [scope](/plugin-samples/component-and-scope/local) 中。 +Then we also need to modify `TimelineInitializerConfigForm` to register `useSubmitActionProps` and `useCloseActionProps` in the [scope](/plugin-samples/component-and-scope/local). ```diff - + ``` -#### 3.3 验证配置表单 +#### 3.3 Verifying the Configuration Form ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -393,24 +393,24 @@ export class PluginInitializerBlockDataModalClient extends Plugin { export default PluginInitializerBlockDataModalClient; ``` -然后访问 `http://localhost:13000/admin/timeline-config-form` 就可以看到对应测试页面的内容了。 +Then visit `http://localhost:13000/admin/timeline-config-form` to see the corresponding content on the test page. -验证完毕后需要删除测试页面。 +After verification, delete the test page. -### 4. 定义区块 Schema +### 4. Defining Block Schema -#### 4.1 定义区块 Schema +#### 4.1 Defining Block Schema -NocoBase 的动态页面都是通过 Schema 来渲染,所以我们需要定义一个 Schema,后续用于在界面中添加 `Timeline` 区块。在实现本小节之前,我们需要先了解一些基础知识: +NocoBase's dynamic pages are rendered through Schema, so we need to define a Schema that will be used to add the `Timeline` block to the interface. Before implementing this section, we need to understand some basic concepts: -- [UI Schema 协议](/development/client/ui-schema/what-is-ui-schema):详细介绍 Schema 的结构和每个属性的作用 -- [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider):数据区块 +- [UI Schema Protocol](/development/client/ui-schema/what-is-ui-schema): Detailed introduction to the structure of Schema and the role of each attribute +- [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider): Data block -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/schema/index.tsx` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/schema/index.tsx`: ```ts import { useDataBlockProps, useDataBlockRequest } from "@nocobase/client"; @@ -466,25 +466,25 @@ export function useTimelineProps(): TimelineProps { } ``` -这里有 2 个点需要说明: +There are 2 points to explain here: -`getTimelineSchema()` 接收 `dataSource`、`collection`、`titleField`、`timeField` 并返回一个 Schema,这个 Schema 用于渲染 `Timeline` 区块: - - `type: 'void'`:表示没有任何数据 - - `x-decorator: 'DataBlockProvider'`:数据区块提供者,用于提供数据,更多关于 DataBlockProvider 可以查看 [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) - - `x-decorator-props`:`DataBlockProvider` 的属性 - - `dataSource`:数据源 - - `collection`:数据表 - - `action: 'list'`:操作类型,这里是 `list`,获取数据列表 - - `params: { sort }`:请求参数,这里我们将 `timeField` 倒叙,更多关于请求参数请参考 [useRequest](https://client.docs.nocobase.com/core/request#userequest) - - `x-component: 'CardItem'`:[CardItem 组件](https://client.docs.nocobase.com/components/card-item),目前的区块都是被包裹在卡片中的,用于提供样式、布局和拖拽等功能 - - `'x-component': 'Timeline'`:区块组件,就是我们定义的 `Timeline` 组件 - - `'x-use-component-props': 'useTimelineProps'`:用于处理 `Timeline` 组件的动态属性,并且因为要存到数据库,所以这里的值类型为 string 类型。 +`getTimelineSchema()` accepts `dataSource`, `collection`, `titleField`, `timeField` and returns a Schema for rendering the `Timeline` block: + - `type: 'void'`: Indicates no data + - `x-decorator: 'DataBlockProvider'`: Data block provider for providing data. For more about DataBlockProvider, see [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) + - `x-decorator-props`: Properties of `DataBlockProvider` + - `dataSource`: Data source + - `collection`: Data table + - `action: 'list'`: Operation type, here it's `list`, to get the data list + - `params: { sort }`: Request parameters, here we sort `timeField` in descending order. For more about request parameters, see [useRequest](https://client.docs.nocobase.com/core/request#userequest) + - `x-component: 'CardItem'`: [CardItem component](https://client.docs.nocobase.com/components/card-item), currently all blocks are wrapped in cards for styling, layout, and drag-and-drop functionality + - `'x-component': 'Timeline'`: Block component, the `Timeline` component we defined + - `'x-use-component-props': 'useTimelineProps'`: Used to handle dynamic properties of the `Timeline` component. Since it needs to be stored in the database, the value type here is string. -`useTimelineProps()`:Timeline 组件的动态属性 - - [useDataBlockProps](https://client.docs.nocobase.com/core/data-block/data-block-provider#usedatablockprops):获取 [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) 的 props 属性,也就是 `x-decorator-props` 的值 - - [useDataBlockRequest](https://client.docs.nocobase.com/core/data-block/data-block-request-provider#usedatablockrequest) 获取数据区块请求,由 [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) 提供 +`useTimelineProps()`: Dynamic properties of the Timeline component + - [useDataBlockProps](https://client.docs.nocobase.com/core/data-block/data-block-provider#usedatablockprops): Gets the props attribute of [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider), which is the value of `x-decorator-props` + - [useDataBlockRequest](https://client.docs.nocobase.com/core/data-block/data-block-request-provider#usedatablockrequest): Gets the data block request, provided by [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) -上述 Schema 转为 React 组件后相当于: +The above Schema translates to the following React component: ```tsx | pure @@ -494,9 +494,9 @@ export function useTimelineProps(): TimelineProps { ``` -#### 4.2 注册 scope +#### 4.2 Registering Scope -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/index.tsx` 文件,将 `useTimelineProps` 注册到系统中,这样 `x-use-component-props` 才能找到对应的 scope。 +Modify `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/index.tsx` to register `useTimelineProps` in the system so that `x-use-component-props` can find the corresponding scope. ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -513,11 +513,11 @@ export class PluginInitializerBlockDataModalClient extends Plugin { export default PluginInitializerBlockDataModalClient; ``` -更多关于 Scope 的说明可以查看 [全局注册 Component 和 Scope](/plugin-samples/component-and-scope/global) +For more about Scope, see [Globally Registering Component and Scope](/plugin-samples/component-and-scope/global) -#### 4.3 验证区块 Schema +#### 4.3 Verifying Block Schema -同验证组件一样,我们可以通过临时页面验证或者文档示例验证的方式来验证 Schema 是否符合需求。我们这里以临时页面验证为例: +Like component verification, we can verify if the Schema meets the requirements through temporary page verification or documentation example verification. Here we use temporary page verification: ```tsx | pure import { Plugin, SchemaComponent } from '@nocobase/client'; @@ -545,20 +545,20 @@ export default PluginInitializerBlockDataModalClient; ``` -- [SchemaComponentOptions](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponentoptions):用于传递 Schema 中所需的 `components` 和 `scope`,具体的可查看 [局部注册 Component 和 Scope](/plugin-samples/component-and-scope/local) -- [SchemaComponent](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponent-1):用于渲染 Schema +- [SchemaComponentOptions](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponentoptions): Used to pass `components` and `scope` required by the Schema. For details, see [Locally Registering Component and Scope](/plugin-samples/component-and-scope/local) +- [SchemaComponent](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponent-1): Used to render Schema -我们访问 `http://localhost:13000/admin/timeline-schema` 就可以看到对应测试页面的内容了。 +Visit `http://localhost:13000/admin/timeline-schema` to see the corresponding content on the test page. -验证完毕后需要删除测试页面。 +After verification, delete the test page. -### 5. 定义 Schema Initializer Item +### 5. Defining Schema Initializer Item -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/initializer/index.tsx` 文件,定义 Schema Initializer Item: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/initializer/index.tsx` to define the Schema Initializer Item: ```tsx | pure import React, { useCallback, useState } from 'react'; @@ -612,34 +612,34 @@ export const timelineInitializerItem: SchemaInitializerItemType = { } ``` -操作流程是,先点击数据表获取 `collection` 和 `dataSource` 的值,然后通过配置表单 `TimelineInitializerConfigForm` 获取 `timeField` 和 `titleField` 字段,当表单提交时,根据数据创建 schema 并插入到页面。 +The workflow is: first click the data table to get the `collection` and `dataSource` values, then get the `timeField` and `titleField` through the configuration form `TimelineInitializerConfigForm`. When the form is submitted, create a schema based on the data and insert it into the page. -实现数据区块的效果核心是 DataBlockInitializer(文档 TODO)。 +The core of implementing data blocks is DataBlockInitializer (documentation TODO). -`timelineInitializerItem`: - - `name`:唯一标识,用于增删改查 - - `Component`:与 [添加简单区块 Simple Block](/plugin-samples/schema-initializer/block-simple) 中使用的是 `type`,这里使用的是 `Component`,[2 种定义方式](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#two-ways-to-define-component-and-type) 都是可以的 +`timelineInitializerItem`: + - `name`: Unique identifier for CRUD operations + - `Component`: Unlike [Adding a Simple Block](/plugin-samples/schema-initializer/block-simple) which uses `type`, here we use `Component`. [Both definition methods](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#two-ways-to-define-component-and-type) are valid -`TimelineInitializerComponent`: +`TimelineInitializerComponent`: - `DataBlockInitializer` - - `title`:标题 - - `icon`:图标,更多图标可以查看 [Ant Design Icons](https://ant.design/components/icon/) - - `componentType`:组件类型,这里是 `Timeline` - - `onCreateBlockSchema`:当点击数据表后的回调 - - `item`:点击的数据表信息 - - `item.name`:数据表名称 - - `item.dataSource`:数据表所属的数据源 - - [useSchemaInitializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializer):提供了插入 Schema 的方法 + - `title`: Title + - `icon`: Icon, more icons can be found at [Ant Design Icons](https://ant.design/components/icon/) + - `componentType`: Component type, here it's `Timeline` + - `onCreateBlockSchema`: Callback when a data table is clicked + - `item`: Information about the clicked data table + - `item.name`: Data table name + - `item.dataSource`: Data source the data table belongs to + - [useSchemaInitializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializer): Provides methods for inserting Schema -更多关于 Schema Initializer 的定义可以参考 [Schema Initializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer) 文档。 +For more details on defining Schema Initializer, see the [Schema Initializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer) documentation. -### 6. 实现 Schema Settings +### 6. Implementing Schema Settings -#### 6.1 定义 Schema Settings +#### 6.1 Defining Schema Settings -一个完整的 Block 还需要有 Schema Settings,用于配置一些属性和操作,但 Schema Settings 不是本示例的重点,所以我们这里仅有一个 `remove` 操作。 +A complete Block also needs Schema Settings for configuring properties and operations. However, Schema Settings is not the focus of this example, so we only include a `remove` operation here. -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/settings/index.ts` 文件,其内容如下: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/settings/index.ts`: ```ts import { SchemaSettings } from "@nocobase/client"; @@ -662,10 +662,10 @@ export const timelineSettings = new SchemaSettings({ ``` - componentProps - - `removeParentsIfNoChildren`:如果没有子节点,是否删除父节点 - - `breakRemoveOn`:删除时的中断条件。因为 `Add Block` 会自动将子项的包裹在 `Grid` 中,所以这里设置 `breakRemoveOn: { 'x-component': 'Grid' }`,当删除 `Grid` 时,不再向上删除。 + - `removeParentsIfNoChildren`: Whether to delete the parent node if there are no children + - `breakRemoveOn`: The break condition when removing. Since `Add Block` automatically wraps child items in `Grid`, we set `breakRemoveOn: { 'x-component': 'Grid' }` so that when deleting `Grid`, it doesn't continue deleting upwards. -#### 6.2 注册 Schema Settings +#### 6.2 Registering Schema Settings ```ts import { Plugin } from '@nocobase/client'; @@ -681,9 +681,9 @@ export class PluginInitializerBlockDataModalClient extends Plugin { export default PluginInitializerBlockDataModalClient; ``` -#### 6.3 使用 Schema Settings +#### 6.3 Using Schema Settings -我们需要修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/schema/index.tsx` 的 `getTimelineSchema()` 为: +Modify `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/schema/index.tsx` `getTimelineSchema()`: ```diff + import { timelineSettings } from '../settings'; @@ -699,21 +699,21 @@ export function getTimelineSchema(options: GetTimelineSchemaOptions) { } ``` -### 7. 添加到 Add block 中 +### 7. Adding to Add Block -系统中有很多个 `Add block` 按钮,但他们的 **name 是不同的**。 +There are many `Add block` buttons in the system, but their **names are different**. ![img_v3_02b4_049b0a62-8e3b-420f-adaf-a6350d84840g](https://static-docs.nocobase.com/img_v3_02b4_049b0a62-8e3b-420f-adaf-a6350d84840g.jpg) -#### 7.1 添加到页面级别 Add block 中 +#### 7.1 Adding to Page-Level Add Block -如果我们需要添加到页面级别的 `Add block` 中,我们需要知道对应的 `name`,我们可以通过 TODO 方式查看对应的 `name`。 +If we need to add to the page-level `Add block`, we need to know the corresponding `name`. We can find the corresponding `name` through the TODO method. TODO -通过上图可以看到页面级别的 `Add block` 对应的 name 为 `page:addBlock`,`Data Blocks` 对应的 name 为 `dataBlocks`。 +From the image above, we can see that the page-level `Add block` corresponds to the name `page:addBlock`, and `Data Blocks` corresponds to the name `dataBlocks`. -然后我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/index.tsx`: ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -737,15 +737,15 @@ export default PluginInitializerBlockDataModalClient; -#### 7.2 添加到弹窗 Add block 中 +#### 7.2 Adding to Popup Add Block -我们不仅需要将其添加到页面级别的 `Add block` 中,还需要将其添加到 `Table` 区块 `Add new` 弹窗的 `Add block` 中。 +We not only need to add it to the page-level `Add block`, but also to the `Add block` in the `Table` block's `Add new` popup. ![img_v3_02b4_fc47fe3a-35a1-4186-999c-0b48e6e001dg](https://static-docs.nocobase.com/img_v3_02b4_fc47fe3a-35a1-4186-999c-0b48e6e001dg.jpg) -我们按照页面级别获取 `name` 的方式获取到 `Table` 区块的 `Add block` 的 `name` 为 `popup:addNew:addBlock`,`Data Blocks` 对应的 name 为 `dataBlocks`。 +Following the method for getting the page-level `name`, the `Table` block's `Add block` `name` is `popup:addNew:addBlock`, and `Data Blocks` corresponds to the name `dataBlocks`. -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/index.tsx`: ```diff import { Plugin } from '@nocobase/client'; @@ -769,13 +769,13 @@ export default PluginInitializerBlockDataModalClient; ![20240529223046](https://static-docs.nocobase.com/20240529223046.png) -#### 7.3 添加到移动端 Add block 中 +#### 7.3 Adding to Mobile Add Block -> 首先要激活移动端插件,参考 [激活插件](/welcome/getting-started/plugin#3-activate-the-plugin) 文档。 +> First, activate the mobile plugin. Refer to the [Activating Plugins](/welcome/getting-started/plugin#3-activate-the-plugin) documentation. -我们可以将其添加到移动端的 `Add block` 中,获取 `name` 的方法这里就不再赘述了。 +We can add it to the mobile `Add block`. The method for getting the `name` is not repeated here. -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/client/index.tsx`: ```ts // ... @@ -792,13 +792,13 @@ export default PluginInitializerBlockDataModalClient; ![20240529223307](https://static-docs.nocobase.com/20240529223307.png) -如果需要更多的 `Add block`,可以继续添加,只需要知道对应的 `name` 即可。 +If you need more `Add block` locations, you can continue adding them by knowing the corresponding `name`. -### 8. 多语言 +### 8. Multi-language Support -#### 8.1 英文 +#### 8.1 English -我们编辑 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/locale/en-US.json` 文件: +Edit `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/locale/en-US.json`: ```diff { @@ -808,9 +808,9 @@ export default PluginInitializerBlockDataModalClient; } ``` -#### 8.2 中文 +#### 8.2 Chinese -我们编辑 `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/locale/zh-CN.json` 文件: +Edit `packages/plugins/@nocobase-sample/plugin-initializer-block-data-modal/src/locale/zh-CN.json`: ```diff { @@ -820,24 +820,24 @@ export default PluginInitializerBlockDataModalClient; } ``` -我们可以通过 [http://localhost:13000/admin/settings/system-settings](http://localhost:13000/admin/settings/system-settings) 添加多个语言,并且在右上角切换语言。 +You can add multiple languages through [http://localhost:13000/admin/settings/system-settings](http://localhost:13000/admin/settings/system-settings) and switch languages in the upper right corner. ![20240611113758](https://static-docs.nocobase.com/20240611113758.png) -## 打包和上传到生产环境 +## Packaging and Uploading to Production Environment -按照 [构建并打包插件](/development/your-fisrt-plugin#构建并打包插件) 文档说明,我们可以打包插件并上传到生产环境。 +Following the [Build and Package Plugin](/development/your-fisrt-plugin#build-and-package-the-plugin) documentation, we can package the plugin and upload it to the production environment. -如果是 clone 的源码,需要先执行一次全量 build,将插件的依赖也构建好。 +If you cloned the source code, you need to run a full build first to build the plugin dependencies. ```bash yarn build ``` -如果是使用的 `create-nocobase-app` 创建的项目,可以直接执行: +If you used `create-nocobase-app` to create the project, you can run: ```bash yarn build @nocobase-sample/plugin-initializer-block-data-modal --tar ``` -这样就可以看到 `storage/tar/@nocobase-sample/plugin-initializer-block-data-modal.tar.gz` 文件了,然后通过[上传的方式](/welcome/getting-started/plugin)进行安装。 +Then you will see the `storage/tar/@nocobase-sample/plugin-initializer-block-data-modal.tar.gz` file, which can be installed through the [upload method](/welcome/getting-started/plugin). diff --git a/docs/en-US/plugin-samples/schema-initializer/block-data.md b/docs/en-US/plugin-samples/schema-initializer/block-data.md index afb1ddb6a8..5a27804679 100644 --- a/docs/en-US/plugin-samples/schema-initializer/block-data.md +++ b/docs/en-US/plugin-samples/schema-initializer/block-data.md @@ -113,7 +113,7 @@ export const Info: FC = withDynamicSchemaProps(({ collectionName, dat }, { displayName: BlockName }) ``` -The `Info` component is essentially a functional component wrapped by `withDynamicSchemaProps`. The [withDynamicSchemaProps](/development/client/ui-schema/what-is-ui-schema#x-component-props-和-x-use-component-props) is a higher-order component used to handle dynamic properties in schemas. +The `Info` component is essentially a functional component wrapped by `withDynamicSchemaProps`. The [withDynamicSchemaProps](/development/client/ui-schema/what-is-ui-schema#x-component-props-and-x-use-component-props) is a higher-order component used to handle dynamic properties in schemas. Without considering `withDynamicSchemaProps`, the `Info` component is a simple functional component. @@ -180,33 +180,16 @@ Then, visit `http://localhost:13000/admin/info-component` to see the correspondi After verification, delete the test page. +### 3. Defining Block Schema +#### 3.1 Defining Block Schema +NocoBase's dynamic pages are rendered through Schema, so we need to define a Schema that will be used to add the `Info` block to the interface. Before implementing this section, we need to understand some basic concepts: +- [UI Schema Protocol](/development/client/ui-schema/what-is-ui-schema): Detailed introduction to the structure of Schema and the role of each attribute +- [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider): Data block provider - - - - - - - - - - - - - -### 3. 定义区块 Schema - -#### 3.1 定义区块 Schema - -NocoBase 的动态页面都是通过 Schema 来渲染,所以我们需要定义一个 Schema,后续用于在界面中添加 `Info` 区块。在实现本小节之前,我们需要先了解一些基础知识: - -- [UI Schema 协议](/development/client/ui-schema/what-is-ui-schema):详细介绍 Schema 的结构和每个属性的作用 -- [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider):数据区块 - -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/schema/index.ts` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/schema/index.ts`: ```ts import { useCollection, useDataBlockRequest } from "@nocobase/client"; @@ -247,27 +230,27 @@ export function getInfoSchema({ dataSource = 'main', collection }) { } ``` -这里有 2 个点需要说明: +There are 2 points to explain here: -- `getInfoSchema()`:之所以定义为函数,因为 `dataSource` 和 `collection` 是动态的,由点击的数据表决定 -- `useInfoProps()`:用于处理 `Info` 组件的动态属性,并且因为要存到数据库,所以这里的值类型为 string 类型。 +- `getInfoSchema()`: Defined as a function because `dataSource` and `collection` are dynamic, determined by the clicked data table +- `useInfoProps()`: Used to handle dynamic properties of the `Info` component, and because it needs to be stored in the database, the value type here is string -`getInfoSchema()`:返回 Info 的 Schema - - `type: 'void'`:表示没有任何数据 - - `x-decorator: 'DataBlockProvider'`:数据区块提供者,用于提供数据,更多关于 DataBlockProvider 可以查看 [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) - - `x-decorator-props`:`DataBlockProvider` 的属性 - - `dataSource`:数据源 - - `collection`:数据表 - - `action: 'list'`:操作类型,这里是 `list`,获取数据列表 - - `x-component: 'CardItem'`:[CardItem 组件](https://client.docs.nocobase.com/components/card-item),目前的区块都是被包裹在卡片中的,用于提供样式、布局和拖拽等功能 - - `properties`:子节点 - - `info`:信息区块 +`getInfoSchema()`: Returns the Info Schema + - `type: 'void'`: Indicates no data + - `x-decorator: 'DataBlockProvider'`: Data block provider for providing data. For more about DataBlockProvider, see [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) + - `x-decorator-props`: Properties of `DataBlockProvider` + - `dataSource`: Data source + - `collection`: Data table + - `action: 'list'`: Operation type, here it's `list`, to get the data list + - `x-component: 'CardItem'`: [CardItem component](https://client.docs.nocobase.com/components/card-item), currently all blocks are wrapped in cards for styling, layout, and drag-and-drop functionality + - `properties`: Child nodes + - `info`: Info block -`useInfoProps()`:Info 组件的动态属性 - - [useCollection](https://client.docs.nocobase.com/core/data-source/collection-provider#usecollection):获取当前数据表,由 [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) 提供 - - [useDataBlockRequest](https://client.docs.nocobase.com/core/data-block/data-block-request-provider#usedatablockrequest) 获取数据区块请求,由 [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) 提供 +`useInfoProps()`: Dynamic properties of the Info component + - [useCollection](https://client.docs.nocobase.com/core/data-source/collection-provider#usecollection): Gets the current data table, provided by [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) + - [useDataBlockRequest](https://client.docs.nocobase.com/core/data-block/data-block-request-provider#usedatablockrequest): Gets the data block request, provided by [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) -上述 Schema 转为 React 组件后相当于: +The above Schema translates to the following React component: ```tsx | pure @@ -277,9 +260,9 @@ export function getInfoSchema({ dataSource = 'main', collection }) { ``` -#### 3.2 注册 scope +#### 3.2 Registering Scope -我们需要将 `useInfoProps` 注册到系统中,这样 [x-use-component-props](/development/client/ui-schema/what-is-ui-schema#x-component-props-和-x-use-component-props) 才能找到对应的 scope。 +We need to register `useInfoProps` in the system so that [x-use-component-props](/development/client/ui-schema/what-is-ui-schema#x-component-props-and-x-use-component-props) can find the corresponding scope. ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -296,11 +279,11 @@ export class PluginInitializerBlockDataClient extends Plugin { export default PluginInitializerBlockDataClient; ``` -更多关于 Scope 的说明可以查看 [全局注册 Component 和 Scope](/plugin-samples/component-and-scope/global) +For more about Scope, see [Globally Registering Component and Scope](/plugin-samples/component-and-scope/global) -#### 3.3 验证区块 Schema +#### 3.3 Verifying Block Schema -同验证组件一样,我们可以通过临时页面验证或者文档示例验证的方式来验证 Schema 是否符合需求。我们这里以临时页面验证为例: +Like component verification, we can verify if the Schema meets the requirements through temporary page verification or documentation example verification. Here we use temporary page verification: ```tsx | pure import React from 'react'; @@ -331,18 +314,18 @@ export class PluginInitializerBlockDataClient extends Plugin { export default PluginInitializerBlockDataClient; ``` -- [SchemaComponentOptions](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponentoptions):用于传递 Schema 中所需的 `components` 和 `scope`,具体的可查看 [局部注册 Component 和 Scope](/plugin-samples/component-and-scope/local) -- [SchemaComponent](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponent-1):用于渲染 Schema +- [SchemaComponentOptions](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponentoptions): Used to pass `components` and `scope` required by the Schema. For details, see [Locally Registering Component and Scope](/plugin-samples/component-and-scope/local) +- [SchemaComponent](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponent-1): Used to render Schema -我们访问 [http://localhost:13000/admin/info-schema](http://localhost:13000/admin/info-schema) 就可以看到对应测试页面的内容了。 +Visit [http://localhost:13000/admin/info-schema](http://localhost:13000/admin/info-schema) to see the corresponding content on the test page. ![20240526170053](https://static-docs.nocobase.com/20240526170053.png) -验证完毕后需要删除测试页面。 +After verification, delete the test page. -### 4. 定义 Schema Initializer Item +### 4. Defining Schema Initializer Item -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/initializer/index.tsx` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/initializer/index.tsx`: ```tsx | pure import React from 'react'; @@ -372,57 +355,30 @@ export const infoInitializerItem: SchemaInitializerItemType = { } ``` -实现数据区块的效果核心是 DataBlockInitializer(文档 TODO)。 - -`infoInitializerItem`: - - `Component`:与 [添加简单区块 Simple Block](/plugin-samples/schema-initializer/block-simple) 中使用的是 `type`,这里使用的是 `Component`,[2 种定义方式](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#two-ways-to-define-component-and-type) 都是可以的 - - `useComponentProps`:`DataBlockInitializer` 组件的属性 - - `title`:标题 - - `icon`:图标,更多图标可以查看 [Ant Design Icons](https://ant.design/components/icon/) - - `componentType`:组件类型,这里是 `Info` - - `onCreateBlockSchema`:当点击数据表后的回调 - - `item`:点击的数据表信息 - - `item.name`:数据表名称 - - `item.dataSource`:数据表所属的数据源 - - [useSchemaInitializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializer):提供了插入 Schema 的方法 - - `"x-toolbar": "BlockSchemaToolbar"`:`BlockSchemaToolbar` 用于左上角显示当前数据表,一般和 `DataBlockProvider` 搭配使用 - -更多关于 Schema Initializer 的定义可以参考 [Schema Initializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer) 文档。 - - - - - - - - - - - - - - - - - - - - - - - - - +The core of implementing data blocks is DataBlockInitializer (documentation TODO). +`infoInitializerItem`: + - `Component`: Unlike [Adding a Simple Block](/plugin-samples/schema-initializer/block-simple) which uses `type`, here we use `Component`. [Both definition methods](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#two-ways-to-define-component-and-type) are valid + - `useComponentProps`: Properties of the `DataBlockInitializer` component + - `title`: Title + - `icon`: Icon, more icons can be found at [Ant Design Icons](https://ant.design/components/icon/) + - `componentType`: Component type, here it's `Info` + - `onCreateBlockSchema`: Callback when a data table is clicked + - `item`: Information about the clicked data table + - `item.name`: Data table name + - `item.dataSource`: Data source the data table belongs to + - [useSchemaInitializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializer): Provides methods for inserting Schema + - `"x-toolbar": "BlockSchemaToolbar"`: `BlockSchemaToolbar` displays the current data table in the upper left corner, usually used with `DataBlockProvider` +For more details on defining Schema Initializer, see the [Schema Initializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer) documentation. -### 5. 实现 Schema Settings +### 5. Implementing Schema Settings -#### 5.1 定义 Schema Settings +#### 5.1 Defining Schema Settings -一个完整的 Block 还需要有 Schema Settings,用于配置一些属性和操作,但 Schema Settings 不是本示例的重点,所以我们这里仅有一个 `remove` 操作。 +A complete Block also needs Schema Settings for configuring properties and operations. However, Schema Settings is not the focus of this example, so we only include a `remove` operation here. -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/settings/index.ts` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/settings/index.ts`: ```ts import { SchemaSettings } from "@nocobase/client"; @@ -445,7 +401,7 @@ export const infoSettings = new SchemaSettings({ }) ``` -#### 5.2 注册 Schema Settings +#### 5.2 Registering Schema Settings ```ts import { Plugin } from '@nocobase/client'; @@ -461,9 +417,9 @@ export class PluginInitializerBlockDataClient extends Plugin { export default PluginInitializerBlockDataClient; ``` -#### 5.3 使用 Schema Settings +#### 5.3 Using Schema Settings -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/schema/index.ts` 文件的 `getInfoSchema` 方法,将 `x-settings` 设置为 `infoSettings.name`。 +Modify the `getInfoSchema` method in `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/schema/index.ts` to set `x-settings` to `infoSettings.name`. ```diff + import { infoSettings } from "../settings"; @@ -478,21 +434,21 @@ export function getInfoSchema({ dataSource = 'main', collection }) { } ``` -### 6. 添加到 Add block 中 +### 6. Adding to Add Block -系统中有很多个 `Add block` 按钮,但他们的 **name 是不同的**。 +There are many `Add block` buttons in the system, but their **names are different**. ![img_v3_02b4_049b0a62-8e3b-420f-adaf-a6350d84840g](https://static-docs.nocobase.com/img_v3_02b4_049b0a62-8e3b-420f-adaf-a6350d84840g.jpg) -#### 6.1 添加到页面级别 Add block 中 +#### 6.1 Adding to Page-Level Add Block -如果我们需要添加到页面级别的 `Add block` 中,我们需要知道对应的 `name`,我们可以通过 TODO 方式查看对应的 `name`。 +If we need to add to the page-level `Add block`, we need to know the corresponding `name`. We can find the corresponding `name` through the TODO method. TODO -通过上图可以看到页面级别的 `Add block` 对应的 name 为 `page:addBlock`,`Data Blocks` 对应的 name 为 `dataBlocks`。 +From the image above, we can see that the page-level `Add block` corresponds to the name `page:addBlock`, and `Data Blocks` corresponds to the name `dataBlocks`. -然后我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/index.tsx`: ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -517,15 +473,15 @@ export default PluginDataBlockInitializerClient; -#### 6.2 添加到弹窗 Add block 中 +#### 6.2 Adding to Popup Add Block -我们不仅需要将其添加到页面级别的 `Add block` 中,还需要将其添加到 `Table` 区块 `Add new` 弹窗的 `Add block` 中。 +We not only need to add it to the page-level `Add block`, but also to the `Add block` in the `Table` block's `Add new` popup. ![img_v3_02b4_fc47fe3a-35a1-4186-999c-0b48e6e001dg](https://static-docs.nocobase.com/img_v3_02b4_fc47fe3a-35a1-4186-999c-0b48e6e001dg.jpg) -我们按照页面级别获取 `name` 的方式获取到 `Table` 区块的 `Add block` 的 `name` 为 `popup:addNew:addBlock`,`Data Blocks` 对应的 name 为 `dataBlocks`。 +Following the method for getting the page-level `name`, the `Table` block's `Add block` `name` is `popup:addNew:addBlock`, and `Data Blocks` corresponds to the name `dataBlocks`. -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/index.tsx`: ```diff import { Plugin } from '@nocobase/client'; @@ -553,13 +509,13 @@ export default PluginDataBlockInitializerClient; ![img_v3_02b4_7062bfab-5a7b-439c-b385-92c5704b6b3g](https://static-docs.nocobase.com/img_v3_02b4_7062bfab-5a7b-439c-b385-92c5704b6b3g.jpg) -#### 6.3 添加到移动端 Add block 中 +#### 6.3 Adding to Mobile Add Block -> 首先要激活移动端插件,参考 [激活插件](/welcome/getting-started/plugin#3-activate-the-plugin) 文档。 +> First, activate the mobile plugin. Refer to the [Activating Plugins](/welcome/getting-started/plugin#3-activate-the-plugin) documentation. -我们可以将其添加到移动端的 `Add block` 中,获取 `name` 的方法这里就不再赘述了。 +We can add it to the mobile `Add block`. The method for getting the `name` is not repeated here. -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client/index.tsx`: ```diff import { Plugin } from '@nocobase/client'; @@ -584,22 +540,22 @@ export class PluginDataBlockInitializerClient extends Plugin { export default PluginDataBlockInitializerClient; ``` -如果需要更多的 `Add block`,可以继续添加,只需要知道对应的 `name` 即可。 +If you need more `Add block` locations, you can continue adding them by knowing the corresponding `name`. -## 打包和上传到生产环境 +## Packaging and Uploading to Production Environment -按照 [构建并打包插件](/development/your-fisrt-plugin#构建并打包插件) 文档说明,我们可以打包插件并上传到生产环境。 +Following the [Build and Package Plugin](/development/your-fisrt-plugin#build-and-package-the-plugin) documentation, we can package the plugin and upload it to the production environment. -如果是 clone 的源码,需要先执行一次全量 build,将插件的依赖也构建好。 +If you cloned the source code, you need to run a full build first to build the plugin dependencies. ```bash yarn build ``` -如果是使用的 `create-nocobase-app` 创建的项目,可以直接执行: +If you used `create-nocobase-app` to create the project, you can run: ```bash yarn build @nocobase-sample/plugin-initializer-block-data --tar ``` -这样就可以看到 `storage/tar/@nocobase-sample/plugin-initializer-block-data.tar.gz` 文件了,然后通过[上传的方式](/welcome/getting-started/plugin)进行安装。 +Then you will see the `storage/tar/@nocobase-sample/plugin-initializer-block-data.tar.gz` file, which can be installed through the [upload method](/welcome/getting-started/plugin). diff --git a/docs/en-US/plugin-samples/schema-initializer/block-simple.md b/docs/en-US/plugin-samples/schema-initializer/block-simple.md index 329eee3bc5..9701bf9927 100644 --- a/docs/en-US/plugin-samples/schema-initializer/block-simple.md +++ b/docs/en-US/plugin-samples/schema-initializer/block-simple.md @@ -1,28 +1,28 @@ -# 添加新的简单区块 Simple Block +# Adding a Simple Block -## 场景说明 +## Scenario Description -NocoBase 有很多 `Add block` 按钮用于向界面添加区块。其中有些和数据表有关系的被成为数据区块 `Data Block`,有些和数据表无关的被称为简单区块 `Simple Block`。 +NocoBase has many `Add block` buttons used to add blocks to the interface. Some blocks that are related to data tables are called Data Blocks, while others that are not related to data tables are called Simple Blocks. ![img_v3_02b4_a4529308-62e3-4fa7-be4d-5dcae332c49g](https://static-docs.nocobase.com/img_v3_02b4_a4529308-62e3-4fa7-be4d-5dcae332c49g.jpg) -但是目前已有的区块类型不一定满足我们的需求,我们就需要根据需求自定开发一些区块,本篇文章就是针对简单区块 `Simple Block` 进行说明。 +However, the existing block types may not fully meet our needs, so we need to custom-develop some blocks according to our requirements. This article specifically explains how to create Simple Blocks. -## 示例说明 +## Example Explanation -本实例会创建一个图片区块类型,并将其添加到 `Page`、`Table` 以及移动端的 `Add block` 中。 +This example will create an Image block type and add it to the `Page`, `Table`, and mobile `Add block` sections. -本实例主要为了演示 initializer 的使用,更多关于区块扩展可以查看 [区块扩展](/plugin-samples/block) 文档。 +This example primarily demonstrates the usage of the initializer. For more information on block extensions, refer to the [Block Extension](/plugin-samples/block) documentation. -本文档完整的示例代码可以在 [plugin-samples](https://github.com/nocobase/plugin-samples/tree/main/packages/plugins/%40nocobase-sample/plugin-initializer-block-simple) 中查看。 +The complete sample code for this document can be found in the [plugin-samples repository](https://github.com/nocobase/plugin-samples/tree/main/packages/plugins/%40nocobase-sample/plugin-initializer-block-simple). -## 初始化插件 +## Initializing the Plugin -我们按照 [编写第一个插件](/development/your-fisrt-plugin) 文档说明,如果没有一个项目,可以先创建一个项目,如果已经有了或者是 clone 的源码,则跳过这一步。 +Following the instructions in the [Creating Your First Plugin](/development/your-fisrt-plugin) document, if you don't have a project yet, you can create one first. If you already have a project or have cloned the source code, skip this step. ```bash yarn create nocobase-app my-nocobase-app -d postgres @@ -31,65 +31,65 @@ yarn install yarn nocobase install ``` -然后初始化一个插件,并添加到系统中: +Next, initialize a plugin and add it to the system: ```bash yarn pm create @nocobase-sample/plugin-initializer-block-simple yarn pm enable @nocobase-sample/plugin-initializer-block-simple ``` -然后启动项目即可: +Then, start the project: ```bash yarn dev ``` -然后登录后访问 [http://localhost:13000/admin/pm/list/local/](http://localhost:13000/admin/pm/list/local/) 就可以看到插件已经安装并启用了。 +After logging in, visit [http://localhost:13000/admin/pm/list/local/](http://localhost:13000/admin/pm/list/local/) to see that the plugin has been installed and enabled. -## 功能实现 +## Feature Implementation -在实现本示例之前,我们需要先了解一些基础知识: +Before implementing this example, we need to understand some basic concepts: -- [SchemaInitializer 教程](/development/client/ui-schema/initializer):用于向界面内添加各种区块、字段、操作等 -- [SchemaInitializer API](https://client.docs.nocobase.com/core/ui-schema/schema-initializer):用于向界面内添加各种区块、字段、操作等 -- [UI Schema 协议](/development/client/ui-schema/what-is-ui-schema):详细介绍 Schema 的结构和每个属性的作用 -- [Designable 设计器](/development/client/ui-schema/designable):用于修改 Schema +- [SchemaInitializer Tutorial](/development/client/ui-schema/initializer): Used to add various blocks, fields, operations, etc., to the interface +- [SchemaInitializer API](https://client.docs.nocobase.com/core/ui-schema/schema-initializer): Provides an API for adding various blocks, fields, operations, etc., to the interface +- [UI Schema Protocol](/development/client/ui-schema/what-is-ui-schema): Detailed introduction to the structure of Schema and the role of each attribute +- [Designable Designer](/development/client/ui-schema/designable): Used for modifying Schema ```bash . -├── client # 客户端插件 -│ ├── initializer # 初始化器 -│ ├── component # 区块组件 -│ ├── index.tsx # 客户端插件入口 -│ ├── locale.ts # 多语言工具函数 -│ ├── constants.ts # 常量 +├── client # Client-side plugin +│ ├── initializer # Initializer +│ ├── component # Block component +│ ├── index.tsx # Client-side plugin entry point +│ ├── locale.ts # Multi-language utility functions +│ ├── constants.ts # Constants │ ├── schema # Schema │ └── settings # Schema Settings -├── locale # 多语言文件 -│ ├── en-US.json # 英语 -│ └── zh-CN.json # 中文 -├── index.ts # 服务端插件入口 -└── server # 服务端插件 +├── locale # Multi-language files +│ ├── en-US.json # English +│ └── zh-CN.json # Chinese +├── index.ts # Server-side plugin entry point +└── server # Server-side plugin ``` -### 1. 定义名称 +### 1. Defining Names -我们首先需要定义区块名称,它将会使用在各个地方。 +First, we need to define the block name, which will be used in various places. -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/constants.ts`: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/constants.ts`: ```ts export const BlockName = 'Image'; export const BlockNameLowercase = BlockName.toLowerCase(); ``` -### 2. 实现区块组件 +### 2. Implementing Block Components -#### 2.1 定义区块组件 +#### 2.1 Defining the Block Component -本示例要做的是一个图片区块组件,我们取名为 `Image`。 +In this example, we will create an Image block component named `Image`. -所以我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/component/Image.tsx` 文件,其内容如下: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/component/Image.tsx` with the following content: ```tsx | pure import React, { FC } from 'react'; @@ -106,19 +106,19 @@ export const Image: FC<{ height?: number }> = withDynamicSchemaProps(({ height = }, { displayName: BlockName }) ``` -`Image` 组件整体来说是一个被 `withDynamicSchemaProps` 包裹的函数组件,[withDynamicSchemaProps](/development/client/ui-schema/what-is-ui-schema#x-component-props-和-x-use-component-props) 是一个高阶组件,用于处理 Schema 中的的动态属性。 +The `Image` component is essentially a functional component wrapped by `withDynamicSchemaProps`. The [withDynamicSchemaProps](/development/client/ui-schema/what-is-ui-schema#x-component-props-and-x-use-component-props) is a higher-order component used to handle dynamic properties in Schema. -如果不看 `withDynamicSchemaProps` 的话,`Image` 组件就是一个简单的函数组件。 +Without considering `withDynamicSchemaProps`, the `Image` component is a simple functional component. -然后将其在 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/component/index.ts` 中导出: +Then export it in `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/component/index.ts`: ```tsx | pure export * from './Image'; ``` -#### 2.2 注册区块组件 +#### 2.2 Registering the Block Component -我们需要将 `Image` 通过插件注册到系统中。 +We need to register the `Image` component in the system via the plugin. ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -133,14 +133,14 @@ export class PluginInitializerBlockSimpleClient extends Plugin { export default PluginInitializerBlockSimpleClient; ``` -#### 2.3 验证区块组件 +#### 2.3 Verifying the Block Component -组件验证方式有 2 种: +There are two ways to verify the component: -- 临时页面验证:我们可以临时建一个页面,然后渲染 `Image` 组件,查看是否符合需求 -- 文档示例验证:可以启动文档 `yarn doc plugins/@nocobase-sample/plugin-initializer-block-simple`,通过写文档示例的方式验证是否符合需求(TODO) +- Temporary page verification: You can create a temporary page, render the `Image` component, and check if it meets the requirements +- Documentation example verification: You can start the documentation with `yarn doc plugins/@nocobase-sample/plugin-initializer-block-simple` and verify by writing documentation examples (TODO) -我们以 `临时页面验证` 为例,我们新建一个页面,根据属性参数添加一个或者多个 `Image` 组件,查看是否符合需求。 +For this example, we'll use **Temporary Page Verification**. Create a page and add one or more `Image` components based on the parameters, then check if it meets the requirements. ```tsx | pure import React from 'react'; @@ -171,21 +171,21 @@ export class PluginInitializerBlockSimpleClient extends Plugin { export default PluginInitializerBlockSimpleClient; ``` -然后访问 `http://localhost:13000/admin/image-component` 就可以看到对应测试页面的内容了。 +Then visit `http://localhost:13000/admin/image-component` to see the corresponding content on the test page. ![20240526165057](https://static-docs.nocobase.com/20240526165057.png) -验证完毕后需要删除测试页面。 +After verification, delete the test page. -### 3. 定义区块 Schema +### 3. Defining Block Schema -#### 3.1 定义区块 Schema +#### 3.1 Defining Block Schema -NocoBase 的动态页面都是通过 Schema 来渲染,所以我们需要定义一个 Schema,后续用于在界面中添加 `Image` 区块。在实现本小节之前,我们需要先了解一些基础知识: +NocoBase's dynamic pages are rendered through Schema, so we need to define a Schema that will be used later to add the `Image` block to the interface. Before implementing this section, we need to understand some basic concepts: -- [UI Schema 协议](/development/client/ui-schema/what-is-ui-schema):详细介绍 Schema 的结构和每个属性的作用 +- [UI Schema Protocol](/development/client/ui-schema/what-is-ui-schema): Detailed introduction to the structure of Schema and the role of each attribute -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/schema/index.ts` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/schema/index.ts`: ```tsx | pure import { ISchema } from "@nocobase/client"; @@ -202,13 +202,13 @@ export const imageSchema: ISchema = { }; ``` -关于 `imageSchema` 的详细说明: +Detailed explanation of `imageSchema`: -- `type`:类型,这里是 `void`,表示纯 UI 节点,没有数据 -- `x-decorator`:装饰器,这里是 [CardItem 组件](https://client.docs.nocobase.com/components/card-item),目前的区块都是被包裹在卡片中的,用于提供样式、布局和拖拽等功能 -- `x-component`:组件,这里是 `Image`,就是我们刚定义的组件 +- `type`: Type, here it's `void`, indicating a pure UI node with no data +- `x-decorator`: Decorator, here it's the [CardItem component](https://client.docs.nocobase.com/components/card-item). Currently, all blocks are wrapped in cards, which provides styling, layout, and drag-and-drop functionality +- `x-component`: Component, here it's `Image`, the component we just defined -上述 Schema 转为 React 组件后相当于: +The above Schema translates to the following React component: ```tsx | pure @@ -216,9 +216,9 @@ export const imageSchema: ISchema = { ``` -#### 3.2 验证区块 Schema +#### 3.2 Verifying Block Schema -同验证组件一样,我们可以通过临时页面验证或者文档示例验证的方式来验证 Schema 是否符合需求。我们这里以临时页面验证为例: +Like component verification, we can verify if the Schema meets the requirements through temporary page verification or documentation example verification. Here we use temporary page verification: ```tsx | pure import React from 'react'; @@ -244,17 +244,17 @@ export class PluginInitializerBlockSimpleClient extends Plugin { export default PluginInitializerBlockSimpleClient; ``` -关于 `SchemaComponent` 的详细说明可以查看 [SchemaComponent](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponent-1) 文档。 +For more details on `SchemaComponent`, see the [SchemaComponent](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponent-1) documentation. -我们访问 [http://localhost:13000/admin/image-schema](http://localhost:13000/admin/image-schema) 就可以看到对应测试页面的内容了。 +Visit [http://localhost:13000/admin/image-schema](http://localhost:13000/admin/image-schema) to see the corresponding content on the test page. ![20240526165408](https://static-docs.nocobase.com/20240526165408.png) -验证完毕后需要删除测试页面。 +After verification, delete the test page. -### 4. 定义 Schema Initializer Item +### 4. Defining Schema Initializer Item -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/initializer/index.ts` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/initializer/index.ts`: ```ts import { SchemaInitializerItemType, useSchemaInitializer } from '@nocobase/client'; @@ -280,22 +280,22 @@ export const imageInitializerItem: SchemaInitializerItemType = { } ``` -- `type`:类型,这里是 `item`,表示是一个文本,其有点击事件,点击后可以插入一个新的 Schema -- `name`:唯一标识符,用于区分不同的 Schema Item 和增删改查操作 -- `icon`:图标,更多 icon 可以参考 [Ant Design Icons](https://ant.design/components/icon) -- `useComponentProps`:返回一个对象,包含 `title` 和 `onClick` 两个属性,`title` 是显示的文本,`onClick` 是点击后的回调函数 -- [useSchemaInitializer()](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializer):用于获取 `SchemaInitializerContext` 上下文 - - `insert`:插入一个新的 Schema +- `type`: Type, here it's `item`, indicating text with a click event that can insert a new Schema when clicked +- `name`: Unique identifier, used to distinguish different Schema Items and CRUD operations +- `icon`: Icon, more icons can be found in [Ant Design Icons](https://ant.design/components/icon) +- `useComponentProps`: Returns an object containing `title` and `onClick` properties. `title` is the displayed text, and `onClick` is the callback function when clicked +- [useSchemaInitializer()](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializer): Used to get the `SchemaInitializerContext` context + - `insert`: Inserts a new Schema -更多关于 Schema Item 的定义可以参考 [Schema Initializer Item](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#built-in-components-and-types) 文档。 +For more details on defining Schema Items, see the [Schema Initializer Item](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#built-in-components-and-types) documentation. -### 5. 实现 Schema Settings +### 5. Implementing Schema Settings -#### 5.1 定义 Schema Settings +#### 5.1 Defining Schema Settings -一个完整的 Block 还需要有 Schema Settings,用于配置一些属性和操作,但 Schema Settings 不是本示例的重点,所以我们这里仅有一个 `remove` 操作。 +A complete Block also needs Schema Settings for configuring properties and operations. However, Schema Settings is not the focus of this example, so we only include a `remove` operation here. -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/settings/index.ts` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/settings/index.ts`: ```ts | pure import { SchemaSettings } from "@nocobase/client"; @@ -319,10 +319,10 @@ export const imageSettings = new SchemaSettings({ ``` - componentProps - - `removeParentsIfNoChildren`:如果没有子节点,是否删除父节点 - - `breakRemoveOn`:删除时的中断条件。因为 `Add Block` 会自动将子项的包裹在 `Grid` 中,所以这里设置 `breakRemoveOn: { 'x-component': 'Grid' }`,当删除 `Grid` 时,不再向上删除。 + - `removeParentsIfNoChildren`: Whether to delete the parent node if there are no children + - `breakRemoveOn`: The break condition when removing. Since `Add Block` automatically wraps child items in `Grid`, we set `breakRemoveOn: { 'x-component': 'Grid' }` so that when deleting `Grid`, it doesn't continue deleting upwards. -#### 5.2 注册 Schema Settings +#### 5.2 Registering Schema Settings ```ts import { Plugin } from '@nocobase/client'; @@ -338,9 +338,9 @@ export class PluginInitializerBlockSimpleClient extends Plugin { export default PluginInitializerBlockSimpleClient; ``` -#### 5.3 使用 Schema Settings +#### 5.3 Using Schema Settings -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/schema/index.ts` 中的 `imageSchema`: +Modify `imageSchema` in `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/schema/index.ts`: ```diff + import { imageSettings } from "../settings"; @@ -353,21 +353,21 @@ const imageSchema: ISchema = { }; ``` -### 6. 添加到 Add block 中 +### 6. Adding to Add Block -系统中有很多个 `Add block` 按钮,但他们的 **name 是不同的**。 +There are many `Add block` buttons in the system, but their **names are different**. ![img_v3_02b4_049b0a62-8e3b-420f-adaf-a6350d84840g](https://static-docs.nocobase.com/img_v3_02b4_049b0a62-8e3b-420f-adaf-a6350d84840g.jpg) -#### 6.1 添加到页面级别 Add block 中 +#### 6.1 Adding to Page-Level Add Block -如果我们需要添加到页面级别的 `Add block` 中,我们需要知道对应的 `name`,我们可以通过 TODO 方式查看对应的 `name`。 +If we need to add to the page-level `Add block`, we need to know the corresponding `name`. We can find the corresponding `name` through the TODO method. TODO -通过上图可以看到页面级别的 `Add block` 对应的 name 为 `page:addBlock`,`Other Blocks` 对应的 name 为 `otherBlocks`。 +From the image above, we can see that the page-level `Add block` corresponds to the name `page:addBlock`, and `Other Blocks` corresponds to the name `otherBlocks`. -然后我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx`: ```tsx | pure import { Plugin } from '@nocobase/client'; @@ -387,27 +387,27 @@ export class PluginInitializerBlockSimpleClient extends Plugin { export default PluginInitializerBlockSimpleClient; ``` -上述代码首先将 `Image` 组件注册到系统中,这样前面 `imageSchema` 定义的 `x-component: 'Image'` 才能找到对应的组件,更多详细解释可以查看 [全局注册 Component 和 Scope](/plugin-samples/component-and-scope/global)。 +The above code first registers the `Image` component in the system, so the `x-component: 'Image'` defined in `imageSchema` can find the corresponding component. For more details, see [Globally Registering Component and Scope](/plugin-samples/component-and-scope/global). -然后将 `imageSettings` 通过 [app.schemaSettingsManager.add](https://client.docs.nocobase.com/core/ui-schema/schema-settings-manager#schemasettingsmanageradd) 添加到系统中。 +Then it adds `imageSettings` to the system through [app.schemaSettingsManager.add](https://client.docs.nocobase.com/core/ui-schema/schema-settings-manager#schemasettingsmanageradd). -然后使用 [app.schemaInitializerManager.addItem](https://client.docs.nocobase.com/core/ui-schema/schema-initializer-manager#schemainitializermanageradditem) 将 `imageInitializerItem` 添加对应 Initializer 子项中,其中 `page:addBlock` 是页面上 `Add block` 的 name,`otherBlocks` 是其父级的 name。 +Then it uses [app.schemaInitializerManager.addItem](https://client.docs.nocobase.com/core/ui-schema/schema-initializer-manager#schemainitializermanageradditem) to add `imageInitializerItem` to the corresponding Initializer sub-item, where `page:addBlock` is the name of the `Add block` on the page, and `otherBlocks` is its parent name. -然后我们 hover `Add block` 按钮,就可以看到 `Image` 这个新的区块类型了,点击 `Image`,就可以添加一个新的 `Image` 区块了。 +Now hover over the `Add block` button to see `Image` as a new block type. Click `Image` to add a new `Image` block. -#### 6.2 添加到弹窗 Add block 中 +#### 6.2 Adding to Popup Add Block -我们不仅需要将其添加到页面级别的 `Add block` 中,还需要将其添加到 `Table` 区块 `Add new` 弹窗的 `Add block` 中。 +We not only need to add it to the page-level `Add block`, but also to the `Add block` in the `Table` block's `Add new` popup. ![img_v3_02b4_fc47fe3a-35a1-4186-999c-0b48e6e001dg](https://static-docs.nocobase.com/img_v3_02b4_fc47fe3a-35a1-4186-999c-0b48e6e001dg.jpg) -我们按照页面级别获取 `name` 的方式获取到 `Table` 区块的 `Add block` 的 `name` 为 `popup:addNew:addBlock`,`Other Blocks` 对应的 name 为 `otherBlocks`。 +Following the method for getting the page-level `name`, the `Table` block's `Add block` `name` is `popup:addNew:addBlock`, and `Other Blocks` corresponds to the name `otherBlocks`. -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx`: ```diff export class PluginInitializerBlockSimpleClient extends Plugin { @@ -423,13 +423,13 @@ export class PluginInitializerBlockSimpleClient extends Plugin { ![img_v3_02b4_7062bfab-5a7b-439c-b385-92c5704b6b3g](https://static-docs.nocobase.com/img_v3_02b4_7062bfab-5a7b-439c-b385-92c5704b6b3g.jpg) -#### 6.3 添加到移动端 Add block 中 +#### 6.3 Adding to Mobile Add Block -> 首先要激活移动端插件,参考 [激活插件](/welcome/getting-started/plugin#3-activate-the-plugin) 文档。 +> First, activate the mobile plugin. Refer to the [Activating Plugins](/welcome/getting-started/plugin#3-activate-the-plugin) documentation. -我们可以将其添加到移动端的 `Add block` 中,获取 `name` 的方法这里就不再赘述了。 +We can add it to the mobile `Add block`. The method for getting the `name` is not repeated here. -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx` 文件: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx`: ```diff export class PluginInitializerBlockSimpleClient extends Plugin { @@ -446,22 +446,22 @@ export class PluginInitializerBlockSimpleClient extends Plugin { ![img_v3_02b4_ec873b25-5a09-4f3a-883f-1d722035799g](https://static-docs.nocobase.com/img_v3_02b4_ec873b25-5a09-4f3a-883f-1d722035799g.jpg) -如果需要更多的 `Add block`,可以继续添加,只需要知道对应的 `name` 即可。 +If you need more `Add block` locations, you can continue adding them by knowing the corresponding `name`. -## 打包和上传到生产环境 +## Packaging and Uploading to Production Environment -按照 [构建并打包插件](/development/your-fisrt-plugin#构建并打包插件) 文档说明,我们可以打包插件并上传到生产环境。 +Following the [Build and Package Plugin](/development/your-fisrt-plugin#build-and-package-the-plugin) documentation, we can package the plugin and upload it to the production environment. -如果是 clone 的源码,需要先执行一次全量 build,将插件的依赖也构建好。 +If you cloned the source code, you need to run a full build first to build the plugin dependencies. ```bash yarn build ``` -如果是使用的 `create-nocobase-app` 创建的项目,可以直接执行: +If you used `create-nocobase-app` to create the project, you can run: ```bash yarn build @nocobase-sample/plugin-initializer-block-simple --tar ``` -这样就可以看到 `storage/tar/@nocobase-sample/plugin-initializer-block-simple.tar.gz` 文件了,然后通过[上传的方式](/welcome/getting-started/plugin)进行安装。 +Then you will see the `storage/tar/@nocobase-sample/plugin-initializer-block-simple.tar.gz` file, which can be installed through the [upload method](/welcome/getting-started/plugin). diff --git a/docs/en-US/plugin-samples/schema-initializer/configure-actions.md b/docs/en-US/plugin-samples/schema-initializer/configure-actions.md index e1521e91c9..43e47f61a6 100644 --- a/docs/en-US/plugin-samples/schema-initializer/configure-actions.md +++ b/docs/en-US/plugin-samples/schema-initializer/configure-actions.md @@ -1,24 +1,24 @@ -# 区块内嵌的 Initializer - 配置操作 +# Block Embedded Initializer - Configure Actions -## 场景说明 +## Scenario Description -如果新创建的区块是一个复杂的数据区块,那么它内部可能包含多个动态添加的部分,其中 `Configure actions` 对应的 initializer 主要是负责动态添加一些按钮实现各种操作。例如 `Details` 区块,我们可以通过 `Configure actions` 添加 `Edit`、`Print` 等按钮。 +If a newly created block is a complex data block, it may contain multiple dynamically added parts. The `Configure actions` initializer is primarily responsible for dynamically adding buttons to implement various operations. For example, in a `Details` block, we can add `Edit`, `Print`, and other buttons through `Configure actions`. ![img_v3_02b4_9b80a4a0-6d9b-4e53-a544-f92c17d81d2g](https://static-docs.nocobase.com/img_v3_02b4_9b80a4a0-6d9b-4e53-a544-f92c17d81d2g.jpg) -## 示例说明 +## Example Explanation -本实例会在 [添加数据区块 Data Block](/plugin-samples/schema-initializer/data-block) 基础上继续实现类似 `Details` 区块的效果,通过 `Configure actions` 来配置按钮。 +This example will continue from [Adding a Data Block](/plugin-samples/schema-initializer/data-block) to implement a `Details` block-like effect, configuring buttons through `Configure actions`. -本文档完整的示例代码可以在 [plugin-samples](https://github.com/nocobase/plugin-samples/tree/main/packages/plugins/%40nocobase-sample/plugin-initializer-configure-actions) 中查看。 +The complete sample code for this document can be found in [plugin-samples](https://github.com/nocobase/plugin-samples/tree/main/packages/plugins/%40nocobase-sample/plugin-initializer-configure-actions). -## 初始化插件 +## Initializing the Plugin -我们按照 [编写第一个插件](/development/your-fisrt-plugin) 文档说明,如果没有一个项目,可以先创建一个项目,如果已经有了或者是 clone 的源码,则跳过这一步。 +Following the instructions in the [Creating Your First Plugin](/development/your-fisrt-plugin) document, if you don't have a project yet, you can create one first. If you already have a project or have cloned the source code, skip this step. ```bash yarn create nocobase-app my-nocobase-app -d postgres @@ -27,35 +27,35 @@ yarn install yarn nocobase install ``` -然后初始化一个插件,并添加到系统中: +Next, initialize a plugin and add it to the system: ```bash yarn pm create @nocobase-sample/plugin-initializer-configure-actions yarn pm enable @nocobase-sample/plugin-initializer-configure-actions ``` -然后启动项目即可: +Then, start the project: ```bash yarn dev ``` -然后登录后访问 [http://localhost:13000/admin/pm/list/local/](http://localhost:13000/admin/pm/list/local/) 就可以看到插件已经安装并启用了。 +After logging in, visit [http://localhost:13000/admin/pm/list/local/](http://localhost:13000/admin/pm/list/local/) to see that the plugin has been installed and enabled. -## 功能实现 +## Feature Implementation -在实现本示例之前,我们需要先了解一些基础知识: +Before implementing this example, we need to understand some basic concepts: -- [SchemaInitializer 教程](/development/client/ui-schema/initializer):用于向界面内添加各种区块、字段、操作等 -- [SchemaInitializer API](https://client.docs.nocobase.com/core/ui-schema/schema-initializer):用于向界面内添加各种区块、字段、操作等 -- [UI Schema](/development/client/ui-schema/what-is-ui-schema):用于定义界面的结构和样式 -- [Designable 设计器](/development/client/ui-schema/designable):用于修改 Schema +- [SchemaInitializer Tutorial](/development/client/ui-schema/initializer): Used to add various blocks, fields, operations, etc., to the interface +- [SchemaInitializer API](https://client.docs.nocobase.com/core/ui-schema/schema-initializer): Provides an API for adding various blocks, fields, operations, etc., to the interface +- [UI Schema](/development/client/ui-schema/what-is-ui-schema): Used for defining the structure and style of the interface +- [Designable Designer](/development/client/ui-schema/designable): Used for modifying Schema -### 1. 创建区块 +### 1. Creating the Block -前面已经说明本示例会在 [添加数据区块 Data Block](/plugin-samples/schema-initializer/data-block) 基础上继续实现,所以我们可以复制 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client` 目录覆盖 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client`。 +As mentioned earlier, this example will continue from [Adding a Data Block](/plugin-samples/schema-initializer/data-block), so we can copy the `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client` directory to `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client`. -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/index.tsx`: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/index.tsx`: ```diff import { Plugin } from '@nocobase/client'; @@ -75,18 +75,18 @@ import { Plugin } from '@nocobase/client'; + export default PluginInitializerConfigureActionsClient; ``` -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/constants.ts`: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/constants.ts`: ```ts export const BlockName = 'InfoV2'; export const BlockNameLowercase = 'info-v2'; ``` -### 2. 实现 initializer +### 2. Implementing the Initializer -#### 2.1 定义 initializer +#### 2.1 Defining the Initializer -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/configureActionsInitializer.ts` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/configureActionsInitializer.ts`: ```tsx | pure import { SchemaInitializer } from "@nocobase/client"; @@ -105,20 +105,20 @@ export const configureActionsInitializer = new SchemaInitializer({ }); ``` -我们通过上述代码定义了一个新的 `SchemaInitializer`,其子项暂时为空。 +We defined a new `SchemaInitializer` with empty items for now. -- [SchemaInitializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer):用于创建一个 Schema Initializer 实例 -- `icon`:图标,更多图标可参考 Ant Design [Icons](https://ant.design/components/icon/) -- `title`:按钮标题 -- [items](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#built-in-components-and-types):按钮下的子项 +- [SchemaInitializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer): Used to create a Schema Initializer instance +- `icon`: Icon, more icons can be found at Ant Design [Icons](https://ant.design/components/icon/) +- `title`: Button title +- [items](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#built-in-components-and-types): Sub-items under the button -然后将其在 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/index.ts` 中导出: +Then export it in `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/index.ts`: ```tsx | pure export * from './configureActionsInitializer'; ``` -并且修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/index.tsx` 将 `configureActions` 导出: +And modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/index.tsx` to export `configureActions`: ```diff import React from 'react'; @@ -129,9 +129,9 @@ import { CodeOutlined } from '@ant-design/icons'; // ... ``` -#### 2.2 注册 initializer +#### 2.2 Registering the Initializer -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/index.tsx` 文件,导入并注册这个 initializer: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/index.tsx` to import and register this initializer: ```tsx | pure // ... @@ -146,9 +146,9 @@ export class PluginInitializerConfigureActionsClient extends Plugin { } ``` -#### 2.3 使用 initializer +#### 2.3 Using the Initializer -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/schema/index.ts` 文件,新增 `actions` 子节点: +Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/schema/index.ts` to add the `actions` child node: ```diff // ... @@ -178,19 +178,18 @@ function getInfoBlockSchema({ dataSource, collection }) { } ``` -`configure actions` 一般与 [ActionBar](https://client.docs.nocobase.com/components/action#actionbar) 组件搭配使用。 +`configure actions` is typically used with the [ActionBar](https://client.docs.nocobase.com/components/action#actionbar) component. +We added an `actions` field to the child nodes of `Info`: -我们在 `Info` 的子节点中添加了一个 `actions` 字段: +- `type: 'void'`: Type is `void`, indicating it's a container +- `x-component: 'ActionBar'`: Uses the [ActionBar](https://client.docs.nocobase.com/components/action#actionbar) component to display buttons +- `x-initializer: configureActionsInitializer.name`: Uses the Schema Initializer we just created +- `x-component-props.layout: 'two-column'`: Two-column layout, see [ActionBar two-column](https://client.docs.nocobase.com/components/action#two-column) for examples -- `type: 'void'`:类型为 `void`,表示这是一个容器 -- `x-component: 'ActionBar'`:使用 [ActionBar](https://client.docs.nocobase.com/components/action#actionbar) 组件,用于展示按钮 -- `x-initializer: configureActionsInitializer.name`:使用我们刚创建的 Schema Initializer -- `x-component-props.layout: 'two-column'`:左右布局,具体示例可参考 [ActionBar two-column](https://client.docs.nocobase.com/components/action#two-column) +#### 2.4 Block Rendering Child Nodes -#### 2.4 区块渲染子节点 - -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/component/Info.tsx` 文件,将 `Info` 组件修改为: +Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/component/Info.tsx` to update the `Info` component: ```diff import React, { FC } from 'react'; @@ -213,15 +212,15 @@ export const InfoV2: FC = withDynamicSchemaProps(({ children, colle }, { displayName: BlockName }) ``` -- `children`: `properties` 的内容会被传入到 `InfoV2` 组件的 `children` 中,所以我们直接将 `children` 渲染出来即可。 +- `children`: The content of `properties` will be passed to the `InfoV2` component's `children`, so we simply render `children`. ![img_v3_02b4_4c6cb675-789e-48d5-99ce-072984dcfc9g](https://static-docs.nocobase.com/img_v3_02b4_4c6cb675-789e-48d5-99ce-072984dcfc9g.jpg) -### 3. 实现 initializer items +### 3. Implementing Initializer Items -#### 3.1 复用:`Custom request` Action +#### 3.1 Reusing: `Custom request` Action -我们继续修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/configureActionsInitializer.ts` 文件: +Continue modifying `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/configureActionsInitializer.ts`: ```diff export const configureActions = new SchemaInitializer({ @@ -238,30 +237,30 @@ export const configureActions = new SchemaInitializer({ }); ``` -因为 `Custom request` 我们这里直接复用了 `CustomRequestInitializer` 组件,更多可复用的 Initializer Item 可参考 *TODO*。 +For `Custom request`, we directly reuse the `CustomRequestInitializer` component. For more reusable Initializer Items, see *TODO*. ![img_v3_02b4_0d439087-cfe1-4681-bfab-4e4bc3e34cbg](https://static-docs.nocobase.com/img_v3_02b4_0d439087-cfe1-4681-bfab-4e4bc3e34cbg.jpg) -#### 3.2 自定义:`Custom Refresh` Action +#### 3.2 Custom: `Custom Refresh` Action -除了复用已有的 Initializer Item,我们也可以自定义 Action。关于自定义 Action 的详细步骤可以参考 [添加简单 Action](/plugin-samples/schema-initializer/action-simple) 和 [添加弹窗 Action](/plugin-samples/schema-initializer/action-modal)。 +Besides reusing existing Initializer Items, we can also customize Actions. For detailed steps on customizing Actions, refer to [Adding a Simple Action](/plugin-samples/schema-initializer/action-simple) and [Adding a Popup Action](/plugin-samples/schema-initializer/action-modal). -这里我们实现一个 `Custom Refresh` Action。 +Here we implement a `Custom Refresh` Action. -#### 3.2.1 定义名称 +#### 3.2.1 Defining the Name -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/constants.ts`: +Create `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/constants.ts`: ```ts export const ActionName = 'Custom Request'; export const ActionNameLowercase = 'customRequest'; ``` -#### 3.2.2 定义 Schema +#### 3.2.2 Defining the Schema -##### 3.2.2.1 定义 Schema +##### 3.2.2.1 Defining the Schema -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/schema.ts` 文件: +Create `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/schema.ts`: ```ts import { ActionProps, useDataBlockRequest, ISchema } from "@nocobase/client"; @@ -287,37 +286,37 @@ export const customRefreshActionSchema: ISchema = { } ``` -我们定义了 `customRefreshActionSchema` 以及动态属性 `useCustomRefreshActionProps`。 +We defined `customRefreshActionSchema` and the dynamic property `useCustomRefreshActionProps`. -`customRefreshActionSchema`: - - `type: 'void'`:类型为 `void`,表示普通 UI,不包含数据 - - `x-component: 'Action'`:使用 [Action](https://client.docs.nocobase.com/components/action) 组件,用于展示按钮 - - `title: 'Custom Refresh'`:按钮标题 - - `x-use-component-props: 'useCustomRefreshActionProps'`:使用 `useCustomRefreshActionProps` 这个 Hooks 返回的属性。因为 Schema 会保存到服务器,所以这里需要使用字符串的方式。 - - `'x-toolbar': 'ActionSchemaToolbar'`:一般于 `Action` 组件搭配使用,与默认的 ToolBar 不同的是,其将 Action 右上角的 `Initializer` 隐藏,仅保留 Drag 和 Settings。 +`customRefreshActionSchema`: + - `type: 'void'`: Type is `void`, indicating pure UI without data + - `x-component: 'Action'`: Uses the [Action](https://client.docs.nocobase.com/components/action) component to display a button + - `title: 'Custom Refresh'`: Button title + - `x-use-component-props: 'useCustomRefreshActionProps'`: Uses the properties returned by this Hook. Since Schema is saved to the server, we use a string here. + - `'x-toolbar': 'ActionSchemaToolbar'`: Typically used with the `Action` component. Unlike the default ToolBar, it hides the Initializer in the upper right corner of Action, keeping only Drag and Settings. -`useCustomRefreshActionProps`:这个是 React Hooks,需要返回 Action 组件的属性。 - - [useDataBlockRequest()](https://client.docs.nocobase.com/core/data-block/data-block-request-provider):数据区块的请求对象,由 `DataBlockProvider` 内部提供,用于自动获取数据区块的数据 - - `runAsync`:一个异步请求方法,用于刷新数据区块的数据 - - `type: 'primary'`:按钮类型为 `primary` - - `onClick`:点击事件。 +`useCustomRefreshActionProps`: This is a React Hook that returns properties for the Action component. + - [useDataBlockRequest()](https://client.docs.nocobase.com/core/data-block/data-block-request-provider): The data block request object, provided internally by `DataBlockProvider`, used to automatically get data block data + - `runAsync`: An async request method for refreshing data block data + - `type: 'primary'`: Button type is `primary` + - `onClick`: Click event. -然后将其在 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/index.ts` 中导出: +Then export it in `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/index.ts`: ```ts export * from './initializer'; ``` -并修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/index.ts` 将 `customRefresh` 导出: +And modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/index.ts` to export `customRefresh`: ```diff export * from './configureActionsInitializer'; + export * from './items/customRefresh'; ``` -##### 3.2.2.2 注册上下文 +##### 3.2.2.2 Registering the Context -我们还需要将 `useCustomRefreshActionProps` 注册到上下文中。我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/index.tsx` 文件: +We also need to register `useCustomRefreshActionProps` in the context. Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/index.tsx`: ```diff // ... @@ -333,13 +332,13 @@ export class PluginInitializerConfigureActionsClient extends Plugin { } ``` -关于 `SchemaComponentOptions` 的使用可以参考 [SchemaComponentOptions](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponentoptions) 文档以及 [全局注册 Component 和 Scope](/plugin-samples/component-and-scope/global)。 +For more about `SchemaComponentOptions`, see the [SchemaComponentOptions](https://client.docs.nocobase.com/core/ui-schema/schema-component#schemacomponentoptions) documentation and [Globally Registering Component and Scope](/plugin-samples/component-and-scope/global). -#### 3.3.2 实现 settings +#### 3.3.2 Implementing Settings -##### 3.3.2.1 定义 settings +##### 3.3.2.1 Defining Settings -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/settings.ts` +Create `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/settings.ts`: ```tsx | pure import { SchemaSettings } from "@nocobase/client"; @@ -356,18 +355,17 @@ export const customRefreshActionSettings = new SchemaSettings({ }) ``` -`customRefreshActionSettings`:这里只简单定义了一个 `remove` 操作,更多关于 Schema Settings 的定义可以参考 [Schema Settings](https://client.docs.nocobase.com/core/ui-schema/schema-settings) 文档。 - +`customRefreshActionSettings`: Here we only simply define a `remove` operation. For more about Schema Settings definition, see the [Schema Settings](https://client.docs.nocobase.com/core/ui-schema/schema-settings) documentation. -修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/index.ts` 将其导出: +Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/index.ts` to export it: ```tsx | pure export * from './settings'; ``` -##### 3.3.2.2 注册 settings +##### 3.3.2.2 Registering Settings -然后将 `customRefreshActionSettings` 注册到系统中。我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/index.tsx` 文件: +Then register `customRefreshActionSettings` in the system. Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/index.tsx`: ```diff - import { infoInitializerItem, useCustomRefreshActionProps } from './initializer'; @@ -380,9 +378,9 @@ export class PluginInitializerConfigureActionsClient extends Plugin { } ``` -##### 3.3.2.2 使用 settings +##### 3.3.2.2 Using Settings -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/schema.ts` 文件的 `customRefreshActionSchema` 方法,将 `x-settings` 设置为 `customRefreshActionSettings.name`。 +Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/schema.ts` `customRefreshActionSchema` to set `x-settings` to `customRefreshActionSettings.name`. ```diff + import { customRefreshActionSettings } from "./settings"; @@ -396,11 +394,11 @@ export const customRefreshActionSchema: ISchema = { } ``` -##### 3.3.3 定义 SchemaInitializer item +##### 3.3.3 Defining SchemaInitializer Item -###### 3.3.3.1 定义 SchemaInitializer item +###### 3.3.3.1 Defining SchemaInitializer Item -我们继续修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/initializer.ts` 文件: +Continue modifying `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/items/customRefresh/initializer.ts`: ```tsx | pure import { SchemaInitializerItemType, useSchemaInitializer } from "@nocobase/client"; @@ -424,22 +422,21 @@ export const customRefreshActionInitializerItem: SchemaInitializerItemType = { }; ``` -- `type: 'item'`:类型为 `item`,表示文本,当点击后会触发 `onClick` 事件 -- `name: 'custom refresh'`:唯一标识符,用于区分不同的 Schema Item 和增删改查操作 -- `title: 'Custom Refresh'`:按钮标题 +- `type: 'item'`: Type is `item`, indicating text that triggers an `onClick` event when clicked +- `name: 'custom refresh'`: Unique identifier for distinguishing different Schema Items and CRUD operations +- `title: 'Custom Refresh'`: Button title -更多关于 Schema Item 的定义可以参考 [Schema Initializer Item](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#built-in-components-and-types) 文档。 +For more about Schema Item definition, see the [Schema Initializer Item](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#built-in-components-and-types) documentation. - -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/index.ts` 将其导出: +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/index.ts` to export it: ```tsx | pure export * from './initializer'; ``` -###### 3.3.3.2 使用 SchemaInitializer item +###### 3.3.3.2 Using SchemaInitializer Item -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/configureActionsInitializer.ts` 文件,将 `customRefreshActionInitializerItem` 添加到 `items` 中: +Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-actions/src/client/initializer/configureActions/configureActionsInitializer.ts` to add `customRefreshActionInitializerItem` to `items`: ```diff import { SchemaInitializer } from "@nocobase/client"; @@ -468,23 +465,22 @@ export const configureActionsInitializer = new SchemaInitializer({ -你可以根据需要实现更多的 `Action`。 +You can implement more `Actions` as needed. -## 打包和上传到生产环境 +## Packaging and Uploading to Production Environment -按照 [构建并打包插件](/development/your-fisrt-plugin#构建并打包插件) 文档说明,我们可以打包插件并上传到生产环境。 +Following the [Build and Package Plugin](/development/your-fisrt-plugin#build-and-package-the-plugin) documentation, we can package the plugin and upload it to the production environment. -如果是 clone 的源码,需要先执行一次全量 build,将插件的依赖也构建好。 +If you cloned the source code, you need to run a full build first to build the plugin dependencies. ```bash yarn build ``` -如果是使用的 `create-nocobase-app` 创建的项目,可以直接执行: +If you used `create-nocobase-app` to create the project, you can run: ```bash yarn build @nocobase-sample/plugin-initializer-configure-actions --tar ``` -这样就可以看到 `storage/tar/@nocobase-sample/plugin-initializer-configure-actions.tar.gz` 文件了,然后通过[上传的方式](/welcome/getting-started/plugin)进行安装。 - +Then you will see the `storage/tar/@nocobase-sample/plugin-initializer-configure-actions.tar.gz` file, which can be installed through the [upload method](/welcome/getting-started/plugin). diff --git a/docs/en-US/plugin-samples/schema-initializer/configure-fields-bk.md b/docs/en-US/plugin-samples/schema-initializer/configure-fields-bk.md index b9699c2107..5f6df02055 100644 --- a/docs/en-US/plugin-samples/schema-initializer/configure-fields-bk.md +++ b/docs/en-US/plugin-samples/schema-initializer/configure-fields-bk.md @@ -1,396 +1,3 @@ -# 实现数据字段 Initializer - -## 场景说明 - -如果新创建的区块是一个复杂的数据区块,那么它内部可能包含多个动态添加的部分,其中重点就是通过 `Configure fields` 对应的 initializer 动态添加字段。例如 `Form` 区块,我们可以通过 `Configure fields` 来配置显示的字段。 - -![img_v3_02b4_111734a2-755f-4100-949d-96803ad1912g](https://static-docs.nocobase.com/img_v3_02b4_111734a2-755f-4100-949d-96803ad1912g.jpg) - -## 示例说明 - -本实例会在 [添加数据区块 Data Block](/plugin-samples/schema-initializer/data-block) 基础上继续实现类似 `Form` 区块的效果,通过 `Configure fields` 来配置显示的字段。 - -本文档完整的示例代码可以在 [plugin-samples](https://github.com/nocobase/plugin-samples/tree/main/packages/plugins/%40nocobase-sample/plugin-initializer-configure-fields) 中查看。 - - - -## 初始化插件 - -我们按照 [编写第一个插件](/development/your-fisrt-plugin) 文档说明,如果没有一个项目,可以先创建一个项目,如果已经有了或者是 clone 的源码,则跳过这一步。 - -```bash -yarn create nocobase-app my-nocobase-app -d postgres -cd my-nocobase-app -yarn install -yarn nocobase install -``` - -然后初始化一个插件,并添加到系统中: - -```bash -yarn pm create @nocobase-sample/plugin-initializer-configure-fields -yarn pm enable @nocobase-sample/plugin-initializer-configure-fields -``` - -然后启动项目即可: - -```bash -yarn dev -``` - -然后登录后访问 [http://localhost:13000/admin/pm/list/local/](http://localhost:13000/admin/pm/list/local/) 就可以看到插件已经安装并启用了。 - -## 功能实现 - -在实现本示例之前,我们需要先了解一些基础知识: - -- [SchemaInitializer 教程](/development/client/ui-schema/initializer):用于向界面内添加各种区块、字段、操作等 -- [SchemaInitializer API](https://client.docs.nocobase.com/core/ui-schema/schema-initializer):用于向界面内添加各种区块、字段、操作等 -- [UI Schema](/development/client/ui-schema/what-is-ui-schema):用于定义界面的结构和样式 -- [Designable 设计器](/development/client/ui-schema/designable):用于修改 Schema - -### 1. Copy 代码并修改插件名称 - -前面已经说明本示例会在 [添加数据区块 Data Block](/plugin-samples/schema-initializer/data-block) 基础上继续实现,所以我们可以复制 `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client` 目录覆盖 `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client`。 - -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/index.tsx`: - -```diff -import { Plugin } from '@nocobase/client'; -import { InfoBlock, infoBlockSettings, infoBlockInitializerItem } from './InfoBlock'; - -- export class PluginInitializerBlockDataClient extends Plugin { -+ export class PluginInitializerConfigureFieldsClient extends Plugin { - async load() { - // ... - } -} - -- export default PluginInitializerBlockDataClient; -+ export default PluginInitializerConfigureFieldsClient; -``` - -为了避免和其他示例冲突,把所有 `InfoBlock` 改为了 `InfoBlock2`,但是本示例文档中仍然按照 `InfoBlock` 来说明。 - -### 2. 创建 `Configure fields` 对应的 initializer - -我们新建 `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/configureFields.tsx` 文件: - -```tsx | pure -import { Grid, SchemaInitializer, useSchemaInitializer } from "@nocobase/client"; - -export const configureFields = new SchemaInitializer({ - name: 'info:configureFields', - icon: 'SettingOutlined', - title: 'Configure fields', - items: [ - { - type: 'itemGroup', - name: 'fields', - title: 'Display fields', - useChildren() { - const { insert } = useSchemaInitializer(); - - return [] - }, - } - ] -}); -``` - -- [SchemaInitializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer):用于创建一个 Schema Initializer 实例 -- `icon`:图标,更多图标可参考 Ant Design [Icons](https://ant.design/components/icon/) -- `title`:按钮标题 -- [items](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#built-in-components-and-types):按钮下的子项 - - `type: 'itemGroup'`:子项类型,用于包装多个子项 - - `name: 'fields'`:子项名称 - - `title: 'Display fields'`:子项标题 - - `useChildren`:子项的子项,返回一个数组,数组中的每一项都是一个子项 - -### 3. 注册 `Configure fields` initializer - -然后修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/index.tsx` 文件,导入并注册这个 initializer: - -```tsx | pure -import { configureFields } from './configureFields' - -export class PluginInitializerConfigureFieldsClient extends Plugin { - async load() { - this.app.schemaInitializerManager.add(configureFields) - } -} -``` - -### 4. 修改 `getInfoBlockSchema()` 区块 - -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/InfoBlock.tsx` 文件,将 `getInfoBlockSchema()` 区块修改为: - -```diff -function getInfoBlockSchema({ dataSource, collection }) { - return { - // ... - properties: { - info: { - type: 'void', - 'x-component': 'InfoBlock', -+ properties: { -+ fields: { -+ type: 'void', -+ 'x-component': 'Grid', -+ 'x-initializer': 'info:configureFields', -+ } -+ } - } - } - } -} -``` - -我们在 `InfoBlock` 的子节点中添加了一个 `fields` 字段,为了更好的布局,我们使用 `Grid` 组件包裹了一下,并且指定了 `x-initializer` 为 `info:configureFields`,因为 `Grid` 内置了 [useSchemaInitializerRender()](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializerrender) 的渲染逻辑,所以我们可以直接使用,如果是一个自定义的组件,需要自己通过 `useSchemaInitializerRender()` 实现渲染逻辑。 - -### 5. 修改 `InfoBlock` 组件 - -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/InfoBlock.tsx` 文件,将 `InfoBlock` 组件修改为: - -```tsx | pure -export const InfoBlock = ({ children }) => { - return
{children}
-} -``` - -`properties` 的内容会被传入到 `InfoBlock` 组件的 `children` 中,所以我们直接将 `children` 渲染出来即可。 - - - -### 6. 读取数据表字段作为 `Configure fields` 的子项 - -我们继续修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/configureFields.tsx` 文件: - -```tsx | pure -interface GetFieldInitializerItemOptions { - collectionField: CollectionFieldOptions; -} - -function getFieldInitializerItem(options: GetFieldInitializerItemOptions) { - const { collectionField } = options; - const title = collectionField.uiSchema?.title || collectionField.name; - const name = collectionField.name; - return { - name: collectionField.name, - title: collectionField.uiSchema?.title || collectionField.name, - type: 'switch', - onClick() { - // TODO - } - } as SchemaInitializerItemType; -} - -export const configureFields = new SchemaInitializer({ - name: 'info:configureFields', - icon: 'SettingOutlined', - title: 'Configure fields', - items: [ - { - type: 'itemGroup', - name: 'fields', - title: 'Display fields', - useChildren() { - const collection = useCollection(); - - const schemaItems = collection - .getFields() - .map(getFieldInitializerItem({ - collectionField, - })) - - return schemaItems; - }, - } - ] -}); -``` - -- [useCollection()](https://client.docs.nocobase.com/core/data-source/collection-provider#usecollection):用于获取当前数据表的实例。在 `getInfoBlockSchema()` 中我们使用了 [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider) ,其内部包含了 [CollectionProvider](https://client.docs.nocobase.com/core/data-source/collection-provider) ,所以我们可以直接使用。 - - `collection.getFields()`:获取数据表的字段 - -- getFieldInitializerItem:用于获取字段的 Schema Initializer Item - - `name`:子项名称,用于唯一标识 - - `title`:子项标题,用于显示,如果字段有 `uiSchema.title` 则使用 `uiSchema.title`,否则使用字段名称,关于 `field.uiSchema` 的数据结构可以参考 [CollectionField](https://client.docs.nocobase.com/core/data-source/collection-field) - - `type: 'switch'`:子项类型,[Switch 类型](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#type-switch--schemainitializerswitch),其核心是要实现 `onClick` 方法,当点击后如果已经存在则删除,如果不存在则添加。 - - `onClick`:点击事件,我们这里暂时不实现,后续会实现。 - -![img_v3_02b4_7d5c145e-cb15-4d93-9004-bde406e42a5g](https://static-docs.nocobase.com/img_v3_02b4_7d5c145e-cb15-4d93-9004-bde406e42a5g.jpg) - -### 7. 实现 `switch` 的添加和删除 - -我们修改 `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/configureFields.tsx` 文件: - -```diff -+ import { CollectionFieldOptions, ISchema, SchemaInitializer, SchemaInitializerItemType, SchemaSettings, useCollection, useDesignable, useSchemaInitializer } from "@nocobase/client"; - -export const configureFields = new SchemaInitializer({ - name: 'info:configureFields', - icon: 'SettingOutlined', - title: 'Configure fields', - items: [ - { - type: 'itemGroup', - name: 'fields', - title: 'Display fields', - useChildren() { -+ const { insert } = useSchemaInitializer(); -+ const { remove } = useDesignable(); -+ const schema = useFieldSchema(); - const collection = useCollection(); - - const schemaItems = collection - .getFields() - .map((collectionField) => getFieldInitializerItem({ - collectionField, -+ schema, -+ remove, -+ insert -+ })) - - return schemaItems; - }, - } - ] -}); -``` - -- [useDesignable()](https://client.docs.nocobase.com/core/ui-schema/designable#usedesignable):可以增删改查 Schema 的方法 -- [useSchemaInitializer()](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializer):用于提供 SchemaInitializer 上下文 - - `insert`:用于插入 Schema。这里之所以使用 `useSchemaInitializer()` 所提供的 insert 方法,而不是 `useDesignable()` 提供的 insert 方法,是因为 Schema 是有层级的,`useSchemaInitializer()` 获取的是 `SchemaInitializer` 所在层级,而 `useDesignable()` 获取的是当前 Schema 所在层级,我们需要插入到 `SchemaInitializer` 所在层级的兄弟层,所以应该使用 `useSchemaInitializer()` 提供的 insert 方法。 - -```tsx | pure -function getInfoItemSchema(collectionFieldName: string) { - return { - type: 'void', - 'x-collection-field': collectionFieldName, - // TODO - } -} - -interface GetFieldInitializerItemOptions { - collectionField: CollectionFieldOptions; - schema: ISchema; - remove: (schema: ISchema) => void; - insert: (schema: ISchema) => void; -} - -function getFieldInitializerItem(options: GetFieldInitializerItemOptions) { - const { collectionField, schema, remove, insert } = options; - const title = collectionField.uiSchema?.title || collectionField.name; - const name = collectionField.name; - const collectionFieldSchema = Object.values(schema.properties || {}).find((item) => item['x-collection-field'] === name); - return { - name, - type: 'switch', - title, - checked: !!collectionFieldSchema, - onClick() { - if (collectionFieldSchema) { - remove(collectionFieldSchema) - return; - } - insert(getInfoItemSchema(name)) - } - } as SchemaInitializerItemType; -} -``` - -首先 `getInfoItemSchema` 用于返回一个字段的 Schema,其中一个关键点是 `x-collection-field` 字段,用于标识这个 Schema 是哪个字段的。 - -然后我们通过读取 `schema.properties` 中的数据,找到对应的字段的 Schema,如果存在则删除,如果不存在则插入。 - -### 8. 完善子节点 Schema 和组件 - -```ts -export const infoItemSettings = new SchemaSettings({ - name: 'fieldSettings:info', - items: [ - { - name: 'remove', - type: 'remove', - componentProps: { - removeParentsIfNoChildren: true, - breakRemoveOn(s) { - return s['x-component'] === 'Grid'; - }, - }, - } - ] -}) - -export const InfoItem = () => { - const fieldSchema = useFieldSchema(); - const collection = useCollection(); - const collectionFieldName = fieldSchema.name; - return
{JSON.stringify(collection.getField(collectionFieldName), null, 2)}
-} - -function getInfoItemSchema(collectionFieldName: string) { - return { - type: 'void', - 'x-collection-field': collectionFieldName, - 'x-component': 'Grid.Row', - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Grid.Col', - properties: { - [collectionFieldName]: { - type: 'void', - 'x-component': 'InfoItem', - 'x-decorator': 'CardItem', - 'x-settings': infoItemSettings.name, - }, - }, - }, - }, - } as ISchema; -} -``` - -我们在 `getInfoBlockSchema()` 中使用 `Grid` 组件作为父级,那么子节点就需要使用 `Grid.Row` 和 `Grid.Col` 组件,然后在 `Grid.Col` 中使用 `InfoItem` 组件。 - -`InfoItem` 就是具体的字段信息展示组件,我们这里做的事情很简单,首先读取当前字段的 Schema,其中 `schema.name` 对应 `collectionFieldName`,然后通过 [collection.getField(collectionFieldName)](https://client.docs.nocobase.com/core/data-source/collection#collectiongetfieldname) 获取字段的详细信息,然后展示出来。 - -然后我们将 `InfoItem` 和 `infoItemSettings` 组件注册到系统中: - -```ts -export class PluginInitializerComplexDataBlockClient extends Plugin { - async load() { - this.app.addComponents({ InfoBlock, InfoItem }); - this.app.schemaSettingsManager.add(infoBlockSettings, infoItemSettings); - } -} -``` - - - -## 打包和上传到生产环境 - -按照 [构建并打包插件](/development/your-fisrt-plugin#构建并打包插件) 文档说明,我们可以打包插件并上传到生产环境。 - -如果是 clone 的源码,需要先执行一次全量 build,将插件的依赖也构建好。 - -```bash -yarn build -``` - -如果是使用的 `create-nocobase-app` 创建的项目,可以直接执行: - -```bash -yarn build @nocobase-sample/plugin-initializer-configure-fields --tar -``` - -这样就可以看到 `storage/tar/@nocobase-sample/plugin-initializer-configure-fields.tar.gz` 文件了,然后通过[上传的方式](/welcome/getting-started/plugin)进行安装。 +# Implementing Data Field Initializer +TODO diff --git a/docs/en-US/plugin-samples/schema-initializer/configure-fields.md b/docs/en-US/plugin-samples/schema-initializer/configure-fields.md index 4e452588a2..80fbd2dfe8 100644 --- a/docs/en-US/plugin-samples/schema-initializer/configure-fields.md +++ b/docs/en-US/plugin-samples/schema-initializer/configure-fields.md @@ -1,3 +1,395 @@ -# 区块内嵌的 Initializer - 配置字段 +# Implementing Data Field Initializer -TODO +## Scenario Description + +If a newly created block is a complex data block, it may contain multiple dynamically added parts. The key focus is dynamically adding fields through the `Configure fields` initializer. For example, in a `Form` block, we can configure the displayed fields through `Configure fields`. + +![img_v3_02b4_111734a2-755f-4100-949d-96803ad1912g](https://static-docs.nocobase.com/img_v3_02b4_111734a2-755f-4100-949d-96803ad1912g.jpg) + +## Example Explanation + +This example will continue from [Adding a Data Block](/plugin-samples/schema-initializer/data-block) to implement a `Form` block-like effect, configuring displayed fields through `Configure fields`. + +The complete sample code for this document can be found in [plugin-samples](https://github.com/nocobase/plugin-samples/tree/main/packages/plugins/%40nocobase-sample/plugin-initializer-configure-fields). + + + +## Initializing the Plugin + +Following the instructions in the [Creating Your First Plugin](/development/your-fisrt-plugin) document, if you don't have a project yet, you can create one first. If you already have a project or have cloned the source code, skip this step. + +```bash +yarn create nocobase-app my-nocobase-app -d postgres +cd my-nocobase-app +yarn install +yarn nocobase install +``` + +Next, initialize a plugin and add it to the system: + +```bash +yarn pm create @nocobase-sample/plugin-initializer-configure-fields +yarn pm enable @nocobase-sample/plugin-initializer-configure-fields +``` + +Then, start the project: + +```bash +yarn dev +``` + +After logging in, visit [http://localhost:13000/admin/pm/list/local/](http://localhost:13000/admin/pm/list/local/) to see that the plugin has been installed and enabled. + +## Feature Implementation + +Before implementing this example, we need to understand some basic concepts: + +- [SchemaInitializer Tutorial](/development/client/ui-schema/initializer): Used to add various blocks, fields, operations, etc., to the interface +- [SchemaInitializer API](https://client.docs.nocobase.com/core/ui-schema/schema-initializer): Provides an API for adding various blocks, fields, operations, etc., to the interface +- [UI Schema](/development/client/ui-schema/what-is-ui-schema): Used for defining the structure and style of the interface +- [Designable Designer](/development/client/ui-schema/designable): Used for modifying Schema + +### 1. Copy Code and Modify Plugin Name + +As mentioned earlier, this example will continue from [Adding a Data Block](/plugin-samples/schema-initializer/data-block), so we can copy the `packages/plugins/@nocobase-sample/plugin-initializer-block-data/src/client` directory to `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client`. + +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/index.tsx`: + +```diff +import { Plugin } from '@nocobase/client'; +import { InfoBlock, infoBlockSettings, infoBlockInitializerItem } from './InfoBlock'; + +- export class PluginInitializerBlockDataClient extends Plugin { ++ export class PluginInitializerConfigureFieldsClient extends Plugin { + async load() { + // ... + } +} + +- export default PluginInitializerBlockDataClient; ++ export default PluginInitializerConfigureFieldsClient; +``` + +To avoid conflicts with other examples, all `InfoBlock` has been changed to `InfoBlock2`, but this documentation still uses `InfoBlock` for explanation. + +### 2. Creating the `Configure fields` Initializer + +Create `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/configureFields.tsx`: + +```tsx | pure +import { Grid, SchemaInitializer, useSchemaInitializer } from "@nocobase/client"; + +export const configureFields = new SchemaInitializer({ + name: 'info:configureFields', + icon: 'SettingOutlined', + title: 'Configure fields', + items: [ + { + type: 'itemGroup', + name: 'fields', + title: 'Display fields', + useChildren() { + const { insert } = useSchemaInitializer(); + + return [] + }, + } + ] +}); +``` + +- [SchemaInitializer](https://client.docs.nocobase.com/core/ui-schema/schema-initializer): Used to create a Schema Initializer instance +- `icon`: Icon, more icons can be found at Ant Design [Icons](https://ant.design/components/icon/) +- `title`: Button title +- [items](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#built-in-components-and-types): Sub-items under the button + - `type: 'itemGroup'`: Sub-item type, used to wrap multiple sub-items + - `name: 'fields'`: Sub-item name + - `title: 'Display fields'`: Sub-item title + - `useChildren`: Sub-items of the sub-item, returns an array where each item is a sub-item + +### 3. Registering the `Configure fields` Initializer + +Then modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/index.tsx` to import and register this initializer: + +```tsx | pure +import { configureFields } from './configureFields' + +export class PluginInitializerConfigureFieldsClient extends Plugin { + async load() { + this.app.schemaInitializerManager.add(configureFields) + } +} +``` + +### 4. Modifying the `getInfoBlockSchema()` Block + +Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/InfoBlock.tsx` to change `getInfoBlockSchema()`: + +```diff +function getInfoBlockSchema({ dataSource, collection }) { + return { + // ... + properties: { + info: { + type: 'void', + 'x-component': 'InfoBlock', ++ properties: { ++ fields: { ++ type: 'void', ++ 'x-component': 'Grid', ++ 'x-initializer': 'info:configureFields', ++ } ++ } + } + } + } +} +``` + +We added a `fields` field to the child nodes of `InfoBlock`. For better layout, we wrapped it with the `Grid` component and specified `x-initializer` as `info:configureFields`. Since `Grid` has built-in [useSchemaInitializerRender()](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializerrender) rendering logic, we can use it directly. If it's a custom component, you need to implement the rendering logic through `useSchemaInitializerRender()`. + +### 5. Modifying the `InfoBlock` Component + +Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/InfoBlock.tsx` to change the `InfoBlock` component: + +```tsx | pure +export const InfoBlock = ({ children }) => { + return
{children}
+} +``` + +The content of `properties` will be passed to the `children` of the `InfoBlock` component, so we simply render `children`. + + + +### 6. Reading Data Table Fields as `Configure fields` Sub-items + +Continue modifying `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/configureFields.tsx`: + +```tsx | pure +interface GetFieldInitializerItemOptions { + collectionField: CollectionFieldOptions; +} + +function getFieldInitializerItem(options: GetFieldInitializerItemOptions) { + const { collectionField } = options; + const title = collectionField.uiSchema?.title || collectionField.name; + const name = collectionField.name; + return { + name: collectionField.name, + title: collectionField.uiSchema?.title || collectionField.name, + type: 'switch', + onClick() { + // TODO + } + } as SchemaInitializerItemType; +} + +export const configureFields = new SchemaInitializer({ + name: 'info:configureFields', + icon: 'SettingOutlined', + title: 'Configure fields', + items: [ + { + type: 'itemGroup', + name: 'fields', + title: 'Display fields', + useChildren() { + const collection = useCollection(); + + const schemaItems = collection + .getFields() + .map(getFieldInitializerItem({ + collectionField, + })) + + return schemaItems; + }, + } + ] +}); +``` + +- [useCollection()](https://client.docs.nocobase.com/core/data-source/collection-provider#usecollection): Used to get the current data table instance. In `getInfoBlockSchema()`, we used [DataBlockProvider](https://client.docs.nocobase.com/core/data-block/data-block-provider), which internally includes [CollectionProvider](https://client.docs.nocobase.com/core/data-source/collection-provider), so we can use it directly. + - `collection.getFields()`: Gets the data table fields + +- getFieldInitializerItem: Gets the Schema Initializer Item for a field + - `name`: Sub-item name, used as a unique identifier + - `title`: Sub-item title for display. If the field has `uiSchema.title`, use it; otherwise, use the field name. For the data structure of `field.uiSchema`, see [CollectionField](https://client.docs.nocobase.com/core/data-source/collection-field) + - `type: 'switch'`: Sub-item type, [Switch type](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#type-switch--schemainitializerswitch). The key is to implement the `onClick` method: when clicked, delete if it exists, add if it doesn't + - `onClick`: Click event, we'll implement this later + +![img_v3_02b4_7d5c145e-cb15-4d93-9004-bde406e42a5g](https://static-docs.nocobase.com/img_v3_02b4_7d5c145e-cb15-4d93-9004-bde406e42a5g.jpg) + +### 7. Implementing `switch` Add and Remove + +Modify `packages/plugins/@nocobase-sample/plugin-initializer-configure-fields/src/client/configureFields.tsx`: + +```diff ++ import { CollectionFieldOptions, ISchema, SchemaInitializer, SchemaInitializerItemType, SchemaSettings, useCollection, useDesignable, useSchemaInitializer } from "@nocobase/client"; + +export const configureFields = new SchemaInitializer({ + name: 'info:configureFields', + icon: 'SettingOutlined', + title: 'Configure fields', + items: [ + { + type: 'itemGroup', + name: 'fields', + title: 'Display fields', + useChildren() { ++ const { insert } = useSchemaInitializer(); ++ const { remove } = useDesignable(); ++ const schema = useFieldSchema(); + const collection = useCollection(); + + const schemaItems = collection + .getFields() + .map((collectionField) => getFieldInitializerItem({ + collectionField, ++ schema, ++ remove, ++ insert ++ })) + + return schemaItems; + }, + } + ] +}); +``` + +- [useDesignable()](https://client.docs.nocobase.com/core/ui-schema/designable#usedesignable): Provides methods for adding, deleting, updating, and querying Schema +- [useSchemaInitializer()](https://client.docs.nocobase.com/core/ui-schema/schema-initializer#useschemainitializer): Provides the SchemaInitializer context + - `insert`: Used to insert Schema. Here we use the insert method from `useSchemaInitializer()` rather than from `useDesignable()` because Schema is hierarchical. `useSchemaInitializer()` gets the level where `SchemaInitializer` is located, while `useDesignable()` gets the current Schema level. We need to insert at the sibling level of `SchemaInitializer`, so we should use the insert method from `useSchemaInitializer()`. + +```tsx | pure +function getInfoItemSchema(collectionFieldName: string) { + return { + type: 'void', + 'x-collection-field': collectionFieldName, + // TODO + } +} + +interface GetFieldInitializerItemOptions { + collectionField: CollectionFieldOptions; + schema: ISchema; + remove: (schema: ISchema) => void; + insert: (schema: ISchema) => void; +} + +function getFieldInitializerItem(options: GetFieldInitializerItemOptions) { + const { collectionField, schema, remove, insert } = options; + const title = collectionField.uiSchema?.title || collectionField.name; + const name = collectionField.name; + const collectionFieldSchema = Object.values(schema.properties || {}).find((item) => item['x-collection-field'] === name); + return { + name, + type: 'switch', + title, + checked: !!collectionFieldSchema, + onClick() { + if (collectionFieldSchema) { + remove(collectionFieldSchema) + return; + } + insert(getInfoItemSchema(name)) + } + } as SchemaInitializerItemType; +} +``` + +First, `getInfoItemSchema` returns a field's Schema, where the key point is the `x-collection-field` field, used to identify which field this Schema belongs to. + +Then we read data from `schema.properties` to find the corresponding field's Schema. If it exists, delete it; if not, insert it. + +### 8. Completing Child Node Schema and Component + +```ts +export const infoItemSettings = new SchemaSettings({ + name: 'fieldSettings:info', + items: [ + { + name: 'remove', + type: 'remove', + componentProps: { + removeParentsIfNoChildren: true, + breakRemoveOn(s) { + return s['x-component'] === 'Grid'; + }, + }, + } + ] +}) + +export const InfoItem = () => { + const fieldSchema = useFieldSchema(); + const collection = useCollection(); + const collectionFieldName = fieldSchema.name; + return
{JSON.stringify(collection.getField(collectionFieldName), null, 2)}
+} + +function getInfoItemSchema(collectionFieldName: string) { + return { + type: 'void', + 'x-collection-field': collectionFieldName, + 'x-component': 'Grid.Row', + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + [collectionFieldName]: { + type: 'void', + 'x-component': 'InfoItem', + 'x-decorator': 'CardItem', + 'x-settings': infoItemSettings.name, + }, + }, + }, + }, + } as ISchema; +} +``` + +In `getInfoBlockSchema()`, we use the `Grid` component as the parent, so child nodes need to use `Grid.Row` and `Grid.Col` components, then use the `InfoItem` component inside `Grid.Col`. + +`InfoItem` is the specific field information display component. What we do here is simple: first read the current field's Schema, where `schema.name` corresponds to `collectionFieldName`, then get the field's detailed information through [collection.getField(collectionFieldName)](https://client.docs.nocobase.com/core/data-source/collection#collectiongetfieldname) and display it. + +Then register the `InfoItem` and `infoItemSettings` components in the system: + +```ts +export class PluginInitializerComplexDataBlockClient extends Plugin { + async load() { + this.app.addComponents({ InfoBlock, InfoItem }); + this.app.schemaSettingsManager.add(infoBlockSettings, infoItemSettings); + } +} +``` + + + +## Packaging and Uploading to Production Environment + +Following the [Build and Package Plugin](/development/your-fisrt-plugin#build-and-package-the-plugin) documentation, we can package the plugin and upload it to the production environment. + +If you cloned the source code, you need to run a full build first to build the plugin dependencies. + +```bash +yarn build +``` + +If you used `create-nocobase-app` to create the project, you can run: + +```bash +yarn build @nocobase-sample/plugin-initializer-configure-fields --tar +``` + +Then you will see the `storage/tar/@nocobase-sample/plugin-initializer-configure-fields.tar.gz` file, which can be installed through the [upload method](/welcome/getting-started/plugin). diff --git a/docs/en-US/plugin-samples/schema-initializer/index.md b/docs/en-US/plugin-samples/schema-initializer/index.md index dbf0a396e1..5b251df273 100644 --- a/docs/en-US/plugin-samples/schema-initializer/index.md +++ b/docs/en-US/plugin-samples/schema-initializer/index.md @@ -1,24 +1,24 @@ # SchemaInitializer -[SchemaInitializer](/development/client/ui-schema/initializer) 用于向界面内添加各种区块、字段、操作等。 +[SchemaInitializer](/development/client/ui-schema/initializer) is used to add various blocks, fields, and actions to the interface. -根据需求不同可能有以下扩展场景: +Depending on requirements, there may be the following extension scenarios: -- 向已有的 Initializer 中添加子项 -- 创建新的 Initializer +- Adding sub-items to an existing Initializer +- Creating a new Initializer -根据以上场景,我们提供了如下示例: +Based on the above scenarios, we provide the following examples: -**向已有的 Initializer 中添加子项** +**Adding sub-items to an existing Initializer** -- [添加简单区块 Simple Block](/plugin-samples/schema-initializer/block-simple) -- [添加数据区块 Data Block](/plugin-samples/schema-initializer/data-block) -- [添加带弹窗的数据区块 Data Block Modal](/plugin-samples/schema-initializer/data-block-modal) -- [添加简单 Action](/plugin-samples/schema-initializer/action-simple) -- [添加弹窗 Action](/plugin-samples/schema-initializer/action-modal) +- [Adding a Simple Block](/plugin-samples/schema-initializer/block-simple) +- [Adding a Data Block](/plugin-samples/schema-initializer/data-block) +- [Adding a Data Block with Modal](/plugin-samples/schema-initializer/data-block-modal) +- [Adding a Simple Action](/plugin-samples/schema-initializer/action-simple) +- [Adding a Popup Action](/plugin-samples/schema-initializer/action-modal) -**创建新的 Initializer** +**Creating a new Initializer** -- [区块内嵌的 Initializer - 配置字段](/plugin-samples/schema-initializer/configure-fields) -- [区块内嵌的 Initializer - 配置操作](/plugin-samples/schema-initializer/configure-actions) - +- [Block Embedded Initializer - Configure Fields](/plugin-samples/schema-initializer/configure-fields) +- [Block Embedded Initializer - Configure Actions](/plugin-samples/schema-initializer/configure-actions) +