@nocobase/flow-engine
Version:
A standalone flow engine for NocoBase, managing workflows, models, and actions.
232 lines (230 loc) • 9.73 kB
JavaScript
/**
* 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.
*/
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var FlowsContextMenu_exports = {};
__export(FlowsContextMenu_exports, {
FlowsContextMenu: () => FlowsContextMenu
});
module.exports = __toCommonJS(FlowsContextMenu_exports);
var import_icons = require("@ant-design/icons");
var import_react = require("@formily/react");
var import_antd = require("antd");
var import_react2 = __toESM(require("react"));
var import_flowContext = require("../../../../flowContext");
var import_hooks = require("../../../../hooks");
var import_utils = require("../../../../utils");
var import_StepSettingsDialog = require("./StepSettingsDialog");
const isModelByIdProps = /* @__PURE__ */ __name((props) => {
return "uid" in props && "modelClassName" in props && Boolean(props.uid) && Boolean(props.modelClassName);
}, "isModelByIdProps");
const FlowsContextMenu = /* @__PURE__ */ __name((props) => {
if (isModelByIdProps(props)) {
return /* @__PURE__ */ import_react2.default.createElement(FlowsContextMenuWithModelById, { ...props });
} else {
return /* @__PURE__ */ import_react2.default.createElement(FlowsContextMenuWithModel, { ...props });
}
}, "FlowsContextMenu");
const FlowsContextMenuWithModel = (0, import_react.observer)(
({ model, children, enabled = true, position = "right", showDeleteButton = true }) => {
const t = (0, import_utils.getT)(model);
const handleMenuClick = (0, import_react2.useCallback)(
({ key }) => {
var _a;
if (key === "delete") {
import_antd.Modal.confirm({
title: t("Confirm delete"),
icon: /* @__PURE__ */ import_react2.default.createElement(import_icons.ExclamationCircleOutlined, null),
content: t("Are you sure you want to delete this item? This action cannot be undone."),
okText: t("Confirm Delete"),
okType: "danger",
cancelText: t("Cancel"),
zIndex: 999999,
onOk() {
try {
model.dispatchEvent("remove");
} catch (error) {
console.error(t("Delete operation failed"), ":", error);
import_antd.Modal.error({
title: t("Delete failed"),
content: t("Delete operation failed, please check the console for details.")
});
}
}
});
} else {
const [flowKey, stepKey] = key.split(":");
try {
const flow = model.getFlow(flowKey);
const step = (_a = flow == null ? void 0 : flow.steps) == null ? void 0 : _a[stepKey];
if (!flow || !step) {
console.error(`Flow ${flowKey} or step ${stepKey} not found`);
return;
}
const ctx = new import_flowContext.FlowRuntimeContext(model, flowKey, "settings");
(0, import_utils.setupRuntimeContextSteps)(ctx, flow.steps, model, flowKey);
ctx.defineProperty("currentStep", { value: step });
(0, import_StepSettingsDialog.openStepSettingsDialog)({
model,
flowKey,
stepKey,
ctx
});
} catch (error) {
console.log("\u914D\u7F6E\u5F39\u7A97\u5DF2\u53D6\u6D88\u6216\u51FA\u9519:", error);
}
}
},
[model]
);
if (!model) {
return /* @__PURE__ */ import_react2.default.createElement(import_antd.Alert, { message: "\u63D0\u4F9B\u7684\u6A21\u578B\u65E0\u6548", type: "error" });
}
if (!enabled || !children) {
return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, children);
}
const getConfigurableFlowsAndSteps = (0, import_react2.useCallback)(() => {
try {
const flows = model.getFlows();
const flowsArray = Array.from(flows.values());
return flowsArray.map((flow) => {
const configurableSteps = Object.entries(flow.steps).map(([stepKey, stepDefinition]) => {
var _a, _b;
const actionStep = stepDefinition;
if (actionStep.hideInSettings) {
return null;
}
const stepUiSchema = actionStep.uiSchema || {};
let actionUiSchema = {};
if (actionStep.use) {
const action = (_b = (_a = model.flowEngine) == null ? void 0 : _a.getAction) == null ? void 0 : _b.call(_a, actionStep.use);
if (action && action.uiSchema) {
actionUiSchema = action.uiSchema;
}
}
const mergedUiSchema = { ...actionUiSchema };
Object.entries(stepUiSchema).forEach(([fieldKey, schema]) => {
if (mergedUiSchema[fieldKey]) {
mergedUiSchema[fieldKey] = { ...mergedUiSchema[fieldKey], ...schema };
} else {
mergedUiSchema[fieldKey] = schema;
}
});
if (Object.keys(mergedUiSchema).length === 0) {
return null;
}
return {
stepKey,
step: actionStep,
uiSchema: mergedUiSchema,
title: actionStep.title || stepKey
};
}).filter(Boolean);
return configurableSteps.length > 0 ? { flow, steps: configurableSteps } : null;
}).filter(Boolean);
} catch (error) {
console.warn("[FlowsContextMenu] \u83B7\u53D6\u53EF\u914D\u7F6Eflows\u5931\u8D25:", error);
return [];
}
}, [model]);
const configurableFlowsAndSteps = getConfigurableFlowsAndSteps();
if (configurableFlowsAndSteps.length === 0 && !showDeleteButton) {
return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, children);
}
const menuItems = [];
if (configurableFlowsAndSteps.length > 0) {
configurableFlowsAndSteps.forEach(({ flow, steps }) => {
menuItems.push({
key: `flow-group-${flow.key}`,
label: flow.title || flow.key,
type: "group"
});
steps.forEach((stepInfo) => {
menuItems.push({
key: `${flow.key}:${stepInfo.stepKey}`,
icon: /* @__PURE__ */ import_react2.default.createElement(import_icons.SettingOutlined, null),
label: stepInfo.title
});
});
});
}
if (showDeleteButton) {
if (configurableFlowsAndSteps.length > 0) {
menuItems.push({
type: "divider"
});
}
menuItems.push({
key: "delete",
icon: /* @__PURE__ */ import_react2.default.createElement(import_icons.DeleteOutlined, null),
label: "\u5220\u9664"
});
}
return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(
import_antd.Dropdown,
{
menu: {
items: menuItems,
onClick: handleMenuClick
},
trigger: ["contextMenu"],
placement: position === "left" ? "bottomLeft" : "bottomRight"
},
/* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "inline-block", width: "100%" } }, children)
));
}
);
const FlowsContextMenuWithModelById = (0, import_react.observer)(
({ uid, modelClassName, children, enabled = true, position = "right", showDeleteButton = true }) => {
const model = (0, import_hooks.useFlowModelById)(uid, modelClassName);
if (!model) {
return /* @__PURE__ */ import_react2.default.createElement(import_antd.Alert, { message: `\u672A\u627E\u5230ID\u4E3A ${uid} \u7684\u6A21\u578B`, type: "error" });
}
return /* @__PURE__ */ import_react2.default.createElement(
FlowsContextMenuWithModel,
{
model,
enabled,
position,
showDeleteButton
},
children
);
}
);
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
FlowsContextMenu
});