Update static/js/pages/visual-route.js
This commit is contained in:
parent
418dba4bb6
commit
a23bb7f94c
1 changed files with 98 additions and 62 deletions
|
|
@ -1,107 +1,143 @@
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
let network = null;
|
||||||
|
let allNodes = new vis.DataSet();
|
||||||
|
let allEdges = new vis.DataSet();
|
||||||
|
|
||||||
const form = document.getElementById('bgprtv-form');
|
const form = document.getElementById('bgprtv-form');
|
||||||
if (!form) {
|
if (!form) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ipAddressInput = document.getElementById('bgprtv-ip-address');
|
const ipAddressInput = document.getElementById('bgprtv-ip-address');
|
||||||
const loader = document.getElementById('bgprtv-loader');
|
const loader = document.getElementById('bgprtv-loader');
|
||||||
const errorMessageContainer = document.getElementById('bgprtv-error-message');
|
const errorMessageContainer = document.getElementById('bgprtv-error-message');
|
||||||
const networkContainer = document.getElementById('bgprtv-mynetwork');
|
const networkContainer = document.getElementById('bgprtv-mynetwork');
|
||||||
|
|
||||||
const graphUrl = networkContainer.dataset.graphUrl;
|
const graphUrl = networkContainer.dataset.graphUrl;
|
||||||
|
|
||||||
|
const filterControls = document.querySelectorAll('input[name="bgprtv-filter"]');
|
||||||
|
const allCommunitiesCheckbox = document.querySelector('input[value="all"]');
|
||||||
|
const activeCheckbox = document.querySelector('input[value="active"]');
|
||||||
|
|
||||||
if (!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.textContent = 'Configuration Error: The graph URL is missing.';
|
||||||
errorMessageContainer.style.display = 'block';
|
errorMessageContainer.style.display = 'block';
|
||||||
const submitButton = form.querySelector('input[type="submit"]');
|
form.querySelector('input[type="submit"]').disabled = true;
|
||||||
if (submitButton) {
|
|
||||||
submitButton.disabled = true;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.addEventListener('submit', function(event) {
|
form.addEventListener('submit', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const ipAddress = ipAddressInput.value;
|
const ipAddress = ipAddressInput.value;
|
||||||
|
|
||||||
loader.style.display = 'block';
|
loader.style.display = 'block';
|
||||||
errorMessageContainer.style.display = 'none';
|
errorMessageContainer.style.display = 'none';
|
||||||
errorMessageContainer.textContent = '';
|
errorMessageContainer.textContent = '';
|
||||||
|
if (network) {
|
||||||
const visContent = networkContainer.querySelector('.vis-network');
|
network.destroy();
|
||||||
if (visContent) {
|
network = null;
|
||||||
visContent.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(graphUrl, {
|
fetch(graphUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ ip_address: ipAddress })
|
body: JSON.stringify({ ip_address: ipAddress })
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
return response.json().then(data => {
|
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
if (!response.ok && data.error) {
|
return response.json();
|
||||||
throw new Error(data.error);
|
|
||||||
}
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
loader.style.display = 'none';
|
loader.style.display = 'none';
|
||||||
if (data.nodes && data.nodes.length > 0) {
|
if (data.error) {
|
||||||
|
errorMessageContainer.textContent = data.error;
|
||||||
|
errorMessageContainer.style.display = 'block';
|
||||||
|
} else if (data.nodes && data.nodes.length > 0) {
|
||||||
drawGraph(data);
|
drawGraph(data);
|
||||||
} else {
|
} else {
|
||||||
errorMessageContainer.textContent = data.error || 'Could not parse any valid AS paths from the API response.';
|
errorMessageContainer.textContent = 'Could not parse any valid AS paths from the API response.';
|
||||||
errorMessageContainer.style.display = 'block';
|
errorMessageContainer.style.display = 'block';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
loader.style.display = 'none';
|
loader.style.display = 'none';
|
||||||
errorMessageContainer.textContent = error.message;
|
errorMessageContainer.textContent = `An unexpected error occurred: ${error.message}`;
|
||||||
errorMessageContainer.style.display = 'block';
|
errorMessageContainer.style.display = 'block';
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function drawGraph(data) {
|
function drawGraph(data) {
|
||||||
const nodes = new vis.DataSet(data.nodes);
|
allNodes = new vis.DataSet(data.nodes);
|
||||||
const edges = new vis.DataSet(data.edges);
|
allEdges = new vis.DataSet(data.edges);
|
||||||
const graphData = { nodes: nodes, edges: edges };
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
layout: { hierarchical: false },
|
layout: { hierarchical: false },
|
||||||
edges: {
|
edges: {
|
||||||
arrows: { to: { enabled: true, scaleFactor: 0.7 } },
|
arrows: { to: { enabled: true, scaleFactor: 0.7 } }
|
||||||
smooth: {
|
},
|
||||||
enabled: true,
|
nodes: {
|
||||||
type: "cubicBezier",
|
shape: 'box',
|
||||||
forceDirection: "horizontal",
|
margin: 15,
|
||||||
roundness: 0.85
|
font: { size: 14, color: '#343a40', multi: 'html', align: 'left' },
|
||||||
}
|
borderWidth: 2
|
||||||
},
|
},
|
||||||
nodes: {
|
physics: { enabled: false },
|
||||||
shape: 'box',
|
interaction: { dragNodes: true, dragView: true, zoomView: true }
|
||||||
margin: 15,
|
};
|
||||||
font: {
|
|
||||||
size: 14,
|
network = new vis.Network(networkContainer, {}, options);
|
||||||
color: '#343a40',
|
|
||||||
multi: 'html',
|
activeCheckbox.checked = false;
|
||||||
align: 'left'
|
allCommunitiesCheckbox.checked = true;
|
||||||
},
|
filterControls.forEach(cb => { if (cb.value !== 'all' && cb.value !== 'active') cb.checked = false; });
|
||||||
borderWidth: 2
|
filterGraph();
|
||||||
},
|
}
|
||||||
physics: { enabled: false },
|
|
||||||
interaction: {
|
function filterGraph() {
|
||||||
dragNodes: true,
|
if (!network) return;
|
||||||
dragView: true,
|
|
||||||
zoomView: true
|
const showOnlyActive = activeCheckbox.checked;
|
||||||
}
|
const selectedCategories = Array.from(filterControls)
|
||||||
|
.filter(cb => cb.checked && cb.value !== 'active' && cb.value !== 'all')
|
||||||
|
.map(cb => cb.value);
|
||||||
|
const showAllCommunities = allCommunitiesCheckbox.checked;
|
||||||
|
|
||||||
|
const itemFilter = (item) => {
|
||||||
|
const activeFilterPassed = !showOnlyActive || item.is_active;
|
||||||
|
|
||||||
|
const categoryFilterPassed = showAllCommunities || selectedCategories.includes(item.path_category);
|
||||||
|
|
||||||
|
return item.path_category === 'global' || (activeFilterPassed && categoryFilterPassed);
|
||||||
};
|
};
|
||||||
new vis.Network(networkContainer, graphData, options);
|
|
||||||
|
const edgeFilter = (item) => {
|
||||||
|
const activeFilterPassed = !showOnlyActive || item.is_active;
|
||||||
|
const categoryFilterPassed = showAllCommunities || selectedCategories.includes(item.path_category);
|
||||||
|
return activeFilterPassed && categoryFilterPassed;
|
||||||
|
};
|
||||||
|
|
||||||
|
const filteredNodes = allNodes.get({ filter: itemFilter });
|
||||||
|
const filteredEdges = allEdges.get({ filter: edgeFilter });
|
||||||
|
|
||||||
|
network.setData({ nodes: new vis.DataSet(filteredNodes), edges: new vis.DataSet(filteredEdges) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filterControls.forEach(checkbox => {
|
||||||
|
checkbox.addEventListener('change', function(e) {
|
||||||
|
const changedValue = e.target.value;
|
||||||
|
|
||||||
|
if (changedValue === 'all' && e.target.checked) {
|
||||||
|
filterControls.forEach(cb => {
|
||||||
|
if (cb.value !== 'all' && cb.value !== 'active') {
|
||||||
|
cb.checked = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (changedValue !== 'all' && changedValue !== 'active' && e.target.checked) {
|
||||||
|
allCommunitiesCheckbox.checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const specificCommunityChecked = Array.from(filterControls).some(cb => cb.checked && cb.value !== 'all' && cb.value !== 'active');
|
||||||
|
if (!specificCommunityChecked) {
|
||||||
|
allCommunitiesCheckbox.checked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterGraph();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue