You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
5.0 KiB

{% extends "base.html" %}
{% block content %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.30.4/cytoscape.min.js"></script>
<style>
/* Reset default margins and paddings */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Set body and html to take full height */
html, body {
height: 100%;
font-family: Arial, sans-serif;
}
/* Container for the entire content */
.container {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
padding: 20px;
background-color: #f9f9f9;
}
/* Style for the graph container */
#cy {
flex: 1;
width: 100%;
max-width: 1200px;
height: 600px;
border: 1px solid #ccc;
background-color: #fff;
}
/* Style for control buttons */
.controls {
margin-bottom: 10px;
}
.controls button {
padding: 10px 20px;
margin: 0 5px;
font-size: 16px;
cursor: pointer;
border: none;
background-color: #0074D9;
color: #fff;
border-radius: 4px;
transition: background-color 0.3s;
}
.controls button:hover {
background-color: #005fa3;
}
</style>
<h1>{{ PAGE_TITLE }}</h1>
<div class="container">
<!-- Control Buttons -->
<div class="controls">
<button id="zoom-in">Zoom In</button>
<button id="zoom-out">Zoom Out</button>
<button id="reset">Reset Zoom</button>
</div>
<!-- Graph Container -->
<div id="cy"></div>
</div>
<script>
// Wait for the DOM to fully load
document.addEventListener('DOMContentLoaded', function() {
// Initialize Cytoscape with elements and style
const data = {{ GRAPH_JSON }};
const elements = [];
// Iterate through each key-value pair in the JSON object
for (const [key, values] of Object.entries(data)) {
// Add a node for the key
elements.push({ data: { id: key, label: key } });
// Add nodes and edges for each value
values.forEach(value => {
elements.push({ data: { id: value, label: value } }); // Node for value
elements.push({ data: { source: value, target: key } }); // Edge from value to key
});
}
var cy = cytoscape({
container: document.getElementById('cy'), // Container to render in
elements: elements,
style: [ // Styling for nodes and edges
{
selector: 'node',
style: {
'background-color': '#0074D9',
'label': 'data(label)',
'color': '#fff',
'text-valign': 'center',
'text-halign': 'center',
'font-size': '10px',
'width': '60px',
'height': '60px'
}
},
{
selector: 'edge',
style: {
'width': 2,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle',
'curve-style': 'bezier'
}
},
{
selector: ':selected',
style: {
'background-color': '#FF4136',
'line-color': '#FF4136',
'target-arrow-color': '#FF4136',
'source-arrow-color': '#FF4136'
}
}
],
layout: {
name: 'breadthfirst',
directed: true,
spacingFactor: 2.75,
animate: true
}
});
// Fit the graph within the container
cy.on('layoutready', function(){
cy.fit(cy.elements(), 50);
});
// Optional: Add interactivity
cy.on('tap', 'node', function(evt){
var node = evt.target;
alert('Tapped node: ' + node.id());
});
// Zoom and Pan Controls
document.getElementById('zoom-in').addEventListener('click', function(){
cy.zoom({
level: cy.zoom() * 1.2, // Zoom in by 20%
renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 }
});
});
document.getElementById('zoom-out').addEventListener('click', function(){
cy.zoom({
level: cy.zoom() / 1.2, // Zoom out by ~16.7%
renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 }
});
});
document.getElementById('reset').addEventListener('click', function(){
cy.fit(cy.elements(), 50); // Fit the graph to the container with padding
});
});
</script>
{% endblock %}