diff --git a/packages/core/client/src/flow/models/base/BlockModel.tsx b/packages/core/client/src/flow/models/base/BlockModel.tsx index 122f5832d7..e843b2fd1b 100644 --- a/packages/core/client/src/flow/models/base/BlockModel.tsx +++ b/packages/core/client/src/flow/models/base/BlockModel.tsx @@ -6,13 +6,16 @@ * 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 { tval } from '@nocobase/utils/client'; import { APIResource, BaseRecordResource, Collection, DefaultStructure, FlowModel } from '@nocobase/flow-engine'; -import { Card } from 'antd'; import React from 'react'; +import { BlockItemCard } from '../common/BlockItemCard'; export class BlockModel extends FlowModel { decoratorProps: Record = {}; + setDecoratorProps(props) { + this.decoratorProps = { ...this.decoratorProps, ...props }; + } renderComponent() { throw new Error('renderComponent method must be implemented in subclasses of BlockModel'); @@ -20,10 +23,92 @@ export class BlockModel extends FlowModel { } render() { - return {this.renderComponent()}; + return {this.renderComponent()}; } } +export const HeightMode = { + DEFAULT: 'defaultHeight', + SPECIFY_VALUE: 'specifyValue', + FULL_HEIGHT: 'fullHeight', +}; + +BlockModel.registerFlow({ + key: 'blockProps', + title: tval('Basic configuration'), + auto: true, + steps: { + editBlockTitleAndDescription: { + title: tval('Edit block title & description'), + uiSchema: { + title: { + 'x-component': 'Input', + 'x-decorator': 'FormItem', + title: tval('Title'), + }, + description: { + 'x-component': 'Input.TextArea', + 'x-decorator': 'FormItem', + title: tval('Description'), + }, + }, + handler(ctx, params) { + const title = ctx.globals.flowEngine.translate(params.title); + const description = ctx.globals.flowEngine.translate(params.description); + ctx.model.setDecoratorProps({ title: title, description: description }); + }, + }, + setBlockHeight: { + title: tval('Set block height'), + uiSchema: { + heightMode: { + type: 'string', + enum: [ + { label: tval('Default'), value: HeightMode.DEFAULT }, + { label: tval('Specify height'), value: HeightMode.SPECIFY_VALUE }, + { label: tval('Full height'), value: HeightMode.FULL_HEIGHT }, + ], + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'Radio.Group', + }, + height: { + title: tval('Height'), + type: 'string', + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'NumberPicker', + 'x-component-props': { + addonAfter: 'px', + }, + 'x-validator': [ + { + minimum: 40, + }, + ], + 'x-reactions': { + dependencies: ['heightMode'], + fulfill: { + state: { + hidden: '{{ $deps[0]==="fullHeight"||$deps[0]==="defaultHeight"}}', + value: '{{$deps[0]!=="specifyValue"?null:$self.value}}', + }, + }, + }, + }, + }, + defaultParams: () => { + return { + heightMode: HeightMode.DEFAULT, + }; + }, + handler(ctx, params) { + ctx.model.setProps('heightMode', params.heightMode); + ctx.model.setProps('height', params.height); + }, + }, + }, +}); export class DataBlockModel extends BlockModel { resource: APIResource; collection: Collection; diff --git a/packages/core/client/src/flow/models/base/GridModel.tsx b/packages/core/client/src/flow/models/base/GridModel.tsx index 85cfbf7119..adb4663b03 100644 --- a/packages/core/client/src/flow/models/base/GridModel.tsx +++ b/packages/core/client/src/flow/models/base/GridModel.tsx @@ -8,20 +8,12 @@ */ import { PlusOutlined } from '@ant-design/icons'; -import { Input } from '@formily/antd-v5'; import { uid } from '@formily/shared'; -import { - AddBlockButton, - FlowModel, - FlowModelRenderer, - FlowSettingsButton, - FlowsFloatContextMenu, - useStepSettingContext, -} from '@nocobase/flow-engine'; +import { AddBlockButton, FlowModel, FlowModelRenderer, FlowSettingsButton } from '@nocobase/flow-engine'; import { tval } from '@nocobase/utils/client'; -import { Alert, Space } from 'antd'; +import { Space } from 'antd'; import _ from 'lodash'; -import React, { useState } from 'react'; +import React from 'react'; import { Grid } from '../../components/Grid'; import JsonEditor from '../../components/JsonEditor'; import { SkeletonFallback } from '../../components/SkeletonFallback'; diff --git a/packages/core/client/src/flow/models/common/BlockItemCard.tsx b/packages/core/client/src/flow/models/common/BlockItemCard.tsx new file mode 100644 index 0000000000..40ff9a3aa0 --- /dev/null +++ b/packages/core/client/src/flow/models/common/BlockItemCard.tsx @@ -0,0 +1,47 @@ +/** + * 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 { theme, Card } from 'antd'; +import _ from 'lodash'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { NAMESPACE_UI_SCHEMA } from '../../../i18n/constant'; +import { MarkdownReadPretty } from '../fields/EditableField/MarkdownEditableFieldModel'; + +export const BlockItemCard = (props) => { + const { t } = useTranslation(); + const { token } = theme.useToken(); + const { title: blockTitle, description, children } = props; + const title = (blockTitle || description) && ( +
+ {t(blockTitle, { ns: NAMESPACE_UI_SCHEMA })} + {description && ( + + )} +
+ ); + return ( + + {children} + + ); +}; diff --git a/packages/core/client/src/flow/models/data-blocks/form/FormModel.tsx b/packages/core/client/src/flow/models/data-blocks/form/FormModel.tsx index 63d97e9a18..49fafe2283 100644 --- a/packages/core/client/src/flow/models/data-blocks/form/FormModel.tsx +++ b/packages/core/client/src/flow/models/data-blocks/form/FormModel.tsx @@ -12,7 +12,6 @@ import { createForm, Form } from '@formily/core'; import { FormProvider } from '@formily/react'; import { AddActionButton, AddFieldButton, FlowModelRenderer, SingleRecordResource } from '@nocobase/flow-engine'; import { tval } from '@nocobase/utils/client'; -import { Card } from 'antd'; import React from 'react'; import { DataBlockModel } from '../../base/BlockModel'; import { EditableFieldModel } from '../../fields/EditableField/EditableFieldModel'; @@ -21,54 +20,51 @@ export class FormModel extends DataBlockModel { form: Form; declare resource: SingleRecordResource; - render() { - console.log(this); + renderComponent() { return ( - - - - {this.mapSubModels('fields', (field) => ( - - ))} - - ({ - use: defaultOptions.use, - stepParams: { - default: { - step1: { - dataSourceKey: this.collection.dataSourceKey, - collectionName: this.collection.name, - fieldPath, - }, + + + {this.mapSubModels('fields', (field) => ( + + ))} + + ({ + use: defaultOptions.use, + stepParams: { + default: { + step1: { + dataSourceKey: this.collection.dataSourceKey, + collectionName: this.collection.name, + fieldPath, }, }, - })} - subModelKey="fields" - model={this} - collection={this.collection} - subModelBaseClass="EditableFieldModel" - onSubModelAdded={async (model: EditableFieldModel) => { - const params = model.getStepParams('default', 'step1'); - this.addAppends(params?.fieldPath, !!this.ctx.shared?.currentFlow?.extra?.filterByTk); - }} - /> - - {this.mapSubModels('actions', (action) => ( - - ))} - - - - + }, + })} + subModelKey="fields" + model={this} + collection={this.collection} + subModelBaseClass="EditableFieldModel" + onSubModelAdded={async (model: EditableFieldModel) => { + const params = model.getStepParams('default', 'step1'); + this.addAppends(params?.fieldPath, !!this.ctx.shared?.currentFlow?.extra?.filterByTk); + }} + /> + + {this.mapSubModels('actions', (action) => ( + + ))} + + + ); } } diff --git a/packages/core/client/src/flow/models/data-blocks/table/TableModel.tsx b/packages/core/client/src/flow/models/data-blocks/table/TableModel.tsx index 4b30ea9a71..38747a13b4 100644 --- a/packages/core/client/src/flow/models/data-blocks/table/TableModel.tsx +++ b/packages/core/client/src/flow/models/data-blocks/table/TableModel.tsx @@ -20,11 +20,11 @@ import { useFlowEngine, } from '@nocobase/flow-engine'; import { tval } from '@nocobase/utils/client'; -import { Card, Space, Spin, Table } from 'antd'; +import { Space, Spin, Table } from 'antd'; import classNames from 'classnames'; -import { t } from 'i18next'; import _ from 'lodash'; import React, { useRef } from 'react'; +import { BlockItemCard } from '../../common/BlockItemCard'; import { ActionModel } from '../../base/ActionModel'; import { DataBlockModel } from '../../base/BlockModel'; import { QuickEditForm } from '../form/QuickEditForm'; diff --git a/packages/core/client/src/flow/models/fields/EditableField/AssociationFieldModel/AssociationSelectEditableFieldModel.tsx b/packages/core/client/src/flow/models/fields/EditableField/AssociationFieldModel/AssociationSelectEditableFieldModel.tsx index 78bfd5c752..31cd8f8886 100644 --- a/packages/core/client/src/flow/models/fields/EditableField/AssociationFieldModel/AssociationSelectEditableFieldModel.tsx +++ b/packages/core/client/src/flow/models/fields/EditableField/AssociationFieldModel/AssociationSelectEditableFieldModel.tsx @@ -9,6 +9,7 @@ import { connect, mapProps, mapReadPretty } from '@formily/react'; import { Select } from 'antd'; import React from 'react'; +import { castArray } from 'lodash'; import { useFlowModel, FlowModel } from '@nocobase/flow-engine'; import { tval } from '@nocobase/utils/client'; import { AssociationFieldEditableFieldModel } from './AssociationFieldEditableFieldModel'; @@ -82,7 +83,42 @@ const AssociationSelect = connect( }, ), mapReadPretty((props) => { - return props.value; + const currentModel: any = useFlowModel(); + + const { fieldNames, value } = props; + if (!value) { + return; + } + const field = currentModel.subModels.field as FlowModel; + const key = value?.[fieldNames.value]; + const fieldModel = field.createFork({}, key); + fieldModel.setSharedContext({ + value: value?.[fieldNames.label], + currentRecord: value, + }); + const arrayValue = castArray(value); + + return ( + <> + {arrayValue.map((v, index) => { + const key = `${index}`; + const fieldModel = field.createFork({}, key); + fieldModel.setSharedContext({ + index, + value: v?.[fieldNames.label], + currentRecord: v, + }); + + const content = v?.[fieldNames.label] ? fieldModel.render() : tval('N/A'); + return ( + + {index > 0 && ', '} + {content} + + ); + })} + + ); }), ); @@ -160,7 +196,7 @@ AssociationSelectEditableFieldModel.registerFlow({ steps: { step1: { async handler(ctx, params) { - const { target } = ctx.model.collectionField.options; + const { target } = ctx.model.collectionField; const apiClient = ctx.app.apiClient; const response = await apiClient.request({ url: `/${target}:list`, @@ -244,9 +280,7 @@ AssociationSelectEditableFieldModel.registerFlow({ async handler(ctx, params) { try { const collectionField = ctx.model.collectionField; - const collectionManager = collectionField.collection.collectionManager; - const targetCollection = collectionManager.getCollection(collectionField.options.target); - + const targetCollection = ctx.model.collectionField.targetCollection; const labelFieldName = ctx.model.field.componentProps.fieldNames.label; const targetLabelField = targetCollection.getField(labelFieldName); diff --git a/packages/core/client/src/flow/models/fields/EditableField/EditableFieldModel.tsx b/packages/core/client/src/flow/models/fields/EditableField/EditableFieldModel.tsx index 3f58e1c21c..90095f8388 100644 --- a/packages/core/client/src/flow/models/fields/EditableField/EditableFieldModel.tsx +++ b/packages/core/client/src/flow/models/fields/EditableField/EditableFieldModel.tsx @@ -119,7 +119,7 @@ EditableFieldModel.registerFlow({ if (collectionField.enum.length) { ctx.model.setDataSource(collectionField.enum); } - const validator = collectionField.options.uiSchema?.['x-validator']; + const validator = collectionField.uiSchema?.['x-validator']; if (validator) { ctx.model.setValidator(validator); } diff --git a/packages/core/client/src/flow/models/fields/EditableField/MarkdownEditableFieldModel/index.tsx b/packages/core/client/src/flow/models/fields/EditableField/MarkdownEditableFieldModel/index.tsx index dd9c115959..23479e484e 100644 --- a/packages/core/client/src/flow/models/fields/EditableField/MarkdownEditableFieldModel/index.tsx +++ b/packages/core/client/src/flow/models/fields/EditableField/MarkdownEditableFieldModel/index.tsx @@ -23,6 +23,7 @@ export const MarkdownReadPretty = (props) => {
); diff --git a/packages/core/client/src/flow/models/fields/EditableField/NanoIDEditableFieldModel.tsx b/packages/core/client/src/flow/models/fields/EditableField/NanoIDEditableFieldModel.tsx index d2d726a737..e6f6f54064 100644 --- a/packages/core/client/src/flow/models/fields/EditableField/NanoIDEditableFieldModel.tsx +++ b/packages/core/client/src/flow/models/fields/EditableField/NanoIDEditableFieldModel.tsx @@ -12,7 +12,7 @@ import { customAlphabet as Alphabet } from 'nanoid'; import { EditableFieldModel } from './EditableFieldModel'; export class NanoIDEditableFieldModel extends EditableFieldModel { - static supportedFieldInterfaces = ['nanoID']; + static supportedFieldInterfaces = ['nanoid']; get component() { return [Input, {}]; @@ -22,7 +22,7 @@ export class NanoIDEditableFieldModel extends EditableFieldModel { NanoIDEditableFieldModel.registerFlow({ key: 'initialValue', auto: true, - sort: 5, + sort: 1000, steps: { initialValue: { handler(ctx, params) {