rework network visualiser code to make it easier to auto update
This commit is contained in:
2
package-lock.json
generated
2
package-lock.json
generated
@@ -13,6 +13,7 @@
|
|||||||
"click-outside-vue3": "^4.0.1",
|
"click-outside-vue3": "^4.0.1",
|
||||||
"electron-prompt": "^1.7.0",
|
"electron-prompt": "^1.7.0",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
|
"vis-data": "^7.1.9",
|
||||||
"vis-network": "^9.1.9",
|
"vis-network": "^9.1.9",
|
||||||
"vite": "^5.4.0",
|
"vite": "^5.4.0",
|
||||||
"vue-router": "^4.4.2"
|
"vue-router": "^4.4.2"
|
||||||
@@ -4535,7 +4536,6 @@
|
|||||||
"version": "7.1.9",
|
"version": "7.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/vis-data/-/vis-data-7.1.9.tgz",
|
"resolved": "https://registry.npmjs.org/vis-data/-/vis-data-7.1.9.tgz",
|
||||||
"integrity": "sha512-COQsxlVrmcRIbZMMTYwD+C2bxYCFDNQ2EHESklPiInbD/Pk3JZ6qNL84Bp9wWjYjAzXfSlsNaFtRk+hO9yBPWA==",
|
"integrity": "sha512-COQsxlVrmcRIbZMMTYwD+C2bxYCFDNQ2EHESklPiInbD/Pk3JZ6qNL84Bp9wWjYjAzXfSlsNaFtRk+hO9yBPWA==",
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/visjs"
|
"url": "https://opencollective.com/visjs"
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
"click-outside-vue3": "^4.0.1",
|
"click-outside-vue3": "^4.0.1",
|
||||||
"electron-prompt": "^1.7.0",
|
"electron-prompt": "^1.7.0",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
|
"vis-data": "^7.1.9",
|
||||||
"vis-network": "^9.1.9",
|
"vis-network": "^9.1.9",
|
||||||
"vite": "^5.4.0",
|
"vite": "^5.4.0",
|
||||||
"vue-router": "^4.4.2"
|
"vue-router": "^4.4.2"
|
||||||
|
|||||||
@@ -5,12 +5,15 @@
|
|||||||
<div id="network" class="w-full h-full"></div>
|
<div id="network" class="w-full h-full"></div>
|
||||||
|
|
||||||
<!-- loading -->
|
<!-- loading -->
|
||||||
<div v-if="isLoading" class="absolute flex top-0 bottom-0 left-0 right-0">
|
<div v-if="isLoading" class="absolute flex top-0 bottom-0 left-0 right-0 bg-gray-100">
|
||||||
<div class="mx-auto my-auto">
|
<div class="flex flex-col mx-auto my-auto">
|
||||||
<svg class="animate-spin h-6 w-6 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<div class="mx-auto">
|
||||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
<svg class="animate-spin h-6 w-6 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||||
</svg>
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>Loading {{ loadingProgress }}%</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -27,6 +30,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import "vis-network/styles/vis-network.css";
|
import "vis-network/styles/vis-network.css";
|
||||||
import { Network } from "vis-network";
|
import { Network } from "vis-network";
|
||||||
|
import { DataSet } from "vis-data";
|
||||||
import Utils from "../../js/Utils";
|
import Utils from "../../js/Utils";
|
||||||
export default {
|
export default {
|
||||||
name: 'NetworkVisualiser',
|
name: 'NetworkVisualiser',
|
||||||
@@ -34,9 +38,13 @@ export default {
|
|||||||
return {
|
return {
|
||||||
config: null,
|
config: null,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
loadingProgress: 0,
|
||||||
interfaces: [],
|
interfaces: [],
|
||||||
pathTable: [],
|
pathTable: [],
|
||||||
announces: {},
|
announces: {},
|
||||||
|
network: null,
|
||||||
|
nodes: new DataSet(),
|
||||||
|
edges: new DataSet(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -48,7 +56,6 @@ export default {
|
|||||||
const response = await axios.get(`/api/v1/interface-stats`);
|
const response = await axios.get(`/api/v1/interface-stats`);
|
||||||
this.interfaces = response.data.interface_stats?.interfaces ?? [];
|
this.interfaces = response.data.interface_stats?.interfaces ?? [];
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
alert("failed to load interface stats");
|
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -57,7 +64,6 @@ export default {
|
|||||||
const response = await axios.get(`/api/v1/path-table`);
|
const response = await axios.get(`/api/v1/path-table`);
|
||||||
this.pathTable = response.data.path_table;
|
this.pathTable = response.data.path_table;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
alert("failed to load path table");
|
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -66,7 +72,6 @@ export default {
|
|||||||
const response = await axios.get("/api/v1/config");
|
const response = await axios.get("/api/v1/config");
|
||||||
this.config = response.data.config;
|
this.config = response.data.config;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
alert("failed to load config");
|
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -88,8 +93,73 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async init() {
|
async init() {
|
||||||
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
|
// create network ui
|
||||||
|
const container = document.getElementById("network");
|
||||||
|
this.network = new Network(container, {
|
||||||
|
nodes: this.nodes,
|
||||||
|
edges: this.edges,
|
||||||
|
}, {
|
||||||
|
interaction: {
|
||||||
|
tooltipDelay: 0, // show tooltip instantly on hover
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
// always layout nodes the same way across reloads if nothing changed
|
||||||
|
randomSeed: 1,
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
color: {
|
||||||
|
border: "#000000",
|
||||||
|
highlight: {
|
||||||
|
border: "#000000",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
physics: {
|
||||||
|
barnesHut: {
|
||||||
|
gravitationalConstant: -5000,
|
||||||
|
// centralGravity: 0,
|
||||||
|
// springConstant: 0.1,
|
||||||
|
// damping: 0.15,
|
||||||
|
},
|
||||||
|
// maxVelocity: 150,
|
||||||
|
// minVelocity: 0.25,
|
||||||
|
},
|
||||||
|
groups: {
|
||||||
|
"me": {
|
||||||
|
shape: "image",
|
||||||
|
image: "/assets/images/reticulum_logo_512.png",
|
||||||
|
},
|
||||||
|
"interface": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"announce": {
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// update loading progress
|
||||||
|
this.network.on("stabilizationProgress", (event) => {
|
||||||
|
|
||||||
|
// calculate percentage stabilized
|
||||||
|
this.loadingProgress = Math.floor((event.iterations / event.total) * 100);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// hide loading once done
|
||||||
|
this.network.on("stabilized", () => {
|
||||||
|
this.isLoading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// update network
|
||||||
await this.update();
|
await this.update();
|
||||||
|
|
||||||
|
// stabilise the network a bit after first load
|
||||||
|
this.network.stabilize(100);
|
||||||
|
|
||||||
},
|
},
|
||||||
async update() {
|
async update() {
|
||||||
|
|
||||||
@@ -156,6 +226,7 @@ export default {
|
|||||||
if(entry.parent_interface_name){
|
if(entry.parent_interface_name){
|
||||||
// add edge from parent interface to interface
|
// add edge from parent interface to interface
|
||||||
edges.push({
|
edges.push({
|
||||||
|
id: `${entry.parent_interface_name}~${entry.name}`,
|
||||||
from: entry.parent_interface_name,
|
from: entry.parent_interface_name,
|
||||||
to: entry.name,
|
to: entry.name,
|
||||||
color: "transparent",
|
color: "transparent",
|
||||||
@@ -168,6 +239,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
// add edge from me to interface
|
// add edge from me to interface
|
||||||
edges.push({
|
edges.push({
|
||||||
|
id: `me-${entry.name}`,
|
||||||
from: "me",
|
from: "me",
|
||||||
to: entry.name,
|
to: entry.name,
|
||||||
color: "transparent",
|
color: "transparent",
|
||||||
@@ -244,6 +316,7 @@ export default {
|
|||||||
|
|
||||||
// add edge from interface to announced aspect
|
// add edge from interface to announced aspect
|
||||||
edges.push({
|
edges.push({
|
||||||
|
id: `${entry.interface}~${entry.hash}`,
|
||||||
from: entry.interface,
|
from: entry.interface,
|
||||||
to: entry.hash,
|
to: entry.hash,
|
||||||
color: "gray",
|
color: "gray",
|
||||||
@@ -251,55 +324,9 @@ export default {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create network ui
|
// update nodes and edges in network
|
||||||
const container = document.getElementById("network");
|
this.nodes.update(nodes);
|
||||||
const network = new Network(container, {
|
this.edges.update(edges);
|
||||||
nodes: nodes,
|
|
||||||
edges: edges,
|
|
||||||
}, {
|
|
||||||
interaction: {
|
|
||||||
tooltipDelay: 0, // show tooltip instantly on hover
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
// always layout nodes the same way across reloads if nothing changed
|
|
||||||
randomSeed: 1,
|
|
||||||
},
|
|
||||||
nodes: {
|
|
||||||
color: {
|
|
||||||
border: "#000000",
|
|
||||||
highlight: {
|
|
||||||
border: "#000000",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
physics: {
|
|
||||||
barnesHut: {
|
|
||||||
gravitationalConstant: -5000,
|
|
||||||
// centralGravity: 0,
|
|
||||||
// springConstant: 0.1,
|
|
||||||
// damping: 0.15,
|
|
||||||
},
|
|
||||||
// maxVelocity: 150,
|
|
||||||
// minVelocity: 0.25,
|
|
||||||
},
|
|
||||||
groups: {
|
|
||||||
"me": {
|
|
||||||
shape: "image",
|
|
||||||
image: "/assets/images/reticulum_logo_512.png",
|
|
||||||
},
|
|
||||||
"interface": {
|
|
||||||
|
|
||||||
},
|
|
||||||
"announce": {
|
|
||||||
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// hide loading once done
|
|
||||||
network.on("stabilized", () => {
|
|
||||||
this.isLoading = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
},
|
||||||
formatBytes: function(bytes) {
|
formatBytes: function(bytes) {
|
||||||
|
|||||||
Reference in New Issue
Block a user