feat: Erweiterung der Module für Geräte, Stockwerke und Racks mit grundlegenden Funktionen und Strukturen

This commit is contained in:
Troy Grunt
2026-02-06 18:47:25 +01:00
parent 3ec3ad7fa5
commit 98a3f4d5b6
8 changed files with 943 additions and 8 deletions

View File

@@ -1 +1,122 @@
// Globale JS-Funktionen, Initialisierung
/**
* app/assets/js/app.js
*
* Zentrale JS-Datei für die Webanwendung
* - Initialisiert alle Module
* - SVG-Editor, Netzwerk-Ansicht, Drag & Drop, Floorplan
* - Event-Handler, globale Variablen
*/
// =========================
// Global Variables / Config
// =========================
window.APP = {
deviceTypes: [], // TODO: alle Gerätetypen laden
devices: [], // TODO: alle Geräte laden
racks: [], // TODO: alle Racks laden
floors: [], // TODO: alle Floors laden
connections: [], // TODO: alle Verbindungen laden
};
// =========================
// Init Functions
// =========================
document.addEventListener('DOMContentLoaded', () => {
console.log('App initialized');
// =========================
// SVG-Port-Editor initialisieren
// =========================
// TODO: import / init svg-editor.js
// if (window.SVGEditor) window.SVGEditor.init();
// =========================
// Netzwerk-Ansicht initialisieren
// =========================
// TODO: import / init network-view.js
// if (window.NetworkView) window.NetworkView.init();
// =========================
// Drag & Drop für Floors / Racks / Devices
// =========================
// TODO: init drag & drop logic
// =========================
// Event-Handler für Buttons / Forms
// =========================
initEventHandlers();
});
// =========================
// Event Handler Setup
// =========================
function initEventHandlers() {
// TODO: Save-Button Device-Type
const saveDeviceTypeBtn = document.querySelector('#save-device-type');
if (saveDeviceTypeBtn) {
saveDeviceTypeBtn.addEventListener('click', (e) => {
e.preventDefault();
// TODO: Save Device-Type via AJAX
});
}
// TODO: Save-Button Device
const saveDeviceBtn = document.querySelector('#save-device');
if (saveDeviceBtn) {
saveDeviceBtn.addEventListener('click', (e) => {
e.preventDefault();
// TODO: Save Device via AJAX
});
}
// TODO: Save-Button Floor
const saveFloorBtn = document.querySelector('#save-floor');
if (saveFloorBtn) {
saveFloorBtn.addEventListener('click', (e) => {
e.preventDefault();
// TODO: Save Floor via AJAX
});
}
// TODO: Save-Button Rack
const saveRackBtn = document.querySelector('#save-rack');
if (saveRackBtn) {
saveRackBtn.addEventListener('click', (e) => {
e.preventDefault();
// TODO: Save Rack via AJAX
});
}
// TODO: Weitere Event-Handler (Löschen, Import, Export, Filter)
}
// =========================
// Utility Functions
// =========================
/**
* AJAX Request Helper
* @param {string} url
* @param {object} data
* @param {function} callback
*/
function ajaxPost(url, data, callback) {
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
callback(JSON.parse(xhr.responseText));
} else {
console.error('AJAX Error:', xhr.statusText);
}
};
xhr.send(JSON.stringify(data));
}
// TODO: weitere Utility-Funktionen (DOM-Helper, SVG-Helper, etc.)

View File

@@ -1,2 +1,156 @@
<?php
// Gerät anlegen oder bearbeiten
/**
* app/devices/edit.php
*
* Konkretes Gerät anlegen / bearbeiten
* - Name, Beschreibung, Standort (Rack / Floor)
* - Gerätetyp wählen
* - Ports automatisch vom Device-Type übernehmen
* - SVG-Position im Rack / Floor
* - Optional: Notizen / Kommentare
*/
// TODO: bootstrap laden
// require_once __DIR__ . '/../../bootstrap.php';
// TODO: Auth erzwingen
// requireAuth();
// =========================
// Kontext bestimmen
// =========================
// Gerät-ID aus GET
// $deviceId = (int)($_GET['id'] ?? 0);
// TODO: Gerät aus DB laden, falls ID vorhanden
// $device = null;
// TODO: Alle Device-Types laden
// $deviceTypes = $sql->get("SELECT * FROM device_types ORDER BY name", "", []);
// TODO: Wenn Gerät vorhanden, Ports laden (vom Device-Type)
$ports = []; // TODO: Ports vorbereiten
?>
<h2>Gerät bearbeiten</h2>
<form method="post" action="/app/devices/save.php" enctype="multipart/form-data">
<!-- =========================
Basisdaten
========================= -->
<fieldset>
<legend>Allgemein</legend>
<label>
Name<br>
<input type="text" name="name" value="">
<!-- TODO: Name vorbelegen -->
</label>
<br><br>
<label>
Beschreibung<br>
<textarea name="description"></textarea>
<!-- TODO: Beschreibung vorbelegen -->
</label>
<br><br>
<label>
Gerätetyp<br>
<select name="device_type_id">
<!-- TODO: Device-Types aus DB -->
<option value="1">Switch</option>
</select>
</label>
</fieldset>
<!-- =========================
Standort / Rack / Floor
========================= -->
<fieldset>
<legend>Standort</legend>
<label>
Stockwerk<br>
<select name="floor_id">
<!-- TODO: Floors laden -->
</select>
</label>
<br><br>
<label>
Rack<br>
<select name="rack_id">
<!-- TODO: Racks laden -->
</select>
</label>
<br><br>
<label>
Position im Rack<br>
<input type="number" name="rack_position" value="">
</label>
</fieldset>
<!-- =========================
Ports
========================= -->
<fieldset>
<legend>Ports</legend>
<p class="hint">Ports werden vom Device-Type übernommen. Positionen können angepasst werden.</p>
<div class="svg-editor-container">
<svg
id="device-svg"
viewBox="0 0 800 400"
width="100%"
height="400"
>
<!-- TODO: SVG laden -->
</svg>
</div>
<!-- TODO: Port-Liste -->
<div class="port-list">
<!-- Ports mit Typ, Name, Modus, VLAN -->
</div>
</fieldset>
<!-- =========================
Aktionen
========================= -->
<fieldset>
<button type="submit">Speichern</button>
<button type="button" onclick="history.back()">Abbrechen</button>
<!-- TODO: Löschen, falls edit -->
</fieldset>
</form>
<!-- =========================
JS-Konfiguration
========================= -->
<script>
/**
* SVG-Editor Konfiguration
*/
// TODO: Device-ID setzen
// window.DEVICE_ID = <?= (int)$deviceId ?>;
// TODO: Ports an JS übergeben
// window.DEVICE_PORTS = <?= json_encode($ports) ?>;
</script>

View File

@@ -1,2 +1,111 @@
<?php
// Liste aller Geräte anzeigen
/**
* app/devices/list.php
*
* Übersicht aller Geräte
* - Anzeigen
* - Bearbeiten
* - Löschen
* - SVG / JPG Vorschau
*/
// TODO: bootstrap laden
// require_once __DIR__ . '/../../bootstrap.php';
// TODO: Auth erzwingen
// requireAuth();
// =========================
// Geräte laden
// =========================
// TODO: Geräte aus DB laden
// $devices = $sql->get("SELECT * FROM devices ORDER BY name", "", []);
?>
<h2>Geräte</h2>
<!-- =========================
Toolbar
========================= -->
<div class="toolbar">
<a href="/?page=devices/edit" class="button">
+ Neues Gerät
</a>
<!-- TODO: Suchfeld -->
<!-- TODO: Filter (Device-Type, Standort, Floor, Rack) -->
</div>
<!-- =========================
Geräte-Tabelle
========================= -->
<table class="device-list">
<thead>
<tr>
<th>Vorschau</th>
<th>Name</th>
<th>Gerätetyp</th>
<th>Standort</th>
<th>Rack</th>
<th>Rack-Pos</th>
<th>Ports</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php /* foreach ($devices as $device): */ ?>
<tr>
<td class="preview">
<!-- TODO: SVG / JPG Thumbnail -->
</td>
<td>
<!-- TODO: Name -->
Gerät XY
</td>
<td>
<!-- TODO: Gerätetyp -->
</td>
<td>
<!-- TODO: Standort / Floor -->
</td>
<td>
<!-- TODO: Rack -->
</td>
<td>
<!-- TODO: Rack-Position -->
</td>
<td>
<!-- TODO: Anzahl Ports -->
</td>
<td>
<a href="/?page=devices/edit&id=1">Bearbeiten</a>
<button> Löschen </button>
</td>
</tr>
<?php /* endforeach; */ ?>
</tbody>
</table>
<!-- =========================
Leerer Zustand
========================= -->
<?php /* if (empty($devices)): */ ?>
<div class="empty-state">
<p>Noch keine Geräte angelegt.</p>
<p><a href="/?page=devices/edit">Erstes Gerät anlegen</a></p>
</div>
<?php /* endif; */ ?>

View File

@@ -1,2 +1,104 @@
<?php
// Gerät speichern (Rack-Position, Typ, Name)
/**
* app/devices/save.php
*
* Speichert:
* - Basisdaten (Name, Beschreibung)
* - Gerätetyp-Zuordnung
* - Standort (Floor, Rack, Rack-Position)
* - Ports (vom Device-Type übernommen)
* - SVG-Positionen
*
* POST JSON oder multipart/form-data
*/
// TODO: bootstrap laden
// require_once __DIR__ . '/../../bootstrap.php';
// TODO: Auth erzwingen
// requireAuth();
// =========================
// Request prüfen
// =========================
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit;
}
// =========================
// Daten aus POST / JSON
// =========================
// TODO: Prüfen, ob multipart/form-data oder JSON
// $data = json_decode(file_get_contents('php://input'), true);
// Basisfelder
// $deviceId = $data['id'] ?? null;
// $name = $data['name'] ?? '';
// $description = $data['description'] ?? '';
// $deviceTypeId = $data['device_type_id'] ?? null;
// $floorId = $data['floor_id'] ?? null;
// $rackId = $data['rack_id'] ?? null;
// $rackPosition = $data['rack_position'] ?? null;
// $svgPositions = $data['svg_positions'] ?? [];
// $portsData = $data['ports'] ?? [];
// =========================
// Validierung
// =========================
// TODO:
// - Name nicht leer
// - Device-Type existiert
// - Floor / Rack gültig
// - Ports valide
// =========================
// Bild / SVG Upload (optional)
// =========================
// TODO: $_FILES['image'] prüfen
// - Upload in /uploads/devices
// - SVG prüfen / sanitizen
// - Pfad speichern
// =========================
// Device speichern
// =========================
if (!empty($deviceId)) {
// TODO: UPDATE devices SET ...
// $rows = $sql->set("UPDATE ...", "???", [...]);
} else {
// TODO: INSERT INTO devices ...
// $deviceId = $sql->set("INSERT ...", "???", [...], true);
}
// =========================
// Ports speichern / übernehmen vom Device-Type
// =========================
// TODO:
// - $portsData iterieren
// - Positionen aus SVG übernehmen
// - port_type_id, name, VLAN, Modus speichern
// =========================
// SVG-Positionen speichern
// =========================
// TODO:
// - device_positions Tabelle?
// - x/y Koordinaten
// - Rotation / Zoom (optional)
// =========================
// Antwort
// =========================
echo json_encode([
'status' => 'ok',
'id' => $deviceId
]);

View File

@@ -1,2 +1,128 @@
<?php
// Stockwerk bearbeiten inkl. SVG-Plan
/**
* app/floors/edit.php
*
* Floor / Stockwerk anlegen oder bearbeiten
* - Name, Beschreibung
* - Zugehörige Räume / Netzwerkdosen
* - SVG-Grundriss laden / speichern
*/
// TODO: bootstrap laden
// require_once __DIR__ . '/../../bootstrap.php';
// TODO: Auth erzwingen
// requireAuth();
// =========================
// Kontext bestimmen
// =========================
// Floor-ID aus GET
// $floorId = (int)($_GET['id'] ?? 0);
// TODO: Floor aus DB laden, falls ID vorhanden
// $floor = null;
// TODO: Räume / Dosen laden, falls Floor existiert
$rooms = []; // TODO: Räume vorbereiten
?>
<h2>Stockwerk bearbeiten</h2>
<form method="post" action="/app/floors/save.php" enctype="multipart/form-data">
<!-- =========================
Basisdaten
========================= -->
<fieldset>
<legend>Allgemein</legend>
<label>
Name<br>
<input type="text" name="name" value="">
<!-- TODO: Name vorbelegen -->
</label>
<br><br>
<label>
Beschreibung<br>
<textarea name="description"></textarea>
<!-- TODO: Beschreibung vorbelegen -->
</label>
</fieldset>
<!-- =========================
Räume / Netzwerkdosen
========================= -->
<fieldset>
<legend>Räume / Netzwerkdosen</legend>
<p class="hint">
Räume hinzufügen / bearbeiten. Netzwerkdosen können einzeln nummeriert / benannt werden.
</p>
<div class="room-list">
<!-- TODO: Räume auflisten -->
<!-- TODO: Netzwerkdosen pro Raum anzeigen -->
</div>
<button type="button" id="add-room">
+ Raum hinzufügen
</button>
</fieldset>
<!-- =========================
SVG Floorplan
========================= -->
<fieldset>
<legend>Grundriss / Floorplan</legend>
<div class="svg-editor-container">
<svg
id="floor-svg"
viewBox="0 0 2000 1000"
width="100%"
height="600"
>
<!-- TODO: Floorplan SVG laden -->
</svg>
</div>
<p class="hint">
Räume und Netzwerkdosen per Drag & Drop platzieren. Nummerierung und Bezeichnungen editierbar.
</p>
</fieldset>
<!-- =========================
Aktionen
========================= -->
<fieldset>
<button type="submit">Speichern</button>
<button type="button" onclick="history.back()">Abbrechen</button>
<!-- TODO: Löschen, falls edit -->
</fieldset>
</form>
<!-- =========================
JS-Konfiguration
========================= -->
<script>
/**
* Konfiguration für Floorplan SVG-Editor
*/
// TODO: Floor-ID aus PHP setzen
// window.FLOOR_ID = <?= (int)$floorId ?>;
// TODO: Räume / Dosen an JS übergeben
// window.ROOMS = <?= json_encode($rooms) ?>;
</script>

View File

@@ -1,2 +1,96 @@
<?php
// Übersicht aller Stockwerke
/**
* app/floors/list.php
*
* Übersicht aller Floors / Stockwerke
* - Anzeigen
* - Bearbeiten
* - Löschen
* - SVG-Vorschau optional
*/
// TODO: bootstrap laden
// require_once __DIR__ . '/../../bootstrap.php';
// TODO: Auth erzwingen
// requireAuth();
// =========================
// Floors laden
// =========================
// TODO: Floors aus DB laden
// $floors = $sql->get("SELECT * FROM floors ORDER BY name", "", []);
?>
<h2>Stockwerke</h2>
<!-- =========================
Toolbar
========================= -->
<div class="toolbar">
<a href="/?page=floors/edit" class="button">
+ Neues Stockwerk
</a>
<!-- TODO: Suchfeld -->
<!-- TODO: Filter (Gebäude / Standort) -->
</div>
<!-- =========================
Floor-Tabelle
========================= -->
<table class="floor-list">
<thead>
<tr>
<th>Vorschau</th>
<th>Name</th>
<th>Beschreibung</th>
<th>Räume</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php /* foreach ($floors as $floor): */ ?>
<tr>
<td class="preview">
<!-- TODO: SVG / JPG Thumbnail Floorplan -->
</td>
<td>
<!-- TODO: Name -->
Floor 1
</td>
<td>
<!-- TODO: Beschreibung -->
</td>
<td>
<!-- TODO: Anzahl Räume -->
</td>
<td>
<a href="/?page=floors/edit&id=1">Bearbeiten</a>
<button>Löschen</button>
</td>
</tr>
<?php /* endforeach; */ ?>
</tbody>
</table>
<!-- =========================
Leerer Zustand
========================= -->
<?php /* if (empty($floors)): */ ?>
<div class="empty-state">
<p>Noch keine Stockwerke angelegt.</p>
<p><a href="/?page=floors/edit">Erstes Stockwerk anlegen</a></p>
</div>
<?php /* endif; */ ?>

View File

@@ -1,2 +1,131 @@
<?php
// Rack anlegen oder bearbeiten
/**
* app/racks/edit.php
*
* Rack anlegen oder bearbeiten
* - Name, Beschreibung
* - Zugehöriges Stockwerk (Floor)
* - Höhe / Slots
* - Gerätepositionen (optional Vorschau)
*/
// TODO: bootstrap laden
// require_once __DIR__ . '/../../bootstrap.php';
// TODO: Auth erzwingen
// requireAuth();
// =========================
// Kontext bestimmen
// =========================
// Rack-ID aus GET
// $rackId = (int)($_GET['id'] ?? 0);
// TODO: Rack aus DB laden, falls ID vorhanden
// $rack = null;
// TODO: Floors laden für Auswahl
// $floors = $sql->get("SELECT * FROM floors ORDER BY name", "", []);
?>
<h2>Rack bearbeiten</h2>
<form method="post" action="/app/racks/save.php" enctype="multipart/form-data">
<!-- =========================
Basisdaten
========================= -->
<fieldset>
<legend>Allgemein</legend>
<label>
Name<br>
<input type="text" name="name" value="">
<!-- TODO: Name vorbelegen -->
</label>
<br><br>
<label>
Beschreibung<br>
<textarea name="description"></textarea>
<!-- TODO: Beschreibung vorbelegen -->
</label>
</fieldset>
<!-- =========================
Zugehöriges Floor
========================= -->
<fieldset>
<legend>Stockwerk / Standort</legend>
<label>
Stockwerk<br>
<select name="floor_id">
<!-- TODO: Floors aus DB -->
</select>
</label>
<br><br>
<label>
Höhe (Anzahl U)<br>
<input type="number" name="height" value="">
<!-- TODO: Höhe vorbelegen -->
</label>
</fieldset>
<!-- =========================
Rack-SVG / Gerätepositionen
========================= -->
<fieldset>
<legend>Rack-Layout</legend>
<div class="svg-editor-container">
<svg
id="rack-svg"
viewBox="0 0 200 1000"
width="100%"
height="600"
>
<!-- TODO: Rack-SVG laden -->
</svg>
</div>
<p class="hint">
Geräte per Drag & Drop im Rack positionieren.
</p>
</fieldset>
<!-- =========================
Aktionen
========================= -->
<fieldset>
<button type="submit">Speichern</button>
<button type="button" onclick="history.back()">Abbrechen</button>
<!-- TODO: Löschen, falls edit -->
</fieldset>
</form>
<!-- =========================
JS-Konfiguration
========================= -->
<script>
/**
* Konfiguration für Rack-SVG-Editor
*/
// TODO: Rack-ID aus PHP setzen
// window.RACK_ID = <?= (int)$rackId ?>;
// TODO: Gerätepositionen an JS übergeben
// window.RACK_DEVICES = <?= json_encode($rackDevices ?? []) ?>;
</script>

View File

@@ -1,2 +1,102 @@
<?php
// Übersicht aller Racks
/**
* app/racks/list.php
*
* Übersicht aller Racks
* - Anzeigen
* - Bearbeiten
* - Löschen
* - Zugehöriges Floor anzeigen
* - SVG-Vorschau optional
*/
// TODO: bootstrap laden
// require_once __DIR__ . '/../../bootstrap.php';
// TODO: Auth erzwingen
// requireAuth();
// =========================
// Racks laden
// =========================
// TODO: Racks aus DB laden
// $racks = $sql->get("SELECT r.*, f.name AS floor_name FROM racks r LEFT JOIN floors f ON r.floor_id = f.id ORDER BY r.name", "", []);
?>
<h2>Racks</h2>
<!-- =========================
Toolbar
========================= -->
<div class="toolbar">
<a href="/?page=racks/edit" class="button">
+ Neues Rack
</a>
<!-- TODO: Suchfeld -->
<!-- TODO: Filter (Floor / Standort) -->
</div>
<!-- =========================
Rack-Tabelle
========================= -->
<table class="rack-list">
<thead>
<tr>
<th>Vorschau</th>
<th>Name</th>
<th>Stockwerk</th>
<th>Höhe (U)</th>
<th>Geräte</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php /* foreach ($racks as $rack): */ ?>
<tr>
<td class="preview">
<!-- TODO: SVG / JPG Thumbnail -->
</td>
<td>
<!-- TODO: Rack-Name -->
Rack 1
</td>
<td>
<!-- TODO: Floor / Standort -->
</td>
<td>
<!-- TODO: Höhe -->
</td>
<td>
<!-- TODO: Anzahl Geräte im Rack -->
</td>
<td>
<a href="/?page=racks/edit&id=1">Bearbeiten</a>
<button>Löschen</button>
</td>
</tr>
<?php /* endforeach; */ ?>
</tbody>
</table>
<!-- =========================
Leerer Zustand
========================= -->
<?php /* if (empty($racks)): */ ?>
<div class="empty-state">
<p>Noch keine Racks angelegt.</p>
<p><a href="/?page=racks/edit">Erstes Rack anlegen</a></p>
</div>
<?php /* endif; */ ?>