171 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
{% 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 %}
 |