Skip to content
This repository was archived by the owner on Mar 27, 2023. It is now read-only.

Commit e964300

Browse files
author
Michel Zimmer
committed
Switch from DOT to JSON data for network graph
1 parent 736166d commit e964300

File tree

7 files changed

+63
-481
lines changed

7 files changed

+63
-481
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ LABEL org.opencontainers.image.vendor="neuland – Büro für Informatik GmbH"
2626
LABEL org.opencontainers.image.licenses="MIT"
2727
LABEL org.opencontainers.image.title="bandwhichd-ui"
2828
LABEL org.opencontainers.image.description="bandwhichd ui displaying network topology and statistics"
29-
LABEL org.opencontainers.image.version="0.5.0"
29+
LABEL org.opencontainers.image.version="0.6.0"
3030
COPY --from=build --chown=root:root /home/node/dist /usr/share/nginx/html

mocks/apiHandler.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,27 @@ const handleWithMocks =
2727
});
2828

2929
request.on("end", () => {
30-
if (request.method !== "GET"
31-
|| request.url !== "/api/v1/stats") {
30+
if (request.url !== "/api/v1/stats") {
3231
response.writeHead(404);
3332
response.end();
3433
return;
3534
}
3635

36+
if (request.method !== "GET") {
37+
response.writeHead(405, {
38+
"Allow": "GET",
39+
});
40+
response.end();
41+
return;
42+
}
43+
3744
if (chunks.length > 0) {
3845
response.writeHead(400);
3946
response.end();
4047
return;
4148
}
4249

43-
const format =
44-
request.headers.accept === "text/vnd.graphviz; q=1.0"
45-
? "dot"
46-
: "json";
47-
48-
const filePath = path.join(process.cwd(), 'mocks', `stats.${format}`);
50+
const filePath = path.join(process.cwd(), 'mocks', `stats.json`);
4951
const fileStat = fs.statSync(filePath);
5052

5153
response.writeHead(200, {

mocks/stats.dot

Lines changed: 0 additions & 441 deletions
This file was deleted.

mocks/stats.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "bandwhichd-ui",
3-
"version": "0.5.0",
3+
"version": "0.6.0",
44
"description": "bandwhichd ui displaying network topology and statistics",
55
"license": "MIT",
66
"private": true,

src/Graph.tsx

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
import React, { useEffect, useRef, useState } from "react";
22
import * as VisNetwork from "vis-network";
3-
import { HostId } from "./Stats";
3+
import { HostId, Stats } from "./Stats";
44

55
import styles from "./Graph.module.css";
6-
7-
const fetchData = async (): Promise<string> => {
8-
const response = await window.fetch("/api/v1/stats", {
9-
method: "GET",
10-
headers: {
11-
"Accept": "text/vnd.graphviz; q=1.0"
12-
}
13-
});
14-
return response.text();
15-
}
6+
import { Seq } from "immutable";
167

178
export interface GraphProps {
9+
maybeStats: Stats | null;
1810
maybeSelectedHostId: HostId | null,
1911
setMaybeSelectedHostId: (maybeSelectedHostId: HostId | null) => void,
2012
}
@@ -26,34 +18,63 @@ export const Graph: React.FC<GraphProps> =
2618
const networkRef = useRef<VisNetwork.Network | null>(null);
2719

2820
useEffect(() => {
29-
if (containerRef.current === null) {
21+
if (containerRef.current === null
22+
|| props.maybeStats === null) {
3023
return;
3124
}
3225
const container = containerRef.current;
26+
const stats = props.maybeStats;
3327

3428
setIsLoading(true);
35-
fetchData().then(data => {
36-
// @ts-ignore
37-
const parsedData = VisNetwork.parseDOTNetwork(data);
38-
parsedData.options.physics = {
29+
const hostNodes: Seq.Indexed<VisNetwork.Node> =
30+
stats.hosts
31+
.entrySeq()
32+
.map(([hostId, host]) => ({
33+
id: hostId,
34+
label: host.hostname,
35+
}));
36+
const unmonitoredHostNodes: Seq.Indexed<VisNetwork.Node> =
37+
stats.unmonitoredHosts
38+
.entrySeq()
39+
.map(([hostId, unmonitoredHost]) => ({
40+
id: hostId,
41+
label: unmonitoredHost.host,
42+
}));
43+
const edges: Seq.Indexed<VisNetwork.Edge> =
44+
stats.hosts
45+
.entrySeq()
46+
.flatMap(([hostId, host]) =>
47+
host.connections
48+
.entrySeq()
49+
.map(([otherHostId, _]) => ({
50+
from: hostId,
51+
to: otherHostId,
52+
}))
53+
);
54+
const data: VisNetwork.Data = {
55+
nodes: hostNodes.concat(unmonitoredHostNodes).toArray(),
56+
edges: edges.toArray(),
57+
};
58+
const options: VisNetwork.Options = {
59+
physics: {
3960
solver: "forceAtlas2Based"
40-
};
41-
const network = new VisNetwork.Network(container, parsedData);
42-
network.on("selectNode", (event) => {
43-
props.setMaybeSelectedHostId(event.nodes[0]);
44-
});
45-
network.on("afterDrawing", (_) => {
46-
setIsLoading(false);
47-
});
48-
networkRef.current = network;
49-
}).catch(console.error);
61+
}
62+
};
63+
const network = new VisNetwork.Network(container, data, options);
64+
network.on("selectNode", (event) => {
65+
props.setMaybeSelectedHostId(event.nodes[0]);
66+
});
67+
network.on("afterDrawing", (_) => {
68+
setIsLoading(false);
69+
});
70+
networkRef.current = network;
5071

5172
return () => {
5273
if (networkRef.current !== null) {
5374
networkRef.current.destroy();
5475
}
5576
}
56-
}, [containerRef]);
77+
}, [containerRef, props.maybeStats]);
5778

5879
useEffect(() => {
5980
if (networkRef.current !== null && props.maybeSelectedHostId !== null) {
@@ -62,7 +83,7 @@ export const Graph: React.FC<GraphProps> =
6283
}, [networkRef, props.maybeSelectedHostId]);
6384

6485
return <section>
65-
{ isLoading && <span className={styles.loading}>Loading…</span> }
86+
{isLoading && <span className={styles.loading}>Loading…</span>}
6687
<div className={styles.container} ref={containerRef}></div>
6788
</section>;
6889
};

src/Main.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export const Main: React.FC =
2929

3030
return <main className={styles.main}>
3131
<NodeSelector {...{ maybeStats, maybeSelectedHostId, setMaybeSelectedHostId }} />
32-
<Graph {...{ maybeSelectedHostId, setMaybeSelectedHostId }} />
32+
<Graph {...{ maybeStats, maybeSelectedHostId, setMaybeSelectedHostId }} />
3333
<HostDetails {...{ maybeStats, maybeSelectedHost, setMaybeSelectedHostId }} />
3434
</main>;
3535
};

0 commit comments

Comments
 (0)