@receptron/graphai_vue_cytoscape 0.0.9 → 0.0.11

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/lib/bundle.umd.js CHANGED
@@ -1,7 +1,7 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue'), require('graphai'), require('cytoscape'), require('cytoscape-klay')) :
3
3
  typeof define === 'function' && define.amd ? define(['exports', 'vue', 'graphai', 'cytoscape', 'cytoscape-klay'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.vue_cytoscape = {}, global.vue, global.graphai, global.cytoscape, global.klay));
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.vue_cytoscape = {}, global.vue, global.graphai, global.cytoscape, global.cytoscapeKlay));
5
5
  })(this, (function (exports, vue, graphai, cytoscape, klay) { 'use strict';
6
6
 
7
7
  cytoscape.use(klay);
@@ -0,0 +1,293 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue'), require('graphai'), require('cytoscape'), require('cytoscape-klay')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'vue', 'graphai', 'cytoscape', 'cytoscape-klay'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.vue_cytoscape = {}, global.vue, global.graphai, global.cytoscape, global["cytoscape-klay"]));
5
+ })(this, (function (exports, vue, graphai, cytoscape, klay) { 'use strict';
6
+
7
+ cytoscape.use(klay);
8
+ const layout = "klay";
9
+ const colorPriority = "#f80";
10
+ const colorStatic = "#88f";
11
+ const calcNodeWidth = (label) => {
12
+ if (label === null || label === undefined) {
13
+ return "50px";
14
+ }
15
+ return Math.max(50, label.length * 8) + "px";
16
+ };
17
+ const cyStyle = [
18
+ {
19
+ selector: "node",
20
+ style: {
21
+ "background-color": "data(color)",
22
+ label: "data(id)",
23
+ shape: (ele) => (ele.data("isStatic") ? "rectangle" : "roundrectangle"),
24
+ width: (ele) => calcNodeWidth(ele.data("id")),
25
+ color: "#fff",
26
+ height: "30px",
27
+ "text-valign": "center",
28
+ "text-halign": "center",
29
+ "font-size": "12px",
30
+ },
31
+ },
32
+ {
33
+ selector: "edge",
34
+ style: {
35
+ width: 3,
36
+ "line-color": "#888",
37
+ "target-arrow-color": "#888",
38
+ "target-arrow-shape": "triangle",
39
+ "curve-style": "straight",
40
+ "text-background-color": "#ffffff",
41
+ "text-background-opacity": 0.8,
42
+ "text-background-shape": "rectangle",
43
+ "font-size": "10px",
44
+ },
45
+ },
46
+ {
47
+ selector: "edge[label]",
48
+ style: {
49
+ label: "data(label)",
50
+ },
51
+ },
52
+ {
53
+ selector: "edge[isUpdate]",
54
+ style: {
55
+ color: "#ddd",
56
+ "line-color": "#ddd",
57
+ "line-style": "dashed",
58
+ "curve-style": "unbundled-bezier",
59
+ "target-arrow-color": "#ddd",
60
+ },
61
+ },
62
+ ];
63
+ const colorMap = {
64
+ [graphai.NodeState.Waiting]: "#888",
65
+ [graphai.NodeState.Completed]: "#000",
66
+ [graphai.NodeState.Executing]: "#0f0",
67
+ ["executing-server"]: "#FFC0CB",
68
+ [graphai.NodeState.Queued]: "#ff0",
69
+ [graphai.NodeState.Injected]: "#00f",
70
+ [graphai.NodeState.TimedOut]: "#f0f",
71
+ [graphai.NodeState.Failed]: "#f00",
72
+ [graphai.NodeState.Skipped]: "#0ff",
73
+ };
74
+ const parseInput = (input) => {
75
+ // WARNING: Assuming the first character is always ":"
76
+ const ids = input.slice(1).split(".");
77
+ const source = ids.shift() || "";
78
+ const label = ids.length ? ids.join(".") : undefined;
79
+ return { source, label };
80
+ };
81
+ const inputs2dataSources = (inputs) => {
82
+ if (Array.isArray(inputs)) {
83
+ return inputs.map((inp) => inputs2dataSources(inp)).flat();
84
+ }
85
+ if (graphai.isObject(inputs)) {
86
+ return Object.values(inputs)
87
+ .map((input) => inputs2dataSources(input))
88
+ .flat();
89
+ }
90
+ if (typeof inputs === "string") {
91
+ const templateMatch = Array.from(inputs.matchAll(/\${(:[^}]+)}/g)).map((m) => m[1]);
92
+ if (templateMatch.length > 0) {
93
+ return inputs2dataSources(templateMatch);
94
+ }
95
+ }
96
+ return inputs;
97
+ };
98
+ const dataSourceNodeIds = (sources) => {
99
+ return sources.filter((source) => source.nodeId).map((source) => source.nodeId);
100
+ };
101
+ const cytoscapeFromGraph = (graph_data) => {
102
+ const elements = Object.keys(graph_data.nodes || {}).reduce((tmp, nodeId) => {
103
+ const node = graph_data.nodes[nodeId];
104
+ const isStatic = "value" in node;
105
+ const cyNode = {
106
+ data: {
107
+ id: nodeId,
108
+ color: isStatic ? colorStatic : colorMap[graphai.NodeState.Waiting],
109
+ isStatic,
110
+ },
111
+ };
112
+ tmp.nodes.push(cyNode);
113
+ tmp.map[nodeId] = cyNode;
114
+ if ("inputs" in node) {
115
+ // computed node
116
+ inputs2dataSources(node.inputs).forEach((input) => {
117
+ if (input[0] === ":") {
118
+ const { source, label } = parseInput(input);
119
+ tmp.edges.push({
120
+ data: {
121
+ source,
122
+ target: nodeId,
123
+ label,
124
+ },
125
+ });
126
+ }
127
+ });
128
+ }
129
+ if ("update" in node && node.update) {
130
+ // static node
131
+ const { source, label } = parseInput(node.update);
132
+ tmp.edges.push({
133
+ data: {
134
+ source,
135
+ target: nodeId,
136
+ isUpdate: true,
137
+ label,
138
+ },
139
+ });
140
+ }
141
+ return tmp;
142
+ }, { nodes: [], edges: [], map: {} });
143
+ return { elements };
144
+ };
145
+ const useCytoscape = (selectedGraph) => {
146
+ let cy = null;
147
+ const cytoscapeData = vue.ref(cytoscapeFromGraph(selectedGraph.value ?? { nodes: {} }));
148
+ const cytoscapeRef = vue.ref();
149
+ const zoomingEnabled = vue.ref(true);
150
+ const updateCytoscape = async (nodeId, state) => {
151
+ if ([graphai.NodeState.Completed, graphai.NodeState.Waiting].includes(state)) {
152
+ await graphai.sleep(100);
153
+ }
154
+ const elements = cytoscapeData.value.elements;
155
+ elements.map[nodeId].data.color = colorMap[state];
156
+ const graph = selectedGraph.value;
157
+ const nodeData = (graph?.nodes ?? {})[nodeId] ?? [];
158
+ if ("agent" in nodeData && state === graphai.NodeState.Queued && (nodeData.priority ?? 0) > 0) {
159
+ // computed node
160
+ elements.map[nodeId].data.color = colorPriority;
161
+ }
162
+ else if ("value" in nodeData && state === graphai.NodeState.Waiting) {
163
+ // static node
164
+ elements.map[nodeId].data.color = colorStatic;
165
+ }
166
+ cytoscapeData.value = { elements };
167
+ if (state === graphai.NodeState.Injected) {
168
+ await graphai.sleep(100);
169
+ elements.map[nodeId].data.color = colorStatic;
170
+ cytoscapeData.value = { elements };
171
+ }
172
+ };
173
+ const createCytoscape = () => {
174
+ try {
175
+ cy = cytoscape({
176
+ container: cytoscapeRef.value,
177
+ style: cyStyle,
178
+ layout: {
179
+ name: layout,
180
+ // fit: true,
181
+ // padding: 30,
182
+ // avoidOverlap: true,
183
+ },
184
+ });
185
+ cy.on("mouseup", storePositions);
186
+ cy.on("touchend", storePositions);
187
+ // cy.on("select", "node", callback);
188
+ // cy.on("select", "edge", callback);
189
+ //store.commit("setCytoscape", cy);
190
+ }
191
+ catch (error) {
192
+ console.error(error);
193
+ // store.commit("setCytoscape", null);
194
+ // error_msg.value = `${error}`;
195
+ }
196
+ };
197
+ const updateGraphData = async () => {
198
+ if (cy) {
199
+ cy.elements().remove();
200
+ cy.add(cytoscapeData.value.elements);
201
+ const name = cytoscapeData.value.elements.nodes.reduce((prevName, node) => {
202
+ if (node.position) {
203
+ return "preset";
204
+ }
205
+ return prevName;
206
+ }, layout);
207
+ console.log("layout", name);
208
+ cy.layout({ name }).run();
209
+ cy.fit();
210
+ if (name === layout) {
211
+ await graphai.sleep(400);
212
+ storePositions();
213
+ }
214
+ }
215
+ };
216
+ const storePositions = () => {
217
+ console.log("storePositions");
218
+ if (cy) {
219
+ cy.nodes().forEach((cynode) => {
220
+ const id = cynode.id();
221
+ const pos = cynode.position();
222
+ const node = cytoscapeData.value.elements.map[id];
223
+ node.position = pos;
224
+ });
225
+ }
226
+ };
227
+ const resetCytoscape = () => {
228
+ const elements = cytoscapeData.value.elements;
229
+ Object.keys(elements.map).forEach((nodeId) => {
230
+ const graph = selectedGraph.value;
231
+ const nodeData = graph.nodes[nodeId];
232
+ elements.map[nodeId].data.color = "value" in nodeData ? colorStatic : colorMap[graphai.NodeState.Waiting];
233
+ });
234
+ cytoscapeData.value = { elements };
235
+ };
236
+ vue.watch(cytoscapeData, () => {
237
+ console.log("updated");
238
+ updateGraphData();
239
+ });
240
+ vue.watch(selectedGraph, () => {
241
+ cytoscapeData.value = cytoscapeFromGraph(selectedGraph.value);
242
+ });
243
+ vue.onMounted(() => {
244
+ createCytoscape();
245
+ updateGraphData();
246
+ });
247
+ const layoutCytoscape = (key) => {
248
+ if (cy) {
249
+ const positions = cy.nodes().map((node) => {
250
+ return {
251
+ id: node.id(),
252
+ position: node.position(),
253
+ };
254
+ });
255
+ console.log(JSON.stringify(positions));
256
+ localStorage.setItem("layoutData-" + key, JSON.stringify(positions));
257
+ }
258
+ };
259
+ const loadLayout = (key) => {
260
+ const savedLayoutData = localStorage.getItem("layoutData-" + key);
261
+ if (savedLayoutData) {
262
+ const positions = JSON.parse(savedLayoutData);
263
+ positions.forEach((data) => {
264
+ if (cy) {
265
+ const node = cy.getElementById(data.id);
266
+ if (node) {
267
+ node.position(data.position);
268
+ }
269
+ }
270
+ });
271
+ }
272
+ };
273
+ vue.watch(zoomingEnabled, (value) => {
274
+ if (cy) {
275
+ cy.zoomingEnabled(value);
276
+ }
277
+ });
278
+ return {
279
+ cytoscapeRef,
280
+ updateCytoscape,
281
+ resetCytoscape,
282
+ layoutCytoscape,
283
+ loadLayout,
284
+ zoomingEnabled,
285
+ };
286
+ };
287
+
288
+ exports.dataSourceNodeIds = dataSourceNodeIds;
289
+ exports.inputs2dataSources = inputs2dataSources;
290
+ exports.useCytoscape = useCytoscape;
291
+
292
+ }));
293
+ //# sourceMappingURL=bundle.umd.js.map
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "@receptron/graphai_vue_cytoscape",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "main": "lib/cytoscape.js",
5
+ "module": "lib/bundle.esm.js",
6
+ "browser": "lib/bundle.umd.js",
5
7
  "files": [
6
8
  "./lib"
7
9
  ],
8
10
  "scripts": {
9
11
  "dev": "vite",
10
12
  "build": "tsc --esModuleInterop --declaration --outDir lib/ src/composables/cytoscape.ts",
11
- "build_old": "run-p type-check \"build-only {@}\" --",
12
13
  "preview": "vite preview",
13
14
  "build-only": "vite build",
14
15
  "rollup": " npx rollup -c",