gontrol/static/agents-graph.js

186 lines
5.1 KiB
JavaScript

let agentData = [];
let isCyInitialized = false;
let cy;
function initializeCytoscape() {
if (isCyInitialized) return;
cy = cytoscape({
container: document.getElementById('cyto-graph'),
style: [
{
selector: 'node',
style: {
'background-color': '#007bff',
'label': 'data(name)', // Ensure the label uses the AgentName
'color': 'white',
'text-outline-width': 2,
'text-outline-color': '#333',
'width': '50px',
'height': '50px'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle'
}
}
],
layout: {
name: 'grid',
rows: 2
}
});
isCyInitialized = true; // Mark Cytoscape as initialized
}
// Load the graph after the page has fully loaded
document.addEventListener('DOMContentLoaded', function () {
console.log('DOMContentLoaded fired.');
initializeCytoscape();
loadGraphData();
});
// Load the graph after HTMX swap
document.body.addEventListener('htmx:afterSwap', function (event) {
console.log('htmx:afterSwap fired.');
if (event.target.id === 'agentList') {
initializeCytoscape();
loadGraphData();
}
});
async function updateGraph(agentData) {
if (!cy) {
console.error('Cytoscape is not initialized yet.');
return;
}
console.log('Updating graph with agent data:', agentData);
// Clear existing nodes and edges
cy.elements().remove();
// Add nodes for each agent with the AgentName as the label
agentData.forEach(agent => {
const id = agent.agentId;
const name = agent.agentName;
const status = agent.status;
if (id && name) {
let nodeColor = (status === 'Connected') ? '#28a745' : '#dc3545'; // Green for connected, Red for disconnected
cy.add({
group: 'nodes',
data: {
id: id,
name: name,
status: status,
type: agent.agentType,
ip: agent.IPv4Address
},
style: {
'background-color': nodeColor,
'label': name, // Display agent's name
'color': 'white',
'text-outline-width': 2,
'text-outline-color': '#333',
'width': '50px',
'height': '50px'
}
});
} else {
console.warn('Skipping agent with missing data:', agent);
}
});
// Define the target node (`g2` in your case)
const targetNode = 'g2';
// Ensure the target node (`g2`) exists, if not, create it
if (cy.getElementById(targetNode).length === 0) {
cy.add({
group: 'nodes',
data: {
id: targetNode,
name: 'g2',
status: 'Target',
type: 'Server',
ip: 'N/A'
},
style: {
'background-color': '#6c757d', // Gray for target node
'label': 'g2',
'color': 'white',
'text-outline-width': 2,
'text-outline-color': '#333',
'width': '50px',
'height': '50px'
}
});
}
// Connect each agent to the target node (`g2`)
agentData.forEach(agent => {
const id = agent.agentId;
if (id) {
cy.add({
group: 'edges',
data: {
source: id,
target: targetNode
}
});
} else {
console.warn('Skipping edge for agent with missing agentId:', agent);
}
});
// Force a layout update
cy.layout({
name: 'grid',
rows: 2
}).run();
}
async function fetchData() {
const url = "http://localhost:3333/agents";
try {
const response = await fetch(url, {headers: {Accept: 'application/json'}});
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
const data = await response.json();
return data; // Return the fetched data
} catch (error) {
console.error(error.message);
return []; // Return an empty array on error
}
}
// Function to get agent data and update the graph
async function loadGraphData() {
console.log("Function loadGraphData()");
// Fetch agent data asynchronously
agentData = await fetchData();
// Check if the data is valid
console.log('Extracted agent data:', agentData);
// Only update the graph if agent data is available
if (agentData && agentData.length > 0) {
await updateGraph(agentData);
} else {
console.log('No agent data found or extracted.');
}
}