@takodotid/circuit 0.34.3 → 0.36.0
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/README.md +14 -15
- package/dist/chunks/index-20kcjxjg.js +174 -0
- package/dist/chunks/index-2r4bbhac.js +977 -0
- package/dist/chunks/index-n7w3tg5y.js +149 -0
- package/dist/chunks/new-w3zys5y4.js +172 -0
- package/dist/chunks/server-gzsf5me5.js +259 -0
- package/dist/cli/index.js +11345 -9024
- package/dist/helpers/index.js +594 -0
- package/dist/index.js +9 -28
- package/dist/types/core/{addresses.d.ts → address-space.d.ts} +23 -7
- package/dist/types/core/address.d.ts +44 -0
- package/dist/types/core/cabling.d.ts +41 -0
- package/dist/types/core/cross-checks.d.ts +28 -0
- package/dist/types/core/define.d.ts +25 -3
- package/dist/types/core/project-files.d.ts +12 -0
- package/dist/types/core/schema-docs.d.ts +13 -4
- package/dist/types/core/secrets.d.ts +62 -21
- package/dist/types/core/{graph.d.ts → topology.d.ts} +32 -12
- package/dist/types/core/utils.d.ts +8 -0
- package/dist/types/core/validator.d.ts +19 -0
- package/dist/types/helpers/bgp.d.ts +97 -0
- package/dist/types/helpers/checks.d.ts +32 -0
- package/dist/types/helpers/exchange.d.ts +49 -0
- package/dist/types/helpers/filters.d.ts +51 -0
- package/dist/types/helpers/index.d.ts +10 -0
- package/dist/types/helpers/route-server.d.ts +52 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/integrations/librenms.d.ts +60 -0
- package/dist/types/integrations/netbox.d.ts +89 -0
- package/dist/types/integrations/peeringdb.d.ts +24 -0
- package/dist/types/integrations/prometheus.d.ts +24 -0
- package/dist/types/integrations/registries.d.ts +8 -0
- package/dist/types/platforms/bgp-wait.d.ts +18 -0
- package/dist/types/platforms/catalog.d.ts +109 -0
- package/dist/types/platforms/derive.d.ts +17 -0
- package/dist/types/platforms/fortios/firewall.d.ts +45 -0
- package/dist/types/platforms/fortios/index.d.ts +134 -0
- package/dist/types/platforms/fortios/names.d.ts +52 -0
- package/dist/types/platforms/fortios/plan.d.ts +104 -0
- package/dist/types/platforms/fortios/render.d.ts +75 -0
- package/dist/types/platforms/fortios/routing.d.ts +56 -0
- package/dist/types/platforms/fortios/tree.d.ts +37 -0
- package/dist/types/platforms/index.d.ts +13 -0
- package/dist/types/platforms/junos/bgp.d.ts +44 -0
- package/dist/types/platforms/junos/index.d.ts +114 -0
- package/dist/types/platforms/junos/render.d.ts +154 -0
- package/dist/types/platforms/line-diff.d.ts +67 -0
- package/dist/types/platforms/platform.d.ts +120 -0
- package/dist/types/platforms/raisecom-ros/index.d.ts +71 -0
- package/dist/types/platforms/raisecom-ros/render.d.ts +41 -0
- package/dist/types/platforms/routeros/export.d.ts +59 -0
- package/dist/types/platforms/routeros/index.d.ts +96 -0
- package/dist/types/{adapters/devices → platforms}/routeros/models.d.ts +4 -0
- package/dist/types/platforms/routeros/plan.d.ts +54 -0
- package/dist/types/platforms/routeros/render.d.ts +240 -0
- package/dist/types/platforms/vrp/index.d.ts +83 -0
- package/dist/types/platforms/vrp/render.d.ts +96 -0
- package/dist/types/schema/common.d.ts +12 -6
- package/dist/types/schema/index.d.ts +1 -0
- package/dist/types/schema/interfaces.d.ts +14 -6
- package/dist/types/schema/policy.d.ts +18 -10
- package/dist/types/schema/routing.d.ts +14 -1
- package/dist/types/schema/system.d.ts +16 -6
- package/dist/types/schema/time-zones.d.ts +2 -0
- package/dist/types/transport/console.d.ts +79 -23
- package/dist/types/transport/path-check.d.ts +32 -0
- package/dist/types/transport/ssh.d.ts +17 -15
- package/package.json +18 -12
- package/src/cli/graph-format.ts +91 -0
- package/src/cli/index.ts +1074 -484
- package/src/cli/new.ts +208 -175
- package/src/cli/rename.ts +97 -91
- package/src/core/address-space.ts +320 -0
- package/src/core/address.ts +202 -0
- package/src/core/cabling.ts +154 -0
- package/src/core/cross-checks.ts +364 -0
- package/src/core/define.ts +26 -3
- package/src/core/project-files.ts +35 -0
- package/src/core/schema-docs.ts +138 -130
- package/src/core/secrets.ts +170 -76
- package/src/core/topology.ts +656 -0
- package/src/core/utils.ts +37 -0
- package/src/core/validator.ts +407 -0
- package/src/helpers/bgp.ts +301 -0
- package/src/helpers/checks.ts +178 -0
- package/src/helpers/exchange.ts +117 -0
- package/src/helpers/filters.ts +107 -0
- package/src/helpers/index.ts +12 -0
- package/src/helpers/route-server.ts +212 -0
- package/src/index.ts +6 -3
- package/src/integrations/librenms.ts +291 -0
- package/src/integrations/netbox.ts +620 -0
- package/src/integrations/peeringdb.ts +173 -0
- package/src/integrations/prometheus.ts +90 -0
- package/src/integrations/registries.ts +25 -0
- package/src/platforms/bgp-wait.ts +41 -0
- package/src/platforms/catalog.ts +69 -0
- package/src/platforms/derive.ts +117 -0
- package/src/{adapters/devices → platforms}/fortios/TRAPS.md +6 -0
- package/src/platforms/fortios/firewall.ts +377 -0
- package/src/platforms/fortios/index.ts +1060 -0
- package/src/platforms/fortios/names.ts +130 -0
- package/src/platforms/fortios/plan.ts +929 -0
- package/src/platforms/fortios/render.ts +779 -0
- package/src/platforms/fortios/routing.ts +476 -0
- package/src/platforms/fortios/tree.ts +129 -0
- package/src/platforms/index.ts +36 -0
- package/src/{adapters/devices → platforms}/junos/TRAPS.md +8 -0
- package/src/platforms/junos/bgp.ts +293 -0
- package/src/platforms/junos/index.ts +1006 -0
- package/src/platforms/junos/render.ts +967 -0
- package/src/platforms/line-diff.ts +244 -0
- package/src/platforms/platform.ts +122 -0
- package/src/platforms/raisecom-ros/TRAPS.md +40 -0
- package/src/platforms/raisecom-ros/index.ts +731 -0
- package/src/platforms/raisecom-ros/render.ts +328 -0
- package/src/{adapters/devices → platforms}/routeros/TRAPS.md +16 -2
- package/src/platforms/routeros/export.ts +342 -0
- package/src/platforms/routeros/index.ts +636 -0
- package/src/{adapters/devices → platforms}/routeros/models.ts +2 -0
- package/src/platforms/routeros/plan.ts +444 -0
- package/src/platforms/routeros/render.ts +1483 -0
- package/src/platforms/vrp/TRAPS.md +45 -0
- package/src/platforms/vrp/index.ts +652 -0
- package/src/platforms/vrp/render.ts +615 -0
- package/src/schema/common.ts +15 -6
- package/src/schema/index.ts +1 -0
- package/src/schema/interfaces.ts +15 -5
- package/src/schema/policy.ts +22 -10
- package/src/schema/routing.ts +16 -1
- package/src/schema/system.ts +16 -6
- package/src/schema/time-zones.ts +482 -0
- package/src/studio/data.ts +172 -168
- package/src/studio/git.ts +95 -90
- package/src/studio/public/app.js +161 -150
- package/src/studio/public/compare.js +219 -212
- package/src/studio/public/diff.js +77 -75
- package/src/studio/public/dom.js +118 -108
- package/src/studio/public/evaluate.js +584 -545
- package/src/studio/public/export.js +120 -118
- package/src/studio/public/graph.js +1343 -1266
- package/src/studio/public/net.js +115 -109
- package/src/studio/public/tables.js +1135 -1083
- package/src/studio/public/tools.js +561 -529
- package/src/studio/server.ts +202 -196
- package/src/transport/console.ts +363 -271
- package/src/transport/path-check.ts +91 -0
- package/src/transport/ssh.ts +98 -94
- package/templates/colocation/checks.ts +11 -6
- package/templates/colocation/edge-01.ts +9 -9
- package/templates/colocation/routing.ts +2 -2
- package/templates/colocation/tenancy.ts +3 -3
- package/templates/colocation/tor-01.ts +3 -3
- package/templates/edge-router/checks.ts +4 -4
- package/templates/edge-router/edge-01.ts +5 -5
- package/templates/edge-router/routing.ts +2 -2
- package/templates/project/AGENTS.md +5 -1
- package/templates/single-site/checks.ts +2 -2
- package/dist/chunks/index-47debt16.js +0 -956
- package/dist/chunks/index-v8zgr7wm.js +0 -128
- package/dist/chunks/new-ny89s7y7.js +0 -166
- package/dist/chunks/server-tjbb3rqc.js +0 -251
- package/dist/presets/index.js +0 -394
- package/dist/types/adapters/devices/catalog.d.ts +0 -86
- package/dist/types/adapters/devices/derive.d.ts +0 -7
- package/dist/types/adapters/devices/fortios/firewall.d.ts +0 -23
- package/dist/types/adapters/devices/fortios/index.d.ts +0 -58
- package/dist/types/adapters/devices/fortios/names.d.ts +0 -48
- package/dist/types/adapters/devices/fortios/plan.d.ts +0 -28
- package/dist/types/adapters/devices/fortios/render.d.ts +0 -38
- package/dist/types/adapters/devices/fortios/routing.d.ts +0 -32
- package/dist/types/adapters/devices/fortios/tree.d.ts +0 -33
- package/dist/types/adapters/devices/index.d.ts +0 -3
- package/dist/types/adapters/devices/junos/bgp.d.ts +0 -11
- package/dist/types/adapters/devices/junos/index.d.ts +0 -42
- package/dist/types/adapters/devices/junos/render.d.ts +0 -52
- package/dist/types/adapters/devices/lines.d.ts +0 -56
- package/dist/types/adapters/devices/raisecom-ros/index.d.ts +0 -28
- package/dist/types/adapters/devices/routeros/export.d.ts +0 -39
- package/dist/types/adapters/devices/routeros/index.d.ts +0 -30
- package/dist/types/adapters/devices/routeros/plan.d.ts +0 -4
- package/dist/types/adapters/devices/routeros/render.d.ts +0 -100
- package/dist/types/adapters/devices/types.d.ts +0 -40
- package/dist/types/adapters/devices/vrp/index.d.ts +0 -27
- package/dist/types/adapters/registries/index.d.ts +0 -3
- package/dist/types/adapters/registries/librenms.d.ts +0 -15
- package/dist/types/adapters/registries/peeringdb.d.ts +0 -16
- package/dist/types/adapters/registries/prometheus.d.ts +0 -16
- package/dist/types/core/across.d.ts +0 -4
- package/dist/types/core/addr.d.ts +0 -34
- package/dist/types/core/files.d.ts +0 -6
- package/dist/types/core/merge.d.ts +0 -4
- package/dist/types/core/time.d.ts +0 -2
- package/dist/types/core/validate.d.ts +0 -2
- package/dist/types/presets/index.d.ts +0 -183
- package/src/adapters/devices/catalog.ts +0 -41
- package/src/adapters/devices/derive.ts +0 -59
- package/src/adapters/devices/fortios/firewall.ts +0 -362
- package/src/adapters/devices/fortios/index.ts +0 -923
- package/src/adapters/devices/fortios/names.ts +0 -115
- package/src/adapters/devices/fortios/plan.ts +0 -888
- package/src/adapters/devices/fortios/render.ts +0 -768
- package/src/adapters/devices/fortios/routing.ts +0 -444
- package/src/adapters/devices/fortios/tree.ts +0 -121
- package/src/adapters/devices/index.ts +0 -9
- package/src/adapters/devices/junos/bgp.ts +0 -269
- package/src/adapters/devices/junos/index.ts +0 -862
- package/src/adapters/devices/junos/render.ts +0 -872
- package/src/adapters/devices/lines.ts +0 -212
- package/src/adapters/devices/raisecom-ros/TRAPS.md +0 -26
- package/src/adapters/devices/raisecom-ros/index.ts +0 -700
- package/src/adapters/devices/routeros/export.ts +0 -321
- package/src/adapters/devices/routeros/index.ts +0 -346
- package/src/adapters/devices/routeros/plan.ts +0 -398
- package/src/adapters/devices/routeros/render.ts +0 -1490
- package/src/adapters/devices/types.ts +0 -38
- package/src/adapters/devices/vrp/TRAPS.md +0 -26
- package/src/adapters/devices/vrp/index.ts +0 -865
- package/src/adapters/registries/index.ts +0 -19
- package/src/adapters/registries/librenms.ts +0 -92
- package/src/adapters/registries/peeringdb.ts +0 -169
- package/src/adapters/registries/prometheus.ts +0 -71
- package/src/cli/graph.ts +0 -89
- package/src/core/across.ts +0 -350
- package/src/core/addr.ts +0 -174
- package/src/core/addresses.ts +0 -316
- package/src/core/files.ts +0 -32
- package/src/core/graph.ts +0 -640
- package/src/core/merge.ts +0 -19
- package/src/core/time.ts +0 -15
- package/src/core/validate.ts +0 -348
- package/src/presets/index.ts +0 -579
- /package/dist/types/{adapters/devices → platforms}/fortios/models.d.ts +0 -0
- /package/dist/types/{adapters/devices → platforms}/junos/models.d.ts +0 -0
- /package/dist/types/{adapters/devices → platforms}/raisecom-ros/models.d.ts +0 -0
- /package/dist/types/{adapters/devices → platforms}/vrp/models.d.ts +0 -0
- /package/src/{adapters/devices → platforms}/fortios/models.ts +0 -0
- /package/src/{adapters/devices → platforms}/junos/models.ts +0 -0
- /package/src/{adapters/devices → platforms}/raisecom-ros/models.ts +0 -0
- /package/src/{adapters/devices → platforms}/vrp/models.ts +0 -0
package/src/studio/public/app.js
CHANGED
|
@@ -2,174 +2,185 @@
|
|
|
2
2
|
/// <reference lib="dom" />
|
|
3
3
|
// Studio's page: loads what the server gathered from the config, shows the place the address names, and loads again whenever the server says the config changed.
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import { Dom } from "./dom.js";
|
|
6
|
+
import { Graph } from "./graph.js";
|
|
7
|
+
import { Tables } from "./tables.js";
|
|
8
|
+
import { Tools } from "./tools.js";
|
|
9
|
+
import { Compare } from "./compare.js";
|
|
10
10
|
|
|
11
11
|
/** @typedef {import("../data").StudioData} StudioData */
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Show the place the address names, such as `#graph/bgp` or `#devices/edge-01/ports`. */
|
|
63
|
-
function route() {
|
|
64
|
-
if (!studio) return;
|
|
65
|
-
|
|
66
|
-
const parts = location.hash.slice(1).split("/").map(decodeURIComponent).filter(Boolean);
|
|
67
|
-
const [view] = parts;
|
|
68
|
-
|
|
69
|
-
// An address from before the tables, such as `#bgp`, still opens that layer.
|
|
70
|
-
const isGraph = !view || view === "graph" || isLayer(view);
|
|
71
|
-
const asked = view === "graph" ? parts[1] : view;
|
|
72
|
-
|
|
73
|
-
const moved = location.hash !== shownRoute;
|
|
74
|
-
shownRoute = location.hash;
|
|
75
|
-
|
|
76
|
-
for (const button of views.querySelectorAll("button")) {
|
|
77
|
-
const pressed = isGraph ? button.dataset.view === "graph" : button.dataset.view === view;
|
|
78
|
-
button.setAttribute("aria-pressed", String(pressed));
|
|
13
|
+
export class App {
|
|
14
|
+
static #views = Dom.byId("views");
|
|
15
|
+
static #search = /** @type {HTMLInputElement} */ (Dom.byId("search"));
|
|
16
|
+
static #summary = Dom.byId("summary");
|
|
17
|
+
static #live = Dom.byId("live");
|
|
18
|
+
static #banner = Dom.byId("banner");
|
|
19
|
+
static #graphView = Dom.byId("graph-view");
|
|
20
|
+
static #tablesView = Dom.byId("tables-view");
|
|
21
|
+
static #tables = Dom.byId("tables");
|
|
22
|
+
static #problems = Dom.byId("problem-count");
|
|
23
|
+
|
|
24
|
+
/** What the server gathered last. @type {StudioData | undefined} */
|
|
25
|
+
static #studio;
|
|
26
|
+
/** The address last shown, so drawing the same place again keeps where the reader had scrolled to. */
|
|
27
|
+
static #shownRoute = "";
|
|
28
|
+
|
|
29
|
+
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
30
|
+
static #searching;
|
|
31
|
+
|
|
32
|
+
static #showSummary() {
|
|
33
|
+
const studio = App.#studio;
|
|
34
|
+
if (!studio) return;
|
|
35
|
+
|
|
36
|
+
const { graph } = studio;
|
|
37
|
+
const devices = studio.devices.length;
|
|
38
|
+
const errors = graph.findings.filter((finding) => finding.level === "error").length;
|
|
39
|
+
const warnings = graph.findings.length - errors;
|
|
40
|
+
const drifted = Object.values(graph.drift).filter((drift) => drift.status === "differs").length;
|
|
41
|
+
|
|
42
|
+
const count = Tables.problemCount(studio);
|
|
43
|
+
App.#problems.textContent = count ? String(count) : "";
|
|
44
|
+
|
|
45
|
+
const items = [
|
|
46
|
+
{ value: devices, label: devices === 1 ? "device" : "devices", state: "neutral" },
|
|
47
|
+
{ value: errors, label: errors === 1 ? "error" : "errors", state: errors ? "error" : "quiet" },
|
|
48
|
+
{ value: warnings, label: warnings === 1 ? "warning" : "warnings", state: warnings ? "warning" : "quiet" },
|
|
49
|
+
{ value: drifted, label: "unlike the snapshot", state: drifted ? "changed" : "quiet" },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
App.#summary.replaceChildren(
|
|
53
|
+
...items.map(({ value, label, state }) => {
|
|
54
|
+
const item = document.createElement("span");
|
|
55
|
+
item.className = `summary-item ${state}`;
|
|
56
|
+
item.append(String(value), ` ${label}`);
|
|
57
|
+
return item;
|
|
58
|
+
})
|
|
59
|
+
);
|
|
79
60
|
}
|
|
80
61
|
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
/** Show the place the address names, such as `#graph/bgp` or `#devices/edge-01/ports`. */
|
|
63
|
+
static #route() {
|
|
64
|
+
const studio = App.#studio;
|
|
65
|
+
if (!studio) return;
|
|
83
66
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
} else if (document.activeElement !== search) {
|
|
87
|
-
search.value = "";
|
|
88
|
-
}
|
|
67
|
+
const parts = location.hash.slice(1).split("/").map(decodeURIComponent).filter(Boolean);
|
|
68
|
+
const [view] = parts;
|
|
89
69
|
|
|
90
|
-
|
|
70
|
+
// An address from before the tables, such as `#bgp`, still opens that layer.
|
|
71
|
+
const isGraph = !view || view === "graph" || Graph.isLayer(view);
|
|
72
|
+
const asked = view === "graph" ? parts[1] : view;
|
|
91
73
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
74
|
+
const moved = location.hash !== App.#shownRoute;
|
|
75
|
+
App.#shownRoute = location.hash;
|
|
96
76
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
tables.scrollTop = moved ? 0 : scrolled;
|
|
77
|
+
for (const button of App.#views.querySelectorAll("button")) {
|
|
78
|
+
const pressed = isGraph ? button.dataset.view === "graph" : button.dataset.view === view;
|
|
79
|
+
button.setAttribute("aria-pressed", String(pressed));
|
|
80
|
+
}
|
|
102
81
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
82
|
+
App.#graphView.hidden = !isGraph;
|
|
83
|
+
App.#tablesView.hidden = isGraph;
|
|
106
84
|
|
|
107
|
-
|
|
85
|
+
if (view === "search") {
|
|
86
|
+
if (App.#search.value !== (parts[1] ?? "")) App.#search.value = parts[1] ?? "";
|
|
87
|
+
} else if (document.activeElement !== App.#search) {
|
|
88
|
+
App.#search.value = "";
|
|
89
|
+
}
|
|
108
90
|
|
|
109
|
-
|
|
110
|
-
document.addEventListener("click", (event) => {
|
|
111
|
-
const target = event.target instanceof Element ? event.target : undefined;
|
|
91
|
+
App.#showSummary();
|
|
112
92
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
119
|
-
let searching;
|
|
120
|
-
|
|
121
|
-
search.addEventListener("input", () => {
|
|
122
|
-
clearTimeout(searching);
|
|
93
|
+
if (isGraph) {
|
|
94
|
+
Graph.show(Graph.isLayer(asked) ? asked : Graph.currentLayer());
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
123
97
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
98
|
+
const tables = App.#tables;
|
|
99
|
+
const scrolled = tables.scrollTop;
|
|
100
|
+
if (view === "tools") Tools.show(parts, tables, studio);
|
|
101
|
+
else if (view === "compare") Compare.show(parts, tables, studio);
|
|
102
|
+
else Tables.show(parts, tables, studio);
|
|
103
|
+
tables.scrollTop = moved ? 0 : scrolled;
|
|
127
104
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
/** @type {(StudioData & { error?: undefined }) | { error: string }} */
|
|
131
|
-
let next;
|
|
132
|
-
|
|
133
|
-
try {
|
|
134
|
-
next = await (await fetch("data", { cache: "no-store" })).json();
|
|
135
|
-
} catch (error) {
|
|
136
|
-
next = { error: `could not reach circuit studio: ${error instanceof Error ? error.message : String(error)}` };
|
|
105
|
+
// A new place comes in; the same place drawn again, because the config changed, stays still.
|
|
106
|
+
if (moved) Dom.enter(tables);
|
|
137
107
|
}
|
|
138
108
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
109
|
+
/** Load what Studio shows, at the start and whenever the server says the config changed. */
|
|
110
|
+
static async #load() {
|
|
111
|
+
/** @type {(StudioData & { error?: undefined }) | { error: string }} */
|
|
112
|
+
let next;
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
next = await (await fetch("data", { cache: "no-store" })).json();
|
|
116
|
+
} catch (error) {
|
|
117
|
+
next = { error: `could not reach circuit studio: ${error instanceof Error ? error.message : String(error)}` };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (next.error !== undefined) {
|
|
121
|
+
App.#banner.textContent = `The config could not be read, so what is shown is the last that could:\n${next.error}`;
|
|
122
|
+
App.#banner.hidden = false;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
App.#banner.hidden = true;
|
|
127
|
+
App.#studio = next;
|
|
128
|
+
Graph.set(next.graph);
|
|
129
|
+
App.#route();
|
|
143
130
|
}
|
|
144
131
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
132
|
+
/** Wire up the page and load what it shows. */
|
|
133
|
+
static start() {
|
|
134
|
+
for (const button of App.#views.querySelectorAll("button")) {
|
|
135
|
+
const view = button.dataset.view ?? "graph";
|
|
136
|
+
button.addEventListener("click", () => Dom.go(view === "graph" ? `graph/${Graph.currentLayer()}` : view));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
window.addEventListener("hashchange", App.#route);
|
|
140
|
+
|
|
141
|
+
// A menu closes once one of its items is chosen, or when the reader clicks anywhere else.
|
|
142
|
+
document.addEventListener("click", (event) => {
|
|
143
|
+
const target = event.target instanceof Element ? event.target : undefined;
|
|
144
|
+
|
|
145
|
+
for (const menu of document.querySelectorAll("details.menu[open]")) {
|
|
146
|
+
if (!target || !menu.contains(target) || target.closest(".menu-items button")) menu.removeAttribute("open");
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
App.#search.addEventListener("input", () => {
|
|
151
|
+
clearTimeout(App.#searching);
|
|
152
|
+
|
|
153
|
+
const query = App.#search.value.trim();
|
|
154
|
+
App.#searching = setTimeout(() => Dom.go(query ? `search/${encodeURIComponent(query)}` : "devices"), 200);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const events = new EventSource("events");
|
|
158
|
+
const live = App.#live;
|
|
159
|
+
|
|
160
|
+
events.addEventListener("open", () => {
|
|
161
|
+
live.textContent = "live";
|
|
162
|
+
live.title = "Watching the config: a saved change shows here at once.";
|
|
163
|
+
live.classList.add("on");
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
events.addEventListener("error", () => {
|
|
167
|
+
live.textContent = "not connected";
|
|
168
|
+
live.title = "Circuit Studio is not answering. Is circuit studio still running?";
|
|
169
|
+
live.classList.remove("on");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// The config changed: load it again, and the live mark beats once to say so. The page itself changed, while working on Circuit: load the page again.
|
|
173
|
+
events.addEventListener("message", (event) => {
|
|
174
|
+
if (event.data === "page") return location.reload();
|
|
175
|
+
|
|
176
|
+
live.classList.remove("beat");
|
|
177
|
+
void live.offsetWidth;
|
|
178
|
+
live.classList.add("beat");
|
|
179
|
+
void App.#load();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
void App.#load();
|
|
183
|
+
}
|
|
149
184
|
}
|
|
150
185
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
events.addEventListener("open", () => {
|
|
154
|
-
live.textContent = "live";
|
|
155
|
-
live.title = "Watching the config: a saved change shows here at once.";
|
|
156
|
-
live.classList.add("on");
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
events.addEventListener("error", () => {
|
|
160
|
-
live.textContent = "not connected";
|
|
161
|
-
live.title = "Circuit Studio is not answering. Is circuit studio still running?";
|
|
162
|
-
live.classList.remove("on");
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
// The config changed: load it again, and the live mark beats once to say so. The page itself changed, while working on Circuit: load the page again.
|
|
166
|
-
events.addEventListener("message", (event) => {
|
|
167
|
-
if (event.data === "page") return location.reload();
|
|
168
|
-
|
|
169
|
-
live.classList.remove("beat");
|
|
170
|
-
void live.offsetWidth;
|
|
171
|
-
live.classList.add("beat");
|
|
172
|
-
void load();
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
void load();
|
|
186
|
+
App.start();
|