From 02c7a72f931f797749c9ab105ed345bf14d08521 Mon Sep 17 00:00:00 2001 From: Blackwhitebear8 Date: Sat, 5 Jul 2025 16:20:55 +0200 Subject: [PATCH] Add static/js/pages/visual-route.js --- static/js/pages/visual-route.js | 105 ++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 static/js/pages/visual-route.js diff --git a/static/js/pages/visual-route.js b/static/js/pages/visual-route.js new file mode 100644 index 0000000..77cefee --- /dev/null +++ b/static/js/pages/visual-route.js @@ -0,0 +1,105 @@ +document.addEventListener('DOMContentLoaded', function() { + const form = document.getElementById('bgprtv-form'); + if (!form) { + return; + } + + const ipAddressInput = document.getElementById('bgprtv-ip-address'); + const loader = document.getElementById('bgprtv-loader'); + const errorMessageContainer = document.getElementById('bgprtv-error-message'); + const networkContainer = document.getElementById('bgprtv-mynetwork'); + + const graphUrl = networkContainer.dataset.graphUrl; + + if (!graphUrl) { + errorMessageContainer.textContent = 'Configuration Error: The graph URL is missing. Ensure the network container div in your HTML has a "data-graph-url" attribute pointing to the correct API endpoint.'; + errorMessageContainer.style.display = 'block'; + const submitButton = form.querySelector('input[type="submit"]'); + if (submitButton) { + submitButton.disabled = true; + } + return; + } + + form.addEventListener('submit', function(event) { + event.preventDefault(); + + const ipAddress = ipAddressInput.value; + + loader.style.display = 'block'; + errorMessageContainer.style.display = 'none'; + errorMessageContainer.textContent = ''; + + const visContent = networkContainer.querySelector('.vis-network'); + if (visContent) { + visContent.remove(); + } + + fetch(graphUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ ip_address: ipAddress }) + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then(data => { + loader.style.display = 'none'; + if (data.error) { + errorMessageContainer.textContent = data.error; + errorMessageContainer.style.display = 'block'; + } else if (data.nodes && data.nodes.length > 0) { + drawGraph(data); + } else { + errorMessageContainer.textContent = 'Could not parse any valid AS paths from the API response.'; + errorMessageContainer.style.display = 'block'; + } + }) + .catch(error => { + loader.style.display = 'none'; + errorMessageContainer.textContent = 'An unexpected error occurred. See console for details.'; + errorMessageContainer.style.display = 'block'; + console.error('Error:', error); + }); + }); + + function drawGraph(data) { + const nodes = new vis.DataSet(data.nodes); + const edges = new vis.DataSet(data.edges); + const graphData = { nodes: nodes, edges: edges }; + + const options = { + layout: { hierarchical: false }, + edges: { + arrows: { to: { enabled: true, scaleFactor: 0.7 } }, + smooth: { + enabled: true, + type: "cubicBezier", + forceDirection: "horizontal", + roundness: 0.85 + } + }, + nodes: { + shape: 'box', + margin: 15, + font: { + size: 14, + color: '#343a40', + multi: 'html', + align: 'left' + }, + borderWidth: 2 + }, + physics: { enabled: false }, + interaction: { + dragNodes: true, + dragView: true, + zoomView: true + } + }; + new vis.Network(networkContainer, graphData, options); + } +}); \ No newline at end of file