diff --git a/packages/core/client/src/locale/zh-CN.json b/packages/core/client/src/locale/zh-CN.json index 5b0af5af52..6199385d4b 100644 --- a/packages/core/client/src/locale/zh-CN.json +++ b/packages/core/client/src/locale/zh-CN.json @@ -363,7 +363,7 @@ "is empty": "为空", "is not empty": "不为空", "Edit chart": "编辑图表", - "Add text": "添加文本", + "Add Markdown": "添加 Markdown", "Filterable fields": "可筛选字段", "Edit button": "编辑按钮", "Hide": "隐藏", @@ -1007,8 +1007,15 @@ "Stay on the current popup or page": "停留在当前弹窗或页面", "Return to the previous popup or page": "返回上一层弹窗或页面", "Action after successful submission": "提交成功后动作", - "Allow disassociation":"允许解除已有数据关联", + "Allow disassociation": "允许解除已有数据关联", "Layout": "布局", "Vertical": "垂直", - "Horizontal": "水平" + "Horizontal": "水平", + "Edit group title": "编辑分组标题", + "Title position": "标题位置", + "Dashed": "虚线", + "Left": "左", + "Center": "居中", + "Right": "右", + "Divider line color": "分割线颜色" } diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-multi/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/data-blocks/details-multi/__e2e__/schemaInitializer.test.ts index 286fc20242..6c54615bde 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/details-multi/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/details-multi/__e2e__/schemaInitializer.test.ts @@ -97,9 +97,9 @@ test.describe('configure fields', () => { page.getByLabel('block-item-CollectionField-general-details-general.manyToOne.nickname'), ).not.toBeVisible(); - // add text + // add markdown await formItemInitializer.hover(); - await page.getByRole('menuitem', { name: 'Add text' }).click(); + await page.getByRole('menuitem', { name: 'Add Markdown' }).click(); await expect(page.getByLabel('block-item-Markdown.Void-general-details')).toBeVisible(); }); }); diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-single/ReadPrettyFormItemInitializers.tsx b/packages/core/client/src/modules/blocks/data-blocks/details-single/ReadPrettyFormItemInitializers.tsx index 1386471f38..bd16684294 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/details-single/ReadPrettyFormItemInitializers.tsx +++ b/packages/core/client/src/modules/blocks/data-blocks/details-single/ReadPrettyFormItemInitializers.tsx @@ -79,7 +79,7 @@ const commonOptions = { }, { name: 'addText', - title: '{{t("Add text")}}', + title: '{{t("Add Markdown")}}', Component: 'BlockItemInitializer', schema: { type: 'void', @@ -97,6 +97,21 @@ const commonOptions = { }, }, }, + { + name: 'addDivider', + title: '{{t("Add group")}}', + Component: 'BlockItemInitializer', + schema: { + type: 'void', + 'x-decorator': 'FormItem', + 'x-toolbar': 'FormItemSchemaToolbar', + 'x-settings': 'blockSettings:divider', + 'x-component': 'Divider', + 'x-component-props': { + children: '{{t("Group")}}', + }, + }, + }, ], }; diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaInitializer.test.ts index 4ad63921c9..3a33949cbb 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaInitializer.test.ts @@ -87,9 +87,9 @@ test.describe('configure fields', () => { page.getByLabel('block-item-CollectionField-general-form-general.manyToOne.nickname'), ).not.toBeVisible(); - // add text + // add markdown await page.getByLabel('schema-initializer-Grid-form:configureFields-general').hover(); - await page.getByRole('menuitem', { name: 'Text' }).click(); + await page.getByRole('menuitem', { name: 'Add Markdown' }).click(); await expect(page.getByLabel('block-item-Markdown.Void-general-form')).toBeVisible(); }); diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/formItemInitializers.tsx b/packages/core/client/src/modules/blocks/data-blocks/form/formItemInitializers.tsx index bd0913b1c1..a0cae9c4d1 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/formItemInitializers.tsx +++ b/packages/core/client/src/modules/blocks/data-blocks/form/formItemInitializers.tsx @@ -36,9 +36,14 @@ const commonOptions = { }, { name: 'addText', - title: '{{t("Add text")}}', + title: '{{t("Add Markdown")}}', Component: 'MarkdownFormItemInitializer', }, + { + name: 'addDivider', + title: '{{t("Add group")}}', + Component: 'DividerFormItemInitializer', + }, ], }; diff --git a/packages/core/client/src/modules/blocks/data-blocks/grid-card/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/data-blocks/grid-card/__e2e__/schemaInitializer.test.ts index 1cc78d4eec..3212167479 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/grid-card/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/grid-card/__e2e__/schemaInitializer.test.ts @@ -182,11 +182,11 @@ test.describe('configure fields', () => { page.getByLabel('block-item-CollectionField-general-grid-card-general.manyToOne.nickname').first(), ).not.toBeVisible(); - // add text + // add markdown await formItemInitializer.hover(); await page.getByRole('menuitem', { name: 'ID', exact: true }).hover(); await page.mouse.wheel(0, 300); - await page.getByRole('menuitem', { name: 'Add text' }).click(); + await page.getByRole('menuitem', { name: 'Add Markdown' }).click(); await expect(page.getByLabel('block-item-Markdown.Void-general-grid-card').first()).toBeVisible(); }); diff --git a/packages/core/client/src/modules/blocks/data-blocks/list/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/data-blocks/list/__e2e__/schemaInitializer.test.ts index dc81bc4543..ea37819b0a 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/list/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/list/__e2e__/schemaInitializer.test.ts @@ -180,9 +180,9 @@ test.describe('configure fields', () => { page.getByLabel('block-item-CollectionField-general-list-general.manyToOne.nickname').first(), ).not.toBeVisible(); - // add text + // add markdown await formItemInitializer.hover(); - await page.getByRole('menuitem', { name: 'Add text' }).click(); + await page.getByRole('menuitem', { name: 'Add Markdown' }).click(); await expect(page.getByLabel('block-item-Markdown.Void-general-list').first()).toBeVisible(); }); }); diff --git a/packages/core/client/src/modules/blocks/filter-blocks/form/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/filter-blocks/form/__e2e__/schemaInitializer.test.ts index 74e4ec18e4..f4bb51468d 100644 --- a/packages/core/client/src/modules/blocks/filter-blocks/form/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/blocks/filter-blocks/form/__e2e__/schemaInitializer.test.ts @@ -75,9 +75,9 @@ test.describe('configure fields', () => { page.getByLabel('block-item-CollectionField-general-filter-form-general.manyToOne.nickname'), ).not.toBeVisible(); - // add text + // add markdown await formItemInitializer.hover(); - await page.getByRole('menuitem', { name: 'Add text' }).click(); + await page.getByRole('menuitem', { name: 'Add Markdown' }).click(); await expect(page.getByLabel('block-item-Markdown.Void-general-filter-form')).toBeVisible(); }); diff --git a/packages/core/client/src/modules/blocks/filter-blocks/form/filterFormItemInitializers.tsx b/packages/core/client/src/modules/blocks/filter-blocks/form/filterFormItemInitializers.tsx index 63ab0e958e..494d27f238 100644 --- a/packages/core/client/src/modules/blocks/filter-blocks/form/filterFormItemInitializers.tsx +++ b/packages/core/client/src/modules/blocks/filter-blocks/form/filterFormItemInitializers.tsx @@ -38,7 +38,7 @@ const commonOptions = { type: 'divider', }, { - title: '{{t("Add text")}}', + title: '{{t("Add Markdown")}}', Component: 'MarkdownFormItemInitializer', name: 'addText', }, diff --git a/packages/core/client/src/modules/blocks/other-blocks/divider/DividerFormItemInitializer.tsx b/packages/core/client/src/modules/blocks/other-blocks/divider/DividerFormItemInitializer.tsx new file mode 100644 index 0000000000..eb50a9bcd6 --- /dev/null +++ b/packages/core/client/src/modules/blocks/other-blocks/divider/DividerFormItemInitializer.tsx @@ -0,0 +1,35 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { LineOutlined } from '@ant-design/icons'; +import React from 'react'; +import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application'; + +export const DividerFormItemInitializer = () => { + const { insert } = useSchemaInitializer(); + const itemConfig = useSchemaInitializerItem(); + return ( + } + onClick={() => { + insert({ + type: 'void', + 'x-decorator': 'FormItem', + 'x-toolbar': 'FormItemSchemaToolbar', + 'x-settings': 'blockSettings:divider', + 'x-component': 'Divider', + 'x-component-props': { + children: '{{t("Group")}}', + }, + }); + }} + /> + ); +}; diff --git a/packages/core/client/src/modules/blocks/other-blocks/divider/dividerSettings.tsx b/packages/core/client/src/modules/blocks/other-blocks/divider/dividerSettings.tsx new file mode 100644 index 0000000000..12e5bd9766 --- /dev/null +++ b/packages/core/client/src/modules/blocks/other-blocks/divider/dividerSettings.tsx @@ -0,0 +1,202 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { useField, useFieldSchema } from '@formily/react'; +import { useTranslation } from 'react-i18next'; +import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings'; +import { SchemaSettingsModalItem } from '../../../../schema-settings'; + +import { useDesignable } from '../../../../schema-component/hooks/useDesignable'; +import { ColorPicker } from '../../../../schema-component'; +import React from 'react'; + +export function GroupTitleEditor(props) { + const field = useField(); + const fieldSchema = useFieldSchema(); + const { dn } = useDesignable(); + const { t } = useTranslation(); + + return ( + { + field.componentProps.children = children; + fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; + fieldSchema['x-component-props'].children = children; + dn.emit('patch', { + schema: { + ['x-uid']: fieldSchema['x-uid'], + 'x-component-props': { + ...fieldSchema['x-component-props'], + }, + }, + }); + dn.refresh(); + }} + /> + ); +} + +export const dividerSettings = new SchemaSettings({ + name: 'blockSettings:divider', + items: [ + { + name: 'editTitle', + type: 'item', + Component: GroupTitleEditor, + }, + { + name: 'orientation', + type: 'select', + useComponentProps() { + const field = useField(); + const fieldSchema = useFieldSchema(); + const { t } = useTranslation(); + const { dn } = useDesignable(); + return { + title: t('Title position'), + value: field.componentProps?.orientation || 'left', + options: [ + { label: t('Left'), value: 'left' }, + { label: t('Center'), value: 'center' }, + { label: t('Right'), value: 'right' }, + ], + onChange: (orientation) => { + field.componentProps = field.componentProps || {}; + field.componentProps.orientation = orientation; + fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; + fieldSchema['x-component-props']['orientation'] = orientation; + dn.emit('patch', { + schema: { + ['x-uid']: fieldSchema['x-uid'], + 'x-component-props': fieldSchema['x-component-props'], + }, + }); + }, + }; + }, + }, + { + name: 'dashed', + type: 'switch', + useComponentProps: () => { + const field = useField(); + const fieldSchema = useFieldSchema(); + const { t } = useTranslation(); + const { dn } = useDesignable(); + + return { + title: t('Dashed'), + defaultChecked: true, + checked: field.componentProps.dashed, + onChange: (flag) => { + field.componentProps.dashed = flag; + fieldSchema['x-component-props'].dashed = flag; + if (flag === false) { + fieldSchema['x-component-props'].dashed = false; + } + dn.emit('patch', { + schema: fieldSchema, + }); + dn.refresh(); + }, + }; + }, + }, + { + name: 'color', + type: 'item', + useComponentProps: () => { + const { t } = useTranslation(); + const { dn } = useDesignable(); + const field = useField(); + const fieldSchema = useFieldSchema(); + return { + title: ( +
+ {t('Color')} +
+ { + field.componentProps = field.componentProps || {}; + field.componentProps.color = value; + fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; + fieldSchema['x-component-props'].color = value; + dn.emit('patch', { + schema: fieldSchema, + }); + dn.refresh(); + }} + /> +
+
+ ), + }; + }, + }, + { + name: 'borderColor', + type: 'item', + useComponentProps: () => { + const { t } = useTranslation(); + const { dn } = useDesignable(); + const field = useField(); + const fieldSchema = useFieldSchema(); + return { + title: ( +
+ {t('Divider line color')} +
+ { + field.componentProps = field.componentProps || {}; + field.componentProps.borderColor = value; + fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; + fieldSchema['x-component-props'].borderColor = value; + dn.emit('patch', { + schema: fieldSchema, + }); + dn.refresh(); + }} + /> +
+
+ ), + }; + }, + }, + { + name: 'delete', + type: 'remove', + useComponentProps() { + return { + removeParentsIfNoChildren: true, + breakRemoveOn: { + 'x-component': 'Grid', + }, + }; + }, + }, + ] as any, +}); diff --git a/packages/core/client/src/schema-component/antd/color-picker/ColorPicker.tsx b/packages/core/client/src/schema-component/antd/color-picker/ColorPicker.tsx index 45a88c92f3..15978b5ce4 100644 --- a/packages/core/client/src/schema-component/antd/color-picker/ColorPicker.tsx +++ b/packages/core/client/src/schema-component/antd/color-picker/ColorPicker.tsx @@ -28,7 +28,7 @@ export const ColorPicker = connect( trigger="hover" {...others} destroyTooltipOnHide - getPopupContainer={(current) => current} + // getPopupContainer={(current) => current} presets={[ { label: 'Recommended', diff --git a/packages/core/client/src/schema-component/antd/divider/Divider.tsx b/packages/core/client/src/schema-component/antd/divider/Divider.tsx new file mode 100644 index 0000000000..31b8015612 --- /dev/null +++ b/packages/core/client/src/schema-component/antd/divider/Divider.tsx @@ -0,0 +1,27 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { connect, mapProps } from '@formily/react'; +import { Divider as AntdDivider } from 'antd'; +import React from 'react'; + +export const Divider = connect( + (props) => { + const { color, borderColor } = props; + return ; + }, + mapProps((props) => { + return { + orientation: 'left', + ...props, + }; + }), +); + +export default Divider; diff --git a/packages/core/client/src/schema-component/antd/divider/index.tsx b/packages/core/client/src/schema-component/antd/divider/index.tsx new file mode 100644 index 0000000000..18438f8936 --- /dev/null +++ b/packages/core/client/src/schema-component/antd/divider/index.tsx @@ -0,0 +1,10 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +export * from './Divider'; diff --git a/packages/core/client/src/schema-component/antd/index.ts b/packages/core/client/src/schema-component/antd/index.ts index 36b5d5bdbe..3dc50cb58e 100644 --- a/packages/core/client/src/schema-component/antd/index.ts +++ b/packages/core/client/src/schema-component/antd/index.ts @@ -63,5 +63,6 @@ export * from './unix-timestamp'; export * from './nanoid-input'; export * from './error-fallback'; export * from './expiresRadio'; +export * from './divider'; import './index.less'; diff --git a/packages/core/client/src/schema-initializer/index.ts b/packages/core/client/src/schema-initializer/index.ts index 8d49ca538b..5a1b16173e 100644 --- a/packages/core/client/src/schema-initializer/index.ts +++ b/packages/core/client/src/schema-initializer/index.ts @@ -114,6 +114,8 @@ import { CollectionFieldInitializer } from '../modules/fields/initializer/Collec import { TableCollectionFieldInitializer } from '../modules/fields/initializer/TableCollectionFieldInitializer'; import { menuItemInitializer, menuItemInitializer_deprecated } from '../modules/menu/menuItemInitializer'; import { blockInitializers, blockInitializers_deprecated } from '../modules/page/BlockInitializers'; +import { DividerFormItemInitializer } from '../modules/blocks/other-blocks/divider/DividerFormItemInitializer'; + import { customFormItemInitializers, customFormItemInitializers_deprecated, @@ -182,6 +184,7 @@ export class SchemaInitializerPlugin extends Plugin { DisassociateActionInitializer, FilterActionInitializer, RefreshActionInitializer, + DividerFormItemInitializer, } as any); this.app.schemaInitializerManager.add(blockInitializers_deprecated); diff --git a/packages/core/client/src/schema-settings/SchemaSettingsPlugin.ts b/packages/core/client/src/schema-settings/SchemaSettingsPlugin.ts index 9f9d228555..8817f8e28f 100644 --- a/packages/core/client/src/schema-settings/SchemaSettingsPlugin.ts +++ b/packages/core/client/src/schema-settings/SchemaSettingsPlugin.ts @@ -75,6 +75,7 @@ import { import { subTablePopoverComponentFieldSettings } from '../modules/fields/component/SubTable/subTablePopoverComponentFieldSettings'; import { tagComponentFieldSettings } from '../modules/fields/component/Tag/tagComponentFieldSettings'; import { unixTimestampComponentFieldSettings } from '../modules/fields/component/UnixTimestamp/unixTimestampComponentFieldSettings'; +import { dividerSettings } from '../modules/blocks/other-blocks/divider/dividerSettings'; export class SchemaSettingsPlugin extends Plugin { async load() { @@ -144,5 +145,6 @@ export class SchemaSettingsPlugin extends Plugin { // this.schemaSettingsManager.add(inputURLComponentFieldSettings); this.schemaSettingsManager.add(uploadAttachmentComponentFieldSettings); this.schemaSettingsManager.add(previewComponentFieldSettings); + this.schemaSettingsManager.add(dividerSettings); } } diff --git a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/BulkEditFormItemInitializers.tsx b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/BulkEditFormItemInitializers.tsx index 1e609eeec8..8ee11e824c 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/BulkEditFormItemInitializers.tsx +++ b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/BulkEditFormItemInitializers.tsx @@ -27,7 +27,7 @@ const commonOptions = { }, { name: 'addText', - title: '{{t("Add text")}}', + title: '{{t("Add Markdown")}}', Component: 'BlockItemInitializer', schema: { type: 'void',