@yarkivaev/scada 2.3.64 → 2.3.65
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/package.json
CHANGED
|
@@ -43,6 +43,9 @@ export default function infraRoute() {
|
|
|
43
43
|
route('GET', '/infra/graph.js', (req, res) => {
|
|
44
44
|
sendFile(res, 'infra/graph.js', 'text/javascript; charset=utf-8');
|
|
45
45
|
}),
|
|
46
|
+
route('GET', '/infra/graphLayout.js', (req, res) => {
|
|
47
|
+
sendFile(res, 'infra/graphLayout.js', 'text/javascript; charset=utf-8');
|
|
48
|
+
}),
|
|
46
49
|
route('GET', '/infra/panel.js', (req, res) => {
|
|
47
50
|
sendFile(res, 'infra/panel.js', 'text/javascript; charset=utf-8');
|
|
48
51
|
})
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import positions from './graphLayout.js';
|
|
2
|
+
|
|
1
3
|
const SVG = 'http://www.w3.org/2000/svg';
|
|
2
4
|
|
|
3
5
|
function shops(nodes) {
|
|
@@ -6,31 +8,11 @@ function shops(nodes) {
|
|
|
6
8
|
});
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function placed(graph) {
|
|
16
|
-
const positions = {};
|
|
17
|
-
shops(graph.nodes).forEach((area, i) => {
|
|
18
|
-
const x = 170 + i * 280;
|
|
19
|
-
positions[area.id] = { x, y: 56 };
|
|
20
|
-
children(graph.nodes, area.id, 'machine').forEach((item, j) => {
|
|
21
|
-
const y = 150 + j * 96;
|
|
22
|
-
positions[item.id] = { x, y };
|
|
23
|
-
children(graph.nodes, item.id, 'collector').forEach((col, k) => {
|
|
24
|
-
positions[col.id] = { x: x + 96, y: y + k * 26 };
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
graph.nodes.filter((node) => {
|
|
29
|
-
return node.kind === 'collector' && !positions[node.id];
|
|
30
|
-
}).forEach((node, i) => {
|
|
31
|
-
positions[node.id] = { x: 72, y: 88 + i * 54 };
|
|
11
|
+
function floor(placed) {
|
|
12
|
+
const ys = Object.values(placed).map((item) => {
|
|
13
|
+
return item.y + 80;
|
|
32
14
|
});
|
|
33
|
-
return
|
|
15
|
+
return Math.max(520, ...ys);
|
|
34
16
|
}
|
|
35
17
|
|
|
36
18
|
function el(name, attrs) {
|
|
@@ -41,10 +23,10 @@ function el(name, attrs) {
|
|
|
41
23
|
return node;
|
|
42
24
|
}
|
|
43
25
|
|
|
44
|
-
function paintLink(svg, graph,
|
|
26
|
+
function paintLink(svg, graph, laid) {
|
|
45
27
|
graph.links.forEach((link) => {
|
|
46
|
-
const from =
|
|
47
|
-
const to =
|
|
28
|
+
const from = laid[link.from];
|
|
29
|
+
const to = laid[link.to];
|
|
48
30
|
if (!from || !to) {
|
|
49
31
|
return;
|
|
50
32
|
}
|
|
@@ -95,12 +77,12 @@ export default function draw(svg, graph, onClick) {
|
|
|
95
77
|
svg.removeChild(svg.firstChild);
|
|
96
78
|
}
|
|
97
79
|
const columns = Math.max(shops(graph.nodes).length, 1);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
paintLink(svg, graph,
|
|
80
|
+
const laid = positions(graph);
|
|
81
|
+
svg.setAttribute('viewBox', `0 0 ${Math.max(960, columns * 280 + 120)} ${floor(laid)}`);
|
|
82
|
+
paintLink(svg, graph, laid);
|
|
101
83
|
graph.nodes.forEach((node) => {
|
|
102
|
-
if (
|
|
103
|
-
paintNode(svg, node,
|
|
84
|
+
if (laid[node.id]) {
|
|
85
|
+
paintNode(svg, node, laid[node.id], onClick);
|
|
104
86
|
}
|
|
105
87
|
});
|
|
106
88
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function shops(nodes) {
|
|
2
|
+
return nodes.filter((node) => {
|
|
3
|
+
return node.kind === 'shop';
|
|
4
|
+
});
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function children(nodes, parentId, kind) {
|
|
8
|
+
return nodes.filter((node) => {
|
|
9
|
+
return node.parent === parentId && node.kind === kind;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function nest(nodes, item, x, y, placed) {
|
|
14
|
+
children(nodes, item.id, 'collector').forEach((col, k) => {
|
|
15
|
+
placed[col.id] = { x: x + 96, y: y + k * 26 };
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function machines(nodes, area, x, base, placed) {
|
|
20
|
+
children(nodes, area.id, 'machine').forEach((item, j) => {
|
|
21
|
+
const y = base + j * 96;
|
|
22
|
+
placed[item.id] = { x, y };
|
|
23
|
+
nest(nodes, item, x, y, placed);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function extras(nodes, area, x, placed) {
|
|
28
|
+
const items = children(nodes, area.id, 'collector');
|
|
29
|
+
items.forEach((col, k) => {
|
|
30
|
+
placed[col.id] = { x, y: 108 + k * 28 };
|
|
31
|
+
});
|
|
32
|
+
return items.length;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function column(area, index, nodes, placed) {
|
|
36
|
+
const x = 170 + index * 280;
|
|
37
|
+
placed[area.id] = { x, y: 56 };
|
|
38
|
+
const count = extras(nodes, area, x, placed);
|
|
39
|
+
const base = count === 0 ? 150 : 108 + count * 28 + 50;
|
|
40
|
+
machines(nodes, area, x, base, placed);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function leftovers(nodes, placed) {
|
|
44
|
+
nodes.filter((node) => {
|
|
45
|
+
return node.kind === 'collector' && !placed[node.id];
|
|
46
|
+
}).forEach((node, i) => {
|
|
47
|
+
placed[node.id] = { x: 72, y: 88 + i * 54 };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Column positions for topology nodes by parent and kind.
|
|
53
|
+
*
|
|
54
|
+
* @param {object} graph - topology contract { nodes }
|
|
55
|
+
* @returns {object} id -> { x, y }
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* positions({ nodes: [{ id: 'area-1', kind: 'shop' }] })['area-1'].x === 170;
|
|
59
|
+
*/
|
|
60
|
+
export default function positions(graph) {
|
|
61
|
+
const nodes = graph.nodes || [];
|
|
62
|
+
const placed = {};
|
|
63
|
+
shops(nodes).forEach((area, i) => {
|
|
64
|
+
column(area, i, nodes, placed);
|
|
65
|
+
});
|
|
66
|
+
leftovers(nodes, placed);
|
|
67
|
+
return placed;
|
|
68
|
+
}
|