@flowgram.ai/free-layout-core 0.1.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/chunk-242F2JCI.js +16 -0
- package/dist/esm/chunk-242F2JCI.js.map +1 -0
- package/dist/esm/chunk-CGOMTQ3G.js +1 -0
- package/dist/esm/chunk-CGOMTQ3G.js.map +1 -0
- package/dist/esm/chunk-CTGO4RKX.js +22 -0
- package/dist/esm/chunk-CTGO4RKX.js.map +1 -0
- package/dist/esm/chunk-DDJTYHXN.js +1 -0
- package/dist/esm/chunk-DDJTYHXN.js.map +1 -0
- package/dist/esm/chunk-EUXUH3YW.js +15 -0
- package/dist/esm/chunk-EUXUH3YW.js.map +1 -0
- package/dist/esm/chunk-IKQUOAWQ.js +7 -0
- package/dist/esm/chunk-IKQUOAWQ.js.map +1 -0
- package/dist/esm/chunk-KNYZRMIO.js +1 -0
- package/dist/esm/chunk-KNYZRMIO.js.map +1 -0
- package/dist/esm/chunk-NU6G5HF4.js +1 -0
- package/dist/esm/chunk-NU6G5HF4.js.map +1 -0
- package/dist/esm/chunk-O4WKIIW2.js +7 -0
- package/dist/esm/chunk-O4WKIIW2.js.map +1 -0
- package/dist/esm/chunk-TQLT57GW.js +1 -0
- package/dist/esm/chunk-TQLT57GW.js.map +1 -0
- package/dist/esm/index.js +3471 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/typings/index.js +27 -0
- package/dist/esm/typings/index.js.map +1 -0
- package/dist/esm/typings/workflow-drag.js +2 -0
- package/dist/esm/typings/workflow-drag.js.map +1 -0
- package/dist/esm/typings/workflow-edge.js +2 -0
- package/dist/esm/typings/workflow-edge.js.map +1 -0
- package/dist/esm/typings/workflow-json.js +8 -0
- package/dist/esm/typings/workflow-json.js.map +1 -0
- package/dist/esm/typings/workflow-line.js +10 -0
- package/dist/esm/typings/workflow-line.js.map +1 -0
- package/dist/esm/typings/workflow-node.js +2 -0
- package/dist/esm/typings/workflow-node.js.map +1 -0
- package/dist/esm/typings/workflow-operation.js +8 -0
- package/dist/esm/typings/workflow-operation.js.map +1 -0
- package/dist/esm/typings/workflow-registry.js +2 -0
- package/dist/esm/typings/workflow-registry.js.map +1 -0
- package/dist/esm/typings/workflow-sub-canvas.js +2 -0
- package/dist/esm/typings/workflow-sub-canvas.js.map +1 -0
- package/dist/index.d.mts +565 -0
- package/dist/index.d.ts +565 -0
- package/dist/index.js +3515 -0
- package/dist/index.js.map +1 -0
- package/dist/typings/index.d.mts +23 -0
- package/dist/typings/index.d.ts +23 -0
- package/dist/typings/index.js +73 -0
- package/dist/typings/index.js.map +1 -0
- package/dist/typings/workflow-drag.d.mts +8 -0
- package/dist/typings/workflow-drag.d.ts +8 -0
- package/dist/typings/workflow-drag.js +19 -0
- package/dist/typings/workflow-drag.js.map +1 -0
- package/dist/typings/workflow-edge.d.mts +15 -0
- package/dist/typings/workflow-edge.d.ts +15 -0
- package/dist/typings/workflow-edge.js +19 -0
- package/dist/typings/workflow-edge.js.map +1 -0
- package/dist/typings/workflow-json.d.mts +8 -0
- package/dist/typings/workflow-json.d.ts +8 -0
- package/dist/typings/workflow-json.js +40 -0
- package/dist/typings/workflow-json.js.map +1 -0
- package/dist/typings/workflow-line.d.mts +8 -0
- package/dist/typings/workflow-line.d.ts +8 -0
- package/dist/typings/workflow-line.js +47 -0
- package/dist/typings/workflow-line.js.map +1 -0
- package/dist/typings/workflow-node.d.mts +8 -0
- package/dist/typings/workflow-node.d.ts +8 -0
- package/dist/typings/workflow-node.js +19 -0
- package/dist/typings/workflow-node.js.map +1 -0
- package/dist/typings/workflow-operation.d.mts +29 -0
- package/dist/typings/workflow-operation.d.ts +29 -0
- package/dist/typings/workflow-operation.js +31 -0
- package/dist/typings/workflow-operation.js.map +1 -0
- package/dist/typings/workflow-registry.d.mts +30 -0
- package/dist/typings/workflow-registry.d.ts +30 -0
- package/dist/typings/workflow-registry.js +19 -0
- package/dist/typings/workflow-registry.js.map +1 -0
- package/dist/typings/workflow-sub-canvas.d.mts +2 -0
- package/dist/typings/workflow-sub-canvas.d.ts +2 -0
- package/dist/typings/workflow-sub-canvas.js +19 -0
- package/dist/typings/workflow-sub-canvas.js.map +1 -0
- package/dist/workflow-line-entity-B2J3fUO1.d.ts +790 -0
- package/dist/workflow-line-entity-CW8YIX-0.d.mts +790 -0
- package/dist/workflow-sub-canvas-IQzlYvPD.d.mts +25 -0
- package/dist/workflow-sub-canvas-IQzlYvPD.d.ts +25 -0
- package/package.json +77 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3515 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
20
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
21
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
22
|
+
if (decorator = decorators[i])
|
|
23
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
24
|
+
if (kind && result) __defProp(target, key, result);
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/index.ts
|
|
29
|
+
var src_exports = {};
|
|
30
|
+
__export(src_exports, {
|
|
31
|
+
EditorCursorState: () => EditorCursorState,
|
|
32
|
+
InteractiveType: () => InteractiveType,
|
|
33
|
+
LINE_HOVER_DISTANCE: () => LINE_HOVER_DISTANCE,
|
|
34
|
+
LineColors: () => LineColors,
|
|
35
|
+
LineType: () => LineType,
|
|
36
|
+
POINT_RADIUS: () => POINT_RADIUS,
|
|
37
|
+
PORT_SIZE: () => PORT_SIZE,
|
|
38
|
+
URLParams: () => URLParams,
|
|
39
|
+
WORKFLOW_LINE_ENTITY: () => WORKFLOW_LINE_ENTITY,
|
|
40
|
+
WorkflowCommands: () => WorkflowCommands,
|
|
41
|
+
WorkflowContentChangeType: () => WorkflowContentChangeType,
|
|
42
|
+
WorkflowDocument: () => WorkflowDocument,
|
|
43
|
+
WorkflowDocumentContainerModule: () => WorkflowDocumentContainerModule,
|
|
44
|
+
WorkflowDocumentOptions: () => WorkflowDocumentOptions,
|
|
45
|
+
WorkflowDocumentOptionsDefault: () => WorkflowDocumentOptionsDefault,
|
|
46
|
+
WorkflowDocumentProvider: () => WorkflowDocumentProvider,
|
|
47
|
+
WorkflowDragService: () => WorkflowDragService,
|
|
48
|
+
WorkflowHoverService: () => WorkflowHoverService,
|
|
49
|
+
WorkflowLineEntity: () => WorkflowLineEntity,
|
|
50
|
+
WorkflowLineRenderData: () => WorkflowLineRenderData,
|
|
51
|
+
WorkflowLinesManager: () => WorkflowLinesManager,
|
|
52
|
+
WorkflowNodeEntity: () => WorkflowNodeEntity,
|
|
53
|
+
WorkflowNodeLinesData: () => WorkflowNodeLinesData,
|
|
54
|
+
WorkflowNodePortsData: () => WorkflowNodePortsData,
|
|
55
|
+
WorkflowOperationBaseService: () => WorkflowOperationBaseService,
|
|
56
|
+
WorkflowOperationBaseServiceImpl: () => WorkflowOperationBaseServiceImpl,
|
|
57
|
+
WorkflowPortEntity: () => WorkflowPortEntity,
|
|
58
|
+
WorkflowResetLayoutService: () => WorkflowResetLayoutService,
|
|
59
|
+
WorkflowSelectService: () => WorkflowSelectService,
|
|
60
|
+
WorkflowSimpleLineContribution: () => WorkflowSimpleLineContribution,
|
|
61
|
+
bindConfigEntity: () => import_core3.bindConfigEntity,
|
|
62
|
+
compose: () => import_utils.compose,
|
|
63
|
+
composeAsync: () => import_utils.composeAsync,
|
|
64
|
+
delay: () => import_utils4.delay,
|
|
65
|
+
domReactToBounds: () => domReactToBounds,
|
|
66
|
+
fitView: () => fitView,
|
|
67
|
+
getAntiOverlapPosition: () => getAntiOverlapPosition,
|
|
68
|
+
getPortEntityId: () => getPortEntityId,
|
|
69
|
+
nanoid: () => nanoid,
|
|
70
|
+
useConfigEntity: () => import_core25.useConfigEntity,
|
|
71
|
+
useCurrentDomNode: () => useCurrentDomNode,
|
|
72
|
+
useCurrentEntity: () => useCurrentEntity,
|
|
73
|
+
useEntities: () => import_core25.useEntities,
|
|
74
|
+
useEntityDataFromContext: () => import_core25.useEntityDataFromContext,
|
|
75
|
+
useEntityFromContext: () => import_core25.useEntityFromContext,
|
|
76
|
+
useListenEvents: () => import_core25.useListenEvents,
|
|
77
|
+
useNodeRender: () => useNodeRender,
|
|
78
|
+
usePlayground: () => import_core25.usePlayground,
|
|
79
|
+
usePlaygroundContainer: () => import_core25.usePlaygroundContainer,
|
|
80
|
+
usePlaygroundContext: () => import_core25.usePlaygroundContext,
|
|
81
|
+
usePlaygroundLatest: () => import_core25.usePlaygroundLatest,
|
|
82
|
+
usePlaygroundReadonlyState: () => usePlaygroundReadonlyState,
|
|
83
|
+
useRefresh: () => import_core25.useRefresh,
|
|
84
|
+
useService: () => import_core25.useService,
|
|
85
|
+
useWorkflowDocument: () => useWorkflowDocument
|
|
86
|
+
});
|
|
87
|
+
module.exports = __toCommonJS(src_exports);
|
|
88
|
+
|
|
89
|
+
// src/workflow-commands.ts
|
|
90
|
+
var WorkflowCommands = /* @__PURE__ */ ((WorkflowCommands2) => {
|
|
91
|
+
WorkflowCommands2["DELETE_NODES"] = "DELETE_NODES";
|
|
92
|
+
WorkflowCommands2["COPY_NODES"] = "COPY_NODES";
|
|
93
|
+
WorkflowCommands2["PASTE_NODES"] = "PASTE_NODES";
|
|
94
|
+
WorkflowCommands2["ZOOM_IN"] = "ZOOM_IN";
|
|
95
|
+
WorkflowCommands2["ZOOM_OUT"] = "ZOOM_OUT";
|
|
96
|
+
WorkflowCommands2["UNDO"] = "UNDO";
|
|
97
|
+
WorkflowCommands2["REDO"] = "REDO";
|
|
98
|
+
return WorkflowCommands2;
|
|
99
|
+
})(WorkflowCommands || {});
|
|
100
|
+
|
|
101
|
+
// src/hooks/index.ts
|
|
102
|
+
var import_core25 = require("@flowgram.ai/core");
|
|
103
|
+
|
|
104
|
+
// src/hooks/use-node-render.tsx
|
|
105
|
+
var import_react2 = require("react");
|
|
106
|
+
var import_reactive = require("@flowgram.ai/reactive");
|
|
107
|
+
var import_node = require("@flowgram.ai/node");
|
|
108
|
+
var import_document12 = require("@flowgram.ai/document");
|
|
109
|
+
var import_core21 = require("@flowgram.ai/core");
|
|
110
|
+
|
|
111
|
+
// src/service/workflow-select-service.ts
|
|
112
|
+
var import_inversify = require("inversify");
|
|
113
|
+
var import_core9 = require("@flowgram.ai/core");
|
|
114
|
+
var import_utils9 = require("@flowgram.ai/utils");
|
|
115
|
+
|
|
116
|
+
// src/utils/index.ts
|
|
117
|
+
var import_core3 = require("@flowgram.ai/core");
|
|
118
|
+
var import_utils4 = require("@flowgram.ai/utils");
|
|
119
|
+
|
|
120
|
+
// src/utils/nanoid.ts
|
|
121
|
+
var import_nanoid = require("nanoid");
|
|
122
|
+
function nanoid(n) {
|
|
123
|
+
return (0, import_nanoid.nanoid)(n);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/utils/compose.ts
|
|
127
|
+
var import_utils = require("@flowgram.ai/utils");
|
|
128
|
+
|
|
129
|
+
// src/utils/fit-view.ts
|
|
130
|
+
var import_core = require("@flowgram.ai/core");
|
|
131
|
+
var import_utils2 = require("@flowgram.ai/utils");
|
|
132
|
+
var fitView = (doc, playgroundConfig, easing = true) => {
|
|
133
|
+
const bounds = import_utils2.Rectangle.enlarge(
|
|
134
|
+
doc.getAllNodes().map((node) => node.getData(import_core.TransformData).bounds)
|
|
135
|
+
);
|
|
136
|
+
return playgroundConfig.fitView(bounds, easing, 30);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// src/utils/get-anti-overlap-position.ts
|
|
140
|
+
var import_core2 = require("@flowgram.ai/core");
|
|
141
|
+
function getAntiOverlapPosition(doc, position, containerNode) {
|
|
142
|
+
let { x, y } = position;
|
|
143
|
+
const nodes = containerNode ? containerNode.collapsedChildren : doc.getAllNodes();
|
|
144
|
+
const positions = nodes.map((n) => {
|
|
145
|
+
const transform = n.getData(import_core2.TransformData);
|
|
146
|
+
return { x: transform.position.x, y: transform.position.y };
|
|
147
|
+
}).sort((a, b) => a.y - b.y);
|
|
148
|
+
const minDistance = 3;
|
|
149
|
+
for (const pos of positions) {
|
|
150
|
+
const { x: posX, y: posY } = pos;
|
|
151
|
+
if (y - posY < -minDistance) {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
const deltaX = Math.abs(x - posX);
|
|
155
|
+
const deltaY = Math.abs(y - posY);
|
|
156
|
+
if (deltaX <= minDistance && deltaY <= minDistance) {
|
|
157
|
+
x += 30;
|
|
158
|
+
y += 30;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return { x, y };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/utils/statics.ts
|
|
165
|
+
var import_utils3 = require("@flowgram.ai/utils");
|
|
166
|
+
var getPortEntityId = (node, portType, portID = "") => `port_${portType}_${node.id}_${portID}`;
|
|
167
|
+
var WORKFLOW_LINE_ENTITY = "WorkflowLineEntity";
|
|
168
|
+
function domReactToBounds(react) {
|
|
169
|
+
return new import_utils3.Rectangle(react.x, react.y, react.width, react.height);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/entities/workflow-node-entity.ts
|
|
173
|
+
var import_document = require("@flowgram.ai/document");
|
|
174
|
+
var WorkflowNodeEntity = import_document.FlowNodeEntity;
|
|
175
|
+
|
|
176
|
+
// src/entities/workflow-line-entity.ts
|
|
177
|
+
var import_lodash_es2 = require("lodash-es");
|
|
178
|
+
var import_utils8 = require("@flowgram.ai/utils");
|
|
179
|
+
var import_core8 = require("@flowgram.ai/core");
|
|
180
|
+
|
|
181
|
+
// src/entity-datas/workflow-node-ports-data.ts
|
|
182
|
+
var import_lodash_es = require("lodash-es");
|
|
183
|
+
var import_document3 = require("@flowgram.ai/document");
|
|
184
|
+
var import_core5 = require("@flowgram.ai/core");
|
|
185
|
+
|
|
186
|
+
// src/entities/workflow-port-entity.ts
|
|
187
|
+
var import_utils5 = require("@flowgram.ai/utils");
|
|
188
|
+
var import_document2 = require("@flowgram.ai/document");
|
|
189
|
+
var import_core4 = require("@flowgram.ai/core");
|
|
190
|
+
var PORT_SIZE = 24;
|
|
191
|
+
var WorkflowPortEntity = class extends import_core4.Entity {
|
|
192
|
+
// relativePosition
|
|
193
|
+
constructor(opts) {
|
|
194
|
+
super(opts);
|
|
195
|
+
this.portID = "";
|
|
196
|
+
this._disabled = false;
|
|
197
|
+
this._hasError = false;
|
|
198
|
+
this._onErrorChangedEmitter = new import_utils5.Emitter();
|
|
199
|
+
this.onErrorChanged = this._onErrorChangedEmitter.event;
|
|
200
|
+
this.portID = opts.portID || "";
|
|
201
|
+
this.portType = opts.type;
|
|
202
|
+
this._disabled = opts.disabled ?? false;
|
|
203
|
+
this.node = opts.node;
|
|
204
|
+
this.updateTargetElement(opts.targetElement);
|
|
205
|
+
this.toDispose.push(this.node.getData(import_core4.TransformData).onDataChange(() => this.fireChange()));
|
|
206
|
+
this.toDispose.push(this.node.onDispose(this.dispose.bind(this)));
|
|
207
|
+
}
|
|
208
|
+
static getPortEntityId(node, portType, portID = "") {
|
|
209
|
+
return getPortEntityId(node, portType, portID);
|
|
210
|
+
}
|
|
211
|
+
// 获取连线是否为错误态
|
|
212
|
+
get hasError() {
|
|
213
|
+
return this._hasError;
|
|
214
|
+
}
|
|
215
|
+
// 设置连线的错误态,外部应使用 validate 进行更新
|
|
216
|
+
set hasError(hasError) {
|
|
217
|
+
this._hasError = hasError;
|
|
218
|
+
this._onErrorChangedEmitter.fire();
|
|
219
|
+
}
|
|
220
|
+
validate() {
|
|
221
|
+
const anyLineHasError = this.allLines.some((line) => {
|
|
222
|
+
if (line.disposed || line.isHidden) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
line.validateSelf();
|
|
226
|
+
return line.hasError;
|
|
227
|
+
});
|
|
228
|
+
const isPortHasError = this.node.document.isErrorPort(this);
|
|
229
|
+
this.hasError = anyLineHasError || isPortHasError;
|
|
230
|
+
}
|
|
231
|
+
isErrorPort() {
|
|
232
|
+
return this.node.document.isErrorPort(this);
|
|
233
|
+
}
|
|
234
|
+
get point() {
|
|
235
|
+
const { targetElement } = this;
|
|
236
|
+
const { bounds } = this.node.getData(import_document2.FlowNodeTransformData);
|
|
237
|
+
if (targetElement) {
|
|
238
|
+
const pos = domReactToBounds(targetElement.getBoundingClientRect()).center;
|
|
239
|
+
return this.entityManager.getEntity(import_core4.PlaygroundConfigEntity).getPosFromMouseEvent({
|
|
240
|
+
clientX: pos.x,
|
|
241
|
+
clientY: pos.y
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
if (this.portType === "input") {
|
|
245
|
+
return bounds.leftCenter;
|
|
246
|
+
}
|
|
247
|
+
return bounds.rightCenter;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* 点的区域
|
|
251
|
+
*/
|
|
252
|
+
get bounds() {
|
|
253
|
+
const { point } = this;
|
|
254
|
+
const halfSize = PORT_SIZE / 2;
|
|
255
|
+
return new import_utils5.Rectangle(point.x - halfSize, point.y - halfSize, PORT_SIZE, PORT_SIZE);
|
|
256
|
+
}
|
|
257
|
+
isHovered(x, y) {
|
|
258
|
+
return this.bounds.contains(x, y);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* 相对节点左上角的位置
|
|
262
|
+
*/
|
|
263
|
+
get relativePosition() {
|
|
264
|
+
const { point } = this;
|
|
265
|
+
const { bounds } = this.node.getData(import_document2.FlowNodeTransformData);
|
|
266
|
+
return {
|
|
267
|
+
x: point.x - bounds.x,
|
|
268
|
+
y: point.y - bounds.y
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
updateTargetElement(el) {
|
|
272
|
+
if (el !== this.targetElement) {
|
|
273
|
+
this.targetElement = el;
|
|
274
|
+
this.fireChange();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* 是否被禁用
|
|
279
|
+
*/
|
|
280
|
+
get disabled() {
|
|
281
|
+
const document2 = this.node.document;
|
|
282
|
+
if (typeof document2.options.isDisabledPort === "function") {
|
|
283
|
+
return document2.options.isDisabledPort(this);
|
|
284
|
+
}
|
|
285
|
+
if (this._disabled) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
const meta = this.node.getNodeMeta();
|
|
289
|
+
if (this.portType === "input") {
|
|
290
|
+
return !!meta.inputDisable;
|
|
291
|
+
}
|
|
292
|
+
return !!meta.outputDisable;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* 当前点位上连接的线条
|
|
296
|
+
* @deprecated use `availableLines` instead
|
|
297
|
+
*/
|
|
298
|
+
get lines() {
|
|
299
|
+
return this.allLines.filter((line) => !line.isDrawing);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* 当前有效的线条,不包含正在画的线条和隐藏的线条(这个出现在线条重连会先把原来的线条隐藏)
|
|
303
|
+
*/
|
|
304
|
+
get availableLines() {
|
|
305
|
+
return this.allLines.filter((line) => !line.isDrawing && !line.isHidden);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* 当前点位上连接的线条(包含 isDrawing === true 的线条)
|
|
309
|
+
*/
|
|
310
|
+
get allLines() {
|
|
311
|
+
const lines = [];
|
|
312
|
+
const allLines = this.entityManager.getEntities({
|
|
313
|
+
type: WORKFLOW_LINE_ENTITY
|
|
314
|
+
});
|
|
315
|
+
allLines.forEach((line) => {
|
|
316
|
+
if (line.toPort === this || line.fromPort === this) {
|
|
317
|
+
lines.push(line);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
return lines;
|
|
321
|
+
}
|
|
322
|
+
dispose() {
|
|
323
|
+
this.lines.forEach((l) => l.dispose());
|
|
324
|
+
super.dispose();
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
WorkflowPortEntity.type = "WorkflowPortEntity";
|
|
328
|
+
|
|
329
|
+
// src/entity-datas/workflow-node-ports-data.ts
|
|
330
|
+
var WorkflowNodePortsData = class extends import_core5.EntityData {
|
|
331
|
+
constructor(entity) {
|
|
332
|
+
super(entity);
|
|
333
|
+
/** 静态的 ports 数据 */
|
|
334
|
+
this._staticPorts = [];
|
|
335
|
+
/** 存储 port 实体的 id,用于判断 port 是否存在 */
|
|
336
|
+
this._portIDSet = /* @__PURE__ */ new Set();
|
|
337
|
+
this.entity = entity;
|
|
338
|
+
const meta = entity.getNodeMeta();
|
|
339
|
+
const defaultPorts = meta.useDynamicPort ? [] : [{ type: "input" }, { type: "output" }];
|
|
340
|
+
this._staticPorts = meta.defaultPorts?.slice() || defaultPorts;
|
|
341
|
+
this.updatePorts(this._staticPorts);
|
|
342
|
+
if (meta.useDynamicPort) {
|
|
343
|
+
this.toDispose.push(
|
|
344
|
+
// 只需要监听节点的大小,因为算的是相对位置
|
|
345
|
+
entity.getData(import_core5.SizeData).onDataChange(() => {
|
|
346
|
+
if (entity.getData(import_core5.SizeData).width && entity.getData(import_core5.SizeData).height) {
|
|
347
|
+
this.updateDynamicPorts();
|
|
348
|
+
}
|
|
349
|
+
})
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
this.onDispose(() => {
|
|
353
|
+
this.allPorts.forEach((port) => port.dispose());
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
getDefaultData() {
|
|
357
|
+
return {};
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* 更新静态的 ports 数据
|
|
361
|
+
*/
|
|
362
|
+
updateStaticPorts(ports) {
|
|
363
|
+
const meta = this.entity.getNodeMeta();
|
|
364
|
+
this._staticPorts = ports;
|
|
365
|
+
if (meta.useDynamicPort) {
|
|
366
|
+
this.updateDynamicPorts();
|
|
367
|
+
} else {
|
|
368
|
+
this.updatePorts(this._staticPorts);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* 动态计算点位,通过 dom 的 data-port-key
|
|
373
|
+
*/
|
|
374
|
+
updateDynamicPorts() {
|
|
375
|
+
const domNode = this.entity.getData(import_document3.FlowNodeRenderData).node;
|
|
376
|
+
const elements = domNode.querySelectorAll("[data-port-id]");
|
|
377
|
+
const staticPorts = this._staticPorts;
|
|
378
|
+
const dynamicPorts = [];
|
|
379
|
+
if (elements.length > 0) {
|
|
380
|
+
dynamicPorts.push(
|
|
381
|
+
...Array.from(elements).map((element) => ({
|
|
382
|
+
portID: element.getAttribute("data-port-id"),
|
|
383
|
+
type: element.getAttribute("data-port-type"),
|
|
384
|
+
targetElement: element
|
|
385
|
+
}))
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
this.updatePorts(staticPorts.concat(dynamicPorts));
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* 根据 key 获取 port 实体
|
|
392
|
+
*/
|
|
393
|
+
getPortEntityByKey(portType, portKey) {
|
|
394
|
+
const entity = this.getOrCreatePortEntity({
|
|
395
|
+
type: portType,
|
|
396
|
+
portID: portKey
|
|
397
|
+
});
|
|
398
|
+
return entity;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* 更新 ports 数据
|
|
402
|
+
*/
|
|
403
|
+
updatePorts(ports) {
|
|
404
|
+
if (!(0, import_lodash_es.isEqual)(this._prePorts, ports)) {
|
|
405
|
+
const portKeys = ports.map((port) => this.getPortId(port.type, port.portID));
|
|
406
|
+
this._portIDSet.forEach((portId) => {
|
|
407
|
+
if (!portKeys.includes(portId)) {
|
|
408
|
+
this.getPortEntity(portId)?.dispose();
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
ports.forEach((port) => this.updatePortEntity(port));
|
|
412
|
+
this._prePorts = ports;
|
|
413
|
+
this.fireChange();
|
|
414
|
+
}
|
|
415
|
+
this.allPorts.forEach((port) => {
|
|
416
|
+
port.allLines.forEach((line) => {
|
|
417
|
+
line.validate();
|
|
418
|
+
});
|
|
419
|
+
port.validate();
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* 获取所有 port entities
|
|
424
|
+
*/
|
|
425
|
+
get allPorts() {
|
|
426
|
+
return Array.from(this._portIDSet).map((portId) => this.getPortEntity(portId)).filter(Boolean);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* 获取输入点位
|
|
430
|
+
*/
|
|
431
|
+
get inputPorts() {
|
|
432
|
+
return this.allPorts.filter((port) => port.portType === "input");
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* 获取输出点位
|
|
436
|
+
*/
|
|
437
|
+
get outputPorts() {
|
|
438
|
+
return this.allPorts.filter((port) => port.portType === "output");
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* 获取输入点位置
|
|
442
|
+
*/
|
|
443
|
+
get inputPoints() {
|
|
444
|
+
return this.inputPorts.map((port) => port.point);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* 获取输出点位置
|
|
448
|
+
*/
|
|
449
|
+
get outputPoints() {
|
|
450
|
+
return this.inputPorts.map((port) => port.point);
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* 根据 key 获取 输入点位置
|
|
454
|
+
*/
|
|
455
|
+
getInputPoint(key) {
|
|
456
|
+
return this.getPortEntityByKey("input", key).point;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* 根据 key 获取输出点位置
|
|
460
|
+
*/
|
|
461
|
+
getOutputPoint(key) {
|
|
462
|
+
return this.getPortEntityByKey("output", key).point;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* 获取 port 实体
|
|
466
|
+
*/
|
|
467
|
+
getPortEntity(portId) {
|
|
468
|
+
if (!this._portIDSet.has(portId)) {
|
|
469
|
+
return void 0;
|
|
470
|
+
}
|
|
471
|
+
return this.entity.entityManager.getEntityById(portId);
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* 拼接 port 实体的 id
|
|
475
|
+
*/
|
|
476
|
+
getPortId(portType, portKey = "") {
|
|
477
|
+
return getPortEntityId(this.entity, portType, portKey);
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* 创建 port 实体
|
|
481
|
+
*/
|
|
482
|
+
createPortEntity(portInfo) {
|
|
483
|
+
const id = this.getPortId(portInfo.type, portInfo.portID);
|
|
484
|
+
let portEntity = this.entity.entityManager.getEntityById(id);
|
|
485
|
+
if (!portEntity) {
|
|
486
|
+
portEntity = this.entity.entityManager.createEntity(WorkflowPortEntity, {
|
|
487
|
+
id,
|
|
488
|
+
node: this.entity,
|
|
489
|
+
...portInfo
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
portEntity.onDispose(() => {
|
|
493
|
+
this._portIDSet.delete(id);
|
|
494
|
+
});
|
|
495
|
+
this._portIDSet.add(id);
|
|
496
|
+
return portEntity;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* 获取或创建 port 实体
|
|
500
|
+
*/
|
|
501
|
+
getOrCreatePortEntity(portInfo) {
|
|
502
|
+
const id = this.getPortId(portInfo.type, portInfo.portID);
|
|
503
|
+
return this.getPortEntity(id) ?? this.createPortEntity(portInfo);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* 更新 port 实体
|
|
507
|
+
*/
|
|
508
|
+
updatePortEntity(portInfo) {
|
|
509
|
+
const portEntity = this.getOrCreatePortEntity(portInfo);
|
|
510
|
+
if (portInfo.targetElement) {
|
|
511
|
+
portEntity.updateTargetElement(portInfo.targetElement);
|
|
512
|
+
}
|
|
513
|
+
return portEntity;
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
WorkflowNodePortsData.type = "WorkflowNodePortsData";
|
|
517
|
+
|
|
518
|
+
// src/entity-datas/workflow-node-lines-data.ts
|
|
519
|
+
var import_utils6 = require("@flowgram.ai/utils");
|
|
520
|
+
var import_core6 = require("@flowgram.ai/core");
|
|
521
|
+
var _WorkflowNodeLinesData = class _WorkflowNodeLinesData extends import_core6.EntityData {
|
|
522
|
+
getDefaultData() {
|
|
523
|
+
return {
|
|
524
|
+
inputLines: [],
|
|
525
|
+
outputLines: []
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
constructor(entity) {
|
|
529
|
+
super(entity);
|
|
530
|
+
this.entity = entity;
|
|
531
|
+
this.entity.preDispose.push(
|
|
532
|
+
import_utils6.Disposable.create(() => {
|
|
533
|
+
this.inputLines.slice().forEach((line) => line.dispose());
|
|
534
|
+
this.outputLines.slice().forEach((line) => line.dispose());
|
|
535
|
+
})
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* 输入线条
|
|
540
|
+
*/
|
|
541
|
+
get inputLines() {
|
|
542
|
+
return this.data.inputLines;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* 输出线条
|
|
546
|
+
*/
|
|
547
|
+
get outputLines() {
|
|
548
|
+
return this.data.outputLines;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* 输入节点
|
|
552
|
+
*/
|
|
553
|
+
get inputNodes() {
|
|
554
|
+
return this.inputLines.map((l) => l.from).filter(Boolean);
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* 所有输入节点
|
|
558
|
+
*/
|
|
559
|
+
get allInputNodes() {
|
|
560
|
+
const nodeSet = /* @__PURE__ */ new Set();
|
|
561
|
+
const handleNode = (node) => {
|
|
562
|
+
if (nodeSet.has(node)) {
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
nodeSet.add(node);
|
|
566
|
+
const { inputNodes } = node.getData(_WorkflowNodeLinesData);
|
|
567
|
+
if (!inputNodes || !inputNodes.length) {
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
inputNodes.forEach((inputNode) => {
|
|
571
|
+
if (inputNode?.parent === node || node?.parent === inputNode) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
handleNode(inputNode);
|
|
575
|
+
});
|
|
576
|
+
};
|
|
577
|
+
handleNode(this.entity);
|
|
578
|
+
nodeSet.delete(this.entity);
|
|
579
|
+
return Array.from(nodeSet);
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* 输出节点
|
|
583
|
+
*/
|
|
584
|
+
get outputNodes() {
|
|
585
|
+
return this.outputLines.map((l) => l.to).filter(Boolean);
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* 输入输出节点
|
|
589
|
+
*/
|
|
590
|
+
get allOutputNodes() {
|
|
591
|
+
const nodeSet = /* @__PURE__ */ new Set();
|
|
592
|
+
const handleNode = (node) => {
|
|
593
|
+
if (nodeSet.has(node)) {
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
nodeSet.add(node);
|
|
597
|
+
const { outputNodes } = node.getData(_WorkflowNodeLinesData);
|
|
598
|
+
if (!outputNodes || !outputNodes.length) {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
outputNodes.forEach((outputNode) => {
|
|
602
|
+
if (outputNode?.parent === node || node?.parent === outputNode) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
handleNode(outputNode);
|
|
606
|
+
});
|
|
607
|
+
};
|
|
608
|
+
handleNode(this.entity);
|
|
609
|
+
nodeSet.delete(this.entity);
|
|
610
|
+
return Array.from(nodeSet);
|
|
611
|
+
}
|
|
612
|
+
addLine(line) {
|
|
613
|
+
if (line.from === this.entity) {
|
|
614
|
+
this.outputLines.push(line);
|
|
615
|
+
} else {
|
|
616
|
+
this.inputLines.push(line);
|
|
617
|
+
}
|
|
618
|
+
this.fireChange();
|
|
619
|
+
}
|
|
620
|
+
removeLine(line) {
|
|
621
|
+
const { inputLines, outputLines } = this;
|
|
622
|
+
const inputIndex = inputLines.indexOf(line);
|
|
623
|
+
const outputIndex = outputLines.indexOf(line);
|
|
624
|
+
if (inputIndex !== -1) {
|
|
625
|
+
inputLines.splice(inputIndex, 1);
|
|
626
|
+
this.fireChange();
|
|
627
|
+
}
|
|
628
|
+
if (outputIndex !== -1) {
|
|
629
|
+
outputLines.splice(outputIndex, 1);
|
|
630
|
+
this.fireChange();
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
_WorkflowNodeLinesData.type = "WorkflowNodeLinesData";
|
|
635
|
+
var WorkflowNodeLinesData = _WorkflowNodeLinesData;
|
|
636
|
+
|
|
637
|
+
// src/entity-datas/workflow-line-render-data.ts
|
|
638
|
+
var import_utils7 = require("@flowgram.ai/utils");
|
|
639
|
+
var import_core7 = require("@flowgram.ai/core");
|
|
640
|
+
var WorkflowLineRenderData = class extends import_core7.EntityData {
|
|
641
|
+
constructor(entity) {
|
|
642
|
+
super(entity);
|
|
643
|
+
this.syncContributions();
|
|
644
|
+
}
|
|
645
|
+
getDefaultData() {
|
|
646
|
+
return {
|
|
647
|
+
version: "",
|
|
648
|
+
contributions: /* @__PURE__ */ new Map(),
|
|
649
|
+
position: {
|
|
650
|
+
from: { x: 0, y: 0 },
|
|
651
|
+
to: { x: 0, y: 0 }
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
get renderVersion() {
|
|
656
|
+
return this.data.version;
|
|
657
|
+
}
|
|
658
|
+
get position() {
|
|
659
|
+
return this.data.position;
|
|
660
|
+
}
|
|
661
|
+
get path() {
|
|
662
|
+
return this.currentLine?.path ?? "";
|
|
663
|
+
}
|
|
664
|
+
calcDistance(pos) {
|
|
665
|
+
return this.currentLine?.calcDistance(pos) ?? Number.MAX_SAFE_INTEGER;
|
|
666
|
+
}
|
|
667
|
+
get bounds() {
|
|
668
|
+
return this.currentLine?.bounds ?? new import_utils7.Rectangle();
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* 更新数据
|
|
672
|
+
* WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排
|
|
673
|
+
*/
|
|
674
|
+
update() {
|
|
675
|
+
this.syncContributions();
|
|
676
|
+
const oldVersion = this.data.version;
|
|
677
|
+
this.updatePosition();
|
|
678
|
+
const newVersion = this.data.version;
|
|
679
|
+
if (oldVersion === newVersion) {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
this.data.version = newVersion;
|
|
683
|
+
this.currentLine?.update({
|
|
684
|
+
fromPos: this.data.position.from,
|
|
685
|
+
toPos: this.data.position.to
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
get lineType() {
|
|
689
|
+
return this.entity.renderType ?? this.entity.linesManager.lineType;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* 更新版本
|
|
693
|
+
* WARNING: 这个方法,必须在 requestAnimationFrame / useLayoutEffect 中调用,否则会引起浏览器强制重排
|
|
694
|
+
*/
|
|
695
|
+
updatePosition() {
|
|
696
|
+
this.data.position.from = this.entity.from.getData(WorkflowNodePortsData).getOutputPoint(this.entity.info.fromPort);
|
|
697
|
+
this.data.position.to = this.entity.info.drawingTo ?? this.entity.to?.getData(WorkflowNodePortsData)?.getInputPoint(this.entity.info.toPort) ?? {
|
|
698
|
+
x: this.data.position.from.x,
|
|
699
|
+
y: this.data.position.from.y
|
|
700
|
+
};
|
|
701
|
+
this.data.version = [
|
|
702
|
+
this.lineType,
|
|
703
|
+
this.data.position.from.x,
|
|
704
|
+
this.data.position.from.y,
|
|
705
|
+
this.data.position.to.x,
|
|
706
|
+
this.data.position.to.y
|
|
707
|
+
].join("-");
|
|
708
|
+
}
|
|
709
|
+
get currentLine() {
|
|
710
|
+
return this.data.contributions.get(this.lineType);
|
|
711
|
+
}
|
|
712
|
+
syncContributions() {
|
|
713
|
+
if (this.entity.linesManager.contributionFactories.length === this.data.contributions.size) {
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
this.entity.linesManager.contributionFactories.forEach((factory) => {
|
|
717
|
+
this.registerContribution(factory);
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
registerContribution(contributionFactory) {
|
|
721
|
+
if (this.data.contributions.has(contributionFactory.type)) {
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
const contribution = new contributionFactory(this.entity);
|
|
725
|
+
this.data.contributions.set(contributionFactory.type, contribution);
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
WorkflowLineRenderData.type = "WorkflowLineRenderData";
|
|
729
|
+
|
|
730
|
+
// src/entities/workflow-line-entity.ts
|
|
731
|
+
var LINE_HOVER_DISTANCE = 8;
|
|
732
|
+
var POINT_RADIUS = 10;
|
|
733
|
+
var _WorkflowLineEntity = class _WorkflowLineEntity extends import_core8.Entity {
|
|
734
|
+
constructor(opts) {
|
|
735
|
+
super(opts);
|
|
736
|
+
this._processing = false;
|
|
737
|
+
this._hasError = false;
|
|
738
|
+
this.stackIndex = 0;
|
|
739
|
+
/**
|
|
740
|
+
* 线条数据
|
|
741
|
+
*/
|
|
742
|
+
this.info = {
|
|
743
|
+
from: ""
|
|
744
|
+
};
|
|
745
|
+
this.document = opts.document;
|
|
746
|
+
this.linesManager = opts.linesManager;
|
|
747
|
+
this.initInfo({
|
|
748
|
+
from: opts.from,
|
|
749
|
+
to: opts.to,
|
|
750
|
+
drawingTo: opts.drawingTo,
|
|
751
|
+
fromPort: opts.fromPort,
|
|
752
|
+
toPort: opts.toPort
|
|
753
|
+
});
|
|
754
|
+
if (opts.drawingTo) {
|
|
755
|
+
this.isDrawing = true;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* 转成线条 id
|
|
760
|
+
* @param info
|
|
761
|
+
*/
|
|
762
|
+
static portInfoToLineId(info) {
|
|
763
|
+
const { from, to, fromPort, toPort } = info;
|
|
764
|
+
return `${from}_${fromPort || ""}-${to || ""}_${toPort || ""}`;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* 获取线条的前置节点
|
|
768
|
+
*/
|
|
769
|
+
get from() {
|
|
770
|
+
return this._from;
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* 获取线条的后置节点
|
|
774
|
+
*/
|
|
775
|
+
get to() {
|
|
776
|
+
return this._to;
|
|
777
|
+
}
|
|
778
|
+
get isHidden() {
|
|
779
|
+
return this.highlightColor === this.linesManager.lineColor.hidden;
|
|
780
|
+
}
|
|
781
|
+
get inContainer() {
|
|
782
|
+
const nodeInContainer = (node) => !!node?.parent && node.parent.flowNodeType !== "root";
|
|
783
|
+
return nodeInContainer(this.from) || nodeInContainer(this.to);
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* 获取是否 testrun processing
|
|
787
|
+
*/
|
|
788
|
+
get processing() {
|
|
789
|
+
return this._processing;
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* 设置 testrun processing 状态
|
|
793
|
+
*/
|
|
794
|
+
set processing(status) {
|
|
795
|
+
if (this._processing !== status) {
|
|
796
|
+
this._processing = status;
|
|
797
|
+
this.fireChange();
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
// 获取连线是否为错误态
|
|
801
|
+
get hasError() {
|
|
802
|
+
return this._hasError;
|
|
803
|
+
}
|
|
804
|
+
// 设置连线的错误态
|
|
805
|
+
set hasError(hasError) {
|
|
806
|
+
if (this._hasError !== hasError) {
|
|
807
|
+
this._hasError = hasError;
|
|
808
|
+
this.fireChange();
|
|
809
|
+
}
|
|
810
|
+
if (this._node) {
|
|
811
|
+
this._node.dataset.hasError = this.hasError ? "true" : "false";
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* 设置线条的后置节点
|
|
816
|
+
*/
|
|
817
|
+
setToPort(toPort) {
|
|
818
|
+
if (!this.isDrawing) {
|
|
819
|
+
throw new Error("[setToPort] only support drawing line.");
|
|
820
|
+
}
|
|
821
|
+
if (this.toPort === toPort) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
if (toPort && toPort.portType === "input" && this.linesManager.canAddLine(this.fromPort, toPort, true)) {
|
|
825
|
+
const { node, portID } = toPort;
|
|
826
|
+
this._to = node;
|
|
827
|
+
this.info.drawingTo = void 0;
|
|
828
|
+
this.info.isDefaultLine = false;
|
|
829
|
+
this.info.to = node.id;
|
|
830
|
+
this.info.toPort = portID;
|
|
831
|
+
} else {
|
|
832
|
+
this._to = void 0;
|
|
833
|
+
this.info.to = void 0;
|
|
834
|
+
this.info.toPort = "";
|
|
835
|
+
}
|
|
836
|
+
this.fireChange();
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* 设置线条画线时的目标位置
|
|
840
|
+
*/
|
|
841
|
+
set drawingTo(pos) {
|
|
842
|
+
const oldDrawingTo = this.info.drawingTo;
|
|
843
|
+
if (!pos) {
|
|
844
|
+
this.info.drawingTo = void 0;
|
|
845
|
+
this.fireChange();
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
if (!oldDrawingTo || pos.x !== oldDrawingTo.x || pos.y !== oldDrawingTo.y) {
|
|
849
|
+
this.info.to = void 0;
|
|
850
|
+
this.info.isDefaultLine = false;
|
|
851
|
+
this.info.drawingTo = pos;
|
|
852
|
+
this.fireChange();
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* 获取线条正在画线的位置
|
|
857
|
+
*/
|
|
858
|
+
get drawingTo() {
|
|
859
|
+
return this.info.drawingTo;
|
|
860
|
+
}
|
|
861
|
+
get highlightColor() {
|
|
862
|
+
return this.info.highlightColor || "";
|
|
863
|
+
}
|
|
864
|
+
set highlightColor(color) {
|
|
865
|
+
if (this.info.highlightColor !== color) {
|
|
866
|
+
this.info.highlightColor = color;
|
|
867
|
+
this.fireChange();
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* 获取线条的边框位置大小
|
|
872
|
+
*/
|
|
873
|
+
get bounds() {
|
|
874
|
+
return this.getData(WorkflowLineRenderData).bounds;
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* 获取点和线最接近的距离
|
|
878
|
+
*/
|
|
879
|
+
getHoverDist(pos) {
|
|
880
|
+
return this.getData(WorkflowLineRenderData).calcDistance(pos);
|
|
881
|
+
}
|
|
882
|
+
get fromPort() {
|
|
883
|
+
return this.from.getData(WorkflowNodePortsData).getPortEntityByKey("output", this.info.fromPort);
|
|
884
|
+
}
|
|
885
|
+
get toPort() {
|
|
886
|
+
if (!this.to) {
|
|
887
|
+
return void 0;
|
|
888
|
+
}
|
|
889
|
+
return this.to.getData(WorkflowNodePortsData).getPortEntityByKey("input", this.info.toPort);
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* 获取线条真实的输入输出节点坐标
|
|
893
|
+
*/
|
|
894
|
+
get position() {
|
|
895
|
+
return this.getData(WorkflowLineRenderData).position;
|
|
896
|
+
}
|
|
897
|
+
/** 是否反转箭头 */
|
|
898
|
+
get reverse() {
|
|
899
|
+
return this.linesManager.isReverseLine(this);
|
|
900
|
+
}
|
|
901
|
+
/** 是否隐藏箭头 */
|
|
902
|
+
get hideArrow() {
|
|
903
|
+
return this.linesManager.isHideArrowLine(this);
|
|
904
|
+
}
|
|
905
|
+
/** 是否流动 */
|
|
906
|
+
get flowing() {
|
|
907
|
+
return this.linesManager.isFlowingLine(this);
|
|
908
|
+
}
|
|
909
|
+
/** 是否禁用 */
|
|
910
|
+
get disabled() {
|
|
911
|
+
return this.linesManager.isDisabledLine(this);
|
|
912
|
+
}
|
|
913
|
+
/** 是否竖向 */
|
|
914
|
+
get vertical() {
|
|
915
|
+
return this.linesManager.isVerticalLine(this);
|
|
916
|
+
}
|
|
917
|
+
/** 获取线条渲染器类型 */
|
|
918
|
+
get renderType() {
|
|
919
|
+
return this.linesManager.setLineRenderType(this);
|
|
920
|
+
}
|
|
921
|
+
/** 获取线条样式 */
|
|
922
|
+
get className() {
|
|
923
|
+
return this.linesManager.setLineClassName(this) ?? "";
|
|
924
|
+
}
|
|
925
|
+
get color() {
|
|
926
|
+
return this.linesManager.getLineColor(this);
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* 初始化线条
|
|
930
|
+
* @param info 线条信息
|
|
931
|
+
*/
|
|
932
|
+
initInfo(info) {
|
|
933
|
+
if (!(0, import_lodash_es2.isEqual)(info, this.info)) {
|
|
934
|
+
this.info = info;
|
|
935
|
+
this._from = this.document.getNode(info.from);
|
|
936
|
+
this._to = info.to ? this.document.getNode(info.to) : void 0;
|
|
937
|
+
this.fireChange();
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
// 校验连线是否为错误态
|
|
941
|
+
validate() {
|
|
942
|
+
const { fromPort, toPort } = this;
|
|
943
|
+
this.validateSelf();
|
|
944
|
+
fromPort?.validate();
|
|
945
|
+
toPort?.validate();
|
|
946
|
+
}
|
|
947
|
+
validateSelf() {
|
|
948
|
+
const { fromPort, toPort } = this;
|
|
949
|
+
if (fromPort) {
|
|
950
|
+
this.hasError = this.linesManager.isErrorLine(fromPort, toPort);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
is(line) {
|
|
954
|
+
if (line instanceof _WorkflowLineEntity) {
|
|
955
|
+
return this === line;
|
|
956
|
+
}
|
|
957
|
+
return _WorkflowLineEntity.portInfoToLineId(line) === this.id;
|
|
958
|
+
}
|
|
959
|
+
canRemove(newLineInfo) {
|
|
960
|
+
return this.linesManager.canRemove(this, newLineInfo);
|
|
961
|
+
}
|
|
962
|
+
get node() {
|
|
963
|
+
if (this._node) return this._node;
|
|
964
|
+
this._node = import_utils8.domUtils.createDivWithClass("gedit-flow-activity-line");
|
|
965
|
+
this._node.dataset.testid = "sdk.workflow.canvas.line";
|
|
966
|
+
this._node.dataset.lineId = this.id;
|
|
967
|
+
this._node.dataset.fromNodeId = this.from.id;
|
|
968
|
+
this._node.dataset.fromPortId = this.fromPort?.id ?? "";
|
|
969
|
+
this._node.dataset.toNodeId = this.to?.id ?? "";
|
|
970
|
+
this._node.dataset.toPortId = this.toPort?.id ?? "";
|
|
971
|
+
this._node.dataset.hasError = this.hasError ? "true" : "false";
|
|
972
|
+
return this._node;
|
|
973
|
+
}
|
|
974
|
+
toJSON() {
|
|
975
|
+
const json = {
|
|
976
|
+
sourceNodeID: this.info.from,
|
|
977
|
+
targetNodeID: this.info.to,
|
|
978
|
+
sourcePortID: this.info.fromPort,
|
|
979
|
+
targetPortID: this.info.toPort
|
|
980
|
+
};
|
|
981
|
+
if (!json.sourcePortID) {
|
|
982
|
+
delete json.sourcePortID;
|
|
983
|
+
}
|
|
984
|
+
if (!json.targetPortID) {
|
|
985
|
+
delete json.targetPortID;
|
|
986
|
+
}
|
|
987
|
+
return json;
|
|
988
|
+
}
|
|
989
|
+
/** 触发线条渲染 */
|
|
990
|
+
fireRender() {
|
|
991
|
+
this.fireChange();
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
_WorkflowLineEntity.type = WORKFLOW_LINE_ENTITY;
|
|
995
|
+
var WorkflowLineEntity = _WorkflowLineEntity;
|
|
996
|
+
|
|
997
|
+
// src/service/workflow-select-service.ts
|
|
998
|
+
var WorkflowSelectService = class {
|
|
999
|
+
get onSelectionChanged() {
|
|
1000
|
+
return this.selectionService.onSelectionChanged;
|
|
1001
|
+
}
|
|
1002
|
+
get selection() {
|
|
1003
|
+
return this.selectionService.selection;
|
|
1004
|
+
}
|
|
1005
|
+
set selection(entities) {
|
|
1006
|
+
this.selectionService.selection = entities;
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* 当前激活的节点只能有一个
|
|
1010
|
+
*/
|
|
1011
|
+
get activatedNode() {
|
|
1012
|
+
const { selectedNodes } = this;
|
|
1013
|
+
if (selectedNodes.length !== 1) {
|
|
1014
|
+
return void 0;
|
|
1015
|
+
}
|
|
1016
|
+
return selectedNodes[0];
|
|
1017
|
+
}
|
|
1018
|
+
isSelected(id) {
|
|
1019
|
+
return this.selectionService.selection.some((s) => s.id === id);
|
|
1020
|
+
}
|
|
1021
|
+
isActivated(id) {
|
|
1022
|
+
return this.activatedNode?.id === id;
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* 选中的节点
|
|
1026
|
+
*/
|
|
1027
|
+
get selectedNodes() {
|
|
1028
|
+
return this.selectionService.selection.filter(
|
|
1029
|
+
(n) => n instanceof WorkflowNodeEntity
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
/**
|
|
1033
|
+
* 选中
|
|
1034
|
+
* @param node
|
|
1035
|
+
*/
|
|
1036
|
+
selectNode(node) {
|
|
1037
|
+
this.selectionService.selection = [node];
|
|
1038
|
+
}
|
|
1039
|
+
toggleSelect(node) {
|
|
1040
|
+
if (this.selectionService.selection.includes(node)) {
|
|
1041
|
+
this.selectionService.selection = this.selectionService.selection.filter((n) => n !== node);
|
|
1042
|
+
} else {
|
|
1043
|
+
this.selectionService.selection = this.selectionService.selection.concat(node);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
select(node) {
|
|
1047
|
+
this.selectionService.selection = [node];
|
|
1048
|
+
}
|
|
1049
|
+
clear() {
|
|
1050
|
+
this.selectionService.selection = [];
|
|
1051
|
+
}
|
|
1052
|
+
/**
|
|
1053
|
+
* 选中并滚动到节点
|
|
1054
|
+
* @param node
|
|
1055
|
+
*/
|
|
1056
|
+
async selectNodeAndScrollToView(node, fitView2) {
|
|
1057
|
+
this.selectNodeAndFocus(node);
|
|
1058
|
+
const DELAY_TIME = 30;
|
|
1059
|
+
await (0, import_utils4.delay)(DELAY_TIME);
|
|
1060
|
+
const scrollConfig = {
|
|
1061
|
+
entities: [node]
|
|
1062
|
+
};
|
|
1063
|
+
if (fitView2) {
|
|
1064
|
+
const bounds = import_utils9.Rectangle.enlarge([node.getData(import_core9.TransformData).bounds]).pad(
|
|
1065
|
+
30,
|
|
1066
|
+
30
|
|
1067
|
+
);
|
|
1068
|
+
const viewport = this.playground.config.getViewport(false);
|
|
1069
|
+
const zoom = import_utils9.SizeSchema.fixSize(bounds, viewport);
|
|
1070
|
+
scrollConfig.zoom = zoom;
|
|
1071
|
+
scrollConfig.scrollToCenter = true;
|
|
1072
|
+
scrollConfig.easing = true;
|
|
1073
|
+
}
|
|
1074
|
+
return this.playground.config.scrollToView(scrollConfig);
|
|
1075
|
+
}
|
|
1076
|
+
selectNodeAndFocus(node) {
|
|
1077
|
+
this.select(node);
|
|
1078
|
+
this.playground.node.focus();
|
|
1079
|
+
}
|
|
1080
|
+
};
|
|
1081
|
+
__decorateClass([
|
|
1082
|
+
(0, import_inversify.inject)(import_core9.SelectionService)
|
|
1083
|
+
], WorkflowSelectService.prototype, "selectionService", 2);
|
|
1084
|
+
__decorateClass([
|
|
1085
|
+
(0, import_inversify.inject)(import_core9.Playground)
|
|
1086
|
+
], WorkflowSelectService.prototype, "playground", 2);
|
|
1087
|
+
WorkflowSelectService = __decorateClass([
|
|
1088
|
+
(0, import_inversify.injectable)()
|
|
1089
|
+
], WorkflowSelectService);
|
|
1090
|
+
|
|
1091
|
+
// src/service/workflow-hover-service.ts
|
|
1092
|
+
var import_inversify2 = require("inversify");
|
|
1093
|
+
var import_utils11 = require("@flowgram.ai/utils");
|
|
1094
|
+
var import_core10 = require("@flowgram.ai/core");
|
|
1095
|
+
var WorkflowHoverService = class {
|
|
1096
|
+
constructor() {
|
|
1097
|
+
this.onHoveredChangeEmitter = new import_utils11.Emitter();
|
|
1098
|
+
this.onUpdateHoverPositionEmitter = new import_utils11.Emitter();
|
|
1099
|
+
this.onHoveredChange = this.onHoveredChangeEmitter.event;
|
|
1100
|
+
this.onUpdateHoverPosition = this.onUpdateHoverPositionEmitter.event;
|
|
1101
|
+
// 当前鼠标 hover 位置
|
|
1102
|
+
this.hoveredPos = { x: 0, y: 0 };
|
|
1103
|
+
/**
|
|
1104
|
+
* 当前 hovered 的 节点或者线条或者点
|
|
1105
|
+
* 1: nodeId / lineId (节点 / 线条)
|
|
1106
|
+
* 2: nodeId:portKey (节点连接点)
|
|
1107
|
+
*/
|
|
1108
|
+
this.hoveredKey = "";
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* 更新 hover 的内容
|
|
1112
|
+
* @param hoveredKey hovered key
|
|
1113
|
+
*/
|
|
1114
|
+
updateHoveredKey(hoveredKey) {
|
|
1115
|
+
if (this.hoveredKey !== hoveredKey) {
|
|
1116
|
+
this.hoveredKey = hoveredKey;
|
|
1117
|
+
this.onHoveredChangeEmitter.fire(hoveredKey);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
updateHoverPosition(position, target) {
|
|
1121
|
+
this.hoveredPos = position;
|
|
1122
|
+
this.onUpdateHoverPositionEmitter.fire({
|
|
1123
|
+
position,
|
|
1124
|
+
target
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* 清空 hover 内容
|
|
1129
|
+
*/
|
|
1130
|
+
clearHovered() {
|
|
1131
|
+
this.updateHoveredKey("");
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* 判断是否 hover
|
|
1135
|
+
* @param nodeId hoveredKey
|
|
1136
|
+
* @returns 是否 hover
|
|
1137
|
+
*/
|
|
1138
|
+
isHovered(nodeId) {
|
|
1139
|
+
return nodeId === this.hoveredKey;
|
|
1140
|
+
}
|
|
1141
|
+
isSomeHovered() {
|
|
1142
|
+
return !!this.hoveredKey;
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* 获取被 hover 的节点或线条
|
|
1146
|
+
*/
|
|
1147
|
+
get hoveredNode() {
|
|
1148
|
+
return this.entityManager.getEntityById(this.hoveredKey);
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
__decorateClass([
|
|
1152
|
+
(0, import_inversify2.inject)(import_core10.EntityManager)
|
|
1153
|
+
], WorkflowHoverService.prototype, "entityManager", 2);
|
|
1154
|
+
WorkflowHoverService = __decorateClass([
|
|
1155
|
+
(0, import_inversify2.injectable)()
|
|
1156
|
+
], WorkflowHoverService);
|
|
1157
|
+
|
|
1158
|
+
// src/service/workflow-drag-service.ts
|
|
1159
|
+
var import_nanoid3 = require("nanoid");
|
|
1160
|
+
var import_inversify6 = require("inversify");
|
|
1161
|
+
var import_utils16 = require("@flowgram.ai/utils");
|
|
1162
|
+
var import_document8 = require("@flowgram.ai/document");
|
|
1163
|
+
var import_document9 = require("@flowgram.ai/document");
|
|
1164
|
+
var import_core15 = require("@flowgram.ai/core");
|
|
1165
|
+
|
|
1166
|
+
// src/workflow-lines-manager.ts
|
|
1167
|
+
var import_lodash_es3 = require("lodash-es");
|
|
1168
|
+
var import_inversify3 = require("inversify");
|
|
1169
|
+
var import_utils12 = require("@flowgram.ai/utils");
|
|
1170
|
+
var import_document5 = require("@flowgram.ai/document");
|
|
1171
|
+
var import_core12 = require("@flowgram.ai/core");
|
|
1172
|
+
|
|
1173
|
+
// src/workflow-document-option.ts
|
|
1174
|
+
var import_form_core2 = require("@flowgram.ai/form-core");
|
|
1175
|
+
var import_document4 = require("@flowgram.ai/document");
|
|
1176
|
+
var import_core11 = require("@flowgram.ai/core");
|
|
1177
|
+
|
|
1178
|
+
// src/utils/flow-node-form-data.ts
|
|
1179
|
+
var import_form_core = require("@flowgram.ai/form-core");
|
|
1180
|
+
|
|
1181
|
+
// src/typings/workflow-json.ts
|
|
1182
|
+
var WorkflowContentChangeType = /* @__PURE__ */ ((WorkflowContentChangeType2) => {
|
|
1183
|
+
WorkflowContentChangeType2["ADD_NODE"] = "ADD_NODE";
|
|
1184
|
+
WorkflowContentChangeType2["DELETE_NODE"] = "DELETE_NODE";
|
|
1185
|
+
WorkflowContentChangeType2["MOVE_NODE"] = "MOVE_NODE";
|
|
1186
|
+
WorkflowContentChangeType2["NODE_DATA_CHANGE"] = "NODE_DATA_CHANGE";
|
|
1187
|
+
WorkflowContentChangeType2["ADD_LINE"] = "ADD_LINE";
|
|
1188
|
+
WorkflowContentChangeType2["DELETE_LINE"] = "DELETE_LINE";
|
|
1189
|
+
WorkflowContentChangeType2["META_CHANGE"] = "META_CHANGE";
|
|
1190
|
+
return WorkflowContentChangeType2;
|
|
1191
|
+
})(WorkflowContentChangeType || {});
|
|
1192
|
+
|
|
1193
|
+
// src/typings/workflow-line.ts
|
|
1194
|
+
var LineType = /* @__PURE__ */ ((LineType2) => {
|
|
1195
|
+
LineType2[LineType2["BEZIER"] = 0] = "BEZIER";
|
|
1196
|
+
LineType2[LineType2["LINE_CHART"] = 1] = "LINE_CHART";
|
|
1197
|
+
return LineType2;
|
|
1198
|
+
})(LineType || {});
|
|
1199
|
+
var LineColors = /* @__PURE__ */ ((LineColors2) => {
|
|
1200
|
+
LineColors2["HIDDEN"] = "var(--g-workflow-line-color-hidden,transparent)";
|
|
1201
|
+
LineColors2["DEFUALT"] = "var(--g-workflow-line-color-default,#4d53e8)";
|
|
1202
|
+
LineColors2["DRAWING"] = "var(--g-workflow-line-color-drawing, #5DD6E3)";
|
|
1203
|
+
LineColors2["HOVER"] = "var(--g-workflow-line-color-hover,#37d0ff)";
|
|
1204
|
+
LineColors2["SELECTED"] = "var(--g-workflow-line-color-selected,#37d0ff)";
|
|
1205
|
+
LineColors2["ERROR"] = "var(--g-workflow-line-color-error,red)";
|
|
1206
|
+
LineColors2["FLOWING"] = "var(--g-workflow-line-color-flowing,#4d53e8)";
|
|
1207
|
+
return LineColors2;
|
|
1208
|
+
})(LineColors || {});
|
|
1209
|
+
|
|
1210
|
+
// src/typings/workflow-operation.ts
|
|
1211
|
+
var WorkflowOperationBaseService = Symbol("WorkflowOperationBaseService");
|
|
1212
|
+
|
|
1213
|
+
// src/typings/index.ts
|
|
1214
|
+
var URLParams = Symbol("");
|
|
1215
|
+
|
|
1216
|
+
// src/utils/flow-node-form-data.ts
|
|
1217
|
+
function getFlowNodeFormData(node) {
|
|
1218
|
+
return node.getData(import_form_core.FlowNodeFormData);
|
|
1219
|
+
}
|
|
1220
|
+
function toFormJSON(node) {
|
|
1221
|
+
const formData = node.getData(import_form_core.FlowNodeFormData);
|
|
1222
|
+
if (!formData || !node.getNodeRegistry().formMeta) return void 0;
|
|
1223
|
+
return formData.toJSON();
|
|
1224
|
+
}
|
|
1225
|
+
function initFormDataFromJSON(node, json, isFirstCreate) {
|
|
1226
|
+
const formData = node.getData(import_form_core.FlowNodeFormData);
|
|
1227
|
+
const registry = node.getNodeRegistry();
|
|
1228
|
+
const { formMeta } = registry;
|
|
1229
|
+
if (formData && formMeta) {
|
|
1230
|
+
if (isFirstCreate) {
|
|
1231
|
+
formData.createForm(formMeta, json.data);
|
|
1232
|
+
formData.onDataChange(() => {
|
|
1233
|
+
node.document.fireContentChange({
|
|
1234
|
+
type: "NODE_DATA_CHANGE" /* NODE_DATA_CHANGE */,
|
|
1235
|
+
toJSON: () => formData.toJSON(),
|
|
1236
|
+
entity: node
|
|
1237
|
+
});
|
|
1238
|
+
});
|
|
1239
|
+
} else {
|
|
1240
|
+
formData.updateFormValues(json.data);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
// src/workflow-document-option.ts
|
|
1246
|
+
var WorkflowDocumentOptions = Symbol("WorkflowDocumentOptions");
|
|
1247
|
+
var WorkflowDocumentOptionsDefault = {
|
|
1248
|
+
cursors: {
|
|
1249
|
+
grab: 'url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC40ODczIDIuNjIzNzhDOS45MDczMSAyLjYyMzc4IDkuNDM3MTMgMy4wOTM5NiA5LjQzNzEzIDMuNjczOTZWNS4xNDM3NkM5LjM5NDI4IDQuNDAyNzQgOC43Nzk3OCAzLjgxNTA0IDguMDI4MDIgMy44MTUwNEM3LjI0ODQ4IDMuODE1MDQgNi42MTY1MyA0LjQ0Njk5IDYuNjE2NTMgNS4yMjY1M1YxMS44Mjg5TDUuNjc0MTggMTEuMDA0OUM1LjE1NDg3IDEwLjU1MDkgNC40MDk1IDEwLjQ2MzYgMy43OTkzOCAxMC43ODU1TDMuNjk2OTQgMTAuODM5NkMzLjA2MjE3IDExLjE3NDUgMi45MjI2IDEyLjAyMjggMy40MTY2MiAxMi41NDM0TDcuMzM5NTkgMTYuNjc3NVYxNy4zMjU5QzcuMzM5NTkgMTcuNzg2MiA3LjcxMjY5IDE4LjE1OTMgOC4xNzI5MiAxOC4xNTkzSDEzLjgwODRDMTQuMjY4NyAxOC4xNTkzIDE0LjY0MTcgMTcuNzg2MiAxNC42NDE3IDE3LjMyNTlWMTYuNzkzNUMxNS44MDk0IDE1LjY0ODUgMTYuNDY3MyAxNC4wODE5IDE2LjQ2NzMgMTIuNDQ2NVYxMS40OTY3TDE2LjQ2NzEgNi42MzY4NUMxNi40NjcxIDUuOTU2MyAxNS45MTU0IDUuNDA0NjEgMTUuMjM0OCA1LjQwNDYxQzE0LjU1NDMgNS40MDQ2MSAxNC4wMDI2IDUuOTU2MyAxNC4wMDI2IDYuNjM2ODVMMTQuMDAyMSA1LjA0NzI4QzE0LjAwMjEgNC4zNjY3MyAxMy40NTA0IDMuODE1MDQgMTIuNzY5OCAzLjgxNTA0QzEyLjA4OTMgMy44MTUwNCAxMS41Mzc2IDQuMzY2NzMgMTEuNTM3NiA1LjA0NzI4TDExLjUzNzUgMy42NzM5NUMxMS41Mzc1IDMuMDkzOTYgMTEuMDY3MyAyLjYyMzc4IDEwLjQ4NzMgMi42MjM3OFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3NCAxLjM3NDAyQzExLjM2MTIgMS4zNzQwMiAxMi4xMjExIDEuODYxMTggMTIuNTEwNSAyLjU3ODY4QzEyLjU5NTggMi41Njk4MyAxMi42ODIzIDIuNTY1MjggMTIuNzcgMi41NjUyOEMxMy44Mjc4IDIuNTY1MjggMTQuNzMxMSAzLjIyNzAxIDE1LjA4ODUgNC4xNTkxMUMxNS4xMzcgNC4xNTYyOSAxNS4xODU4IDQuMTU0ODYgMTUuMjM1IDQuMTU0ODZDMTYuNjA1OSA0LjE1NDg2IDE3LjcxNzIgNS4yNjYxOSAxNy43MTcyIDYuNjM3MDlMMTcuNzE3NCAxMi40NDY3QzE3LjcxNzQgMTQuMjM1NSAxNy4wNjQ0IDE1Ljk1NTkgMTUuODkxOSAxNy4yOTA0VjE3LjMyNjJDMTUuODkxOSAxOC40NzY4IDE0Ljk1OTEgMTkuNDA5NSAxMy44MDg1IDE5LjQwOTVIOC4xNzMwNkM3LjAyMjQ3IDE5LjQwOTUgNi4wODk3MyAxOC40NzY4IDYuMDg5NzMgMTcuMzI2MlYxNy4xNzY0TDIuNTEwMDMgMTMuNDA0MUMxLjQ0NTk5IDEyLjI4MjggMS43NDY2IDEwLjQ1NTUgMy4xMTM3OSA5LjczNDI0TDMuMjE2MjQgOS42ODAxOUMzLjg5MTY4IDkuMzIzODMgNC42NjE4NSA5LjI1NDAxIDUuMzY2NjYgOS40NTE5OFY1LjIyNjc4QzUuMzY2NjYgMy43NTY4NyA2LjU1ODI2IDIuNTY1MjggOC4wMjgxNiAyLjU2NTI4QzguMTcyOTMgMi41NjUyOCA4LjMxNDk5IDIuNTc2ODQgOC40NTM0NyAyLjU5OTA3QzguODM5NDMgMS44NzA0MiA5LjYwNTQ2IDEuMzc0MDIgMTAuNDg3NCAxLjM3NDAyWk0xMi40NDc2IDMuODU3ODdWOS40NzY0NkMxMi40NDc2IDkuNzI4NTIgMTIuMjQzMyA5LjkzMjg1IDExLjk5MTMgOS45MzI4NUMxMS43MzkyIDkuOTMyODUgMTEuNTM0OSA5LjcyODUyIDExLjUzNDkgOS40NzY0NlYzLjc5NjU1QzExLjUzNDkgMy43Nzk1NiAxMS41MzU4IDMuNzYyNzcgMTEuNTM3NiAzLjc0NjI2VjMuNjc0MkMxMS41Mzc2IDMuNDMyODIgMTEuNDU2MiAzLjIxMDQ2IDExLjMxOTMgMy4wMzMwOUMxMS4xMjcyIDIuNzg0MjggMTAuODI2MSAyLjYyNDAyIDEwLjQ4NzQgMi42MjQwMkMxMC4xMjM4IDIuNjI0MDIgOS44MDMzMiAyLjgwODg2IDkuNjE0ODMgMy4wODk3QzkuNTAyNjkgMy4yNTY3OSA5LjQzNzI2IDMuNDU3ODUgOS40MzcyNiAzLjY3NDJWMy43ODU3M0M5LjQzNzM1IDMuNzg5MzMgOS40MzczOSAzLjc5Mjk0IDkuNDM3MzkgMy43OTY1NVY5LjkwMTdDOS40MzczOSAxMC4xNTM3IDkuMjMzMDYgMTAuMzU4MSA4Ljk4MTAxIDEwLjM1ODFDOC43Mjg5NSAxMC4zNTgxIDguNTI0NjIgMTAuMTUzNyA4LjUyNDYyIDkuOTAxN1YzLjkwNTA3QzguNDE3NzMgMy44NjQ5IDguMzA0NjggMy44MzczMiA4LjE4NzI2IDMuODI0MTVDOC4xMzUwNCAzLjgxODI5IDguMDgxOTUgMy44MTUyOCA4LjAyODE2IDMuODE1MjhDNy4yNDg2MSAzLjgxNTI4IDYuNjE2NjYgNC40NDcyMyA2LjYxNjY2IDUuMjI2NzhWMTEuODI5Mkw1LjY3NDMxIDExLjAwNTJDNS41Nzg2OCAxMC45MjE2IDUuNDc1MzcgMTAuODUwNCA1LjM2NjY2IDEwLjc5MTlDNC44ODUwNiAxMC41MzI5IDQuMjk3MjggMTAuNTIzMSAzLjc5OTUyIDEwLjc4NThMMy42OTcwNyAxMC44Mzk4QzMuMDYyMzEgMTEuMTc0NyAyLjkyMjczIDEyLjAyMzEgMy40MTY3NSAxMi41NDM3TDcuMzM5NzMgMTYuNjc3N1YxNy4zMjYyQzcuMzM5NzMgMTcuNzg2NCA3LjcxMjgyIDE4LjE1OTUgOC4xNzMwNiAxOC4xNTk1SDEzLjgwODVDMTQuMjY4OCAxOC4xNTk1IDE0LjY0MTkgMTcuNzg2NCAxNC42NDE5IDE3LjMyNjJWMTYuNzkzOEMxNS43Mzc5IDE1LjcxOSAxNi4zODQ3IDE0LjI3MjggMTYuNDYgMTIuNzQ3QzE2LjQ2NDEgMTIuNjY0MSAxNi40NjY1IDEyLjU4MDkgMTYuNDY3MiAxMi40OTc1TDE2LjQ2NzQgMTIuNDQ2N0wxNi40NjcyIDYuNjM3MDlDMTYuNDY3MiA1Ljk2MjMgMTUuOTI0OCA1LjQxNDE5IDE1LjI1MjIgNS40MDQ5N0wxNS4yMzUgNS40MDQ4NkMxNS4xMjQ2IDUuNDA0ODYgMTUuMDE3NyA1LjQxOTM2IDE0LjkxNTkgNS40NDY1NlY5LjYwMjI2QzE0LjkxNTkgOS44NTQzMSAxNC43MTE2IDEwLjA1ODYgMTQuNDU5NSAxMC4wNTg2QzE0LjIwNzUgMTAuMDU4NiAxNC4wMDMxIDkuODU0MzEgMTQuMDAzMSA5LjYwMjI2VjYuNjA1MTRDMTQuMDAyOSA2LjYxNTc2IDE0LjAwMjcgNi42MjY0MSAxNC4wMDI3IDYuNjM3MDlWOS4yNzcwNUwxNC4wMDIyIDUuMDQ3NTJDMTQuMDAyMiA0Ljg2OTEzIDEzLjk2NDMgNC42OTk2IDEzLjg5NjEgNC41NDY1M0MxMy43MDY0IDQuMTIwNzIgMTMuMjgyMiAzLjgyMjM1IDEyLjc4NzYgMy44MTU0MUwxMi43NyAzLjgxNTI4QzEyLjY1ODQgMy44MTUyOCAxMi41NTA0IDMuODMwMSAxMi40NDc2IDMuODU3ODdaIiBmaWxsPSIjMUQxQzIzIi8+Cjwvc3ZnPg=="), auto',
|
|
1250
|
+
grabbing: 'url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMCAyMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02LjYxODE3IDUuNTk4NzVDNi42MTgxNyA0LjgxOTIgNy4yNTAxMiA0LjE4NzI2IDguMDI5NjcgNC4xODcyNkM4Ljc3ODczIDQuMTg3MjYgOS4zOTE1MiA0Ljc3MDc1IDkuNDM4MjkgNS41MDgwMUM5LjQ1OTkyIDQuOTQ3MSA5LjkyMTQ3IDQuNDk5MDIgMTAuNDg3NyA0LjQ5OTAyQzExLjA2NzcgNC40OTkwMiAxMS41Mzc4IDQuOTY5MiAxMS41Mzc4IDUuNTQ5MTlWOC43NjI0NkwxMS41Mzc5IDYuNzExNUMxMS41Mzc5IDYuMDMwOTUgMTIuMDg5NiA1LjQ3OTI2IDEyLjc3MDIgNS40NzkyNkMxMy40NTA3IDUuNDc5MjYgMTQuMDAyNCA2LjAzMDk1IDE0LjAwMjQgNi43MTE1TDE0LjAwMjQgOC43NjI0NkwxNC4wMDI5IDguMDE5ODNDMTQuMDAyOSA3LjMzOTI5IDE0LjU1NDYgNi43ODc1OSAxNS4yMzUyIDYuNzg3NTlDMTUuOTE1NyA2Ljc4NzU5IDE2LjQ2NzQgNy4zMzkyOCAxNi40Njc0IDguMDE5ODNWMTEuNDk3TDE2LjQ2NzUgMTIuNDQ2N0MxNi40Njc1IDE0LjA4MjEgMTUuODA5NiAxNS42NDg3IDE0LjY0MiAxNi43OTM4VjE3LjMyNjJDMTQuNjQyIDE3Ljc4NjQgMTQuMjY4OSAxOC4xNTk1IDEzLjgwODcgMTguMTU5NUg4LjE3MzE3QzcuNzEyOTMgMTguMTU5NSA3LjMzOTg0IDE3Ljc4NjQgNy4zMzk4NCAxNy4zMjYyVjE1Ljk0MjRMNS4zNDU2MiAxNC43NTM0QzQuNTg5MjQgMTQuMzAyNCA0LjEyNTkxIDEzLjQ4NjcgNC4xMjU4OSAxMi42MDYxTDQuMTI1ODMgOS4yODM4M0M0LjEyNTgyIDguOTU0MjcgNC4zMjAwMyA4LjY1NTY2IDQuNjIxMjkgOC41MjIwNUw2LjYxODE3IDcuNjM2MzRWNS41OTg3NVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuNDg3OCAzLjI0OTAyQzExLjI3OTYgMy4yNDkwMiAxMS45Nzc4IDMuNjQ5MDIgMTIuMzkxNyA0LjI1Nzk2QzEyLjUxNTEgNC4yMzkwNiAxMi42NDE2IDQuMjI5MjYgMTIuNzcwMyA0LjIyOTI2QzEzLjcyMjQgNC4yMjkyNiAxNC41NDkzIDQuNzY1MzEgMTQuOTY1NyA1LjU1MjA3QzE1LjA1NDMgNS41NDI1IDE1LjE0NDIgNS41Mzc1OSAxNS4yMzUzIDUuNTM3NTlDMTYuNjA2MiA1LjUzNzU5IDE3LjcxNzYgNi42NDg5MyAxNy43MTc2IDguMDE5ODNMMTcuNzE3NyAxMi40NDY3QzE3LjcxNzcgMTQuMjM1NSAxNy4wNjQ3IDE1Ljk1NTkgMTUuODkyMSAxNy4yOTA0VjE3LjMyNjJDMTUuODkyMSAxOC40NzY4IDE0Ljk1OTQgMTkuNDA5NSAxMy44MDg4IDE5LjQwOTVIOC4xNzMzMkM3LjAyMjczIDE5LjQwOTUgNi4wODk5OCAxOC40NzY4IDYuMDg5OTggMTcuMzI2MlYxNi42NTI0TDQuNzA1NjMgMTUuODI3QzMuNTcxMDYgMTUuMTUwNSAyLjg3NjA3IDEzLjkyNzEgMi44NzYwNCAxMi42MDYxTDIuODc1OTggOS4yODM4NUMyLjg3NTk2IDguNDU5OTYgMy4zNjE0OSA3LjcxMzQ1IDQuMTE0NjIgNy4zNzk0TDUuMzY4MzIgNi44MjMzM1Y1LjU5ODc1QzUuMzY4MzIgNC4xMjg4NSA2LjU1OTkxIDIuOTM3MjYgOC4wMjk4MiAyLjkzNzI2QzguNjA4MzEgMi45MzcyNiA5LjE0MzU1IDMuMTIxNyA5LjU4MDA1IDMuNDM1MDVDOS44NTg1MyAzLjMxNTMyIDEwLjE2NTQgMy4yNDkwMiAxMC40ODc4IDMuMjQ5MDJaTTEyLjQ0NzkgNS41MjE4NlY5LjQ3NTU3QzEyLjQ0NzkgOS43Mjc2MiAxMi4yNDM2IDkuOTMxOTUgMTEuOTkxNiA5LjkzMTk1QzExLjc1NjggOS45MzE5NSAxMS41NjM0IDkuNzU0NjUgMTEuNTM4IDkuNTI2NjNDMTEuNTM2MSA5LjUwOTg3IDExLjUzNTIgOS40OTI4MyAxMS41MzUyIDkuNDc1NTdWNS40NzE1OEMxMS41MTU0IDUuMjAwODMgMTEuMzkzIDQuOTU4NTggMTEuMjA2NiA0Ljc4MzU4QzExLjAxODggNC42MDcxMSAxMC43NjU5IDQuNDk5MDIgMTAuNDg3OCA0LjQ5OTAyQzEwLjQ3NjYgNC40OTkwMiAxMC40NjU0IDQuNDk5MTkgMTAuNDU0MiA0LjQ5OTU0QzkuOTAzNDcgNC41MTY4NCA5LjQ1OTY0IDQuOTU4MjQgOS40Mzg0NCA1LjUwODAxQzkuNDM4MiA1LjUwNDMgOS40Mzc5NSA1LjUwMDU4IDkuNDM3NjkgNS40OTY4OFY5LjkwMjQzQzkuNDM3NjkgMTAuMTU0NSA5LjIzMzM2IDEwLjM1ODggOC45ODEzMSAxMC4zNTg4QzguNzI5MjUgMTAuMzU4OCA4LjUyNDkyIDEwLjE1NDUgOC41MjQ5MiA5LjkwMjQzVjQuMjc2NTNDOC4zNzA4NiA0LjIxODgyIDguMjA0MDIgNC4xODcyNiA4LjAyOTgyIDQuMTg3MjZDNy4yNTAyNyA0LjE4NzI2IDYuNjE4MzIgNC44MTkyIDYuNjE4MzIgNS41OTg3NUw2LjYxODI3IDkuOTc1OTlDNi42MTgyNyAxMC4yMjggNi40MTM5NCAxMC40MzI0IDYuMTYxODkgMTAuNDMyNEM1LjkwOTgzIDEwLjQzMjQgNS43MDU1IDEwLjIyOCA1LjcwNTUgOS45NzU5OVY4LjA0MTIyTDQuNjIxNDQgOC41MjIwNUM0LjMyMDE4IDguNjU1NjYgNC4xMjU5NyA4Ljk1NDI3IDQuMTI1OTggOS4yODM4M0w0LjEyNjA0IDEyLjYwNjFDNC4xMjYwNiAxMy40ODY3IDQuNTg5MzkgMTQuMzAyNCA1LjM0NTc2IDE0Ljc1MzRMNy4zMzk5OCAxNS45NDI0VjE3LjMyNjJDNy4zMzk5OCAxNy43ODY0IDcuNzEzMDggMTguMTU5NSA4LjE3MzMyIDE4LjE1OTVIMTMuODA4OEMxNC4yNjkgMTguMTU5NSAxNC42NDIxIDE3Ljc4NjQgMTQuNjQyMSAxNy4zMjYyVjE2Ljc5MzhDMTUuNzM4MSAxNS43MTkgMTYuMzg1IDE0LjI3MjggMTYuNDYwMyAxMi43NDdDMTYuNDY0NiAxMi42NiAxNi40NjcgMTIuNTcyOCAxNi40Njc2IDEyLjQ4NTRMMTYuNDY3NyAxMi40NDY3TDE2LjQ2NzYgOC4wMTk4M0MxNi40Njc2IDcuMzQ1MDQgMTUuOTI1MiA2Ljc5NjkzIDE1LjI1MjUgNi43ODc3MUwxNS4yMzUzIDYuNzg3NTlDMTUuMTI1IDYuNzg3NTkgMTUuMDE4IDYuODAyMSAxNC45MTYyIDYuODI5MzFWOS42MDEzNkMxNC45MTYyIDkuODUzNDIgMTQuNzExOSAxMC4wNTc3IDE0LjQ1OTggMTAuMDU3N0MxNC4yMDc4IDEwLjA1NzcgMTQuMDAzNCA5Ljg1MzQxIDE0LjAwMzQgOS42MDEzNlY3Ljk4OTg1QzE0LjAwMzIgNy45OTk4MiAxNC4wMDMxIDguMDA5ODEgMTQuMDAzMSA4LjAxOTgzTDE0LjAwMzQgOS42MDEzNkwxNC4wMDI1IDYuNzExNUMxNC4wMDI1IDYuNDQ5NzQgMTMuOTIwOSA2LjIwNzA1IDEzLjc4MTggNi4wMDc0OEMxMy41NjIgNS42OTI0MiAxMy4xOTg5IDUuNDg0ODMgMTIuNzg3IDUuNDc5MzdMMTIuNzcwMyA1LjQ3OTI2QzEyLjY1ODggNS40NzkyNiAxMi41NTA3IDUuNDk0MDggMTIuNDQ3OSA1LjUyMTg2WiIgZmlsbD0iIzFEMUMyMyIvPgo8L3N2Zz4="), auto'
|
|
1251
|
+
},
|
|
1252
|
+
fromNodeJSON(node, json, isFirstCreate) {
|
|
1253
|
+
initFormDataFromJSON(node, json, isFirstCreate);
|
|
1254
|
+
return;
|
|
1255
|
+
},
|
|
1256
|
+
toNodeJSON(node) {
|
|
1257
|
+
const nodeError = node.getData(import_form_core2.FlowNodeErrorData)?.getError();
|
|
1258
|
+
if (nodeError) {
|
|
1259
|
+
throw nodeError;
|
|
1260
|
+
}
|
|
1261
|
+
const transform = node.getData(import_core11.TransformData);
|
|
1262
|
+
let formJSON = toFormJSON(node);
|
|
1263
|
+
const metaData = {};
|
|
1264
|
+
const nodeMeta = node.getNodeMeta();
|
|
1265
|
+
const subCanvas = nodeMeta.subCanvas?.(node);
|
|
1266
|
+
if (subCanvas?.isCanvas === false) {
|
|
1267
|
+
const canvasNodeTransform = subCanvas.canvasNode.getData(import_document4.FlowNodeTransformData);
|
|
1268
|
+
const { x, y } = canvasNodeTransform.transform.position;
|
|
1269
|
+
metaData.canvasPosition = { x, y };
|
|
1270
|
+
}
|
|
1271
|
+
const json = {
|
|
1272
|
+
id: node.id,
|
|
1273
|
+
type: node.flowNodeType,
|
|
1274
|
+
meta: {
|
|
1275
|
+
position: { x: transform.position.x, y: transform.position.y },
|
|
1276
|
+
...metaData
|
|
1277
|
+
},
|
|
1278
|
+
data: formJSON
|
|
1279
|
+
};
|
|
1280
|
+
return json;
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
|
|
1284
|
+
// src/workflow-lines-manager.ts
|
|
1285
|
+
var WorkflowLinesManager = class {
|
|
1286
|
+
constructor() {
|
|
1287
|
+
this.toDispose = new import_utils12.DisposableCollection();
|
|
1288
|
+
// 线条类型
|
|
1289
|
+
this._lineType = 0 /* BEZIER */;
|
|
1290
|
+
this.onAvailableLinesChangeEmitter = new import_utils12.Emitter();
|
|
1291
|
+
this.onForceUpdateEmitter = new import_utils12.Emitter();
|
|
1292
|
+
/**
|
|
1293
|
+
* 有效的线条被添加或者删除时候触发,未连上的线条不算
|
|
1294
|
+
*/
|
|
1295
|
+
this.onAvailableLinesChange = this.onAvailableLinesChangeEmitter.event;
|
|
1296
|
+
/**
|
|
1297
|
+
* 强制渲染 lines
|
|
1298
|
+
*/
|
|
1299
|
+
this.onForceUpdate = this.onForceUpdateEmitter.event;
|
|
1300
|
+
this.contributionFactories = [];
|
|
1301
|
+
/**
|
|
1302
|
+
* 是否在调整线条
|
|
1303
|
+
*/
|
|
1304
|
+
this.isDrawing = false;
|
|
1305
|
+
}
|
|
1306
|
+
init(doc) {
|
|
1307
|
+
this.document = doc;
|
|
1308
|
+
}
|
|
1309
|
+
forceUpdate() {
|
|
1310
|
+
this.onForceUpdateEmitter.fire();
|
|
1311
|
+
}
|
|
1312
|
+
get lineType() {
|
|
1313
|
+
return this._lineType;
|
|
1314
|
+
}
|
|
1315
|
+
get lineColor() {
|
|
1316
|
+
const color = {
|
|
1317
|
+
default: "var(--g-workflow-line-color-default,#4d53e8)" /* DEFUALT */,
|
|
1318
|
+
error: "var(--g-workflow-line-color-error,red)" /* ERROR */,
|
|
1319
|
+
hidden: "var(--g-workflow-line-color-hidden,transparent)" /* HIDDEN */,
|
|
1320
|
+
drawing: "var(--g-workflow-line-color-drawing, #5DD6E3)" /* DRAWING */,
|
|
1321
|
+
hovered: "var(--g-workflow-line-color-hover,#37d0ff)" /* HOVER */,
|
|
1322
|
+
selected: "var(--g-workflow-line-color-selected,#37d0ff)" /* SELECTED */,
|
|
1323
|
+
flowing: "var(--g-workflow-line-color-flowing,#4d53e8)" /* FLOWING */
|
|
1324
|
+
};
|
|
1325
|
+
if (this.options.lineColor) {
|
|
1326
|
+
Object.assign(color, this.options.lineColor);
|
|
1327
|
+
}
|
|
1328
|
+
return color;
|
|
1329
|
+
}
|
|
1330
|
+
switchLineType(newType) {
|
|
1331
|
+
if (newType === void 0) {
|
|
1332
|
+
if (this._lineType === 0 /* BEZIER */) {
|
|
1333
|
+
newType = 1 /* LINE_CHART */;
|
|
1334
|
+
} else {
|
|
1335
|
+
newType = 0 /* BEZIER */;
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
if (newType !== this._lineType) {
|
|
1339
|
+
this._lineType = newType;
|
|
1340
|
+
this.getAllLines().forEach((line) => {
|
|
1341
|
+
line.getData(WorkflowLineRenderData).update();
|
|
1342
|
+
});
|
|
1343
|
+
window.requestAnimationFrame(() => {
|
|
1344
|
+
this.entityManager.fireEntityChanged(WorkflowLineEntity.type);
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
return this._lineType;
|
|
1348
|
+
}
|
|
1349
|
+
getAllLines() {
|
|
1350
|
+
return this.entityManager.getEntities(WorkflowLineEntity);
|
|
1351
|
+
}
|
|
1352
|
+
hasLine(portInfo) {
|
|
1353
|
+
return !!this.entityManager.getEntityById(
|
|
1354
|
+
WorkflowLineEntity.portInfoToLineId(portInfo)
|
|
1355
|
+
);
|
|
1356
|
+
}
|
|
1357
|
+
getLine(portInfo) {
|
|
1358
|
+
return this.entityManager.getEntityById(
|
|
1359
|
+
WorkflowLineEntity.portInfoToLineId(portInfo)
|
|
1360
|
+
);
|
|
1361
|
+
}
|
|
1362
|
+
replaceLine(oldPortInfo, newPortInfo) {
|
|
1363
|
+
const oldLine = this.getLine(oldPortInfo);
|
|
1364
|
+
if (oldLine) {
|
|
1365
|
+
oldLine.dispose();
|
|
1366
|
+
}
|
|
1367
|
+
return this.createLine(newPortInfo);
|
|
1368
|
+
}
|
|
1369
|
+
createLine(options) {
|
|
1370
|
+
const { from, to, drawingTo, fromPort, toPort } = options;
|
|
1371
|
+
const available = Boolean(from && to);
|
|
1372
|
+
const key = options.key || WorkflowLineEntity.portInfoToLineId(options);
|
|
1373
|
+
let line = this.entityManager.getEntityById(key);
|
|
1374
|
+
if (line) {
|
|
1375
|
+
line.highlightColor = "";
|
|
1376
|
+
line.validate();
|
|
1377
|
+
return line;
|
|
1378
|
+
}
|
|
1379
|
+
const fromNode = this.entityManager.getEntityById(from)?.getData(WorkflowNodeLinesData);
|
|
1380
|
+
const toNode = to ? this.entityManager.getEntityById(to).getData(WorkflowNodeLinesData) : void 0;
|
|
1381
|
+
if (!fromNode) {
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
this.isDrawing = Boolean(drawingTo);
|
|
1385
|
+
line = this.entityManager.createEntity(WorkflowLineEntity, {
|
|
1386
|
+
id: key,
|
|
1387
|
+
document: this.document,
|
|
1388
|
+
linesManager: this,
|
|
1389
|
+
from,
|
|
1390
|
+
fromPort,
|
|
1391
|
+
toPort,
|
|
1392
|
+
to,
|
|
1393
|
+
drawingTo
|
|
1394
|
+
});
|
|
1395
|
+
this.registerData(line);
|
|
1396
|
+
fromNode.addLine(line);
|
|
1397
|
+
toNode?.addLine(line);
|
|
1398
|
+
line.onDispose(() => {
|
|
1399
|
+
if (drawingTo) {
|
|
1400
|
+
this.isDrawing = false;
|
|
1401
|
+
}
|
|
1402
|
+
fromNode.removeLine(line);
|
|
1403
|
+
toNode?.removeLine(line);
|
|
1404
|
+
line.validate();
|
|
1405
|
+
});
|
|
1406
|
+
line.onDispose(() => {
|
|
1407
|
+
if (available) {
|
|
1408
|
+
this.onAvailableLinesChangeEmitter.fire({
|
|
1409
|
+
type: "DELETE_LINE" /* DELETE_LINE */,
|
|
1410
|
+
toJSON: () => line.toJSON(),
|
|
1411
|
+
entity: line
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
});
|
|
1415
|
+
if (available) {
|
|
1416
|
+
this.onAvailableLinesChangeEmitter.fire({
|
|
1417
|
+
type: "ADD_LINE" /* ADD_LINE */,
|
|
1418
|
+
toJSON: () => line.toJSON(),
|
|
1419
|
+
entity: line
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
line.validate();
|
|
1423
|
+
return line;
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* 获取线条中距离鼠标位置最近的线条和距离
|
|
1427
|
+
* @param mousePos 鼠标位置
|
|
1428
|
+
* @param minDistance 最小检测距离
|
|
1429
|
+
* @returns 距离鼠标位置最近的线条 以及距离
|
|
1430
|
+
*/
|
|
1431
|
+
getCloseInLineFromMousePos(mousePos, minDistance = LINE_HOVER_DISTANCE) {
|
|
1432
|
+
let targetLine, targetLineDist;
|
|
1433
|
+
this.getAllLines().forEach((line) => {
|
|
1434
|
+
const dist = line.getHoverDist(mousePos);
|
|
1435
|
+
if (dist <= minDistance && (!targetLineDist || targetLineDist >= dist)) {
|
|
1436
|
+
targetLineDist = dist;
|
|
1437
|
+
targetLine = line;
|
|
1438
|
+
}
|
|
1439
|
+
});
|
|
1440
|
+
return targetLine;
|
|
1441
|
+
}
|
|
1442
|
+
dispose() {
|
|
1443
|
+
this.toDispose.dispose();
|
|
1444
|
+
}
|
|
1445
|
+
get disposed() {
|
|
1446
|
+
return this.toDispose.disposed;
|
|
1447
|
+
}
|
|
1448
|
+
isErrorLine(fromPort, toPort) {
|
|
1449
|
+
if (this.options.isErrorLine) {
|
|
1450
|
+
return this.options.isErrorLine(fromPort, toPort, this);
|
|
1451
|
+
}
|
|
1452
|
+
return false;
|
|
1453
|
+
}
|
|
1454
|
+
isReverseLine(line) {
|
|
1455
|
+
if (this.options.isReverseLine) {
|
|
1456
|
+
return this.options.isReverseLine(line);
|
|
1457
|
+
}
|
|
1458
|
+
return false;
|
|
1459
|
+
}
|
|
1460
|
+
isHideArrowLine(line) {
|
|
1461
|
+
if (this.options.isHideArrowLine) {
|
|
1462
|
+
return this.options.isHideArrowLine(line);
|
|
1463
|
+
}
|
|
1464
|
+
return false;
|
|
1465
|
+
}
|
|
1466
|
+
isFlowingLine(line) {
|
|
1467
|
+
if (this.options.isFlowingLine) {
|
|
1468
|
+
return this.options.isFlowingLine(line);
|
|
1469
|
+
}
|
|
1470
|
+
return false;
|
|
1471
|
+
}
|
|
1472
|
+
isDisabledLine(line) {
|
|
1473
|
+
if (this.options.isDisabledLine) {
|
|
1474
|
+
return this.options.isDisabledLine(line);
|
|
1475
|
+
}
|
|
1476
|
+
return false;
|
|
1477
|
+
}
|
|
1478
|
+
isVerticalLine(line) {
|
|
1479
|
+
if (this.options.isVerticalLine) {
|
|
1480
|
+
return this.options.isVerticalLine(line);
|
|
1481
|
+
}
|
|
1482
|
+
return false;
|
|
1483
|
+
}
|
|
1484
|
+
setLineRenderType(line) {
|
|
1485
|
+
if (this.options.setLineRenderType) {
|
|
1486
|
+
return this.options.setLineRenderType(line);
|
|
1487
|
+
}
|
|
1488
|
+
return void 0;
|
|
1489
|
+
}
|
|
1490
|
+
setLineClassName(line) {
|
|
1491
|
+
if (this.options.setLineClassName) {
|
|
1492
|
+
return this.options.setLineClassName(line);
|
|
1493
|
+
}
|
|
1494
|
+
return void 0;
|
|
1495
|
+
}
|
|
1496
|
+
getLineColor(line) {
|
|
1497
|
+
if (line.isHidden) {
|
|
1498
|
+
return this.lineColor.hidden;
|
|
1499
|
+
}
|
|
1500
|
+
if (line.hasError) {
|
|
1501
|
+
return this.lineColor.error;
|
|
1502
|
+
}
|
|
1503
|
+
if (line.highlightColor) {
|
|
1504
|
+
return line.highlightColor;
|
|
1505
|
+
}
|
|
1506
|
+
if (line.drawingTo) {
|
|
1507
|
+
return this.lineColor.drawing;
|
|
1508
|
+
}
|
|
1509
|
+
if (this.hoverService.isHovered(line.id)) {
|
|
1510
|
+
return this.lineColor.hovered;
|
|
1511
|
+
}
|
|
1512
|
+
if (this.selectService.isSelected(line.id)) {
|
|
1513
|
+
return this.lineColor.selected;
|
|
1514
|
+
}
|
|
1515
|
+
if (this.isFlowingLine(line)) {
|
|
1516
|
+
return this.lineColor.flowing;
|
|
1517
|
+
}
|
|
1518
|
+
return this.lineColor.default;
|
|
1519
|
+
}
|
|
1520
|
+
canAddLine(fromPort, toPort, silent) {
|
|
1521
|
+
if (fromPort === toPort || fromPort.node === toPort.node || fromPort.portType !== "output" || toPort.portType !== "input" || toPort.disabled) {
|
|
1522
|
+
return false;
|
|
1523
|
+
}
|
|
1524
|
+
if (this.options.canAddLine) {
|
|
1525
|
+
return this.options.canAddLine(fromPort, toPort, this, silent);
|
|
1526
|
+
}
|
|
1527
|
+
return fromPort.node !== toPort.node;
|
|
1528
|
+
}
|
|
1529
|
+
toJSON() {
|
|
1530
|
+
return this.getAllLines().filter((l) => !l.isDrawing).map((l) => l.toJSON());
|
|
1531
|
+
}
|
|
1532
|
+
getPortById(portId) {
|
|
1533
|
+
return this.entityManager.getEntityById(portId);
|
|
1534
|
+
}
|
|
1535
|
+
canRemove(line, newLineInfo, silent) {
|
|
1536
|
+
if (this.options && this.options.canDeleteLine && !this.options.canDeleteLine(line, newLineInfo, silent)) {
|
|
1537
|
+
return false;
|
|
1538
|
+
}
|
|
1539
|
+
return true;
|
|
1540
|
+
}
|
|
1541
|
+
canReset(fromPort, oldToPort, newToPort) {
|
|
1542
|
+
if (this.options && this.options.canResetLine && !this.options.canResetLine(fromPort, oldToPort, newToPort, this)) {
|
|
1543
|
+
return false;
|
|
1544
|
+
}
|
|
1545
|
+
return true;
|
|
1546
|
+
}
|
|
1547
|
+
/**
|
|
1548
|
+
* 根据鼠标位置找到 port
|
|
1549
|
+
* @param pos
|
|
1550
|
+
*/
|
|
1551
|
+
getPortFromMousePos(pos) {
|
|
1552
|
+
const allNodes = this.getSortedNodes().reverse();
|
|
1553
|
+
const allPorts = allNodes.map((node) => node.getData(WorkflowNodePortsData).allPorts).flat();
|
|
1554
|
+
const targetPort = allPorts.find((port) => port.isHovered(pos.x, pos.y));
|
|
1555
|
+
if (targetPort) {
|
|
1556
|
+
const containNodes = this.getContainNodesFromMousePos(pos);
|
|
1557
|
+
const targetNode = (0, import_lodash_es3.last)(containNodes);
|
|
1558
|
+
if (targetNode && targetNode !== targetPort.node) {
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
return targetPort;
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* 根据鼠标位置找到 node
|
|
1566
|
+
* @param pos - 鼠标位置
|
|
1567
|
+
*/
|
|
1568
|
+
getNodeFromMousePos(pos) {
|
|
1569
|
+
const { selection } = this.selectService;
|
|
1570
|
+
const containNodes = this.getContainNodesFromMousePos(pos);
|
|
1571
|
+
if (selection?.length) {
|
|
1572
|
+
const filteredNodes = containNodes.filter(
|
|
1573
|
+
(node) => selection.some((_node) => node.id === _node.id)
|
|
1574
|
+
);
|
|
1575
|
+
if (filteredNodes?.length) {
|
|
1576
|
+
return (0, import_lodash_es3.last)(filteredNodes);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
return (0, import_lodash_es3.last)(containNodes);
|
|
1580
|
+
}
|
|
1581
|
+
registerContribution(factory) {
|
|
1582
|
+
this.contributionFactories.push(factory);
|
|
1583
|
+
return this;
|
|
1584
|
+
}
|
|
1585
|
+
registerData(line) {
|
|
1586
|
+
line.addData(WorkflowLineRenderData);
|
|
1587
|
+
}
|
|
1588
|
+
getSortedNodes() {
|
|
1589
|
+
return this.document.getAllNodes().sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));
|
|
1590
|
+
}
|
|
1591
|
+
/** 获取鼠标坐标位置的所有节点(stackIndex 从小到大排序) */
|
|
1592
|
+
getContainNodesFromMousePos(pos) {
|
|
1593
|
+
const allNodes = this.getSortedNodes();
|
|
1594
|
+
const zoom = this.entityManager.getEntity(import_core12.PlaygroundConfigEntity)?.config?.zoom || 1;
|
|
1595
|
+
const containNodes = allNodes.map((node) => {
|
|
1596
|
+
const { bounds } = node.getData(import_document5.FlowNodeTransformData);
|
|
1597
|
+
if (bounds.clone().pad(4 / zoom).contains(pos.x, pos.y)) {
|
|
1598
|
+
return node;
|
|
1599
|
+
}
|
|
1600
|
+
}).filter(Boolean);
|
|
1601
|
+
return containNodes;
|
|
1602
|
+
}
|
|
1603
|
+
getNodeIndex(node) {
|
|
1604
|
+
const nodeRenderData = node.getData(import_document5.FlowNodeRenderData);
|
|
1605
|
+
return nodeRenderData.stackIndex;
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
1608
|
+
__decorateClass([
|
|
1609
|
+
(0, import_inversify3.inject)(WorkflowHoverService)
|
|
1610
|
+
], WorkflowLinesManager.prototype, "hoverService", 2);
|
|
1611
|
+
__decorateClass([
|
|
1612
|
+
(0, import_inversify3.inject)(WorkflowSelectService)
|
|
1613
|
+
], WorkflowLinesManager.prototype, "selectService", 2);
|
|
1614
|
+
__decorateClass([
|
|
1615
|
+
(0, import_inversify3.inject)(import_core12.EntityManager)
|
|
1616
|
+
], WorkflowLinesManager.prototype, "entityManager", 2);
|
|
1617
|
+
__decorateClass([
|
|
1618
|
+
(0, import_inversify3.inject)(WorkflowDocumentOptions)
|
|
1619
|
+
], WorkflowLinesManager.prototype, "options", 2);
|
|
1620
|
+
WorkflowLinesManager = __decorateClass([
|
|
1621
|
+
(0, import_inversify3.injectable)()
|
|
1622
|
+
], WorkflowLinesManager);
|
|
1623
|
+
|
|
1624
|
+
// src/workflow-document.ts
|
|
1625
|
+
var import_nanoid2 = require("nanoid");
|
|
1626
|
+
var import_inversify5 = require("inversify");
|
|
1627
|
+
var import_utils14 = require("@flowgram.ai/utils");
|
|
1628
|
+
var import_form_core3 = require("@flowgram.ai/form-core");
|
|
1629
|
+
var import_document7 = require("@flowgram.ai/document");
|
|
1630
|
+
var import_core14 = require("@flowgram.ai/core");
|
|
1631
|
+
|
|
1632
|
+
// src/layout/free-layout.ts
|
|
1633
|
+
var import_inversify4 = require("inversify");
|
|
1634
|
+
var import_utils13 = require("@flowgram.ai/utils");
|
|
1635
|
+
var import_document6 = require("@flowgram.ai/document");
|
|
1636
|
+
var import_core13 = require("@flowgram.ai/core");
|
|
1637
|
+
var FREE_LAYOUT_KEY = "free-layout";
|
|
1638
|
+
var FreeLayout = class {
|
|
1639
|
+
constructor() {
|
|
1640
|
+
this.name = FREE_LAYOUT_KEY;
|
|
1641
|
+
}
|
|
1642
|
+
get document() {
|
|
1643
|
+
return this.documentProvider();
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1646
|
+
* 更新布局
|
|
1647
|
+
*/
|
|
1648
|
+
update() {
|
|
1649
|
+
if (this.document.root.getData(import_document6.FlowNodeTransformData)?.localDirty) {
|
|
1650
|
+
this.document.root.clearMemoGlobal();
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
syncTransform(node) {
|
|
1654
|
+
const transform = node.getData(import_document6.FlowNodeTransformData);
|
|
1655
|
+
if (!transform.localDirty) {
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1658
|
+
node.clearMemoGlobal();
|
|
1659
|
+
node.clearMemoLocal();
|
|
1660
|
+
transform.transform.update({
|
|
1661
|
+
size: transform.data.size
|
|
1662
|
+
});
|
|
1663
|
+
if (!node.parent) {
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
node.parent.clearMemoGlobal();
|
|
1667
|
+
node.parent.clearMemoLocal();
|
|
1668
|
+
const parentTransform = node.parent.getData(import_document6.FlowNodeTransformData);
|
|
1669
|
+
parentTransform.transform.fireChange();
|
|
1670
|
+
}
|
|
1671
|
+
/**
|
|
1672
|
+
* 更新所有受影响的上下游节点
|
|
1673
|
+
*/
|
|
1674
|
+
updateAffectedTransform(node) {
|
|
1675
|
+
const transformData = node.transform;
|
|
1676
|
+
if (!transformData.localDirty) {
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1679
|
+
const allParents = this.getAllParents(node);
|
|
1680
|
+
const allBlocks = this.getAllBlocks(node).reverse();
|
|
1681
|
+
const affectedNodes = [...allBlocks, ...allParents];
|
|
1682
|
+
affectedNodes.forEach((node2) => {
|
|
1683
|
+
this.fireChange(node2);
|
|
1684
|
+
});
|
|
1685
|
+
}
|
|
1686
|
+
/**
|
|
1687
|
+
* 获取节点的 padding 数据
|
|
1688
|
+
* @param node
|
|
1689
|
+
*/
|
|
1690
|
+
getPadding(node) {
|
|
1691
|
+
const { padding } = node.getNodeMeta();
|
|
1692
|
+
const transform = node.getData(import_document6.FlowNodeTransformData);
|
|
1693
|
+
if (padding) {
|
|
1694
|
+
return typeof padding === "function" ? padding(transform) : padding;
|
|
1695
|
+
}
|
|
1696
|
+
return import_utils13.PaddingSchema.empty();
|
|
1697
|
+
}
|
|
1698
|
+
/**
|
|
1699
|
+
* 默认滚动到 fitview 区域
|
|
1700
|
+
* @param contentSize
|
|
1701
|
+
*/
|
|
1702
|
+
getInitScroll(contentSize) {
|
|
1703
|
+
const bounds = import_utils13.Rectangle.enlarge(
|
|
1704
|
+
this.document.getAllNodes().map((node) => node.getData(import_core13.TransformData).bounds)
|
|
1705
|
+
).pad(30, 30);
|
|
1706
|
+
const viewport = this.playgroundConfig.getViewport(false);
|
|
1707
|
+
const zoom = import_utils13.SizeSchema.fixSize(bounds, viewport);
|
|
1708
|
+
return {
|
|
1709
|
+
scrollX: (bounds.x + bounds.width / 2) * zoom - this.playgroundConfig.config.width / 2,
|
|
1710
|
+
scrollY: (bounds.y + bounds.height / 2) * zoom - this.playgroundConfig.config.height / 2
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
/**
|
|
1714
|
+
* 获取默认输入点
|
|
1715
|
+
*/
|
|
1716
|
+
getDefaultInputPoint(node) {
|
|
1717
|
+
return node.getData(import_core13.TransformData).bounds.leftCenter;
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* 获取默认输出点
|
|
1721
|
+
*/
|
|
1722
|
+
getDefaultOutputPoint(node) {
|
|
1723
|
+
return node.getData(import_core13.TransformData).bounds.rightCenter;
|
|
1724
|
+
}
|
|
1725
|
+
/**
|
|
1726
|
+
* 水平中心点
|
|
1727
|
+
*/
|
|
1728
|
+
getDefaultNodeOrigin() {
|
|
1729
|
+
return { x: 0.5, y: 0 };
|
|
1730
|
+
}
|
|
1731
|
+
getAllParents(node) {
|
|
1732
|
+
const parents = [];
|
|
1733
|
+
let current = node.parent;
|
|
1734
|
+
while (current) {
|
|
1735
|
+
parents.push(current);
|
|
1736
|
+
current = current.parent;
|
|
1737
|
+
}
|
|
1738
|
+
return parents;
|
|
1739
|
+
}
|
|
1740
|
+
getAllBlocks(node) {
|
|
1741
|
+
return node.blocks.reduce(
|
|
1742
|
+
(acc, child) => [...acc, ...this.getAllBlocks(child)],
|
|
1743
|
+
[node]
|
|
1744
|
+
);
|
|
1745
|
+
}
|
|
1746
|
+
fireChange(node) {
|
|
1747
|
+
const transformData = node?.transform;
|
|
1748
|
+
if (!node || !transformData?.localDirty) {
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1751
|
+
node.clearMemoGlobal();
|
|
1752
|
+
node.clearMemoLocal();
|
|
1753
|
+
transformData.transform.fireChange();
|
|
1754
|
+
}
|
|
1755
|
+
};
|
|
1756
|
+
__decorateClass([
|
|
1757
|
+
(0, import_inversify4.inject)(import_core13.PlaygroundConfigEntity)
|
|
1758
|
+
], FreeLayout.prototype, "playgroundConfig", 2);
|
|
1759
|
+
__decorateClass([
|
|
1760
|
+
(0, import_inversify4.inject)(import_document6.FlowDocumentProvider)
|
|
1761
|
+
], FreeLayout.prototype, "documentProvider", 2);
|
|
1762
|
+
FreeLayout = __decorateClass([
|
|
1763
|
+
(0, import_inversify4.injectable)()
|
|
1764
|
+
], FreeLayout);
|
|
1765
|
+
|
|
1766
|
+
// src/workflow-document.ts
|
|
1767
|
+
var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890", 5);
|
|
1768
|
+
var WorkflowDocumentProvider = Symbol("WorkflowDocumentProvider");
|
|
1769
|
+
var WorkflowDocument = class extends import_document7.FlowDocument {
|
|
1770
|
+
constructor() {
|
|
1771
|
+
super(...arguments);
|
|
1772
|
+
this._onContentChangeEmitter = new import_utils14.Emitter();
|
|
1773
|
+
this.onLoadedEmitter = new import_utils14.Emitter();
|
|
1774
|
+
this.onContentChange = this._onContentChangeEmitter.event;
|
|
1775
|
+
this._onReloadEmitter = new import_utils14.Emitter();
|
|
1776
|
+
this.onReload = this._onReloadEmitter.event;
|
|
1777
|
+
/**
|
|
1778
|
+
* 数据加载完成
|
|
1779
|
+
*/
|
|
1780
|
+
this.onLoaded = this.onLoadedEmitter.event;
|
|
1781
|
+
this._loading = false;
|
|
1782
|
+
this.options = {};
|
|
1783
|
+
}
|
|
1784
|
+
get loading() {
|
|
1785
|
+
return this._loading;
|
|
1786
|
+
}
|
|
1787
|
+
async fitView(easing) {
|
|
1788
|
+
return fitView(this, this.playgroundConfig, easing).then(() => {
|
|
1789
|
+
this.linesManager.forceUpdate();
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
init() {
|
|
1793
|
+
super.init();
|
|
1794
|
+
this.currentLayoutKey = this.options.defaultLayout || FREE_LAYOUT_KEY;
|
|
1795
|
+
this.linesManager.init(this);
|
|
1796
|
+
this.playgroundConfig.getCursors = () => this.options.cursors;
|
|
1797
|
+
this.linesManager.onAvailableLinesChange((e) => this.fireContentChange(e));
|
|
1798
|
+
this.playgroundConfig.onReadonlyOrDisabledChange(({ readonly }) => {
|
|
1799
|
+
if (this.nodeEngineContext) {
|
|
1800
|
+
this.nodeEngineContext.readonly = readonly;
|
|
1801
|
+
}
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
async load() {
|
|
1805
|
+
if (this.disposed) return;
|
|
1806
|
+
this._loading = true;
|
|
1807
|
+
await super.load();
|
|
1808
|
+
this._loading = false;
|
|
1809
|
+
this.onLoadedEmitter.fire();
|
|
1810
|
+
}
|
|
1811
|
+
async reload(json, delayTime = 0) {
|
|
1812
|
+
if (this.disposed) return;
|
|
1813
|
+
this._loading = true;
|
|
1814
|
+
this.clear();
|
|
1815
|
+
this.fromJSON(json);
|
|
1816
|
+
await (0, import_utils4.delay)(delayTime);
|
|
1817
|
+
this._loading = false;
|
|
1818
|
+
this._onReloadEmitter.fire(this);
|
|
1819
|
+
}
|
|
1820
|
+
/**
|
|
1821
|
+
* 从数据加载
|
|
1822
|
+
* @param json
|
|
1823
|
+
*/
|
|
1824
|
+
fromJSON(json, fireRender = true) {
|
|
1825
|
+
if (this.disposed) return;
|
|
1826
|
+
const workflowJSON = {
|
|
1827
|
+
nodes: json.nodes ?? [],
|
|
1828
|
+
edges: json.edges ?? []
|
|
1829
|
+
};
|
|
1830
|
+
this.entityManager.changeEntityLocked = true;
|
|
1831
|
+
this.renderJSON(workflowJSON);
|
|
1832
|
+
this.entityManager.changeEntityLocked = false;
|
|
1833
|
+
this.transformer.loading = false;
|
|
1834
|
+
if (fireRender) {
|
|
1835
|
+
this.fireRender();
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
/**
|
|
1839
|
+
* 清空画布
|
|
1840
|
+
*/
|
|
1841
|
+
clear() {
|
|
1842
|
+
this.getAllNodes().map((node) => node.dispose());
|
|
1843
|
+
this.linesManager.getAllLines().map((line) => line.dispose());
|
|
1844
|
+
this.getAllPorts().map((port) => port.dispose());
|
|
1845
|
+
this.selectServices.clear();
|
|
1846
|
+
}
|
|
1847
|
+
/**
|
|
1848
|
+
* 创建流程节点
|
|
1849
|
+
* @param json
|
|
1850
|
+
*/
|
|
1851
|
+
createWorkflowNode(json, isClone = false, parentId) {
|
|
1852
|
+
const isExistedNode = this.getNode(json.id);
|
|
1853
|
+
const parent = this.getNode(parentId ?? this.root.id) ?? this.root;
|
|
1854
|
+
const node = this.addNode(
|
|
1855
|
+
{
|
|
1856
|
+
...json,
|
|
1857
|
+
parent
|
|
1858
|
+
},
|
|
1859
|
+
void 0,
|
|
1860
|
+
true
|
|
1861
|
+
);
|
|
1862
|
+
const registry = node.getNodeRegistry();
|
|
1863
|
+
const { formMeta } = registry;
|
|
1864
|
+
const meta = node.getNodeMeta();
|
|
1865
|
+
const formData = getFlowNodeFormData(node);
|
|
1866
|
+
const transform = node.getData(import_document7.FlowNodeTransformData);
|
|
1867
|
+
const freeLayout = this.layout;
|
|
1868
|
+
if (!isExistedNode) {
|
|
1869
|
+
transform.onDataChange(() => {
|
|
1870
|
+
freeLayout.syncTransform(node);
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
let { position } = meta;
|
|
1874
|
+
if (!position) {
|
|
1875
|
+
position = this.getNodeDefaultPosition(json.type);
|
|
1876
|
+
}
|
|
1877
|
+
node.getData(import_core14.TransformData).update({
|
|
1878
|
+
position
|
|
1879
|
+
});
|
|
1880
|
+
if (formMeta && formData && !formData.formModel.initialized) {
|
|
1881
|
+
formData.createForm(formMeta, json.data);
|
|
1882
|
+
formData.onDataChange(() => {
|
|
1883
|
+
this.fireContentChange({
|
|
1884
|
+
type: "NODE_DATA_CHANGE" /* NODE_DATA_CHANGE */,
|
|
1885
|
+
toJSON: () => formData.toJSON(),
|
|
1886
|
+
entity: node
|
|
1887
|
+
});
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
const positionData = node.getData(import_core14.PositionData);
|
|
1891
|
+
if (!isExistedNode) {
|
|
1892
|
+
positionData.onDataChange(() => {
|
|
1893
|
+
this.fireContentChange({
|
|
1894
|
+
type: "MOVE_NODE" /* MOVE_NODE */,
|
|
1895
|
+
toJSON: () => positionData.toJSON(),
|
|
1896
|
+
entity: node
|
|
1897
|
+
});
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
const subCanvas = this.getNodeSubCanvas(node);
|
|
1901
|
+
if (!isExistedNode && !subCanvas?.isCanvas) {
|
|
1902
|
+
this.fireContentChange({
|
|
1903
|
+
type: "ADD_NODE" /* ADD_NODE */,
|
|
1904
|
+
entity: node,
|
|
1905
|
+
toJSON: () => this.toNodeJSON(node)
|
|
1906
|
+
});
|
|
1907
|
+
node.onDispose(() => {
|
|
1908
|
+
if (!node.parent || node.parent.flowNodeType === import_document7.FlowNodeBaseType.ROOT) {
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
const parentTransform = node.parent.getData(import_document7.FlowNodeTransformData);
|
|
1912
|
+
parentTransform.fireChange();
|
|
1913
|
+
});
|
|
1914
|
+
let lastDeleteNodeData;
|
|
1915
|
+
node.preDispose.onDispose(() => {
|
|
1916
|
+
lastDeleteNodeData = this.toNodeJSON(node);
|
|
1917
|
+
});
|
|
1918
|
+
node.onDispose(() => {
|
|
1919
|
+
this.fireContentChange({
|
|
1920
|
+
type: "DELETE_NODE" /* DELETE_NODE */,
|
|
1921
|
+
entity: node,
|
|
1922
|
+
toJSON: () => lastDeleteNodeData
|
|
1923
|
+
});
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
if (json.blocks) {
|
|
1927
|
+
this.renderJSON(
|
|
1928
|
+
{ nodes: json.blocks, edges: json.edges ?? [] },
|
|
1929
|
+
{
|
|
1930
|
+
parent: node,
|
|
1931
|
+
isClone
|
|
1932
|
+
}
|
|
1933
|
+
);
|
|
1934
|
+
}
|
|
1935
|
+
if (subCanvas) {
|
|
1936
|
+
const canvasTransform = subCanvas.canvasNode.getData(import_core14.TransformData);
|
|
1937
|
+
canvasTransform.update({
|
|
1938
|
+
position: subCanvas.parentNode.getNodeMeta()?.canvasPosition
|
|
1939
|
+
});
|
|
1940
|
+
if (!isExistedNode) {
|
|
1941
|
+
subCanvas.parentNode.onDispose(() => {
|
|
1942
|
+
subCanvas.canvasNode.dispose();
|
|
1943
|
+
});
|
|
1944
|
+
subCanvas.canvasNode.onDispose(() => {
|
|
1945
|
+
subCanvas.parentNode.dispose();
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
if (!isExistedNode) {
|
|
1950
|
+
this.onNodeCreateEmitter.fire({
|
|
1951
|
+
node,
|
|
1952
|
+
data: json,
|
|
1953
|
+
json
|
|
1954
|
+
});
|
|
1955
|
+
} else {
|
|
1956
|
+
this.onNodeUpdateEmitter.fire({
|
|
1957
|
+
node,
|
|
1958
|
+
data: json,
|
|
1959
|
+
json
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1962
|
+
return node;
|
|
1963
|
+
}
|
|
1964
|
+
/**
|
|
1965
|
+
* 添加节点,如果节点已经存在则不会重复创建
|
|
1966
|
+
* @param data
|
|
1967
|
+
* @param addedNodes
|
|
1968
|
+
*/
|
|
1969
|
+
addNode(data, addedNodes, ignoreCreateAndUpdateEvent) {
|
|
1970
|
+
const { id, type = "block", originParent, parent, meta, hidden, index } = data;
|
|
1971
|
+
let node = this.getNode(id);
|
|
1972
|
+
let isNew = false;
|
|
1973
|
+
const register = this.getNodeRegistry(type, data.originParent);
|
|
1974
|
+
if (node && node.flowNodeType !== data.type) {
|
|
1975
|
+
node.dispose();
|
|
1976
|
+
node = void 0;
|
|
1977
|
+
}
|
|
1978
|
+
if (!node) {
|
|
1979
|
+
const { dataRegistries } = register;
|
|
1980
|
+
node = this.entityManager.createEntity(WorkflowNodeEntity, {
|
|
1981
|
+
id,
|
|
1982
|
+
document: this,
|
|
1983
|
+
flowNodeType: type,
|
|
1984
|
+
originParent,
|
|
1985
|
+
meta
|
|
1986
|
+
});
|
|
1987
|
+
const datas = dataRegistries ? this.nodeDataRegistries.concat(...dataRegistries) : this.nodeDataRegistries;
|
|
1988
|
+
node.addInitializeData(datas);
|
|
1989
|
+
node.onDispose(() => this.onNodeDisposeEmitter.fire({ node }));
|
|
1990
|
+
this.options.fromNodeJSON?.(node, data, true);
|
|
1991
|
+
isNew = true;
|
|
1992
|
+
} else {
|
|
1993
|
+
this.options.fromNodeJSON?.(node, data, false);
|
|
1994
|
+
}
|
|
1995
|
+
node.initData({
|
|
1996
|
+
originParent,
|
|
1997
|
+
parent,
|
|
1998
|
+
meta,
|
|
1999
|
+
hidden,
|
|
2000
|
+
index
|
|
2001
|
+
});
|
|
2002
|
+
addedNodes?.push(node);
|
|
2003
|
+
if (register.onCreate) {
|
|
2004
|
+
const extendNodes = register.onCreate(node, data);
|
|
2005
|
+
if (extendNodes && addedNodes) {
|
|
2006
|
+
addedNodes.push(...extendNodes);
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
if (!ignoreCreateAndUpdateEvent) {
|
|
2010
|
+
if (isNew) {
|
|
2011
|
+
this.onNodeCreateEmitter.fire({
|
|
2012
|
+
node,
|
|
2013
|
+
data,
|
|
2014
|
+
json: data
|
|
2015
|
+
});
|
|
2016
|
+
} else {
|
|
2017
|
+
this.onNodeUpdateEmitter.fire({ node, data, json: data });
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
return node;
|
|
2021
|
+
}
|
|
2022
|
+
get layout() {
|
|
2023
|
+
const layout = this.layouts.find((layout2) => layout2.name == this.currentLayoutKey);
|
|
2024
|
+
if (!layout) {
|
|
2025
|
+
throw new Error(`Unknown flow layout: ${this.currentLayoutKey}`);
|
|
2026
|
+
}
|
|
2027
|
+
return layout;
|
|
2028
|
+
}
|
|
2029
|
+
/**
|
|
2030
|
+
* 获取默认的 x y 坐标, 默认为当前画布可视区域中心
|
|
2031
|
+
* @param type
|
|
2032
|
+
* @protected
|
|
2033
|
+
*/
|
|
2034
|
+
getNodeDefaultPosition(type) {
|
|
2035
|
+
const { size } = this.getNodeRegistry(type).meta || {};
|
|
2036
|
+
let position = this.playgroundConfig.getViewport(true).center;
|
|
2037
|
+
if (size) {
|
|
2038
|
+
position = {
|
|
2039
|
+
x: position.x,
|
|
2040
|
+
y: position.y - size.height / 2
|
|
2041
|
+
};
|
|
2042
|
+
}
|
|
2043
|
+
return getAntiOverlapPosition(this, position);
|
|
2044
|
+
}
|
|
2045
|
+
/**
|
|
2046
|
+
* 通过类型创建节点, 如果没有提供position 则直接放在画布中间
|
|
2047
|
+
* @param type
|
|
2048
|
+
*/
|
|
2049
|
+
createWorkflowNodeByType(type, position, json = {}, parentID) {
|
|
2050
|
+
let id = json.id;
|
|
2051
|
+
if (id === void 0) {
|
|
2052
|
+
do {
|
|
2053
|
+
id = `1${nanoid2()}`;
|
|
2054
|
+
} while (this.entityManager.getEntityById(id));
|
|
2055
|
+
} else {
|
|
2056
|
+
if (this.entityManager.getEntityById(id)) {
|
|
2057
|
+
throw new Error(`[WorkflowDocument.createWorkflowNodeByType] Node Id "${id}" duplicated.`);
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
return this.createWorkflowNode(
|
|
2061
|
+
{
|
|
2062
|
+
...json,
|
|
2063
|
+
id,
|
|
2064
|
+
type,
|
|
2065
|
+
meta: { position, ...json?.meta },
|
|
2066
|
+
// TODO title 和 meta 要从注册数据去拿
|
|
2067
|
+
data: json?.data,
|
|
2068
|
+
blocks: json?.blocks,
|
|
2069
|
+
edges: json?.edges
|
|
2070
|
+
},
|
|
2071
|
+
false,
|
|
2072
|
+
parentID
|
|
2073
|
+
);
|
|
2074
|
+
}
|
|
2075
|
+
getAllNodes() {
|
|
2076
|
+
return this.entityManager.getEntities(WorkflowNodeEntity).filter((n) => n.id !== import_document7.FlowNodeBaseType.ROOT);
|
|
2077
|
+
}
|
|
2078
|
+
getAllPorts() {
|
|
2079
|
+
return this.entityManager.getEntities(WorkflowPortEntity).filter((p) => p.node.id !== import_document7.FlowNodeBaseType.ROOT);
|
|
2080
|
+
}
|
|
2081
|
+
/**
|
|
2082
|
+
* 获取画布中的非游离节点
|
|
2083
|
+
* 1. 开始节点
|
|
2084
|
+
* 2. 从开始节点出发能走到的节点
|
|
2085
|
+
* 3. 结束节点
|
|
2086
|
+
* 4. 默认所有子画布内节点为游离节点
|
|
2087
|
+
*/
|
|
2088
|
+
getAssociatedNodes() {
|
|
2089
|
+
const allNode = this.getAllNodes();
|
|
2090
|
+
const allLines = this.linesManager.getAllLines().filter((line) => line.from && line.to).map((line) => ({
|
|
2091
|
+
from: line.from.id,
|
|
2092
|
+
to: line.to.id
|
|
2093
|
+
}));
|
|
2094
|
+
const startNodeId = allNode.find((node) => node.isStart).id;
|
|
2095
|
+
const endNodeId = allNode.find((node) => node.isNodeEnd).id;
|
|
2096
|
+
const nodeInContainer = allNode.filter((node) => node.parent?.getNodeMeta().isContainer).map((node) => node.id);
|
|
2097
|
+
const associatedCache = /* @__PURE__ */ new Set([endNodeId, ...nodeInContainer]);
|
|
2098
|
+
const bfs = (nodeId) => {
|
|
2099
|
+
if (associatedCache.has(nodeId)) {
|
|
2100
|
+
return;
|
|
2101
|
+
}
|
|
2102
|
+
associatedCache.add(nodeId);
|
|
2103
|
+
const nextNodes = allLines.reduce((ids, { from, to }) => {
|
|
2104
|
+
if (from === nodeId && !associatedCache.has(to)) {
|
|
2105
|
+
ids.push(to);
|
|
2106
|
+
}
|
|
2107
|
+
return ids;
|
|
2108
|
+
}, []);
|
|
2109
|
+
nextNodes.forEach(bfs);
|
|
2110
|
+
};
|
|
2111
|
+
bfs(startNodeId);
|
|
2112
|
+
const associatedNodes = allNode.filter((node) => associatedCache.has(node.id));
|
|
2113
|
+
return associatedNodes;
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* 触发渲染
|
|
2117
|
+
*/
|
|
2118
|
+
fireRender() {
|
|
2119
|
+
this.entityManager.fireEntityChanged(WorkflowNodeEntity.type);
|
|
2120
|
+
this.entityManager.fireEntityChanged(WorkflowLineEntity.type);
|
|
2121
|
+
this.entityManager.fireEntityChanged(WorkflowPortEntity.type);
|
|
2122
|
+
}
|
|
2123
|
+
fireContentChange(event) {
|
|
2124
|
+
if (this._loading || this.disposed || this.entityManager.changeEntityLocked) {
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
this._onContentChangeEmitter.fire(event);
|
|
2128
|
+
}
|
|
2129
|
+
toNodeJSON(node) {
|
|
2130
|
+
const subCanvas = this.getNodeSubCanvas(node);
|
|
2131
|
+
if (subCanvas?.isCanvas === true) {
|
|
2132
|
+
return this.toNodeJSON(subCanvas.parentNode);
|
|
2133
|
+
}
|
|
2134
|
+
const json = this.toNodeJSONFromOptions(node);
|
|
2135
|
+
const children = this.getNodeChildren(node);
|
|
2136
|
+
const blocks = children.map((child) => this.toNodeJSON(child));
|
|
2137
|
+
const linesMap = /* @__PURE__ */ new Map();
|
|
2138
|
+
children.forEach((child) => {
|
|
2139
|
+
const childLinesData = child.getData(WorkflowNodeLinesData);
|
|
2140
|
+
[...childLinesData.inputLines, ...childLinesData.outputLines].filter(Boolean).forEach((line) => {
|
|
2141
|
+
const lineJSON = this.toLineJSON(line);
|
|
2142
|
+
if (!lineJSON || linesMap.has(line.id)) {
|
|
2143
|
+
return;
|
|
2144
|
+
}
|
|
2145
|
+
linesMap.set(line.id, lineJSON);
|
|
2146
|
+
});
|
|
2147
|
+
});
|
|
2148
|
+
const edges = Array.from(linesMap.values());
|
|
2149
|
+
if (blocks.length > 0) json.blocks = blocks;
|
|
2150
|
+
if (edges.length > 0) json.edges = edges;
|
|
2151
|
+
return json;
|
|
2152
|
+
}
|
|
2153
|
+
/**
|
|
2154
|
+
* 节点转换为JSON, 没有format的过程
|
|
2155
|
+
* @param node
|
|
2156
|
+
* @returns
|
|
2157
|
+
*/
|
|
2158
|
+
toNodeJSONFromOptions(node) {
|
|
2159
|
+
if (this.options.toNodeJSON) {
|
|
2160
|
+
return this.options.toNodeJSON(node);
|
|
2161
|
+
}
|
|
2162
|
+
return WorkflowDocumentOptionsDefault.toNodeJSON(node);
|
|
2163
|
+
}
|
|
2164
|
+
copyNode(node, newNodeId, format, position) {
|
|
2165
|
+
let json = this.toNodeJSON(node);
|
|
2166
|
+
if (format) {
|
|
2167
|
+
json = format(json);
|
|
2168
|
+
}
|
|
2169
|
+
position = position || {
|
|
2170
|
+
x: json.meta.position.x + 30,
|
|
2171
|
+
y: json.meta.position.y + 30
|
|
2172
|
+
};
|
|
2173
|
+
return this.createWorkflowNode(
|
|
2174
|
+
{
|
|
2175
|
+
id: newNodeId || `1${nanoid2()}`,
|
|
2176
|
+
type: node.flowNodeType,
|
|
2177
|
+
meta: {
|
|
2178
|
+
...json.meta,
|
|
2179
|
+
position
|
|
2180
|
+
},
|
|
2181
|
+
data: json.data,
|
|
2182
|
+
blocks: json.blocks,
|
|
2183
|
+
edges: json.edges
|
|
2184
|
+
},
|
|
2185
|
+
true,
|
|
2186
|
+
node.parent?.id
|
|
2187
|
+
);
|
|
2188
|
+
}
|
|
2189
|
+
copyNodeFromJSON(flowNodeType, nodeJSON, newNodeId, position, parentId) {
|
|
2190
|
+
position = position || {
|
|
2191
|
+
x: nodeJSON.meta.position.x + 30,
|
|
2192
|
+
y: nodeJSON.meta.position.y + 30
|
|
2193
|
+
};
|
|
2194
|
+
return this.createWorkflowNode(
|
|
2195
|
+
{
|
|
2196
|
+
id: newNodeId || `1${nanoid2()}`,
|
|
2197
|
+
type: flowNodeType,
|
|
2198
|
+
meta: {
|
|
2199
|
+
...nodeJSON.meta,
|
|
2200
|
+
position
|
|
2201
|
+
},
|
|
2202
|
+
data: nodeJSON.data,
|
|
2203
|
+
blocks: nodeJSON.blocks,
|
|
2204
|
+
edges: nodeJSON.edges
|
|
2205
|
+
},
|
|
2206
|
+
true,
|
|
2207
|
+
parentId
|
|
2208
|
+
);
|
|
2209
|
+
}
|
|
2210
|
+
canRemove(node, silent) {
|
|
2211
|
+
const meta = node.getNodeMeta();
|
|
2212
|
+
if (meta.deleteDisable) {
|
|
2213
|
+
return false;
|
|
2214
|
+
}
|
|
2215
|
+
if (this.options.canDeleteNode && !this.options.canDeleteNode(node, silent)) {
|
|
2216
|
+
return false;
|
|
2217
|
+
}
|
|
2218
|
+
return true;
|
|
2219
|
+
}
|
|
2220
|
+
/**
|
|
2221
|
+
* 判断端口是否为错误态
|
|
2222
|
+
*/
|
|
2223
|
+
isErrorPort(port) {
|
|
2224
|
+
if (typeof this.options.isErrorPort === "function") {
|
|
2225
|
+
return this.options.isErrorPort(port);
|
|
2226
|
+
}
|
|
2227
|
+
return false;
|
|
2228
|
+
}
|
|
2229
|
+
/**
|
|
2230
|
+
* 导出数据
|
|
2231
|
+
*/
|
|
2232
|
+
toJSON() {
|
|
2233
|
+
const rootJSON = this.toNodeJSON(this.root);
|
|
2234
|
+
return {
|
|
2235
|
+
nodes: rootJSON.blocks ?? [],
|
|
2236
|
+
edges: rootJSON.edges ?? []
|
|
2237
|
+
};
|
|
2238
|
+
}
|
|
2239
|
+
dispose() {
|
|
2240
|
+
super.dispose();
|
|
2241
|
+
this._onReloadEmitter.dispose();
|
|
2242
|
+
}
|
|
2243
|
+
/**
|
|
2244
|
+
* 逐层创建节点和线条
|
|
2245
|
+
*/
|
|
2246
|
+
renderJSON(json, options) {
|
|
2247
|
+
const { parent = this.root, isClone = false } = options ?? {};
|
|
2248
|
+
const containerID = this.getNodeSubCanvas(parent)?.canvasNode.id ?? parent.id;
|
|
2249
|
+
const nodes = json.nodes.map(
|
|
2250
|
+
(nodeJSON) => this.createWorkflowNode(nodeJSON, isClone, containerID)
|
|
2251
|
+
);
|
|
2252
|
+
const edges = json.edges.map((edge) => this.createWorkflowLine(edge, containerID)).filter(Boolean);
|
|
2253
|
+
return { nodes, edges };
|
|
2254
|
+
}
|
|
2255
|
+
getNodeSubCanvas(node) {
|
|
2256
|
+
if (!node) return;
|
|
2257
|
+
const nodeMeta = node.getNodeMeta();
|
|
2258
|
+
const subCanvas = nodeMeta.subCanvas?.(node);
|
|
2259
|
+
return subCanvas;
|
|
2260
|
+
}
|
|
2261
|
+
getNodeChildren(node) {
|
|
2262
|
+
if (!node) return [];
|
|
2263
|
+
const subCanvas = this.getNodeSubCanvas(node);
|
|
2264
|
+
const childrenWithCanvas = subCanvas ? subCanvas.canvasNode.collapsedChildren : node.collapsedChildren;
|
|
2265
|
+
const children = childrenWithCanvas.filter((child) => {
|
|
2266
|
+
const childMeta = child.getNodeMeta();
|
|
2267
|
+
return !childMeta.subCanvas?.(node)?.isCanvas;
|
|
2268
|
+
}).filter(Boolean);
|
|
2269
|
+
return children;
|
|
2270
|
+
}
|
|
2271
|
+
toLineJSON(line) {
|
|
2272
|
+
const lineJSON = line.toJSON();
|
|
2273
|
+
if (!line.from || !line.info.from || !line.fromPort || !line.to || !line.info.to || !line.toPort) {
|
|
2274
|
+
return;
|
|
2275
|
+
}
|
|
2276
|
+
const fromSubCanvas = this.getNodeSubCanvas(line.from);
|
|
2277
|
+
const toSubCanvas = this.getNodeSubCanvas(line.to);
|
|
2278
|
+
if (fromSubCanvas && !fromSubCanvas.isCanvas && toSubCanvas && toSubCanvas.isCanvas) {
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
if (line.from === line.to.parent && fromSubCanvas) {
|
|
2282
|
+
return {
|
|
2283
|
+
...lineJSON,
|
|
2284
|
+
sourceNodeID: fromSubCanvas.parentNode.id
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
if (line.to === line.from.parent && toSubCanvas) {
|
|
2288
|
+
return {
|
|
2289
|
+
...lineJSON,
|
|
2290
|
+
targetNodeID: toSubCanvas.parentNode.id
|
|
2291
|
+
};
|
|
2292
|
+
}
|
|
2293
|
+
return lineJSON;
|
|
2294
|
+
}
|
|
2295
|
+
createWorkflowLine(json, parentId) {
|
|
2296
|
+
const fromNode = this.getNode(json.sourceNodeID);
|
|
2297
|
+
const toNode = this.getNode(json.targetNodeID);
|
|
2298
|
+
if (!fromNode || !toNode) {
|
|
2299
|
+
return;
|
|
2300
|
+
}
|
|
2301
|
+
const lineInfo = {
|
|
2302
|
+
from: json.sourceNodeID,
|
|
2303
|
+
fromPort: json.sourcePortID,
|
|
2304
|
+
to: json.targetNodeID,
|
|
2305
|
+
toPort: json.targetPortID
|
|
2306
|
+
};
|
|
2307
|
+
if (!parentId) {
|
|
2308
|
+
return this.linesManager.createLine(lineInfo);
|
|
2309
|
+
}
|
|
2310
|
+
const canvasNode = this.getNode(parentId);
|
|
2311
|
+
if (!canvasNode) {
|
|
2312
|
+
return this.linesManager.createLine(lineInfo);
|
|
2313
|
+
}
|
|
2314
|
+
const parentSubCanvas = this.getNodeSubCanvas(canvasNode);
|
|
2315
|
+
if (!parentSubCanvas) {
|
|
2316
|
+
return this.linesManager.createLine(lineInfo);
|
|
2317
|
+
}
|
|
2318
|
+
if (lineInfo.from === parentSubCanvas.parentNode.id) {
|
|
2319
|
+
return this.linesManager.createLine({
|
|
2320
|
+
...lineInfo,
|
|
2321
|
+
from: parentSubCanvas.canvasNode.id
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
if (lineInfo.to === parentSubCanvas.parentNode.id) {
|
|
2325
|
+
return this.linesManager.createLine({
|
|
2326
|
+
...lineInfo,
|
|
2327
|
+
to: parentSubCanvas.canvasNode.id
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
return this.linesManager.createLine(lineInfo);
|
|
2331
|
+
}
|
|
2332
|
+
};
|
|
2333
|
+
__decorateClass([
|
|
2334
|
+
(0, import_inversify5.inject)(WorkflowLinesManager)
|
|
2335
|
+
], WorkflowDocument.prototype, "linesManager", 2);
|
|
2336
|
+
__decorateClass([
|
|
2337
|
+
(0, import_inversify5.inject)(import_core14.PlaygroundConfigEntity)
|
|
2338
|
+
], WorkflowDocument.prototype, "playgroundConfig", 2);
|
|
2339
|
+
__decorateClass([
|
|
2340
|
+
(0, import_core14.injectPlaygroundContext)()
|
|
2341
|
+
], WorkflowDocument.prototype, "playgroundContext", 2);
|
|
2342
|
+
__decorateClass([
|
|
2343
|
+
(0, import_inversify5.inject)(WorkflowDocumentOptions)
|
|
2344
|
+
], WorkflowDocument.prototype, "options", 2);
|
|
2345
|
+
__decorateClass([
|
|
2346
|
+
(0, import_inversify5.inject)(import_form_core3.NodeEngineContext),
|
|
2347
|
+
(0, import_inversify5.optional)()
|
|
2348
|
+
], WorkflowDocument.prototype, "nodeEngineContext", 2);
|
|
2349
|
+
__decorateClass([
|
|
2350
|
+
(0, import_inversify5.inject)(WorkflowSelectService)
|
|
2351
|
+
], WorkflowDocument.prototype, "selectServices", 2);
|
|
2352
|
+
__decorateClass([
|
|
2353
|
+
(0, import_inversify5.postConstruct)()
|
|
2354
|
+
], WorkflowDocument.prototype, "init", 1);
|
|
2355
|
+
WorkflowDocument = __decorateClass([
|
|
2356
|
+
(0, import_inversify5.injectable)()
|
|
2357
|
+
], WorkflowDocument);
|
|
2358
|
+
|
|
2359
|
+
// src/service/workflow-drag-service.ts
|
|
2360
|
+
var DRAG_TIMEOUT = 100;
|
|
2361
|
+
var DRAG_MIN_DELTA = 5;
|
|
2362
|
+
function checkDragSuccess(time, e, originLine) {
|
|
2363
|
+
if (!originLine || time > DRAG_TIMEOUT || Math.abs(e.endPos.x - e.startPos.x) >= DRAG_MIN_DELTA || Math.abs(e.endPos.y - e.startPos.y) >= DRAG_MIN_DELTA) {
|
|
2364
|
+
return true;
|
|
2365
|
+
}
|
|
2366
|
+
return false;
|
|
2367
|
+
}
|
|
2368
|
+
var WorkflowDragService = class {
|
|
2369
|
+
constructor() {
|
|
2370
|
+
this._onDragLineEventEmitter = new import_utils16.Emitter();
|
|
2371
|
+
this.onDragLineEventChange = this._onDragLineEventEmitter.event;
|
|
2372
|
+
this.isDragging = false;
|
|
2373
|
+
this._nodesDragEmitter = new import_utils16.Emitter();
|
|
2374
|
+
this.onNodesDrag = this._nodesDragEmitter.event;
|
|
2375
|
+
this._toDispose = new import_utils16.DisposableCollection();
|
|
2376
|
+
this._droppableTransforms = [];
|
|
2377
|
+
this.posAdjusters = /* @__PURE__ */ new Set();
|
|
2378
|
+
this._onDragLineEndCallbacks = /* @__PURE__ */ new Map();
|
|
2379
|
+
}
|
|
2380
|
+
init() {
|
|
2381
|
+
this._toDispose.pushAll([this._onDragLineEventEmitter, this._nodesDragEmitter]);
|
|
2382
|
+
if (this.options.onDragLineEnd) {
|
|
2383
|
+
this._toDispose.push(this.onDragLineEnd(this.options.onDragLineEnd));
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
dispose() {
|
|
2387
|
+
this._toDispose.dispose();
|
|
2388
|
+
}
|
|
2389
|
+
/**
|
|
2390
|
+
* 拖拽选中节点
|
|
2391
|
+
* @param triggerEvent
|
|
2392
|
+
*/
|
|
2393
|
+
async startDragSelectedNodes(triggerEvent) {
|
|
2394
|
+
let { selectedNodes } = this.selectService;
|
|
2395
|
+
if (selectedNodes.length === 0 || this.playgroundConfig.readonly || this.playgroundConfig.disabled || this.isDragging) {
|
|
2396
|
+
return Promise.resolve(false);
|
|
2397
|
+
}
|
|
2398
|
+
this.isDragging = true;
|
|
2399
|
+
const sameParent = this.childrenOfContainer(selectedNodes);
|
|
2400
|
+
if (sameParent && sameParent.flowNodeType !== import_document9.FlowNodeBaseType.ROOT) {
|
|
2401
|
+
selectedNodes = [sameParent];
|
|
2402
|
+
}
|
|
2403
|
+
let startPosition = this.getNodesPosition(selectedNodes);
|
|
2404
|
+
let startPositions = selectedNodes.map((node) => {
|
|
2405
|
+
const transform = node.getData(import_core15.TransformData);
|
|
2406
|
+
return { x: transform.position.x, y: transform.position.y };
|
|
2407
|
+
});
|
|
2408
|
+
let dragSuccess = false;
|
|
2409
|
+
const startTime = Date.now();
|
|
2410
|
+
const dragger = new import_core15.PlaygroundDrag({
|
|
2411
|
+
onDragStart: (dragEvent) => {
|
|
2412
|
+
this._nodesDragEmitter.fire({
|
|
2413
|
+
type: "onDragStart",
|
|
2414
|
+
nodes: selectedNodes,
|
|
2415
|
+
startPositions,
|
|
2416
|
+
dragEvent,
|
|
2417
|
+
triggerEvent,
|
|
2418
|
+
dragger
|
|
2419
|
+
});
|
|
2420
|
+
},
|
|
2421
|
+
onDrag: (dragEvent) => {
|
|
2422
|
+
if (!dragSuccess && checkDragSuccess(Date.now() - startTime, dragEvent)) {
|
|
2423
|
+
dragSuccess = true;
|
|
2424
|
+
}
|
|
2425
|
+
const offset = this.getDragPosOffset({
|
|
2426
|
+
event: dragEvent,
|
|
2427
|
+
selectedNodes,
|
|
2428
|
+
startPosition
|
|
2429
|
+
});
|
|
2430
|
+
const positions = [];
|
|
2431
|
+
selectedNodes.forEach((node, index) => {
|
|
2432
|
+
const transform = node.getData(import_core15.TransformData);
|
|
2433
|
+
const nodeStartPosition = startPositions[index];
|
|
2434
|
+
const newPosition = {
|
|
2435
|
+
x: nodeStartPosition.x + offset.x,
|
|
2436
|
+
y: nodeStartPosition.y + offset.y
|
|
2437
|
+
};
|
|
2438
|
+
transform.update({
|
|
2439
|
+
position: newPosition
|
|
2440
|
+
});
|
|
2441
|
+
this.document.layout.updateAffectedTransform(node);
|
|
2442
|
+
positions.push(newPosition);
|
|
2443
|
+
});
|
|
2444
|
+
this._nodesDragEmitter.fire({
|
|
2445
|
+
type: "onDragging",
|
|
2446
|
+
nodes: selectedNodes,
|
|
2447
|
+
startPositions,
|
|
2448
|
+
positions,
|
|
2449
|
+
dragEvent,
|
|
2450
|
+
triggerEvent,
|
|
2451
|
+
dragger
|
|
2452
|
+
});
|
|
2453
|
+
},
|
|
2454
|
+
onDragEnd: (dragEvent) => {
|
|
2455
|
+
this.isDragging = false;
|
|
2456
|
+
this._nodesDragEmitter.fire({
|
|
2457
|
+
type: "onDragEnd",
|
|
2458
|
+
nodes: selectedNodes,
|
|
2459
|
+
startPositions,
|
|
2460
|
+
dragEvent,
|
|
2461
|
+
triggerEvent,
|
|
2462
|
+
dragger
|
|
2463
|
+
});
|
|
2464
|
+
}
|
|
2465
|
+
});
|
|
2466
|
+
const { clientX, clientY } = import_core15.MouseTouchEvent.getEventCoord(triggerEvent);
|
|
2467
|
+
return dragger.start(clientX, clientY, this.playgroundConfig)?.then(() => dragSuccess);
|
|
2468
|
+
}
|
|
2469
|
+
/**
|
|
2470
|
+
* 通过拖入卡片添加
|
|
2471
|
+
* @param type
|
|
2472
|
+
* @param event
|
|
2473
|
+
* @param data 节点数据
|
|
2474
|
+
*/
|
|
2475
|
+
async dropCard(type, event, data, parent) {
|
|
2476
|
+
const mousePos = this.playgroundConfig.getPosFromMouseEvent(event);
|
|
2477
|
+
if (!this.playgroundConfig.getViewport().contains(mousePos.x, mousePos.y)) {
|
|
2478
|
+
return;
|
|
2479
|
+
}
|
|
2480
|
+
const position = this.adjustSubNodePosition(type, parent, mousePos);
|
|
2481
|
+
const node = await this.document.createWorkflowNodeByType(
|
|
2482
|
+
type,
|
|
2483
|
+
position,
|
|
2484
|
+
data,
|
|
2485
|
+
parent?.id
|
|
2486
|
+
);
|
|
2487
|
+
return node;
|
|
2488
|
+
}
|
|
2489
|
+
/**
|
|
2490
|
+
* 拖拽卡片到画布
|
|
2491
|
+
* 返回创建结果
|
|
2492
|
+
* @param type
|
|
2493
|
+
* @param event
|
|
2494
|
+
*/
|
|
2495
|
+
async startDragCard(type, event, data, cloneNode) {
|
|
2496
|
+
let domNode;
|
|
2497
|
+
let startPos = { x: 0, y: 0 };
|
|
2498
|
+
const deferred = new import_utils16.PromiseDeferred();
|
|
2499
|
+
const dragger = new import_core15.PlaygroundDrag({
|
|
2500
|
+
onDragStart: (e) => {
|
|
2501
|
+
const targetNode = event.currentTarget;
|
|
2502
|
+
domNode = cloneNode ? cloneNode(e) : targetNode.cloneNode(true);
|
|
2503
|
+
const bounds = targetNode.getBoundingClientRect();
|
|
2504
|
+
startPos = { x: bounds.left, y: bounds.top };
|
|
2505
|
+
import_utils16.domUtils.setStyle(domNode, {
|
|
2506
|
+
zIndex: 1e3,
|
|
2507
|
+
position: "absolute",
|
|
2508
|
+
left: startPos.x,
|
|
2509
|
+
top: startPos.y,
|
|
2510
|
+
boxShadow: "0 6px 8px 0 rgba(28, 31, 35, .2)"
|
|
2511
|
+
});
|
|
2512
|
+
document.body.appendChild(domNode);
|
|
2513
|
+
this.updateDroppableTransforms();
|
|
2514
|
+
},
|
|
2515
|
+
onDrag: (e) => {
|
|
2516
|
+
const deltaX = e.endPos.x - e.startPos.x;
|
|
2517
|
+
const deltaY = e.endPos.y - e.startPos.y;
|
|
2518
|
+
const left = startPos.x + deltaX;
|
|
2519
|
+
const right = startPos.y + deltaY;
|
|
2520
|
+
domNode.style.left = `${left}px`;
|
|
2521
|
+
domNode.style.top = `${right}px`;
|
|
2522
|
+
const { x, y } = this.playgroundConfig.getPosFromMouseEvent(e);
|
|
2523
|
+
const draggingRect = new import_utils16.Rectangle(x, y, 170, 90);
|
|
2524
|
+
const collisionTransform = this._droppableTransforms.find((transform) => {
|
|
2525
|
+
const { bounds, entity } = transform;
|
|
2526
|
+
const padding = this.document.layout.getPadding(entity);
|
|
2527
|
+
const transformRect = new import_utils16.Rectangle(
|
|
2528
|
+
bounds.x + padding.left + padding.right,
|
|
2529
|
+
bounds.y,
|
|
2530
|
+
bounds.width,
|
|
2531
|
+
bounds.height
|
|
2532
|
+
);
|
|
2533
|
+
return import_utils16.Rectangle.intersects(draggingRect, transformRect);
|
|
2534
|
+
});
|
|
2535
|
+
this.updateDropNode(collisionTransform?.entity);
|
|
2536
|
+
},
|
|
2537
|
+
onDragEnd: async (e) => {
|
|
2538
|
+
const dropNode = this._dropNode;
|
|
2539
|
+
const { allowDrop } = this.canDropToNode({
|
|
2540
|
+
dragNodeType: type,
|
|
2541
|
+
dropNodeType: dropNode?.flowNodeType,
|
|
2542
|
+
dropNode
|
|
2543
|
+
});
|
|
2544
|
+
const dragNode = allowDrop ? await this.dropCard(type, e, data, dropNode) : void 0;
|
|
2545
|
+
this.clearDrop();
|
|
2546
|
+
if (dragNode) {
|
|
2547
|
+
domNode.remove();
|
|
2548
|
+
deferred.resolve(dragNode);
|
|
2549
|
+
} else {
|
|
2550
|
+
domNode.style.transition = "all ease .2s";
|
|
2551
|
+
domNode.style.left = `${startPos.x}px`;
|
|
2552
|
+
domNode.style.top = `${startPos.y}px`;
|
|
2553
|
+
const TIMEOUT = 200;
|
|
2554
|
+
await (0, import_utils16.delay)(TIMEOUT);
|
|
2555
|
+
domNode.remove();
|
|
2556
|
+
deferred.resolve();
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
});
|
|
2560
|
+
await dragger.start(event.clientX, event.clientY);
|
|
2561
|
+
return deferred.promise;
|
|
2562
|
+
}
|
|
2563
|
+
/**
|
|
2564
|
+
* 如果存在容器节点,且传入鼠标坐标,需要用容器的坐标减去传入的鼠标坐标
|
|
2565
|
+
*/
|
|
2566
|
+
adjustSubNodePosition(subNodeType, containerNode, mousePos) {
|
|
2567
|
+
if (!mousePos) {
|
|
2568
|
+
return { x: 0, y: 0 };
|
|
2569
|
+
}
|
|
2570
|
+
if (!subNodeType || !containerNode || containerNode.flowNodeType === import_document9.FlowNodeBaseType.ROOT) {
|
|
2571
|
+
return mousePos;
|
|
2572
|
+
}
|
|
2573
|
+
const isParentEmpty = !containerNode.children || containerNode.children.length === 0;
|
|
2574
|
+
const parentPadding = this.document.layout.getPadding(containerNode);
|
|
2575
|
+
const containerWorldTransform = containerNode.transform.transform.worldTransform;
|
|
2576
|
+
if (isParentEmpty) {
|
|
2577
|
+
return {
|
|
2578
|
+
x: 0,
|
|
2579
|
+
y: parentPadding.top
|
|
2580
|
+
};
|
|
2581
|
+
} else {
|
|
2582
|
+
return {
|
|
2583
|
+
x: mousePos.x - containerWorldTransform.tx,
|
|
2584
|
+
y: mousePos.y - containerWorldTransform.ty
|
|
2585
|
+
};
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
/**
|
|
2589
|
+
* 注册位置调整
|
|
2590
|
+
*/
|
|
2591
|
+
registerPosAdjuster(adjuster) {
|
|
2592
|
+
this.posAdjusters.add(adjuster);
|
|
2593
|
+
return {
|
|
2594
|
+
dispose: () => this.posAdjusters.delete(adjuster)
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2597
|
+
/**
|
|
2598
|
+
* 判断是否可以放置节点
|
|
2599
|
+
*/
|
|
2600
|
+
canDropToNode(params) {
|
|
2601
|
+
const { canDropToNode } = this.document.options;
|
|
2602
|
+
const { dragNodeType, dropNode } = params;
|
|
2603
|
+
if (canDropToNode) {
|
|
2604
|
+
const result = canDropToNode(params);
|
|
2605
|
+
if (result) {
|
|
2606
|
+
return {
|
|
2607
|
+
allowDrop: true,
|
|
2608
|
+
dropNode
|
|
2609
|
+
};
|
|
2610
|
+
}
|
|
2611
|
+
return {
|
|
2612
|
+
allowDrop: false
|
|
2613
|
+
};
|
|
2614
|
+
}
|
|
2615
|
+
if (!dragNodeType) {
|
|
2616
|
+
return {
|
|
2617
|
+
allowDrop: false,
|
|
2618
|
+
message: "Please select a node to drop"
|
|
2619
|
+
};
|
|
2620
|
+
}
|
|
2621
|
+
return {
|
|
2622
|
+
allowDrop: true,
|
|
2623
|
+
dropNode
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
/**
|
|
2627
|
+
* 获取拖拽偏移
|
|
2628
|
+
*/
|
|
2629
|
+
getDragPosOffset(params) {
|
|
2630
|
+
const { event, selectedNodes, startPosition } = params;
|
|
2631
|
+
const { finalScale } = this.playgroundConfig;
|
|
2632
|
+
const mouseOffset = {
|
|
2633
|
+
x: (event.endPos.x - event.startPos.x) / finalScale,
|
|
2634
|
+
y: (event.endPos.y - event.startPos.y) / finalScale
|
|
2635
|
+
};
|
|
2636
|
+
const wholePosition = {
|
|
2637
|
+
x: startPosition.x + mouseOffset.x,
|
|
2638
|
+
y: startPosition.y + mouseOffset.y
|
|
2639
|
+
};
|
|
2640
|
+
const adjustedOffsets = Array.from(this.posAdjusters.values()).map(
|
|
2641
|
+
(adjuster) => adjuster({
|
|
2642
|
+
selectedNodes,
|
|
2643
|
+
position: wholePosition
|
|
2644
|
+
})
|
|
2645
|
+
);
|
|
2646
|
+
const offset = adjustedOffsets.reduce(
|
|
2647
|
+
(offset2, adjustOffset) => ({
|
|
2648
|
+
x: offset2.x + adjustOffset.x,
|
|
2649
|
+
y: offset2.y + adjustOffset.y
|
|
2650
|
+
}),
|
|
2651
|
+
mouseOffset
|
|
2652
|
+
);
|
|
2653
|
+
return offset;
|
|
2654
|
+
}
|
|
2655
|
+
updateDroppableTransforms() {
|
|
2656
|
+
this._droppableTransforms = this.document.getRenderDatas(import_document8.FlowNodeTransformData, false).filter((transform) => {
|
|
2657
|
+
const { entity } = transform;
|
|
2658
|
+
if (entity.originParent) {
|
|
2659
|
+
return this.nodeSelectable(entity) && this.nodeSelectable(entity.originParent);
|
|
2660
|
+
}
|
|
2661
|
+
return this.nodeSelectable(entity);
|
|
2662
|
+
}).filter((transform) => this.isContainer(transform.entity));
|
|
2663
|
+
}
|
|
2664
|
+
/** 是否容器节点 */
|
|
2665
|
+
isContainer(node) {
|
|
2666
|
+
return node?.getNodeMeta().isContainer ?? false;
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* 获取节点整体位置
|
|
2670
|
+
*/
|
|
2671
|
+
getNodesPosition(nodes) {
|
|
2672
|
+
const selectedBounds = import_utils16.Rectangle.enlarge(
|
|
2673
|
+
nodes.map((n) => n.getData(import_document8.FlowNodeTransformData).bounds)
|
|
2674
|
+
);
|
|
2675
|
+
const position = {
|
|
2676
|
+
x: selectedBounds.x,
|
|
2677
|
+
y: selectedBounds.y
|
|
2678
|
+
};
|
|
2679
|
+
return position;
|
|
2680
|
+
}
|
|
2681
|
+
nodeSelectable(node) {
|
|
2682
|
+
const selectable = node.getNodeMeta().selectable;
|
|
2683
|
+
if (typeof selectable === "function") {
|
|
2684
|
+
return selectable(node);
|
|
2685
|
+
} else {
|
|
2686
|
+
return selectable;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
updateDropNode(node) {
|
|
2690
|
+
if (this._dropNode) {
|
|
2691
|
+
if (this._dropNode.id === node?.id) {
|
|
2692
|
+
return;
|
|
2693
|
+
}
|
|
2694
|
+
this.selectService.clear();
|
|
2695
|
+
}
|
|
2696
|
+
if (node) {
|
|
2697
|
+
this.selectService.selectNode(node);
|
|
2698
|
+
}
|
|
2699
|
+
this._dropNode = node;
|
|
2700
|
+
}
|
|
2701
|
+
clearDrop() {
|
|
2702
|
+
if (this._dropNode) {
|
|
2703
|
+
this.selectService.clear();
|
|
2704
|
+
}
|
|
2705
|
+
this._dropNode = void 0;
|
|
2706
|
+
this._droppableTransforms = [];
|
|
2707
|
+
}
|
|
2708
|
+
setLineColor(line, color) {
|
|
2709
|
+
line.highlightColor = color;
|
|
2710
|
+
this.hoverService.clearHovered();
|
|
2711
|
+
}
|
|
2712
|
+
handleDragOnNode(toNode, fromPort, line, toPort, originLine) {
|
|
2713
|
+
if (toPort && (originLine?.toPort === toPort || toPort.portType === "input" && this.linesManager.canAddLine(fromPort, toPort, true))) {
|
|
2714
|
+
this.hoverService.updateHoveredKey(toPort.id);
|
|
2715
|
+
line.setToPort(toPort);
|
|
2716
|
+
this._onDragLineEventEmitter.fire({
|
|
2717
|
+
type: "onDrag",
|
|
2718
|
+
onDragNodeId: toNode.id
|
|
2719
|
+
});
|
|
2720
|
+
return {
|
|
2721
|
+
hasError: false
|
|
2722
|
+
};
|
|
2723
|
+
} else if (this.isContainer(toNode)) {
|
|
2724
|
+
return {
|
|
2725
|
+
hasError: false
|
|
2726
|
+
};
|
|
2727
|
+
} else {
|
|
2728
|
+
this.setLineColor(line, this.linesManager.lineColor.error);
|
|
2729
|
+
return {
|
|
2730
|
+
hasError: true
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
childrenOfContainer(nodes) {
|
|
2735
|
+
if (nodes.length === 0) {
|
|
2736
|
+
return;
|
|
2737
|
+
}
|
|
2738
|
+
const sourceContainer = nodes[0]?.parent;
|
|
2739
|
+
if (!sourceContainer || sourceContainer.collapsedChildren.length !== nodes.length) {
|
|
2740
|
+
return;
|
|
2741
|
+
}
|
|
2742
|
+
const valid = nodes.every((node) => node?.parent === sourceContainer);
|
|
2743
|
+
if (!valid) {
|
|
2744
|
+
return;
|
|
2745
|
+
}
|
|
2746
|
+
return sourceContainer;
|
|
2747
|
+
}
|
|
2748
|
+
/**
|
|
2749
|
+
* 绘制线条
|
|
2750
|
+
* @param opts
|
|
2751
|
+
* @param event
|
|
2752
|
+
*/
|
|
2753
|
+
async startDrawingLine(fromPort, event, originLine) {
|
|
2754
|
+
const isFromInActivePort = !originLine && fromPort.isErrorPort() && fromPort.disabled;
|
|
2755
|
+
if (originLine?.disabled || isFromInActivePort || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
|
|
2756
|
+
return { dragSuccess: false, newLine: void 0 };
|
|
2757
|
+
}
|
|
2758
|
+
this.selectService.clear();
|
|
2759
|
+
const config = this.playgroundConfig;
|
|
2760
|
+
const deferred = new import_utils16.PromiseDeferred();
|
|
2761
|
+
const preCursor = config.cursor;
|
|
2762
|
+
let line, toPort, toNode, lineErrorReset = false;
|
|
2763
|
+
const startTime = Date.now();
|
|
2764
|
+
let dragSuccess = false;
|
|
2765
|
+
const dragger = new import_core15.PlaygroundDrag({
|
|
2766
|
+
onDrag: (e) => {
|
|
2767
|
+
if (!line && checkDragSuccess(Date.now() - startTime, e, originLine)) {
|
|
2768
|
+
if (originLine) {
|
|
2769
|
+
originLine.highlightColor = this.linesManager.lineColor.hidden;
|
|
2770
|
+
}
|
|
2771
|
+
dragSuccess = true;
|
|
2772
|
+
line = this.linesManager.createLine({
|
|
2773
|
+
from: fromPort.node.id,
|
|
2774
|
+
fromPort: fromPort.portID,
|
|
2775
|
+
drawingTo: config.getPosFromMouseEvent(event)
|
|
2776
|
+
});
|
|
2777
|
+
if (!line) {
|
|
2778
|
+
return;
|
|
2779
|
+
}
|
|
2780
|
+
config.updateCursor("grab");
|
|
2781
|
+
line.highlightColor = this.linesManager.lineColor.drawing;
|
|
2782
|
+
this.hoverService.updateHoveredKey("");
|
|
2783
|
+
}
|
|
2784
|
+
if (!line) {
|
|
2785
|
+
return;
|
|
2786
|
+
}
|
|
2787
|
+
lineErrorReset = false;
|
|
2788
|
+
const dragPos = config.getPosFromMouseEvent(e);
|
|
2789
|
+
toNode = this.linesManager.getNodeFromMousePos(dragPos);
|
|
2790
|
+
toPort = this.linesManager.getPortFromMousePos(dragPos);
|
|
2791
|
+
if (!toPort) {
|
|
2792
|
+
line.setToPort(void 0);
|
|
2793
|
+
} else if (!this.linesManager.canAddLine(fromPort, toPort, true)) {
|
|
2794
|
+
line.highlightColor = this.linesManager.lineColor.error;
|
|
2795
|
+
lineErrorReset = true;
|
|
2796
|
+
line.setToPort(void 0);
|
|
2797
|
+
} else {
|
|
2798
|
+
line.setToPort(toPort);
|
|
2799
|
+
}
|
|
2800
|
+
this._onDragLineEventEmitter.fire({
|
|
2801
|
+
type: "onDrag"
|
|
2802
|
+
});
|
|
2803
|
+
this.setLineColor(line, this.linesManager.lineColor.drawing);
|
|
2804
|
+
if (toNode && this.canBuildContainerLine(toNode, dragPos)) {
|
|
2805
|
+
toPort = this.getNearestPort(toNode, dragPos);
|
|
2806
|
+
const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);
|
|
2807
|
+
lineErrorReset = hasError;
|
|
2808
|
+
}
|
|
2809
|
+
if (line.toPort) {
|
|
2810
|
+
line.drawingTo = { x: line.toPort.point.x, y: line.toPort.point.y };
|
|
2811
|
+
} else {
|
|
2812
|
+
line.drawingTo = { x: dragPos.x, y: dragPos.y };
|
|
2813
|
+
}
|
|
2814
|
+
originLine?.validate();
|
|
2815
|
+
line.validate();
|
|
2816
|
+
},
|
|
2817
|
+
// eslint-disable-next-line complexity
|
|
2818
|
+
onDragEnd: async (e) => {
|
|
2819
|
+
const dragPos = config.getPosFromMouseEvent(e);
|
|
2820
|
+
const onDragLineEndCallbacks = Array.from(this._onDragLineEndCallbacks.values());
|
|
2821
|
+
config.updateCursor(preCursor);
|
|
2822
|
+
await Promise.all(
|
|
2823
|
+
onDragLineEndCallbacks.map(
|
|
2824
|
+
(callback) => callback({
|
|
2825
|
+
fromPort,
|
|
2826
|
+
toPort,
|
|
2827
|
+
mousePos: dragPos,
|
|
2828
|
+
line,
|
|
2829
|
+
originLine,
|
|
2830
|
+
event: e
|
|
2831
|
+
})
|
|
2832
|
+
)
|
|
2833
|
+
);
|
|
2834
|
+
line?.dispose();
|
|
2835
|
+
this._onDragLineEventEmitter.fire({
|
|
2836
|
+
type: "onDragEnd"
|
|
2837
|
+
});
|
|
2838
|
+
if (originLine) {
|
|
2839
|
+
originLine.highlightColor = "";
|
|
2840
|
+
}
|
|
2841
|
+
const end = () => {
|
|
2842
|
+
originLine?.validate();
|
|
2843
|
+
deferred.resolve({ dragSuccess });
|
|
2844
|
+
};
|
|
2845
|
+
if (dragSuccess) {
|
|
2846
|
+
if (originLine && originLine.toPort === toPort) {
|
|
2847
|
+
return end();
|
|
2848
|
+
}
|
|
2849
|
+
if (toPort && toPort.portType !== "input") {
|
|
2850
|
+
return end();
|
|
2851
|
+
}
|
|
2852
|
+
const newLineInfo = toPort ? {
|
|
2853
|
+
from: fromPort.node.id,
|
|
2854
|
+
fromPort: fromPort.portID,
|
|
2855
|
+
to: toPort.node.id,
|
|
2856
|
+
toPort: toPort.portID
|
|
2857
|
+
} : void 0;
|
|
2858
|
+
const isReset = originLine && toPort;
|
|
2859
|
+
if (isReset && !this.linesManager.canReset(
|
|
2860
|
+
originLine.fromPort,
|
|
2861
|
+
originLine.toPort,
|
|
2862
|
+
toPort
|
|
2863
|
+
)) {
|
|
2864
|
+
return end();
|
|
2865
|
+
}
|
|
2866
|
+
if (originLine && (!this.linesManager.canRemove(originLine, newLineInfo, false) || lineErrorReset)) {
|
|
2867
|
+
return end();
|
|
2868
|
+
} else {
|
|
2869
|
+
originLine?.dispose();
|
|
2870
|
+
}
|
|
2871
|
+
if (!toPort || !this.linesManager.canAddLine(fromPort, toPort, false)) {
|
|
2872
|
+
return end();
|
|
2873
|
+
}
|
|
2874
|
+
const newLine = this.linesManager.createLine(newLineInfo);
|
|
2875
|
+
if (!newLine) {
|
|
2876
|
+
end();
|
|
2877
|
+
}
|
|
2878
|
+
deferred.resolve({
|
|
2879
|
+
dragSuccess,
|
|
2880
|
+
newLine
|
|
2881
|
+
});
|
|
2882
|
+
} else {
|
|
2883
|
+
end();
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
});
|
|
2887
|
+
const { clientX, clientY } = import_core15.MouseTouchEvent.getEventCoord(event);
|
|
2888
|
+
await dragger.start(clientX, clientY, config);
|
|
2889
|
+
return deferred.promise;
|
|
2890
|
+
}
|
|
2891
|
+
/**
|
|
2892
|
+
* 重新连接线条
|
|
2893
|
+
* @param line
|
|
2894
|
+
* @param e
|
|
2895
|
+
*/
|
|
2896
|
+
async resetLine(line, e) {
|
|
2897
|
+
const { fromPort } = line;
|
|
2898
|
+
const { dragSuccess } = await this.startDrawingLine(fromPort, e, line);
|
|
2899
|
+
if (!dragSuccess) {
|
|
2900
|
+
this.selectService.select(line);
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
/** 线条拖拽结束 */
|
|
2904
|
+
onDragLineEnd(callback) {
|
|
2905
|
+
const id = (0, import_nanoid3.nanoid)();
|
|
2906
|
+
this._onDragLineEndCallbacks.set(id, callback);
|
|
2907
|
+
return {
|
|
2908
|
+
dispose: () => {
|
|
2909
|
+
this._onDragLineEndCallbacks.delete(id);
|
|
2910
|
+
}
|
|
2911
|
+
};
|
|
2912
|
+
}
|
|
2913
|
+
/** 能否建立容器连线 */
|
|
2914
|
+
canBuildContainerLine(node, mousePos) {
|
|
2915
|
+
const isContainer = this.isContainer(node);
|
|
2916
|
+
if (!isContainer) {
|
|
2917
|
+
return true;
|
|
2918
|
+
}
|
|
2919
|
+
const { padding, bounds } = node.transform;
|
|
2920
|
+
const contentRect = new import_utils16.Rectangle(bounds.x, bounds.y, padding.left * 2 / 3, bounds.height);
|
|
2921
|
+
return contentRect.contains(mousePos.x, mousePos.y);
|
|
2922
|
+
}
|
|
2923
|
+
/** 获取最近的 port */
|
|
2924
|
+
getNearestPort(node, mousePos) {
|
|
2925
|
+
const portsData = node.getData(WorkflowNodePortsData);
|
|
2926
|
+
const distanceSortedPorts = portsData.inputPorts.sort((a, b) => {
|
|
2927
|
+
const aDistance = Math.abs(mousePos.y - a.point.y);
|
|
2928
|
+
const bDistance = Math.abs(mousePos.y - b.point.y);
|
|
2929
|
+
return aDistance - bDistance;
|
|
2930
|
+
});
|
|
2931
|
+
return distanceSortedPorts[0];
|
|
2932
|
+
}
|
|
2933
|
+
};
|
|
2934
|
+
__decorateClass([
|
|
2935
|
+
(0, import_inversify6.inject)(import_core15.PlaygroundConfigEntity)
|
|
2936
|
+
], WorkflowDragService.prototype, "playgroundConfig", 2);
|
|
2937
|
+
__decorateClass([
|
|
2938
|
+
(0, import_inversify6.inject)(WorkflowHoverService)
|
|
2939
|
+
], WorkflowDragService.prototype, "hoverService", 2);
|
|
2940
|
+
__decorateClass([
|
|
2941
|
+
(0, import_inversify6.inject)(WorkflowDocument)
|
|
2942
|
+
], WorkflowDragService.prototype, "document", 2);
|
|
2943
|
+
__decorateClass([
|
|
2944
|
+
(0, import_inversify6.inject)(WorkflowLinesManager)
|
|
2945
|
+
], WorkflowDragService.prototype, "linesManager", 2);
|
|
2946
|
+
__decorateClass([
|
|
2947
|
+
(0, import_inversify6.inject)(import_core15.CommandService)
|
|
2948
|
+
], WorkflowDragService.prototype, "commandService", 2);
|
|
2949
|
+
__decorateClass([
|
|
2950
|
+
(0, import_inversify6.inject)(WorkflowSelectService)
|
|
2951
|
+
], WorkflowDragService.prototype, "selectService", 2);
|
|
2952
|
+
__decorateClass([
|
|
2953
|
+
(0, import_inversify6.inject)(import_document8.FlowOperationBaseService)
|
|
2954
|
+
], WorkflowDragService.prototype, "operationService", 2);
|
|
2955
|
+
__decorateClass([
|
|
2956
|
+
(0, import_inversify6.inject)(WorkflowDocumentOptions)
|
|
2957
|
+
], WorkflowDragService.prototype, "options", 2);
|
|
2958
|
+
__decorateClass([
|
|
2959
|
+
(0, import_inversify6.postConstruct)()
|
|
2960
|
+
], WorkflowDragService.prototype, "init", 1);
|
|
2961
|
+
WorkflowDragService = __decorateClass([
|
|
2962
|
+
(0, import_inversify6.injectable)()
|
|
2963
|
+
], WorkflowDragService);
|
|
2964
|
+
|
|
2965
|
+
// src/service/workflow-reset-layout-service.ts
|
|
2966
|
+
var import_inversify7 = require("inversify");
|
|
2967
|
+
var import_core17 = require("@flowgram.ai/core");
|
|
2968
|
+
var import_core18 = require("@flowgram.ai/core");
|
|
2969
|
+
var import_utils17 = require("@flowgram.ai/utils");
|
|
2970
|
+
|
|
2971
|
+
// src/utils/layout-to-positions.ts
|
|
2972
|
+
var import_document10 = require("@flowgram.ai/document");
|
|
2973
|
+
var import_core16 = require("@flowgram.ai/core");
|
|
2974
|
+
var layoutToPositions = async (nodes, nodePositionMap) => {
|
|
2975
|
+
const newNodePositionMap = {};
|
|
2976
|
+
nodes.forEach((node) => {
|
|
2977
|
+
const transform = node.getData(import_core16.TransformData);
|
|
2978
|
+
const nodeTransform = node.getData(import_document10.FlowNodeTransformData);
|
|
2979
|
+
newNodePositionMap[node.id] = {
|
|
2980
|
+
x: transform.position.x,
|
|
2981
|
+
y: transform.position.y + nodeTransform.bounds.height / 2
|
|
2982
|
+
};
|
|
2983
|
+
});
|
|
2984
|
+
return new Promise((resolve) => {
|
|
2985
|
+
(0, import_core16.startTween)({
|
|
2986
|
+
from: { d: 0 },
|
|
2987
|
+
to: { d: 100 },
|
|
2988
|
+
duration: 300,
|
|
2989
|
+
onUpdate: (v) => {
|
|
2990
|
+
nodes.forEach((node) => {
|
|
2991
|
+
const transform = node.getData(import_core16.TransformData);
|
|
2992
|
+
const deltaX = (nodePositionMap[node.id].x - transform.position.x) * v.d / 100;
|
|
2993
|
+
const deltaY = (nodePositionMap[node.id].y - transform.bounds.height / 2 - transform.position.y) * v.d / 100;
|
|
2994
|
+
transform.update({
|
|
2995
|
+
position: {
|
|
2996
|
+
x: transform.position.x + deltaX,
|
|
2997
|
+
y: transform.position.y + deltaY
|
|
2998
|
+
}
|
|
2999
|
+
});
|
|
3000
|
+
const document2 = node.document;
|
|
3001
|
+
document2.layout.updateAffectedTransform(node);
|
|
3002
|
+
});
|
|
3003
|
+
},
|
|
3004
|
+
onComplete: () => {
|
|
3005
|
+
resolve(newNodePositionMap);
|
|
3006
|
+
}
|
|
3007
|
+
});
|
|
3008
|
+
});
|
|
3009
|
+
};
|
|
3010
|
+
|
|
3011
|
+
// src/service/workflow-reset-layout-service.ts
|
|
3012
|
+
var WorkflowResetLayoutService = class {
|
|
3013
|
+
constructor() {
|
|
3014
|
+
this._resetLayoutEmitter = new import_utils17.Emitter();
|
|
3015
|
+
/**
|
|
3016
|
+
* reset layout事件
|
|
3017
|
+
*/
|
|
3018
|
+
this.onResetLayout = this._resetLayoutEmitter.event;
|
|
3019
|
+
this._toDispose = new import_utils17.DisposableCollection();
|
|
3020
|
+
}
|
|
3021
|
+
init() {
|
|
3022
|
+
this._toDispose.push(this._resetLayoutEmitter);
|
|
3023
|
+
}
|
|
3024
|
+
/**
|
|
3025
|
+
* 触发重置布局
|
|
3026
|
+
* @param nodeIds 节点id
|
|
3027
|
+
* @param positionMap 新布局数据
|
|
3028
|
+
* @param oldPositionMap 老布局数据
|
|
3029
|
+
*/
|
|
3030
|
+
fireResetLayout(nodeIds, positionMap, oldPositionMap) {
|
|
3031
|
+
this._resetLayoutEmitter.fire({
|
|
3032
|
+
nodeIds,
|
|
3033
|
+
positionMap,
|
|
3034
|
+
oldPositionMap
|
|
3035
|
+
});
|
|
3036
|
+
}
|
|
3037
|
+
/**
|
|
3038
|
+
* 根据数据重新布局
|
|
3039
|
+
* @param positionMap
|
|
3040
|
+
* @returns
|
|
3041
|
+
*/
|
|
3042
|
+
async layoutToPositions(nodeIds, positionMap) {
|
|
3043
|
+
const nodes = nodeIds.map((id) => this._entityManager.getEntityById(id)).filter(Boolean);
|
|
3044
|
+
const positions = await layoutToPositions(nodes, positionMap);
|
|
3045
|
+
fitView(this._document, this._config, true);
|
|
3046
|
+
return positions;
|
|
3047
|
+
}
|
|
3048
|
+
/**
|
|
3049
|
+
* 销毁
|
|
3050
|
+
*/
|
|
3051
|
+
dispose() {
|
|
3052
|
+
this._toDispose.dispose();
|
|
3053
|
+
}
|
|
3054
|
+
};
|
|
3055
|
+
__decorateClass([
|
|
3056
|
+
(0, import_inversify7.inject)(import_core17.PlaygroundConfigEntity)
|
|
3057
|
+
], WorkflowResetLayoutService.prototype, "_config", 2);
|
|
3058
|
+
__decorateClass([
|
|
3059
|
+
(0, import_inversify7.inject)(WorkflowDocument)
|
|
3060
|
+
], WorkflowResetLayoutService.prototype, "_document", 2);
|
|
3061
|
+
__decorateClass([
|
|
3062
|
+
(0, import_inversify7.inject)(import_core18.EntityManager)
|
|
3063
|
+
], WorkflowResetLayoutService.prototype, "_entityManager", 2);
|
|
3064
|
+
__decorateClass([
|
|
3065
|
+
(0, import_inversify7.postConstruct)()
|
|
3066
|
+
], WorkflowResetLayoutService.prototype, "init", 1);
|
|
3067
|
+
WorkflowResetLayoutService = __decorateClass([
|
|
3068
|
+
(0, import_inversify7.injectable)()
|
|
3069
|
+
], WorkflowResetLayoutService);
|
|
3070
|
+
|
|
3071
|
+
// src/service/workflow-operation-base-service.ts
|
|
3072
|
+
var import_inversify8 = require("inversify");
|
|
3073
|
+
var import_utils19 = require("@flowgram.ai/utils");
|
|
3074
|
+
var import_document11 = require("@flowgram.ai/document");
|
|
3075
|
+
var import_core19 = require("@flowgram.ai/core");
|
|
3076
|
+
var WorkflowOperationBaseServiceImpl = class extends import_document11.FlowOperationBaseServiceImpl {
|
|
3077
|
+
constructor() {
|
|
3078
|
+
super(...arguments);
|
|
3079
|
+
this.onNodePostionUpdateEmitter = new import_utils19.Emitter();
|
|
3080
|
+
this.onNodePostionUpdate = this.onNodePostionUpdateEmitter.event;
|
|
3081
|
+
}
|
|
3082
|
+
updateNodePosition(nodeOrId, position) {
|
|
3083
|
+
const node = this.toNodeEntity(nodeOrId);
|
|
3084
|
+
if (!node) {
|
|
3085
|
+
return;
|
|
3086
|
+
}
|
|
3087
|
+
const transformData = node.getData(import_core19.TransformData);
|
|
3088
|
+
const oldPosition = {
|
|
3089
|
+
x: transformData.position.x,
|
|
3090
|
+
y: transformData.position.y
|
|
3091
|
+
};
|
|
3092
|
+
transformData.update({
|
|
3093
|
+
position
|
|
3094
|
+
});
|
|
3095
|
+
this.onNodePostionUpdateEmitter.fire({
|
|
3096
|
+
node,
|
|
3097
|
+
oldPosition,
|
|
3098
|
+
newPosition: position
|
|
3099
|
+
});
|
|
3100
|
+
}
|
|
3101
|
+
};
|
|
3102
|
+
__decorateClass([
|
|
3103
|
+
(0, import_inversify8.inject)(WorkflowDocument)
|
|
3104
|
+
], WorkflowOperationBaseServiceImpl.prototype, "document", 2);
|
|
3105
|
+
|
|
3106
|
+
// src/hooks/use-playground-readonly-state.ts
|
|
3107
|
+
var import_react = require("react");
|
|
3108
|
+
var import_core20 = require("@flowgram.ai/core");
|
|
3109
|
+
function usePlaygroundReadonlyState(listenChange) {
|
|
3110
|
+
const playground = (0, import_core20.usePlayground)();
|
|
3111
|
+
const refresh = (0, import_core20.useRefresh)();
|
|
3112
|
+
(0, import_react.useEffect)(() => {
|
|
3113
|
+
let dispose = void 0;
|
|
3114
|
+
if (listenChange) {
|
|
3115
|
+
dispose = playground.config.onReadonlyOrDisabledChange(() => refresh());
|
|
3116
|
+
}
|
|
3117
|
+
return () => dispose?.dispose();
|
|
3118
|
+
}, [listenChange]);
|
|
3119
|
+
return playground.config.readonly;
|
|
3120
|
+
}
|
|
3121
|
+
|
|
3122
|
+
// src/hooks/use-node-render.tsx
|
|
3123
|
+
function checkTargetDraggable(el) {
|
|
3124
|
+
return el && el.tagName !== "INPUT" && el.tagName !== "TEXTAREA" && !el.closest(".flow-canvas-not-draggable");
|
|
3125
|
+
}
|
|
3126
|
+
function useNodeRender(nodeFromProps) {
|
|
3127
|
+
const node = nodeFromProps || (0, import_react2.useContext)(import_core21.PlaygroundEntityContext);
|
|
3128
|
+
const renderData = node.getData(import_document12.FlowNodeRenderData);
|
|
3129
|
+
const portsData = node.getData(WorkflowNodePortsData);
|
|
3130
|
+
const readonly = usePlaygroundReadonlyState();
|
|
3131
|
+
const dragService = (0, import_core21.useService)(WorkflowDragService);
|
|
3132
|
+
const selectionService = (0, import_core21.useService)(WorkflowSelectService);
|
|
3133
|
+
const isDragging = (0, import_react2.useRef)(false);
|
|
3134
|
+
const [formValueVersion, updateFormValueVersion] = (0, import_react2.useState)(0);
|
|
3135
|
+
const formValueDependRef = (0, import_react2.useRef)(false);
|
|
3136
|
+
formValueDependRef.current = false;
|
|
3137
|
+
const nodeRef = (0, import_react2.useRef)(null);
|
|
3138
|
+
const [linkingNodeId, setLinkingNodeId] = (0, import_react2.useState)("");
|
|
3139
|
+
(0, import_react2.useEffect)(() => {
|
|
3140
|
+
const disposable = dragService.onDragLineEventChange(({ type, onDragNodeId }) => {
|
|
3141
|
+
if (type === "onDrag") {
|
|
3142
|
+
setLinkingNodeId(onDragNodeId || "");
|
|
3143
|
+
} else {
|
|
3144
|
+
setLinkingNodeId("");
|
|
3145
|
+
}
|
|
3146
|
+
});
|
|
3147
|
+
return () => {
|
|
3148
|
+
disposable.dispose();
|
|
3149
|
+
};
|
|
3150
|
+
}, []);
|
|
3151
|
+
const startDrag = (0, import_react2.useCallback)(
|
|
3152
|
+
(e) => {
|
|
3153
|
+
import_core21.MouseTouchEvent.preventDefault(e);
|
|
3154
|
+
if (!selectionService.isSelected(node.id)) {
|
|
3155
|
+
selectNode(e);
|
|
3156
|
+
}
|
|
3157
|
+
if (!import_core21.MouseTouchEvent.isTouchEvent(e)) {
|
|
3158
|
+
if (!checkTargetDraggable(e.target) || !checkTargetDraggable(document.activeElement)) {
|
|
3159
|
+
return;
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
isDragging.current = true;
|
|
3163
|
+
dragService.startDragSelectedNodes(e)?.finally(
|
|
3164
|
+
() => setTimeout(() => {
|
|
3165
|
+
isDragging.current = false;
|
|
3166
|
+
})
|
|
3167
|
+
);
|
|
3168
|
+
},
|
|
3169
|
+
[dragService, node]
|
|
3170
|
+
);
|
|
3171
|
+
const selectNode = (0, import_react2.useCallback)(
|
|
3172
|
+
(e) => {
|
|
3173
|
+
if (isDragging.current) {
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
if (e.shiftKey) {
|
|
3177
|
+
selectionService.toggleSelect(node);
|
|
3178
|
+
} else {
|
|
3179
|
+
selectionService.selectNode(node);
|
|
3180
|
+
}
|
|
3181
|
+
if (e.target) {
|
|
3182
|
+
e.target.focus();
|
|
3183
|
+
}
|
|
3184
|
+
},
|
|
3185
|
+
[node]
|
|
3186
|
+
);
|
|
3187
|
+
const deleteNode = (0, import_react2.useCallback)(() => node.dispose(), [node]);
|
|
3188
|
+
(0, import_core21.useListenEvents)(portsData.onDataChange);
|
|
3189
|
+
const isFirefox = navigator?.userAgent?.includes?.("Firefox");
|
|
3190
|
+
const onFocus = (0, import_react2.useCallback)(() => {
|
|
3191
|
+
if (isFirefox) {
|
|
3192
|
+
nodeRef.current?.setAttribute("draggable", "false");
|
|
3193
|
+
}
|
|
3194
|
+
}, []);
|
|
3195
|
+
const onBlur = (0, import_react2.useCallback)(() => {
|
|
3196
|
+
if (isFirefox) {
|
|
3197
|
+
nodeRef.current?.setAttribute("draggable", "true");
|
|
3198
|
+
}
|
|
3199
|
+
}, []);
|
|
3200
|
+
const getExtInfo = (0, import_react2.useCallback)(() => node.getExtInfo(), [node]);
|
|
3201
|
+
const updateExtInfo = (0, import_react2.useCallback)(
|
|
3202
|
+
(data) => {
|
|
3203
|
+
node.updateExtInfo(data);
|
|
3204
|
+
},
|
|
3205
|
+
[node]
|
|
3206
|
+
);
|
|
3207
|
+
const form = (0, import_react2.useMemo)(() => (0, import_node.getNodeForm)(node), [node]);
|
|
3208
|
+
const formState = (0, import_reactive.useObserve)(form?.state);
|
|
3209
|
+
const toggleExpand = (0, import_react2.useCallback)(() => {
|
|
3210
|
+
renderData.toggleExpand();
|
|
3211
|
+
}, [renderData]);
|
|
3212
|
+
const selected = selectionService.isSelected(node.id);
|
|
3213
|
+
const activated = selectionService.isActivated(node.id);
|
|
3214
|
+
const expanded = renderData.expanded;
|
|
3215
|
+
(0, import_react2.useEffect)(() => {
|
|
3216
|
+
const toDispose = form?.onFormValuesChange(() => {
|
|
3217
|
+
if (formValueDependRef.current) {
|
|
3218
|
+
updateFormValueVersion((v) => v + 1);
|
|
3219
|
+
}
|
|
3220
|
+
});
|
|
3221
|
+
return () => toDispose?.dispose();
|
|
3222
|
+
}, [form]);
|
|
3223
|
+
return (0, import_react2.useMemo)(
|
|
3224
|
+
() => ({
|
|
3225
|
+
id: node.id,
|
|
3226
|
+
type: node.flowNodeType,
|
|
3227
|
+
get data() {
|
|
3228
|
+
if (form) {
|
|
3229
|
+
formValueDependRef.current = true;
|
|
3230
|
+
return form.values;
|
|
3231
|
+
}
|
|
3232
|
+
return getExtInfo();
|
|
3233
|
+
},
|
|
3234
|
+
updateData(values) {
|
|
3235
|
+
if (form) {
|
|
3236
|
+
form.updateFormValues(values);
|
|
3237
|
+
} else {
|
|
3238
|
+
updateExtInfo(values);
|
|
3239
|
+
}
|
|
3240
|
+
},
|
|
3241
|
+
node,
|
|
3242
|
+
selected,
|
|
3243
|
+
activated,
|
|
3244
|
+
expanded,
|
|
3245
|
+
startDrag,
|
|
3246
|
+
get ports() {
|
|
3247
|
+
return portsData.allPorts;
|
|
3248
|
+
},
|
|
3249
|
+
deleteNode,
|
|
3250
|
+
selectNode,
|
|
3251
|
+
readonly,
|
|
3252
|
+
linkingNodeId,
|
|
3253
|
+
nodeRef,
|
|
3254
|
+
onFocus,
|
|
3255
|
+
onBlur,
|
|
3256
|
+
getExtInfo,
|
|
3257
|
+
updateExtInfo,
|
|
3258
|
+
toggleExpand,
|
|
3259
|
+
get form() {
|
|
3260
|
+
if (!form) return void 0;
|
|
3261
|
+
return {
|
|
3262
|
+
...form,
|
|
3263
|
+
get values() {
|
|
3264
|
+
formValueDependRef.current = true;
|
|
3265
|
+
return form.values;
|
|
3266
|
+
},
|
|
3267
|
+
get state() {
|
|
3268
|
+
return formState;
|
|
3269
|
+
}
|
|
3270
|
+
};
|
|
3271
|
+
}
|
|
3272
|
+
}),
|
|
3273
|
+
[
|
|
3274
|
+
node,
|
|
3275
|
+
selected,
|
|
3276
|
+
activated,
|
|
3277
|
+
expanded,
|
|
3278
|
+
startDrag,
|
|
3279
|
+
deleteNode,
|
|
3280
|
+
selectNode,
|
|
3281
|
+
readonly,
|
|
3282
|
+
linkingNodeId,
|
|
3283
|
+
nodeRef,
|
|
3284
|
+
onFocus,
|
|
3285
|
+
onBlur,
|
|
3286
|
+
getExtInfo,
|
|
3287
|
+
updateExtInfo,
|
|
3288
|
+
toggleExpand,
|
|
3289
|
+
formValueVersion
|
|
3290
|
+
]
|
|
3291
|
+
);
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
// src/hooks/use-current-dom-node.ts
|
|
3295
|
+
var import_document13 = require("@flowgram.ai/document");
|
|
3296
|
+
var import_core22 = require("@flowgram.ai/core");
|
|
3297
|
+
function useCurrentDomNode() {
|
|
3298
|
+
const entity = (0, import_core22.useEntityFromContext)();
|
|
3299
|
+
const renderData = entity.getData(import_document13.FlowNodeRenderData);
|
|
3300
|
+
return renderData.node;
|
|
3301
|
+
}
|
|
3302
|
+
|
|
3303
|
+
// src/hooks/use-current-entity.ts
|
|
3304
|
+
var import_core23 = require("@flowgram.ai/core");
|
|
3305
|
+
function useCurrentEntity() {
|
|
3306
|
+
return (0, import_core23.useEntityFromContext)();
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3309
|
+
// src/hooks/use-workflow-document.ts
|
|
3310
|
+
var import_core24 = require("@flowgram.ai/core");
|
|
3311
|
+
function useWorkflowDocument() {
|
|
3312
|
+
return (0, import_core24.useService)(WorkflowDocument);
|
|
3313
|
+
}
|
|
3314
|
+
|
|
3315
|
+
// src/constants.ts
|
|
3316
|
+
var EditorCursorState = /* @__PURE__ */ ((EditorCursorState2) => {
|
|
3317
|
+
EditorCursorState2["GRAB"] = "GRAB";
|
|
3318
|
+
EditorCursorState2["SELECT"] = "SELECT";
|
|
3319
|
+
return EditorCursorState2;
|
|
3320
|
+
})(EditorCursorState || {});
|
|
3321
|
+
var InteractiveType = /* @__PURE__ */ ((InteractiveType2) => {
|
|
3322
|
+
InteractiveType2["MOUSE"] = "MOUSE";
|
|
3323
|
+
InteractiveType2["PAD"] = "PAD";
|
|
3324
|
+
return InteractiveType2;
|
|
3325
|
+
})(InteractiveType || {});
|
|
3326
|
+
|
|
3327
|
+
// src/workflow-document-container-module.ts
|
|
3328
|
+
var import_inversify10 = require("inversify");
|
|
3329
|
+
var import_utils20 = require("@flowgram.ai/utils");
|
|
3330
|
+
var import_document15 = require("@flowgram.ai/document");
|
|
3331
|
+
|
|
3332
|
+
// src/workflow-document-contribution.ts
|
|
3333
|
+
var import_inversify9 = require("inversify");
|
|
3334
|
+
var import_document14 = require("@flowgram.ai/document");
|
|
3335
|
+
var WorkflowDocumentContribution = class {
|
|
3336
|
+
registerDocument(document2) {
|
|
3337
|
+
document2.registerNodeDatas(
|
|
3338
|
+
import_document14.FlowNodeTransformData,
|
|
3339
|
+
import_document14.FlowNodeRenderData,
|
|
3340
|
+
WorkflowNodePortsData,
|
|
3341
|
+
WorkflowNodeLinesData
|
|
3342
|
+
);
|
|
3343
|
+
document2.registerLayout(this.freeLayout);
|
|
3344
|
+
}
|
|
3345
|
+
};
|
|
3346
|
+
__decorateClass([
|
|
3347
|
+
(0, import_inversify9.inject)(FreeLayout)
|
|
3348
|
+
], WorkflowDocumentContribution.prototype, "freeLayout", 2);
|
|
3349
|
+
WorkflowDocumentContribution = __decorateClass([
|
|
3350
|
+
(0, import_inversify9.injectable)()
|
|
3351
|
+
], WorkflowDocumentContribution);
|
|
3352
|
+
|
|
3353
|
+
// src/utils/get-url-params.ts
|
|
3354
|
+
function getUrlParams() {
|
|
3355
|
+
return location.search.replace(/^\?/, "").split("&").reduce((res, key) => {
|
|
3356
|
+
const [k, v] = key.split("=");
|
|
3357
|
+
res[k] = v;
|
|
3358
|
+
return res;
|
|
3359
|
+
}, {});
|
|
3360
|
+
}
|
|
3361
|
+
|
|
3362
|
+
// src/workflow-document-container-module.ts
|
|
3363
|
+
var WorkflowDocumentContainerModule = new import_inversify10.ContainerModule(
|
|
3364
|
+
(bind, unbind, isBound, rebind) => {
|
|
3365
|
+
bind(WorkflowDocument).toSelf().inSingletonScope();
|
|
3366
|
+
bind(WorkflowLinesManager).toSelf().inSingletonScope();
|
|
3367
|
+
bind(FreeLayout).toSelf().inSingletonScope();
|
|
3368
|
+
bind(WorkflowDragService).toSelf().inSingletonScope();
|
|
3369
|
+
bind(WorkflowSelectService).toSelf().inSingletonScope();
|
|
3370
|
+
bind(WorkflowHoverService).toSelf().inSingletonScope();
|
|
3371
|
+
bind(WorkflowResetLayoutService).toSelf().inSingletonScope();
|
|
3372
|
+
bind(WorkflowOperationBaseService).to(WorkflowOperationBaseServiceImpl).inSingletonScope();
|
|
3373
|
+
bind(URLParams).toDynamicValue(() => getUrlParams()).inSingletonScope();
|
|
3374
|
+
(0, import_utils20.bindContributions)(bind, WorkflowDocumentContribution, [import_document15.FlowDocumentContribution]);
|
|
3375
|
+
bind(WorkflowDocumentOptions).toConstantValue({
|
|
3376
|
+
...WorkflowDocumentOptionsDefault
|
|
3377
|
+
});
|
|
3378
|
+
rebind(import_document15.FlowDocument).toService(WorkflowDocument);
|
|
3379
|
+
bind(WorkflowDocumentProvider).toDynamicValue((ctx) => () => ctx.container.get(WorkflowDocument)).inSingletonScope();
|
|
3380
|
+
}
|
|
3381
|
+
);
|
|
3382
|
+
|
|
3383
|
+
// src/utils/simple-line.ts
|
|
3384
|
+
var import_utils21 = require("@flowgram.ai/utils");
|
|
3385
|
+
var LINE_PADDING = 12;
|
|
3386
|
+
var WorkflowSimpleLineContribution = class {
|
|
3387
|
+
constructor(entity) {
|
|
3388
|
+
this.entity = entity;
|
|
3389
|
+
}
|
|
3390
|
+
get path() {
|
|
3391
|
+
return this.data?.path ?? "";
|
|
3392
|
+
}
|
|
3393
|
+
calcDistance(pos) {
|
|
3394
|
+
if (!this.data) {
|
|
3395
|
+
return Number.MAX_SAFE_INTEGER;
|
|
3396
|
+
}
|
|
3397
|
+
const [start, end] = this.data.points;
|
|
3398
|
+
return import_utils21.Point.getDistance(pos, this.projectPointOnLine(pos, start, end));
|
|
3399
|
+
}
|
|
3400
|
+
get bounds() {
|
|
3401
|
+
if (!this.data) {
|
|
3402
|
+
return new import_utils21.Rectangle();
|
|
3403
|
+
}
|
|
3404
|
+
return this.data.bbox;
|
|
3405
|
+
}
|
|
3406
|
+
update(params) {
|
|
3407
|
+
const { fromPos, toPos } = params;
|
|
3408
|
+
const { vertical } = this.entity;
|
|
3409
|
+
const sourceOffset = {
|
|
3410
|
+
x: vertical ? 0 : POINT_RADIUS,
|
|
3411
|
+
y: vertical ? POINT_RADIUS : 0
|
|
3412
|
+
};
|
|
3413
|
+
const targetOffset = {
|
|
3414
|
+
x: vertical ? 0 : -POINT_RADIUS,
|
|
3415
|
+
y: vertical ? -POINT_RADIUS : 0
|
|
3416
|
+
};
|
|
3417
|
+
const points = [
|
|
3418
|
+
{
|
|
3419
|
+
x: fromPos.x + sourceOffset.x,
|
|
3420
|
+
y: fromPos.y + sourceOffset.y
|
|
3421
|
+
},
|
|
3422
|
+
{
|
|
3423
|
+
x: toPos.x + targetOffset.x,
|
|
3424
|
+
y: toPos.y + targetOffset.y
|
|
3425
|
+
}
|
|
3426
|
+
];
|
|
3427
|
+
const bbox = import_utils21.Rectangle.createRectangleWithTwoPoints(points[0], points[1]);
|
|
3428
|
+
const adjustedPoints = points.map((p) => ({
|
|
3429
|
+
x: p.x - bbox.x + LINE_PADDING,
|
|
3430
|
+
y: p.y - bbox.y + LINE_PADDING
|
|
3431
|
+
}));
|
|
3432
|
+
const path = `M ${adjustedPoints[0].x} ${adjustedPoints[0].y} L ${adjustedPoints[1].x} ${adjustedPoints[1].y}`;
|
|
3433
|
+
this.data = {
|
|
3434
|
+
points,
|
|
3435
|
+
path,
|
|
3436
|
+
bbox
|
|
3437
|
+
};
|
|
3438
|
+
}
|
|
3439
|
+
projectPointOnLine(point, lineStart, lineEnd) {
|
|
3440
|
+
const dx = lineEnd.x - lineStart.x;
|
|
3441
|
+
const dy = lineEnd.y - lineStart.y;
|
|
3442
|
+
if (dx === 0) {
|
|
3443
|
+
return { x: lineStart.x, y: point.y };
|
|
3444
|
+
}
|
|
3445
|
+
if (dy === 0) {
|
|
3446
|
+
return { x: point.x, y: lineStart.y };
|
|
3447
|
+
}
|
|
3448
|
+
const t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / (dx * dx + dy * dy);
|
|
3449
|
+
const clampedT = Math.max(0, Math.min(1, t));
|
|
3450
|
+
return {
|
|
3451
|
+
x: lineStart.x + clampedT * dx,
|
|
3452
|
+
y: lineStart.y + clampedT * dy
|
|
3453
|
+
};
|
|
3454
|
+
}
|
|
3455
|
+
};
|
|
3456
|
+
WorkflowSimpleLineContribution.type = "WorkflowSimpleLineContribution";
|
|
3457
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3458
|
+
0 && (module.exports = {
|
|
3459
|
+
EditorCursorState,
|
|
3460
|
+
InteractiveType,
|
|
3461
|
+
LINE_HOVER_DISTANCE,
|
|
3462
|
+
LineColors,
|
|
3463
|
+
LineType,
|
|
3464
|
+
POINT_RADIUS,
|
|
3465
|
+
PORT_SIZE,
|
|
3466
|
+
URLParams,
|
|
3467
|
+
WORKFLOW_LINE_ENTITY,
|
|
3468
|
+
WorkflowCommands,
|
|
3469
|
+
WorkflowContentChangeType,
|
|
3470
|
+
WorkflowDocument,
|
|
3471
|
+
WorkflowDocumentContainerModule,
|
|
3472
|
+
WorkflowDocumentOptions,
|
|
3473
|
+
WorkflowDocumentOptionsDefault,
|
|
3474
|
+
WorkflowDocumentProvider,
|
|
3475
|
+
WorkflowDragService,
|
|
3476
|
+
WorkflowHoverService,
|
|
3477
|
+
WorkflowLineEntity,
|
|
3478
|
+
WorkflowLineRenderData,
|
|
3479
|
+
WorkflowLinesManager,
|
|
3480
|
+
WorkflowNodeEntity,
|
|
3481
|
+
WorkflowNodeLinesData,
|
|
3482
|
+
WorkflowNodePortsData,
|
|
3483
|
+
WorkflowOperationBaseService,
|
|
3484
|
+
WorkflowOperationBaseServiceImpl,
|
|
3485
|
+
WorkflowPortEntity,
|
|
3486
|
+
WorkflowResetLayoutService,
|
|
3487
|
+
WorkflowSelectService,
|
|
3488
|
+
WorkflowSimpleLineContribution,
|
|
3489
|
+
bindConfigEntity,
|
|
3490
|
+
compose,
|
|
3491
|
+
composeAsync,
|
|
3492
|
+
delay,
|
|
3493
|
+
domReactToBounds,
|
|
3494
|
+
fitView,
|
|
3495
|
+
getAntiOverlapPosition,
|
|
3496
|
+
getPortEntityId,
|
|
3497
|
+
nanoid,
|
|
3498
|
+
useConfigEntity,
|
|
3499
|
+
useCurrentDomNode,
|
|
3500
|
+
useCurrentEntity,
|
|
3501
|
+
useEntities,
|
|
3502
|
+
useEntityDataFromContext,
|
|
3503
|
+
useEntityFromContext,
|
|
3504
|
+
useListenEvents,
|
|
3505
|
+
useNodeRender,
|
|
3506
|
+
usePlayground,
|
|
3507
|
+
usePlaygroundContainer,
|
|
3508
|
+
usePlaygroundContext,
|
|
3509
|
+
usePlaygroundLatest,
|
|
3510
|
+
usePlaygroundReadonlyState,
|
|
3511
|
+
useRefresh,
|
|
3512
|
+
useService,
|
|
3513
|
+
useWorkflowDocument
|
|
3514
|
+
});
|
|
3515
|
+
//# sourceMappingURL=index.js.map
|