(data.title ?? typeTitle);
const [editingConfig, setEditingConfig] = useState(false);
+ const [formValueChanged, setFormValueChanged] = useState(false);
- async function onChangeTitle(next) {
- const title = next || typeTitle;
- setEditingTitle(title);
- if (title === data.title) {
- return;
- }
- await api.resource('flow_nodes').update?.({
- filterByTk: data.id,
- values: {
- title,
- },
+ const form = useMemo(() => {
+ const values = cloneDeep(data.config);
+ return createForm({
+ initialValues: values,
+ values,
+ disabled: workflow.executed,
});
- refresh();
- }
+ }, [data, workflow]);
- function onOpenDrawer(ev) {
+ const resetForm = useCallback(
+ (changed) => {
+ setFormValueChanged(changed);
+ if (!changed) {
+ form.reset();
+ }
+ },
+ [form],
+ );
+
+ const onChangeTitle = useCallback(
+ async function (next) {
+ const title = next || typeTitle;
+ setEditingTitle(title);
+ if (title === data.title) {
+ return;
+ }
+ await api.resource('flow_nodes').update?.({
+ filterByTk: data.id,
+ values: {
+ title,
+ },
+ });
+ refresh();
+ },
+ [data],
+ );
+
+ const onOpenDrawer = useCallback(function (ev) {
if (ev.target === ev.currentTarget) {
setEditingConfig(true);
return;
@@ -310,7 +338,7 @@ export function NodeDefaultView(props) {
return;
}
}
- }
+ }, []);
return (
@@ -324,20 +352,25 @@ export function NodeDefaultView(props) {
{typeTitle}
{data.id}
-
- setEditingTitle(ev.target.value)}
- onBlur={(ev) => onChangeTitle(ev.target.value)}
- autoSize
- />
-
+ setEditingTitle(ev.target.value)}
+ onBlur={(ev) => onChangeTitle(ev.target.value)}
+ autoSize
+ />
-
+
),
- 'x-component': 'Action.Drawer',
- 'x-decorator': 'Form',
+ 'x-decorator': 'FormV2',
'x-decorator-props': {
- disabled: workflow.executed,
- useValues(options) {
- const { config } = useNodeContext();
- return useRequest(() => {
- return Promise.resolve({ data: config });
- }, options);
- },
+ form,
},
+ 'x-component': 'Action.Drawer',
properties: {
...(instruction.description
? {
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/loop.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/loop.tsx
index 897c60be3..927d0e4bc 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/loop.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/loop.tsx
@@ -1,18 +1,14 @@
-import { ArrowUpOutlined } from '@ant-design/icons';
-import { css, cx, useCompile } from '@nocobase/client';
import React from 'react';
+import { ArrowUpOutlined } from '@ant-design/icons';
+
+import { css, cx, useCompile } from '@nocobase/client';
+
import { NodeDefaultView } from '.';
import { Branch } from '../Branch';
import { useFlowContext } from '../FlowContext';
import { NAMESPACE, lang } from '../locale';
import useStyles from '../style';
-import {
- VariableOption,
- defaultFieldNames,
- nodesOptions,
- triggerOptions,
- useWorkflowVariableOptions,
-} from '../variable';
+import { VariableOption, WorkflowVariableInput, defaultFieldNames, nodesOptions, triggerOptions } from '../variable';
function findOption(options: VariableOption[], paths: string[]) {
let opts = options;
@@ -45,9 +41,8 @@ export default {
title: `{{t("Loop target", { ns: "${NAMESPACE}" })}}`,
description: `{{t("A single number will be treated as a loop count, a single string will be treated as an array of characters, and other non-array values will be converted to arrays. The loop node ends when the loop count is reached, or when the array loop is completed. You can also add condition nodes to the loop to terminate it.", { ns: "${NAMESPACE}" })}}`,
'x-decorator': 'FormItem',
- 'x-component': 'Variable.Input',
+ 'x-component': 'WorkflowVariableInput',
'x-component-props': {
- scope: '{{useWorkflowVariableOptions()}}',
changeOnSelect: true,
useTypedConstant: ['string', 'number', 'null'],
className: css`
@@ -95,10 +90,10 @@ export default {
);
},
- scope: {
- useWorkflowVariableOptions,
+ scope: {},
+ components: {
+ WorkflowVariableInput,
},
- components: {},
useScopeVariables(node, options) {
const compile = useCompile();
const { target } = node.config;
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 70b2021ce..c2ac2f354 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/query.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/query.tsx
@@ -12,7 +12,7 @@ import { appends, collection, filter, pagination, sort } from '../schemas/collec
import { NAMESPACE } from '../locale';
import { CollectionBlockInitializer } from '../components/CollectionBlockInitializer';
import { FilterDynamicComponent } from '../components/FilterDynamicComponent';
-import { getCollectionFieldOptions, useWorkflowVariableOptions } from '../variable';
+import { WorkflowVariableInput, getCollectionFieldOptions } from '../variable';
import { useForm } from '@formily/react';
export default {
@@ -59,7 +59,6 @@ export default {
view: {},
scope: {
useCollectionDataSource,
- useWorkflowVariableOptions,
useSortableFields() {
const compile = useCompile();
const { getCollectionFields, getInterface } = useCollectionManager();
@@ -88,6 +87,7 @@ export default {
ArrayItems,
FilterDynamicComponent,
SchemaComponentContext,
+ WorkflowVariableInput,
},
useVariables({ key: name, title, config }, options) {
const compile = useCompile();
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/request.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/request.tsx
index 6e090cdf6..2807028f5 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/request.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/request.tsx
@@ -1,9 +1,8 @@
import { ArrayItems } from '@formily/antd-v5';
-import React from 'react';
-import { Variable } from '@nocobase/client';
+import { defaultFieldNames } from '@nocobase/client';
import { NAMESPACE } from '../locale';
-import { useWorkflowVariableOptions } from '../variable';
+import { WorkflowVariableInput } from '../variable';
export default {
title: `{{t("HTTP request", { ns: "${NAMESPACE}" })}}`,
@@ -66,9 +65,8 @@ export default {
value: {
type: 'string',
'x-decorator': 'FormItem',
- 'x-component': 'Variable.Input',
+ 'x-component': 'WorkflowVariableInput',
'x-component-props': {
- scope: '{{useWorkflowVariableOptions()}}',
useTypedConstant: true,
},
},
@@ -112,9 +110,8 @@ export default {
value: {
type: 'string',
'x-decorator': 'FormItem',
- 'x-component': 'Variable.Input',
+ 'x-component': 'WorkflowVariableInput',
'x-component-props': {
- scope: '{{useWorkflowVariableOptions()}}',
useTypedConstant: true,
},
},
@@ -140,7 +137,7 @@ export default {
title: `{{t("Body", { ns: "${NAMESPACE}" })}}`,
'x-decorator': 'FormItem',
'x-decorator-props': {},
- 'x-component': 'RequestBody',
+ 'x-component': 'WorkflowVariableJSON',
'x-component-props': {
changeOnSelect: true,
autoSize: {
@@ -171,14 +168,15 @@ export default {
},
},
view: {},
- scope: {
- useWorkflowVariableOptions,
- },
+ scope: {},
components: {
ArrayItems,
- RequestBody(props) {
- const scope = useWorkflowVariableOptions();
- return ;
- },
+ WorkflowVariableInput,
+ },
+ useVariables({ key, title }, { types, fieldNames = defaultFieldNames }) {
+ return {
+ [fieldNames.value]: key,
+ [fieldNames.label]: title,
+ };
},
};
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/sql.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/sql.tsx
index a9feed6a0..147021528 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/sql.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/sql.tsx
@@ -1,9 +1,7 @@
-import React from 'react';
-
-import { Variable, css } from '@nocobase/client';
+import { css, defaultFieldNames } from '@nocobase/client';
import { NAMESPACE } from '../locale';
-import { useWorkflowVariableOptions } from '../variable';
+import { WorkflowVariableRawTextArea } from '../variable';
export default {
title: `{{t("SQL action", { ns: "${NAMESPACE}" })}}`,
@@ -17,7 +15,7 @@ export default {
title: 'SQL',
description: `{{t("Usage of SQL query result is not supported yet.", { ns: "${NAMESPACE}" })}}`,
'x-decorator': 'FormItem',
- 'x-component': 'SQLInput',
+ 'x-component': 'WorkflowVariableRawTextArea',
'x-component-props': {
rows: 20,
className: css`
@@ -29,9 +27,12 @@ export default {
},
scope: {},
components: {
- SQLInput(props) {
- const scope = useWorkflowVariableOptions();
- return ;
- },
+ WorkflowVariableRawTextArea,
+ },
+ useVariables({ key, title }, { types, fieldNames = defaultFieldNames }) {
+ return {
+ [fieldNames.value]: key,
+ [fieldNames.label]: title,
+ };
},
};
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/collection.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/collection.ts
index 90863172d..0a0e92d4a 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/collection.ts
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/schemas/collection.ts
@@ -135,9 +135,8 @@ export const pagination = {
type: 'number',
title: '{{t("Page number")}}',
'x-decorator': 'FormItem',
- 'x-component': 'Variable.Input',
+ 'x-component': 'WorkflowVariableInput',
'x-component-props': {
- scope: '{{useWorkflowVariableOptions()}}',
useTypedConstant: ['number', 'null'],
},
default: 1,
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 e2a89ea89..b01d87547 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx
+++ b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/index.tsx
@@ -14,7 +14,7 @@ import {
} from '@nocobase/client';
import { Registry } from '@nocobase/utils/client';
import { Button, Input, Tag, message } from 'antd';
-import React, { useEffect, useMemo, useState } from 'react';
+import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useFlowContext } from '../FlowContext';
import { DrawerDescription } from '../components/DrawerDescription';
import { NAMESPACE, lang } from '../locale';
@@ -23,6 +23,7 @@ import { VariableOptions } from '../variable';
import collection from './collection';
import formTrigger from './form';
import schedule from './schedule/';
+import { cloneDeep } from 'lodash';
function useUpdateConfigAction() {
const form = useForm();
@@ -43,6 +44,7 @@ function useUpdateConfigAction() {
config: form.values,
},
});
+ ctx.setFormValueChanged(false);
ctx.setVisible(false);
refresh();
},
@@ -146,50 +148,61 @@ export const TriggerConfig = () => {
const { workflow, refresh } = useFlowContext();
const [editingTitle, setEditingTitle] = useState('');
const [editingConfig, setEditingConfig] = useState(false);
+ const [formValueChanged, setFormValueChanged] = useState(false);
const { styles } = useStyles();
- let typeTitle = '';
+ const compile = useCompile();
+
+ const { title, type, executed } = workflow;
+ const trigger = triggers.get(type);
+ const typeTitle = compile(trigger.title);
+ const { fieldset, scope, components } = trigger;
+ const detailText = executed ? '{{t("View")}}' : '{{t("Configure")}}';
+ const titleText = lang('Trigger');
+
useEffect(() => {
if (workflow) {
setEditingTitle(workflow.title ?? typeTitle);
}
}, [workflow]);
- const form = useMemo(
- () =>
- createForm({
- initialValues: workflow?.config,
- values: workflow?.config,
- disabled: workflow?.executed,
- }),
+ const form = useMemo(() => {
+ const values = cloneDeep(workflow?.config);
+ return createForm({
+ initialValues: values,
+ values,
+ disabled: workflow?.executed,
+ });
+ }, [workflow]);
+
+ const resetForm = useCallback(
+ (changed) => {
+ setFormValueChanged(changed);
+ if (!changed) {
+ form.reset();
+ }
+ },
+ [form],
+ );
+
+ const onChangeTitle = useCallback(
+ async function (next) {
+ const t = next || typeTitle;
+ setEditingTitle(t);
+ if (t === title) {
+ return;
+ }
+ await api.resource('workflows').update?.({
+ filterByTk: workflow.id,
+ values: {
+ title: t,
+ },
+ });
+ refresh();
+ },
[workflow],
);
- if (!workflow || !workflow.type) {
- return null;
- }
- const { title, type, executed } = workflow;
- const trigger = triggers.get(type);
- const { fieldset, scope, components } = trigger;
- typeTitle = trigger.title;
- const detailText = executed ? '{{t("View")}}' : '{{t("Configure")}}';
- const titleText = lang('Trigger');
-
- async function onChangeTitle(next) {
- const t = next || typeTitle;
- setEditingTitle(t);
- if (t === title) {
- return;
- }
- await api.resource('workflows').update?.({
- filterByTk: workflow.id,
- values: {
- title: t,
- },
- });
- refresh();
- }
-
- function onOpenDrawer(ev) {
+ const onOpenDrawer = useCallback(function (ev) {
if (ev.target === ev.currentTarget) {
setEditingConfig(true);
return;
@@ -202,7 +215,7 @@ export const TriggerConfig = () => {
return;
}
}
- }
+ }, []);
return (
{
/>
-
+
{
- const children = item.useOptions?.(opts)?.filter(Boolean);
- return {
- [fieldNames.label]: compile(item.label),
- [fieldNames.value]: item.value,
- key: item[fieldNames.value],
- [fieldNames.children]: children,
- disabled: !children || !children.length,
- };
- });
+ const result = [
+ useOptions(scopeOptions, opts),
+ useOptions(nodesOptions, opts),
+ useOptions(triggerOptions, opts),
+ useOptions(systemOptions, opts),
+ ];
+ // const cache = useMemo(() => result, [result]);
return result;
}
@@ -349,3 +361,23 @@ export function getCollectionFieldOptions(options): VariableOption[] {
return result;
}
+
+export function WorkflowVariableInput({ variableOptions, ...props }): JSX.Element {
+ const scope = useWorkflowVariableOptions(variableOptions);
+ return ;
+}
+
+export function WorkflowVariableTextArea({ variableOptions, ...props }): JSX.Element {
+ const scope = useWorkflowVariableOptions(variableOptions);
+ return ;
+}
+
+export function WorkflowVariableRawTextArea({ variableOptions, ...props }): JSX.Element {
+ const scope = useWorkflowVariableOptions(variableOptions);
+ return ;
+}
+
+export function WorkflowVariableJSON({ variableOptions, ...props }): JSX.Element {
+ const scope = useWorkflowVariableOptions(variableOptions);
+ return ;
+}
diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/schedule.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/schedule.ts
index 53e5bb6fe..2b54ca0f0 100644
--- a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/schedule.ts
+++ b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/schedule.ts
@@ -511,7 +511,7 @@ export default class ScheduleTrigger extends Trigger {
const should = await this.shouldCache(workflow, now);
if (should) {
- this.plugin.app.logger.info('caching scheduled workflow will run in next minute:', workflow.id);
+ this.plugin.getLogger(workflow.id).info('caching scheduled workflow will run in next minute');
}
this.setCache(workflow, !should);