diff --git a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/AggregateInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/AggregateInstruction.tsx
index 6ab62c34fc..0db525c3a5 100644
--- a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/AggregateInstruction.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/AggregateInstruction.tsx
@@ -10,6 +10,7 @@
import { useForm } from '@formily/react';
import { Cascader } from 'antd';
import React, { useCallback, useEffect, useState } from 'react';
+import { BarChartOutlined } from '@ant-design/icons';
import {
SchemaComponentContext,
@@ -169,6 +170,7 @@ export default class extends Instruction {
type = 'aggregate';
group = 'collection';
description = `{{t("Counting, summing, finding maximum, minimum, and average values for multiple records of a collection or associated data of a record.", { ns: "${NAMESPACE}" })}}`;
+ icon = ( );
fieldset = {
aggregator: {
type: 'string',
diff --git a/packages/plugins/@nocobase/plugin-workflow-delay/src/client/DelayInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-delay/src/client/DelayInstruction.tsx
index 9ffcf50f5f..81935fa347 100644
--- a/packages/plugins/@nocobase/plugin-workflow-delay/src/client/DelayInstruction.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-delay/src/client/DelayInstruction.tsx
@@ -9,8 +9,10 @@
import React from 'react';
import { InputNumber, Select } from 'antd';
-import { css, useCompile, usePlugin } from '@nocobase/client';
-import WorkflowPlugin, { Instruction, JOB_STATUS } from '@nocobase/plugin-workflow/client';
+import { HourglassOutlined } from '@ant-design/icons';
+
+import { css, useCompile } from '@nocobase/client';
+import { Instruction, JOB_STATUS } from '@nocobase/plugin-workflow/client';
import { NAMESPACE } from '../locale';
@@ -68,6 +70,7 @@ export default class extends Instruction {
type = 'delay';
group = 'control';
description = `{{t("Delay a period of time and then continue or exit the process. Can be used to set wait or timeout times in parallel branches.", { ns: "${NAMESPACE}" })}}`;
+ icon = ( );
fieldset = {
duration: {
type: 'number',
diff --git a/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/src/client/DynamicCalculation.tsx b/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/src/client/DynamicCalculation.tsx
index a5c0dc293f..efd6043827 100644
--- a/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/src/client/DynamicCalculation.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/src/client/DynamicCalculation.tsx
@@ -8,6 +8,7 @@
*/
import React from 'react';
+import { FunctionOutlined } from '@ant-design/icons';
import { SchemaInitializerItemType, Variable, useCollectionManager_deprecated } from '@nocobase/client';
import {
@@ -47,6 +48,7 @@ export default class extends Instruction {
type = 'dynamic-calculation';
group = 'calculation';
description = `{{t("Calculate an expression based on a calculation engine and obtain a value as the result. Variables in the upstream nodes can be used in the expression. The expression is dynamic one from an expression collections.", { ns: "${NAMESPACE}" })}}`;
+ icon = ( );
fieldset = {
expression: {
type: 'string',
diff --git a/packages/plugins/@nocobase/plugin-workflow-loop/src/client/LoopInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-loop/src/client/LoopInstruction.tsx
index b3e72c902d..c10914cf06 100644
--- a/packages/plugins/@nocobase/plugin-workflow-loop/src/client/LoopInstruction.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-loop/src/client/LoopInstruction.tsx
@@ -8,7 +8,7 @@
*/
import React, { useCallback } from 'react';
-import { ArrowUpOutlined } from '@ant-design/icons';
+import { ArrowUpOutlined, RollbackOutlined } from '@ant-design/icons';
import { Card, Checkbox } from 'antd';
import { FormLayout, FormItem } from '@formily/antd-v5';
import { useForm } from '@formily/react';
@@ -28,7 +28,6 @@ import {
Instruction,
RadioWithTooltip,
renderEngineReference,
- RadioWithTooltipOption,
CalculationConfig,
useWorkflowVariableOptions,
UseVariableOptions,
@@ -246,6 +245,7 @@ export default class extends Instruction {
type = 'loop';
group = 'control';
description = `{{t("By using a loop node, you can perform the same operation on multiple sets of data. The source of these sets can be either multiple records from a query node or multiple associated records of a single record. Loop node can also be used for iterating a certain number of times or for looping through each character in a string. However, excessive looping may cause performance issues, so use with caution.", { ns: "${NAMESPACE}" })}}`;
+ icon = ( );
fieldset = {
target: {
type: 'string',
@@ -381,7 +381,7 @@ export default class extends Instruction {
className={cx(
styles.branchBlockClass,
css`
- padding-left: 20em;
+ padding-left: 16em;
`,
)}
>
@@ -389,7 +389,7 @@ export default class extends Instruction {
-
diff --git a/packages/plugins/@nocobase/plugin-workflow-mailer/src/client/MailerInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-mailer/src/client/MailerInstruction.tsx
index deccb74dfa..08c148521d 100644
--- a/packages/plugins/@nocobase/plugin-workflow-mailer/src/client/MailerInstruction.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-mailer/src/client/MailerInstruction.tsx
@@ -7,6 +7,8 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import React from 'react';
+import { MailOutlined } from '@ant-design/icons';
import { ArrayItems } from '@formily/antd-v5';
import { SchemaComponentContext, css } from '@nocobase/client';
@@ -32,6 +34,7 @@ export default class extends Instruction {
type = 'mailer';
group = 'extended';
description = `{{t("Send email. You can use the variables in the upstream nodes as receivers, subject and content of the email.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
provider: {
type: 'object',
diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/index.tsx b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/index.tsx
index b345d54dae..0d0c440eaf 100644
--- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/index.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/index.tsx
@@ -7,6 +7,9 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import React from 'react';
+import { SolutionOutlined } from '@ant-design/icons';
+
import { SchemaInitializerItemType, useCollectionManager_deprecated, useCompile, usePlugin } from '@nocobase/client';
import {
@@ -75,6 +78,7 @@ export default class extends Instruction {
type = 'manual';
group = 'manual';
description = `{{t("Could be used for manually submitting data, and determine whether to continue or exit. Workflow will generate a todo item for assigned user when it reaches a manual node, and continue processing after user submits the form.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
assignees: {
type: 'array',
diff --git a/packages/plugins/@nocobase/plugin-workflow-notification/src/client/NotificationInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-notification/src/client/NotificationInstruction.tsx
index 1054c394eb..ba1115be95 100644
--- a/packages/plugins/@nocobase/plugin-workflow-notification/src/client/NotificationInstruction.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-notification/src/client/NotificationInstruction.tsx
@@ -7,6 +7,7 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import React from 'react';
+import { NotificationOutlined } from '@ant-design/icons';
import { Instruction, useWorkflowVariableOptions } from '@nocobase/plugin-workflow/client';
import { MessageConfigForm } from '@nocobase/plugin-notification-manager/client';
@@ -22,6 +23,7 @@ export default class extends Instruction {
type = 'notification';
group = 'extended';
description = `{{t("Send notification. You can use the variables in the upstream nodes as content and ohter config.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
message: {
type: 'void',
diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/ParallelInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/ParallelInstruction.tsx
index 13006e1bc2..689ff20c17 100644
--- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/ParallelInstruction.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/ParallelInstruction.tsx
@@ -9,7 +9,7 @@
import React, { useState } from 'react';
import { Button, Tooltip } from 'antd';
-import { PlusOutlined } from '@ant-design/icons';
+import { ApartmentOutlined, PlusOutlined } from '@ant-design/icons';
import { css } from '@nocobase/client';
@@ -30,6 +30,7 @@ export default class extends Instruction {
type = 'parallel';
group = 'control';
description = `{{t("Run multiple branch processes in parallel.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
mode: {
type: 'string',
diff --git a/packages/plugins/@nocobase/plugin-workflow-request/src/client/RequestInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-request/src/client/RequestInstruction.tsx
index fcacdc3fe0..91703f7129 100644
--- a/packages/plugins/@nocobase/plugin-workflow-request/src/client/RequestInstruction.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-request/src/client/RequestInstruction.tsx
@@ -11,7 +11,9 @@ import { onFieldValueChange } from '@formily/core';
import { uid } from '@formily/shared';
import { useForm, useField, useFormEffects } from '@formily/react';
import { ArrayItems } from '@formily/antd-v5';
+import { GlobalOutlined } from '@ant-design/icons';
+import { SchemaComponent, css } from '@nocobase/client';
import {
Instruction,
WorkflowVariableJSON,
@@ -21,7 +23,6 @@ import {
} from '@nocobase/plugin-workflow/client';
import { NAMESPACE, useLang } from '../locale';
-import { SchemaComponent, css } from '@nocobase/client';
const BodySchema = {
'application/json': {
@@ -155,6 +156,7 @@ export default class extends Instruction {
type = 'request';
group = 'extended';
description = `{{t("Send HTTP request to a URL. You can use the variables in the upstream nodes as request headers, parameters and request body.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
method: {
type: 'string',
diff --git a/packages/plugins/@nocobase/plugin-workflow-sql/src/client/SQLInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-sql/src/client/SQLInstruction.tsx
index 28762241af..1a90a4904b 100644
--- a/packages/plugins/@nocobase/plugin-workflow-sql/src/client/SQLInstruction.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow-sql/src/client/SQLInstruction.tsx
@@ -12,6 +12,7 @@ import { DEFAULT_DATA_SOURCE_KEY, css } from '@nocobase/client';
import { Instruction, WorkflowVariableRawTextArea, defaultFieldNames } from '@nocobase/plugin-workflow/client';
import React from 'react';
+import { ConsoleSqlOutlined } from '@ant-design/icons';
import { Trans } from 'react-i18next';
import { NAMESPACE } from '../locale';
@@ -20,6 +21,7 @@ export default class extends Instruction {
type = 'sql';
group = 'collection';
description = `{{t("Execute a SQL statement in database.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
dataSource: {
type: 'string',
diff --git a/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2ePageObjectModel.ts b/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2ePageObjectModel.ts
index fbb03a7c32..1d43f4ae14 100644
--- a/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2ePageObjectModel.ts
+++ b/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2ePageObjectModel.ts
@@ -110,7 +110,7 @@ export class ApprovalTriggerNode {
this.page = page;
this.node = page.getByLabel(`Trigger-${triggerName}`);
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole('textbox');
- this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.collectionDropDown = page
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
.locator('.ant-select-selection-search-input');
@@ -168,9 +168,7 @@ export class ApprovalPassthroughModeNode {
this.page = page;
this.node = page.getByLabel(`Approval-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Approval-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Approval-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.addAssigneesButton = page.getByRole('button', { name: 'plus Add assignee' });
this.addSelectAssigneesMenu = page.getByRole('button', { name: 'Select assignees' });
this.addQueryAssigneesMenu = page.getByRole('button', { name: 'Query assignees' });
@@ -241,9 +239,7 @@ export class ApprovalBranchModeNode {
this.page = page;
this.node = page.getByLabel(`Approval-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Approval-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Approval-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.addAssigneesButton = page.getByRole('button', { name: 'plus Add assignee' });
this.addSelectAssigneesMenu = page.getByRole('button', { name: 'Select assignees' });
this.addQueryAssigneesMenu = page.getByRole('button', { name: 'Query assignees' });
@@ -298,9 +294,9 @@ export class ScheduleTriggerNode {
addNodeButton: Locator;
constructor(page: Page, triggerName: string, collectionName: string) {
this.page = page;
- this.node = page.getByText('TriggeraConfigure');
+ this.node = page.getByLabel(`Trigger-${triggerName}`);
this.nodeTitle = page.locator('textarea').filter({ hasText: triggerName });
- this.nodeConfigure = page.getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.customTimeTriggerOptions = page.getByLabel('Based on certain date');
this.startTimeEntryBox = page.getByPlaceholder('Select date');
this.RrpeatModeDropdown = page.getByLabel('block-item-RepeatField-workflows-Repeat mode');
@@ -330,7 +326,7 @@ export class CollectionTriggerNode {
this.page = page;
this.node = page.getByLabel(`Trigger-${triggerName}`);
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole('textbox');
- this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
// this.collectionDropDown = page.getByRole('button', { name: 'Select collection' });
this.collectionDropDown = page
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
@@ -358,7 +354,7 @@ export class FormEventTriggerNode {
this.page = page;
this.node = page.getByLabel(`Trigger-${triggerName}`);
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole('textbox');
- this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.collectionDropDown = page
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
.locator('.ant-select-selection-search-input');
@@ -383,7 +379,7 @@ export class CustomActionEventTriggerNode {
this.page = page;
this.node = page.getByLabel(`Trigger-${triggerName}`);
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole('textbox');
- this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.collectionDropDown = page
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
.locator('.ant-select-selection-search-input');
@@ -408,9 +404,7 @@ export class CalculationNode {
this.page = page;
this.node = page.getByLabel(`Calculation-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Calculation-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Calculation-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.mathCalculationEngine = page.getByLabel('Math.js');
this.formulaCalculationEngine = page.getByLabel('Formula.js');
this.calculationExpression = page.getByLabel('textbox');
@@ -441,9 +435,7 @@ export class QueryRecordNode {
this.page = page;
this.node = page.getByLabel(`Query record-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Query record-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Query record-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.collectionDropDown = page
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
.locator('.ant-select-selection-search-input');
@@ -475,9 +467,7 @@ export class CreateRecordNode {
this.page = page;
this.node = page.getByLabel(`Create record-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Create record-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Create record-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.collectionDropDown = page
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
.locator('.ant-select-selection-search-input');
@@ -504,9 +494,7 @@ export class UpdateRecordNode {
this.page = page;
this.node = page.getByLabel(`Update record-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Update record-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Update record-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.collectionDropDown = page
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
.locator('.ant-select-selection-search-input');
@@ -536,9 +524,7 @@ export class DeleteRecordNode {
this.page = page;
this.node = page.getByLabel(`Delete record-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Delete record-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Delete record-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.collectionDropDown = page
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
.locator('.ant-select-selection-search-input');
@@ -570,9 +556,7 @@ export class AggregateNode {
this.page = page;
this.node = page.getByLabel(`Aggregate-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Aggregate-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Aggregate-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.countRadio = page.getByLabel('COUNT');
this.sumRadio = page.getByLabel('SUM', { exact: true });
this.avgRadio = page.getByLabel('AVG', { exact: true });
@@ -615,9 +599,7 @@ export class ManualNode {
this.page = page;
this.node = page.getByLabel(`Manual-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Manual-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Manual-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.assigneesDropDown = page.getByTestId('select-single');
this.configureUserInterfaceButton = page.getByRole('button', { name: 'Configure user interface' });
this.addBlockButton = page.getByLabel(
@@ -650,9 +632,7 @@ export class ConditionYesNode {
this.page = page;
this.node = page.getByLabel(`Condition-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Condition-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Condition-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.conditionExpressionEditBox = page.getByLabel('textbox');
// await page.getByLabel('variable-constant').first().click();
// await page.getByLabel('variable-button').first().click();
@@ -687,9 +667,7 @@ export class ConditionBranchNode {
this.page = page;
this.node = page.getByLabel(`Condition-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`Condition-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`Condition-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.conditionExpressionEditBox = page.getByLabel('textbox');
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
@@ -715,9 +693,7 @@ export class SQLNode {
this.page = page;
this.node = page.getByLabel(`SQL action-${nodeName}`, { exact: true });
this.nodeTitle = page.getByLabel(`SQL action-${nodeName}`, { exact: true }).getByRole('textbox');
- this.nodeConfigure = page
- .getByLabel(`SQL action-${nodeName}`, { exact: true })
- .getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.sqlEditBox = page.getByLabel('block-item-WorkflowVariableRawTextArea-workflows-SQL').getByRole('textbox');
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
@@ -741,7 +717,7 @@ export class ParallelBranchNode {
this.page = page;
this.node = page.getByLabel(`Parallel branch-${nodeName}`, { exact: true });
this.nodeTitle = page.locator('textarea').filter({ hasText: nodeName });
- this.nodeConfigure = page.getByLabel(`Parallel branch-${nodeName}`).getByRole('button', { name: 'Configure' });
+ this.nodeConfigure = this.node.locator('>div').first();
this.addBranchButton = page.getByLabel(`add-button-parallel-${nodeName}-add-branch`, { exact: true });
this.allSucceededRadio = page.getByLabel('All succeeded', { exact: true });
this.anySucceededRadio = page.getByLabel('Any succeeded', { exact: true });
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/AddNodeContext.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/AddNodeContext.tsx
index 4d418e3e24..798fbbc300 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/AddNodeContext.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/AddNodeContext.tsx
@@ -14,6 +14,7 @@ import { observer, useForm } from '@formily/react';
import {
ActionContextProvider,
css,
+ cx,
SchemaComponent,
useActionContext,
useAPIClient,
@@ -68,6 +69,7 @@ export function AddButton(props: AddButtonProps) {
'aria-label': item.type,
key: item.type,
label: item.title,
+ icon: item.icon,
})),
};
})
@@ -89,7 +91,7 @@ export function AddButton(props: AddButtonProps) {
}
return (
-
+
{controller}
-
+
{list.map((item) => (
))}
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/calculation.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/calculation.tsx
index 1aec3ca660..28c9fd676e 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/calculation.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/calculation.tsx
@@ -7,6 +7,9 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import React from 'react';
+import { CalculatorOutlined } from '@ant-design/icons';
+
import { SchemaInitializerItemType } from '@nocobase/client';
import { Evaluator, evaluators, getOptions } from '@nocobase/evaluators/client';
@@ -22,6 +25,7 @@ export default class extends Instruction {
type = 'calculation';
group = 'calculation';
description = `{{t("Calculate an expression based on a calculation engine and obtain a value as the result. Variables in the upstream nodes can be used in the expression.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
engine: {
type: 'string',
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/condition.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/condition.tsx
index c22382a470..c0b39d58a8 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/condition.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/condition.tsx
@@ -19,6 +19,7 @@ import { lang, NAMESPACE } from '../locale';
import useStyles from '../style';
import { useWorkflowVariableOptions, WorkflowVariableTextArea } from '../variable';
import { CalculationConfig } from '../components/Calculation';
+import { QuestionCircleOutlined } from '@ant-design/icons';
const BRANCH_INDEX = {
DEFAULT: null,
@@ -31,6 +32,7 @@ export default class extends Instruction {
type = 'condition';
group = 'control';
description = `{{t('Based on boolean result of the calculation to determine whether to "continue" or "exit" the process, or continue on different branches of "yes" and "no".', { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
rejectOnFalse: {
type: 'boolean',
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/create.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/create.tsx
index 7224401656..a189906cf6 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/create.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/create.tsx
@@ -7,6 +7,9 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import React from 'react';
+import { FileAddOutlined } from '@ant-design/icons';
+
import { SchemaInitializerItemType, parseCollectionName, useCollectionDataSource, useCompile } from '@nocobase/client';
import { CollectionBlockInitializer } from '../components/CollectionBlockInitializer';
@@ -52,6 +55,7 @@ export default class extends Instruction {
type = 'create';
group = 'collection';
description = `{{t("Add new record to a collection. You can use variables from upstream nodes to assign values to fields.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
collection: {
...collection,
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/destroy.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/destroy.tsx
index 12eb6e0921..f40e237761 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/destroy.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/destroy.tsx
@@ -7,6 +7,9 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import React from 'react';
+import { DeleteOutlined } from '@ant-design/icons';
+
import { useCollectionDataSource } from '@nocobase/client';
import { isValidFilter } from '@nocobase/utils/client';
@@ -20,6 +23,7 @@ export default class extends Instruction {
type = 'destroy';
group = 'collection';
description = `{{t("Delete records of a collection. Could use variables in workflow context as filter. All records match the filter will be deleted.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
collection: {
...collection,
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/end.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/end.tsx
index 614cf69240..7011285ff7 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/end.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/end.tsx
@@ -7,6 +7,9 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import React from 'react';
+import { StopOutlined } from '@ant-design/icons';
+
import { Instruction } from '.';
import { NAMESPACE } from '../locale';
import { JOB_STATUS } from '../constants';
@@ -16,6 +19,7 @@ export default class extends Instruction {
type = 'end';
group = 'control';
description = `{{t("End the process immediately, with set status.", { ns: "${NAMESPACE}" })}}`;
+ icon = (
);
fieldset = {
endStatus: {
type: 'number',
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx
index 38f664c1ff..00e2134c5a 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx
@@ -60,6 +60,7 @@ export abstract class Instruction {
type: string;
group: string;
description?: string;
+ icon?: JSX.Element;
/**
* @deprecated migrate to `presetFieldset` instead
*/
@@ -610,7 +611,7 @@ export function NodeDefaultView(props) {
>
- {typeTitle}
+ {typeTitle}
{data.id}
@@ -646,15 +647,15 @@ export function NodeDefaultView(props) {
type: 'void',
properties: {
...(instruction.view ? { view: instruction.view } : {}),
- button: {
- type: 'void',
- 'x-content': detailText,
- 'x-component': Button,
- 'x-component-props': {
- type: 'link',
- className: 'workflow-node-config-button',
- },
- },
+ // button: {
+ // type: 'void',
+ // 'x-content': detailText,
+ // 'x-component': Button,
+ // 'x-component-props': {
+ // type: 'link',
+ // className: 'workflow-node-config-button',
+ // },
+ // },
[data.id]: {
type: 'void',
title: (
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/query.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/query.tsx
index e0877801a1..41a4973b7f 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/query.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/query.tsx
@@ -7,6 +7,8 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import React from 'react';
+import { FileSearchOutlined } from '@ant-design/icons';
import { ArrayItems } from '@formily/antd-v5';
import {
@@ -62,6 +64,7 @@ export default class extends Instruction {
type = 'query';
group = 'collection';
description = `{{t("Query records from a collection. You can use variables from upstream nodes as query conditions.", { ns: "${NAMESPACE}" })}}`;
+ icon = ( );
fieldset = {
collection: {
...collection,
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/update.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/update.tsx
index 46b0f42fc0..f57f627685 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/update.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/update.tsx
@@ -7,7 +7,8 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
-import { uid } from '@formily/shared';
+import React from 'react';
+import { EditOutlined } from '@ant-design/icons';
import { useCollectionDataSource } from '@nocobase/client';
import { isValidFilter } from '@nocobase/utils/client';
@@ -26,6 +27,7 @@ export default class extends Instruction {
type = 'update';
group = 'collection';
description = `{{t("Update records of a collection. You can use variables from upstream nodes as query conditions and field values.", { ns: "${NAMESPACE}" })}}`;
+ icon = ( );
fieldset = {
collection: {
...collection,
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/style.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/style.tsx
index 2f65c72940..0fba0947cd 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/style.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/style.tsx
@@ -152,11 +152,22 @@ const useStyles = createStyles(({ css, token }) => {
flex-direction: column;
align-items: center;
position: relative;
- min-width: 20em;
+ min-width: 16em;
padding: 0 2em;
.workflow-node-list {
flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ > :last-child {
+ > .workflow-add-node-button {
+ &:after {
+ display: none;
+ }
+ }
+ }
}
.workflow-branch-lines {
@@ -214,7 +225,7 @@ const useStyles = createStyles(({ css, token }) => {
align-items: center;
justify-content: center;
width: 0;
- height: 6em;
+ height: 4em;
border-left: 1px dashed ${token.colorBgLayout};
.anticon {
@@ -242,7 +253,7 @@ const useStyles = createStyles(({ css, token }) => {
nodeCardClass: css`
position: relative;
- width: 20em;
+ width: 16em;
background: ${token.colorBgContainer};
padding: 1em;
box-shadow: ${token.boxShadowTertiary};
@@ -363,14 +374,32 @@ const useStyles = createStyles(({ css, token }) => {
`,
addButtonClass: css`
+ position: relative;
flex-shrink: 0;
- padding: 2em 0;
+ padding: 1em 0;
> .ant-btn {
&:disabled {
visibility: hidden;
}
}
+
+ &:after {
+ content: '';
+ display: block;
+ position: absolute;
+ bottom: 0.1em;
+ left: calc(50% - 0.25em);
+ width: 0.5em;
+ height: 0.5em;
+ border: 1px solid ${token.colorBorder};
+ border-width: 0 1px 1px 0;
+ transform: rotate(45deg);
+ }
+
+ &:first-child:last-child:after {
+ display: none;
+ }
`,
conditionClass: css`
@@ -396,6 +425,9 @@ const useStyles = createStyles(({ css, token }) => {
transform: translateY(-50%);
width: 2em;
height: 6em;
+ flex-shrink: 0;
+ padding: 2em 0;
+ font-size: 14px;
`,
terminalClass: css`
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx
index 068a15a564..91f8ffe5c3 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx
@@ -306,15 +306,15 @@ export const TriggerConfig = () => {
name: `workflow-trigger-${workflow.id}`,
type: 'void',
properties: {
- config: {
- type: 'void',
- 'x-content': detailText,
- 'x-component': Button,
- 'x-component-props': {
- type: 'link',
- className: 'workflow-node-config-button',
- },
- },
+ // config: {
+ // type: 'void',
+ // 'x-content': detailText,
+ // 'x-component': Button,
+ // 'x-component-props': {
+ // type: 'link',
+ // className: 'workflow-node-config-button',
+ // },
+ // },
drawer: {
type: 'void',
title: titleText,