mirror of
https://github.com/jcreek/OpenNetworkDiagram.git
synced 2026-07-13 02:53:45 +00:00
refactor(*): Change to use components and css
This commit is contained in:
+1
-5
@@ -41,9 +41,5 @@
|
|||||||
"esbuild"
|
"esbuild"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0",
|
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
|
||||||
"dependencies": {
|
|
||||||
"cytoscape": "^3.31.2",
|
|
||||||
"cytoscape-dagre": "^2.5.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
-43
@@ -7,13 +7,6 @@ settings:
|
|||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
|
||||||
cytoscape:
|
|
||||||
specifier: ^3.31.2
|
|
||||||
version: 3.31.2
|
|
||||||
cytoscape-dagre:
|
|
||||||
specifier: ^2.5.0
|
|
||||||
version: 2.5.0(cytoscape@3.31.2)
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@eslint/compat':
|
'@eslint/compat':
|
||||||
specifier: ^1.2.5
|
specifier: ^1.2.5
|
||||||
@@ -698,18 +691,6 @@ packages:
|
|||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
cytoscape-dagre@2.5.0:
|
|
||||||
resolution: {integrity: sha512-VG2Knemmshop4kh5fpLO27rYcyUaaDkRw+6PiX4bstpB+QFt0p2oauMrsjVbUamGWQ6YNavh7x2em2uZlzV44g==}
|
|
||||||
peerDependencies:
|
|
||||||
cytoscape: ^3.2.22
|
|
||||||
|
|
||||||
cytoscape@3.31.2:
|
|
||||||
resolution: {integrity: sha512-/eOXg2uGdMdpGlEes5Sf6zE+jUG+05f3htFNQIxLxduOH/SsaUZiPBfAwP1btVIVzsnhiNOdi+hvDRLYfMZjGw==}
|
|
||||||
engines: {node: '>=0.10'}
|
|
||||||
|
|
||||||
dagre@0.8.5:
|
|
||||||
resolution: {integrity: sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==}
|
|
||||||
|
|
||||||
debug@4.4.0:
|
debug@4.4.0:
|
||||||
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
|
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
@@ -880,9 +861,6 @@ packages:
|
|||||||
graphemer@1.4.0:
|
graphemer@1.4.0:
|
||||||
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
|
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
|
||||||
|
|
||||||
graphlib@2.1.8:
|
|
||||||
resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==}
|
|
||||||
|
|
||||||
has-flag@4.0.0:
|
has-flag@4.0.0:
|
||||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1035,9 +1013,6 @@ packages:
|
|||||||
lodash.merge@4.6.2:
|
lodash.merge@4.6.2:
|
||||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||||
|
|
||||||
lodash@4.17.21:
|
|
||||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
|
||||||
|
|
||||||
magic-string@0.30.17:
|
magic-string@0.30.17:
|
||||||
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
||||||
|
|
||||||
@@ -1920,18 +1895,6 @@ snapshots:
|
|||||||
|
|
||||||
cssesc@3.0.0: {}
|
cssesc@3.0.0: {}
|
||||||
|
|
||||||
cytoscape-dagre@2.5.0(cytoscape@3.31.2):
|
|
||||||
dependencies:
|
|
||||||
cytoscape: 3.31.2
|
|
||||||
dagre: 0.8.5
|
|
||||||
|
|
||||||
cytoscape@3.31.2: {}
|
|
||||||
|
|
||||||
dagre@0.8.5:
|
|
||||||
dependencies:
|
|
||||||
graphlib: 2.1.8
|
|
||||||
lodash: 4.17.21
|
|
||||||
|
|
||||||
debug@4.4.0:
|
debug@4.4.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
@@ -2134,10 +2097,6 @@ snapshots:
|
|||||||
|
|
||||||
graphemer@1.4.0: {}
|
graphemer@1.4.0: {}
|
||||||
|
|
||||||
graphlib@2.1.8:
|
|
||||||
dependencies:
|
|
||||||
lodash: 4.17.21
|
|
||||||
|
|
||||||
has-flag@4.0.0: {}
|
has-flag@4.0.0: {}
|
||||||
|
|
||||||
ignore@5.3.2: {}
|
ignore@5.3.2: {}
|
||||||
@@ -2249,8 +2208,6 @@ snapshots:
|
|||||||
|
|
||||||
lodash.merge@4.6.2: {}
|
lodash.merge@4.6.2: {}
|
||||||
|
|
||||||
lodash@4.17.21: {}
|
|
||||||
|
|
||||||
magic-string@0.30.17:
|
magic-string@0.30.17:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.5.0
|
'@jridgewell/sourcemap-codec': 1.5.0
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { Device } from '../../stores/networkStore';
|
||||||
|
export let device: Device;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="device-card">
|
||||||
|
<h3>{device.name}</h3>
|
||||||
|
<p><strong>Type:</strong> {device.type}</p>
|
||||||
|
<p><strong>IP:</strong> {device.ipAddress}</p>
|
||||||
|
{#if device.notes}
|
||||||
|
<p><em>{device.notes}</em></p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.device-card {
|
||||||
|
border: 1px dashed #aaa;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { Machine } from '../../stores/networkStore';
|
||||||
|
import VMCard from './VMCard.svelte';
|
||||||
|
|
||||||
|
export let machine: Machine;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="machine-card">
|
||||||
|
<h2>{machine.machineName}</h2>
|
||||||
|
<p><strong>Role:</strong> {machine.role}</p>
|
||||||
|
<p><strong>IP Address:</strong> {machine.ipAddress}</p>
|
||||||
|
<p><strong>OS:</strong> {machine.operatingSystem}</p>
|
||||||
|
|
||||||
|
{#if machine.software?.vms?.length}
|
||||||
|
<details>
|
||||||
|
<summary>Show VMs (Total: {machine.software.vms.length})</summary>
|
||||||
|
<div class="vm-list">
|
||||||
|
{#each machine.software.vms as vm}
|
||||||
|
<VMCard {vm} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.machine-card {
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
max-width: 300px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
.machine-card h2 {
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
}
|
||||||
|
.vm-list {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,324 +1,48 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import type { NetworkData } from '../types';
|
import { networkStore, loadNetworkData } from '../../stores/networkStore';
|
||||||
import cytoscape from 'cytoscape';
|
import { get } from 'svelte/store';
|
||||||
import dagre from 'cytoscape-dagre';
|
|
||||||
let cy: cytoscape.Core | undefined;
|
|
||||||
cytoscape.use(dagre);
|
|
||||||
|
|
||||||
const networkData: NetworkData = {
|
import MachineCard from './MachineCard.svelte';
|
||||||
machines: [
|
import DeviceCard from './DeviceCard.svelte';
|
||||||
{
|
|
||||||
machineName: 'ProxRouter',
|
// Optionally pass in a JSON path as a prop
|
||||||
ipAddress: '10.0.0.3',
|
export let jsonPath: string = '/data/network.json';
|
||||||
role: 'Hypervisor',
|
|
||||||
operatingSystem: 'Proxmox',
|
// Local state
|
||||||
software: {
|
let data: any;
|
||||||
vms: [
|
|
||||||
{
|
onMount(async () => {
|
||||||
name: 'OpnSense',
|
// Load data into the store
|
||||||
role: 'Router',
|
await loadNetworkData(jsonPath);
|
||||||
ipAddress: '10.0.0.4'
|
|
||||||
},
|
// Subscribe once or use the $ syntax in markup
|
||||||
{
|
data = get(networkStore);
|
||||||
name: 'PiVPN',
|
|
||||||
role: 'VPN Server',
|
|
||||||
ipAddress: '10.0.0.5'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PiHole',
|
|
||||||
role: 'DNS Ad-blocker',
|
|
||||||
ipAddress: '10.0.0.6'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Dashy',
|
|
||||||
role: 'Dashboard',
|
|
||||||
ipAddress: '10.0.0.12'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'DockerHost',
|
|
||||||
role: 'Docker/Reverse Proxy',
|
|
||||||
ipAddress: '10.0.0.23'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
hardware: {
|
|
||||||
cpu: 'Intel N100',
|
|
||||||
ram: '8GB',
|
|
||||||
networkPorts: 4,
|
|
||||||
networkPortSpeedGbps: 1,
|
|
||||||
gpu: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
machineName: 'Asustor NAS',
|
|
||||||
ipAddress: '10.0.0.9',
|
|
||||||
role: 'NAS',
|
|
||||||
operatingSystem: 'Asustor ADM',
|
|
||||||
software: {
|
|
||||||
vms: []
|
|
||||||
},
|
|
||||||
hardware: {
|
|
||||||
cpu: 'Realtek RTD1296 Quad Core 1.4GHz',
|
|
||||||
ram: '2GB',
|
|
||||||
networkPorts: 1,
|
|
||||||
networkPortSpeedGbps: 1,
|
|
||||||
gpu: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
machineName: 'Home Assistant Green',
|
|
||||||
ipAddress: '10.0.0.13',
|
|
||||||
role: 'Smart Home Controller',
|
|
||||||
operatingSystem: 'Home Assistant OS',
|
|
||||||
software: {
|
|
||||||
vms: []
|
|
||||||
},
|
|
||||||
hardware: {
|
|
||||||
cpu: 'Home Assistant Custom SoC',
|
|
||||||
ram: 'Unknown',
|
|
||||||
networkPorts: 1,
|
|
||||||
networkPortSpeedGbps: 1,
|
|
||||||
gpu: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
machineName: 'Plex Server',
|
|
||||||
ipAddress: '10.0.0.11',
|
|
||||||
role: 'Media Server',
|
|
||||||
operatingSystem: 'Ubuntu Server',
|
|
||||||
software: {
|
|
||||||
vms: []
|
|
||||||
},
|
|
||||||
hardware: {
|
|
||||||
cpu: 'Intel N100',
|
|
||||||
ram: 'Unknown',
|
|
||||||
networkPorts: 1,
|
|
||||||
networkPortSpeedGbps: 1,
|
|
||||||
gpu: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
machineName: 'Win11 N100',
|
|
||||||
ipAddress: '10.0.0.8',
|
|
||||||
role: 'Media Downloader',
|
|
||||||
operatingSystem: 'Windows 11',
|
|
||||||
software: {
|
|
||||||
vms: []
|
|
||||||
},
|
|
||||||
hardware: {
|
|
||||||
cpu: 'Intel N100',
|
|
||||||
ram: 'Unknown',
|
|
||||||
networkPorts: 1,
|
|
||||||
networkPortSpeedGbps: 1,
|
|
||||||
gpu: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
machineName: 'Win11 Backblaze NAS',
|
|
||||||
ipAddress: '10.0.0.7',
|
|
||||||
role: 'Backup NAS + Hypervisor',
|
|
||||||
operatingSystem: 'TrueNAS Scale',
|
|
||||||
software: {
|
|
||||||
vms: [
|
|
||||||
{
|
|
||||||
name: 'Win11-Backblaze',
|
|
||||||
role: 'Backblaze Backup',
|
|
||||||
ipAddress: '10.0.0.24'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'UbuntuDockerHost',
|
|
||||||
role: 'Docker Host',
|
|
||||||
ipAddress: '10.0.0.14'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'MakeMKV',
|
|
||||||
role: 'Blu-ray Ripper',
|
|
||||||
ipAddress: '10.0.0.14'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Handbrake',
|
|
||||||
role: 'Video Transcoder',
|
|
||||||
ipAddress: '10.0.0.15'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'NextCloud',
|
|
||||||
role: 'Cloud Storage',
|
|
||||||
ipAddress: 'TBD'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
hardware: {
|
|
||||||
cpu: 'AMD Ryzen 5 4600G',
|
|
||||||
ram: '16GB',
|
|
||||||
networkPorts: 1,
|
|
||||||
networkPortSpeedGbps: 1,
|
|
||||||
gpu: 'EVGA GeForce GTX 1050 Ti'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
machineName: 'AI Server',
|
|
||||||
ipAddress: '10.0.0.20',
|
|
||||||
role: 'AI Dev/Inference',
|
|
||||||
operatingSystem: 'Pop!_OS',
|
|
||||||
software: {
|
|
||||||
vms: [
|
|
||||||
{
|
|
||||||
name: 'Ollama',
|
|
||||||
role: 'LLM Inference',
|
|
||||||
ipAddress: '10.0.0.21'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Bot Training',
|
|
||||||
role: 'AI Training',
|
|
||||||
ipAddress: '10.0.0.22'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
hardware: {
|
|
||||||
cpu: 'AMD Ryzen 5 3600',
|
|
||||||
ram: '32GB',
|
|
||||||
networkPorts: 1,
|
|
||||||
networkPortSpeedGbps: 1,
|
|
||||||
gpu: 'Gigabyte GeForce GTX 1080'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
devices: [
|
|
||||||
{
|
|
||||||
name: 'Router',
|
|
||||||
ipAddress: '10.0.0.1',
|
|
||||||
type: 'Gateway',
|
|
||||||
notes: 'Main internet-facing router'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'HDHomeRun',
|
|
||||||
ipAddress: '10.0.0.2',
|
|
||||||
type: 'TV Tuner'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Omada Controller',
|
|
||||||
ipAddress: '10.0.0.4',
|
|
||||||
type: 'Network Controller',
|
|
||||||
notes: 'Access via port 8043'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '3DS',
|
|
||||||
ipAddress: '10.0.0.17',
|
|
||||||
type: 'Handheld Console'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '2DS',
|
|
||||||
ipAddress: '10.0.0.18',
|
|
||||||
type: 'Handheld Console'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Nintendo Switch',
|
|
||||||
ipAddress: '10.0.0.19',
|
|
||||||
type: 'Gaming Console',
|
|
||||||
notes: 'IP to be confirmed'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
onMount(() => {
|
|
||||||
const container = document.getElementById('cy') as HTMLDivElement;
|
|
||||||
if (!container) {
|
|
||||||
console.error("Container element '#cy' not found in the DOM.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
renderDiagram(networkData, container);
|
|
||||||
});
|
});
|
||||||
function renderDiagram(data: NetworkData, container: HTMLDivElement) {
|
|
||||||
if (cy) {
|
|
||||||
cy.destroy();
|
|
||||||
}
|
|
||||||
const nodes: cytoscape.NodeDefinition[] = [];
|
|
||||||
const edges: cytoscape.EdgeDefinition[] = [];
|
|
||||||
data.machines.forEach((machine) => {
|
|
||||||
nodes.push({
|
|
||||||
data: { id: machine.machineName, label: machine.machineName },
|
|
||||||
classes: 'machine-node',
|
|
||||||
position: { x: 0, y: 0 } // Initial position
|
|
||||||
});
|
|
||||||
machine.software.vms.forEach((vm) => {
|
|
||||||
nodes.push({
|
|
||||||
data: { id: vm.name, label: vm.name, parent: machine.machineName },
|
|
||||||
classes: 'vm-node'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const elementsArray = [...nodes, ...edges];
|
|
||||||
cy = cytoscape({
|
|
||||||
container: container,
|
|
||||||
elements: elementsArray,
|
|
||||||
style: [
|
|
||||||
{
|
|
||||||
selector: 'node',
|
|
||||||
style: {
|
|
||||||
'background-color': '#3e4451',
|
|
||||||
'border-color': '#555555',
|
|
||||||
'border-width': 2,
|
|
||||||
color: '#ffffff',
|
|
||||||
'font-size': '14px',
|
|
||||||
'text-halign': 'center',
|
|
||||||
'text-valign': 'top',
|
|
||||||
'text-margin-y': 20,
|
|
||||||
padding: '20px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selector: '.machine-node',
|
|
||||||
style: {
|
|
||||||
label: 'data(label)',
|
|
||||||
'background-color': '#61afef',
|
|
||||||
color: '#282c34',
|
|
||||||
height: 150, // Set height and width for the parent node
|
|
||||||
width: 200,
|
|
||||||
shape: 'roundrectangle'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selector: '.vm-node',
|
|
||||||
style: {
|
|
||||||
label: 'data(label)',
|
|
||||||
'background-color': '#c6c6c6',
|
|
||||||
color: '#282c34',
|
|
||||||
height: 50, // Set height and width for the child nodes
|
|
||||||
width: 150,
|
|
||||||
shape: 'roundrectangle'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selector: 'edge',
|
|
||||||
style: {
|
|
||||||
width: 3,
|
|
||||||
'line-color': '#9dbaea',
|
|
||||||
'target-arrow-color': '#9dbaea',
|
|
||||||
'target-arrow-shape': 'triangle',
|
|
||||||
'curve-style': 'bezier'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
selector: ':parent',
|
|
||||||
style: {
|
|
||||||
'border-width': 3,
|
|
||||||
'border-color': '#555555'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
layout: {
|
|
||||||
name: 'dagre',
|
|
||||||
rankDir: 'TB', // Top-to-Bottom direction
|
|
||||||
nodeSep: 50, // Pixel value between each node on the same level
|
|
||||||
edgeSep: 30, // Minimum vertical separation that’s enforced between edges
|
|
||||||
rankSep: 80 // Vertical separation that's used between ranks (levels of nodes)
|
|
||||||
},
|
|
||||||
minZoom: 1, // Set min and max zoom levels if needed
|
|
||||||
maxZoom: 3
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div id="cy" style="width: 100%; height: 1000px; background-color: #282c34;"></div>
|
{#if data}
|
||||||
|
<div class="diagram-container">
|
||||||
|
<!-- Render Machines -->
|
||||||
|
{#each data.machines as machine}
|
||||||
|
<MachineCard {machine} />
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<!-- Render Other Devices -->
|
||||||
|
{#each data.devices as device}
|
||||||
|
<DeviceCard {device} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.diagram-container {
|
||||||
|
/* Example layout style - customize as needed */
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { VMInfo } from '../../stores/networkStore';
|
||||||
|
export let vm: VMInfo;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="vm-card">
|
||||||
|
<p><strong>{vm.name}</strong></p>
|
||||||
|
<p>Role: {vm.role}</p>
|
||||||
|
<p>IP: {vm.ipAddress}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.vm-card {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background-color: #eaeaea;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
export interface VMInfo {
|
||||||
|
name: string;
|
||||||
|
role: string;
|
||||||
|
ipAddress: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Software {
|
||||||
|
vms: VMInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Hardware {
|
||||||
|
cpu: string;
|
||||||
|
ram: string;
|
||||||
|
networkPorts: number;
|
||||||
|
networkPortSpeedGbps?: number;
|
||||||
|
gpu?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Machine {
|
||||||
|
machineName: string;
|
||||||
|
ipAddress: string;
|
||||||
|
role: string;
|
||||||
|
operatingSystem: string;
|
||||||
|
software: Software;
|
||||||
|
hardware: Hardware;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Device {
|
||||||
|
name: string;
|
||||||
|
ipAddress: string;
|
||||||
|
type: string;
|
||||||
|
notes?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NetworkData {
|
||||||
|
machines: Machine[];
|
||||||
|
devices: Device[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a writable store for the data
|
||||||
|
export const networkStore = writable<NetworkData>({
|
||||||
|
machines: [],
|
||||||
|
devices: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// A function to load JSON from an API or local file if needed
|
||||||
|
export async function loadNetworkData(jsonPath: string) {
|
||||||
|
// For a real app, fetch the file or do an import:
|
||||||
|
// const response = await fetch(jsonPath);
|
||||||
|
// const data = await response.json();
|
||||||
|
// networkStore.set(data);
|
||||||
|
|
||||||
|
// For now, set a static example:
|
||||||
|
const exampleData: NetworkData = {
|
||||||
|
machines: [
|
||||||
|
{
|
||||||
|
machineName: 'ProxRouter',
|
||||||
|
ipAddress: '10.0.0.3',
|
||||||
|
role: 'Hypervisor',
|
||||||
|
operatingSystem: 'Proxmox',
|
||||||
|
software: {
|
||||||
|
vms: [
|
||||||
|
{
|
||||||
|
name: 'OpnSense',
|
||||||
|
role: 'Router',
|
||||||
|
ipAddress: '10.0.0.4'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'PiVPN',
|
||||||
|
role: 'VPN Server',
|
||||||
|
ipAddress: '10.0.0.5'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'PiHole',
|
||||||
|
role: 'DNS Ad-blocker',
|
||||||
|
ipAddress: '10.0.0.6'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Dashy',
|
||||||
|
role: 'Dashboard',
|
||||||
|
ipAddress: '10.0.0.12'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'DockerHost',
|
||||||
|
role: 'Docker/Reverse Proxy',
|
||||||
|
ipAddress: '10.0.0.23'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
hardware: {
|
||||||
|
cpu: 'Intel N100',
|
||||||
|
ram: '8GB',
|
||||||
|
networkPorts: 4,
|
||||||
|
networkPortSpeedGbps: 1,
|
||||||
|
gpu: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
machineName: 'Asustor NAS',
|
||||||
|
ipAddress: '10.0.0.9',
|
||||||
|
role: 'NAS',
|
||||||
|
operatingSystem: 'Asustor ADM',
|
||||||
|
software: {
|
||||||
|
vms: []
|
||||||
|
},
|
||||||
|
hardware: {
|
||||||
|
cpu: 'Realtek RTD1296 Quad Core 1.4GHz',
|
||||||
|
ram: '2GB',
|
||||||
|
networkPorts: 1,
|
||||||
|
networkPortSpeedGbps: 1,
|
||||||
|
gpu: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
machineName: 'Home Assistant Green',
|
||||||
|
ipAddress: '10.0.0.13',
|
||||||
|
role: 'Smart Home Controller',
|
||||||
|
operatingSystem: 'Home Assistant OS',
|
||||||
|
software: {
|
||||||
|
vms: []
|
||||||
|
},
|
||||||
|
hardware: {
|
||||||
|
cpu: 'Home Assistant Custom SoC',
|
||||||
|
ram: 'Unknown',
|
||||||
|
networkPorts: 1,
|
||||||
|
networkPortSpeedGbps: 1,
|
||||||
|
gpu: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
machineName: 'Plex Server',
|
||||||
|
ipAddress: '10.0.0.11',
|
||||||
|
role: 'Media Server',
|
||||||
|
operatingSystem: 'Ubuntu Server',
|
||||||
|
software: {
|
||||||
|
vms: []
|
||||||
|
},
|
||||||
|
hardware: {
|
||||||
|
cpu: 'Intel N100',
|
||||||
|
ram: 'Unknown',
|
||||||
|
networkPorts: 1,
|
||||||
|
networkPortSpeedGbps: 1,
|
||||||
|
gpu: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
machineName: 'Win11 N100',
|
||||||
|
ipAddress: '10.0.0.8',
|
||||||
|
role: 'Media Downloader',
|
||||||
|
operatingSystem: 'Windows 11',
|
||||||
|
software: {
|
||||||
|
vms: []
|
||||||
|
},
|
||||||
|
hardware: {
|
||||||
|
cpu: 'Intel N100',
|
||||||
|
ram: 'Unknown',
|
||||||
|
networkPorts: 1,
|
||||||
|
networkPortSpeedGbps: 1,
|
||||||
|
gpu: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
machineName: 'Win11 Backblaze NAS',
|
||||||
|
ipAddress: '10.0.0.7',
|
||||||
|
role: 'Backup NAS + Hypervisor',
|
||||||
|
operatingSystem: 'TrueNAS Scale',
|
||||||
|
software: {
|
||||||
|
vms: [
|
||||||
|
{
|
||||||
|
name: 'Win11-Backblaze',
|
||||||
|
role: 'Backblaze Backup',
|
||||||
|
ipAddress: '10.0.0.24'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'UbuntuDockerHost',
|
||||||
|
role: 'Docker Host',
|
||||||
|
ipAddress: '10.0.0.14'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'MakeMKV',
|
||||||
|
role: 'Blu-ray Ripper',
|
||||||
|
ipAddress: '10.0.0.14'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Handbrake',
|
||||||
|
role: 'Video Transcoder',
|
||||||
|
ipAddress: '10.0.0.15'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NextCloud',
|
||||||
|
role: 'Cloud Storage',
|
||||||
|
ipAddress: 'TBD'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
hardware: {
|
||||||
|
cpu: 'AMD Ryzen 5 4600G',
|
||||||
|
ram: '16GB',
|
||||||
|
networkPorts: 1,
|
||||||
|
networkPortSpeedGbps: 1,
|
||||||
|
gpu: 'EVGA GeForce GTX 1050 Ti'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
machineName: 'AI Server',
|
||||||
|
ipAddress: '10.0.0.20',
|
||||||
|
role: 'AI Dev/Inference',
|
||||||
|
operatingSystem: 'Pop!_OS',
|
||||||
|
software: {
|
||||||
|
vms: [
|
||||||
|
{
|
||||||
|
name: 'Ollama',
|
||||||
|
role: 'LLM Inference',
|
||||||
|
ipAddress: '10.0.0.21'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bot Training',
|
||||||
|
role: 'AI Training',
|
||||||
|
ipAddress: '10.0.0.22'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
hardware: {
|
||||||
|
cpu: 'AMD Ryzen 5 3600',
|
||||||
|
ram: '32GB',
|
||||||
|
networkPorts: 1,
|
||||||
|
networkPortSpeedGbps: 1,
|
||||||
|
gpu: 'Gigabyte GeForce GTX 1080'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
devices: [
|
||||||
|
{
|
||||||
|
name: 'Router',
|
||||||
|
ipAddress: '10.0.0.1',
|
||||||
|
type: 'Gateway',
|
||||||
|
notes: 'Main internet-facing router'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'HDHomeRun',
|
||||||
|
ipAddress: '10.0.0.2',
|
||||||
|
type: 'TV Tuner'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Omada Controller',
|
||||||
|
ipAddress: '10.0.0.4',
|
||||||
|
type: 'Network Controller',
|
||||||
|
notes: 'Access via port 8043'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '3DS',
|
||||||
|
ipAddress: '10.0.0.17',
|
||||||
|
type: 'Handheld Console'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '2DS',
|
||||||
|
ipAddress: '10.0.0.18',
|
||||||
|
type: 'Handheld Console'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Nintendo Switch',
|
||||||
|
ipAddress: '10.0.0.19',
|
||||||
|
type: 'Gaming Console',
|
||||||
|
notes: 'IP to be confirmed'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
networkStore.set(exampleData);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user