diff --git a/NEXT_STEPS.md b/NEXT_STEPS.md index 3e82073..efbd2e8 100644 --- a/NEXT_STEPS.md +++ b/NEXT_STEPS.md @@ -9,15 +9,15 @@ - [x] Validierungsfehler anzeigen ### Package 2: Delete-Funktionen (1h) -- [ ] DELETE-Endpoints für alle Module -- [ ] AJAX-Bestätigung vor Löschen -- [ ] Kaskadierendes Löschen prüfen (z.B. Floor → Racks) +- [x] DELETE-Endpoints für alle Module +- [x] AJAX-Bestätigung vor Löschen +- [x] Kaskadierendes Löschen prüfen (z.B. Floor → Racks) ### Package 3: Port-Management (2-3h) -- [ ] Ports zu Device-Types verwalten -- [ ] Ports zu Devices anzeigen -- [ ] Port-Status (aktiv/inaktiv) -- [ ] VLAN-Zuordnung zu Ports +- [x] Ports zu Device-Types verwalten +- [x] Ports zu Devices anzeigen +- [x] Port-Status (aktiv/inaktiv) +- [x] VLAN-Zuordnung zu Ports ### Package 4: SVG-Editor für Floorplans (4-5h) - [ ] Interaktiver SVG-Editor für Rooms diff --git a/app/modules/connections/delete.php b/app/modules/connections/delete.php index fb0797a..a4d25c8 100644 --- a/app/modules/connections/delete.php +++ b/app/modules/connections/delete.php @@ -2,12 +2,19 @@ /** * app/modules/connections/delete.php * - * Loescht eine Verbindung und leitet zur Liste zurueck. + * Loescht eine Verbindung (AJAX-POST bevorzugt, GET-Fallback fuer Redirects). */ -$connectionId = (int)($_GET['id'] ?? $_POST['id'] ?? 0); +$isPost = ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST'; +$connectionId = (int)($_POST['id'] ?? $_GET['id'] ?? 0); if ($connectionId <= 0) { + if ($isPost) { + header('Content-Type: application/json; charset=utf-8'); + http_response_code(400); + echo json_encode(['success' => false, 'message' => 'Ungueltige Verbindungs-ID']); + exit; + } $_SESSION['error'] = 'Ungueltige Verbindungs-ID'; header('Location: ?module=connections&action=list'); exit; @@ -20,6 +27,12 @@ $connection = $sql->single( ); if (!$connection) { + if ($isPost) { + header('Content-Type: application/json; charset=utf-8'); + http_response_code(404); + echo json_encode(['success' => false, 'message' => 'Verbindung nicht gefunden']); + exit; + } $_SESSION['error'] = 'Verbindung nicht gefunden'; header('Location: ?module=connections&action=list'); exit; @@ -31,6 +44,17 @@ $rows = $sql->set( [$connectionId] ); +if ($isPost) { + header('Content-Type: application/json; charset=utf-8'); + if ($rows > 0) { + echo json_encode(['success' => true, 'message' => 'Verbindung geloescht']); + } else { + http_response_code(500); + echo json_encode(['success' => false, 'message' => 'Verbindung konnte nicht geloescht werden']); + } + exit; +} + if ($rows > 0) { $_SESSION['success'] = 'Verbindung geloescht'; } else { diff --git a/app/modules/connections/list.php b/app/modules/connections/list.php index 9cb4ff3..abde9c5 100644 --- a/app/modules/connections/list.php +++ b/app/modules/connections/list.php @@ -335,11 +335,12 @@ $buildListUrl = static function (array $extra = []) use ($search, $deviceId): st Details Bearbeiten Von/Nach tauschen - + @@ -382,7 +383,12 @@ $buildListUrl = static function (array $extra = []) use ($search, $deviceId): st

Keine Verbindung ausgewaehlt.

@@ -474,3 +480,35 @@ $buildListUrl = static function (array $extra = []) use ($search, $deviceId): st } } + + diff --git a/app/modules/devices/delete.php b/app/modules/devices/delete.php index 12992be..a4e66da 100644 --- a/app/modules/devices/delete.php +++ b/app/modules/devices/delete.php @@ -3,12 +3,20 @@ * app/modules/devices/delete.php * * Loescht ein Geraet. Bei Abhaengigkeiten ist force=1 erforderlich. + * Unterstuetzt GET-Redirects und AJAX-POST. */ -$deviceId = (int)($_GET['id'] ?? 0); -$forceDelete = (int)($_GET['force'] ?? 0) === 1; +$isPost = ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST'; +$deviceId = (int)($_POST['id'] ?? $_GET['id'] ?? 0); +$forceDelete = (int)($_POST['force'] ?? $_GET['force'] ?? 0) === 1; if ($deviceId <= 0) { + if ($isPost) { + header('Content-Type: application/json; charset=utf-8'); + http_response_code(400); + echo json_encode(['success' => false, 'message' => 'Ungueltige Geraete-ID']); + exit; + } $_SESSION['error'] = "Ungueltige Geraete-ID"; header('Location: ?module=devices&action=list'); exit; @@ -21,6 +29,12 @@ $device = $sql->single( ); if (!$device) { + if ($isPost) { + header('Content-Type: application/json; charset=utf-8'); + http_response_code(404); + echo json_encode(['success' => false, 'message' => 'Geraet nicht gefunden']); + exit; + } $_SESSION['error'] = "Geraet nicht gefunden"; header('Location: ?module=devices&action=list'); exit; @@ -70,7 +84,23 @@ if ($hasDependencies && !$forceDelete) { $parts[] = $moduleCount . ' Port-Module'; } - $_SESSION['error'] = "Geraet hat abhaengige Daten (" . implode(', ', $parts) . "). Loeschen bitte bestaetigen."; + $dependencyMessage = "Geraet hat abhaengige Daten (" . implode(', ', $parts) . "). Loeschen bitte bestaetigen."; + if ($isPost) { + header('Content-Type: application/json; charset=utf-8'); + http_response_code(409); + echo json_encode([ + 'success' => false, + 'requires_force' => true, + 'message' => $dependencyMessage, + 'dependencies' => [ + 'connections' => $connectionCount, + 'ports' => $portCount, + 'modules' => $moduleCount + ] + ]); + exit; + } + $_SESSION['error'] = $dependencyMessage; header('Location: ?module=devices&action=edit&id=' . urlencode((string)$deviceId)); exit; } @@ -91,8 +121,19 @@ $deleted = $sql->set( ); if ($deleted > 0) { + if ($isPost) { + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['success' => true, 'message' => "Geraet geloescht: " . $device['name']]); + exit; + } $_SESSION['success'] = "Geraet geloescht: " . $device['name']; } else { + if ($isPost) { + header('Content-Type: application/json; charset=utf-8'); + http_response_code(500); + echo json_encode(['success' => false, 'message' => 'Geraet konnte nicht geloescht werden']); + exit; + } $_SESSION['error'] = "Geraet konnte nicht geloescht werden"; } diff --git a/app/modules/devices/edit.php b/app/modules/devices/edit.php index 192e4a1..72d87cf 100644 --- a/app/modules/devices/edit.php +++ b/app/modules/devices/edit.php @@ -64,6 +64,19 @@ if ($isEdit) { // ========================= $deviceTypes = $sql->get("SELECT id, name, category FROM device_types ORDER BY name", "", []); $racks = $sql->get("SELECT id, name FROM racks ORDER BY name", "", []); +$devicePorts = []; + +if ($isEdit) { + $devicePorts = $sql->get( + "SELECT dp.id, dp.name, dp.status, dp.mode, dp.vlan_config, pt.name AS port_type_name + FROM device_ports dp + LEFT JOIN port_types pt ON pt.id = dp.port_type_id + WHERE dp.device_id = ? + ORDER BY dp.id", + "i", + [$deviceId] + ); +} ?> @@ -160,6 +173,67 @@ $racks = $sql->get("SELECT id, name FROM racks ORDER BY name", "", []); +
+ Ports + + +

Portstatus und VLAN-Zuordnung koennen hier direkt gepflegt werden (VLANs kommagetrennt, z. B. 10,20,30).

+ + + + + + + + + + + + + + + + + + + + + + +
NamePort-TypStatusModusVLANs
+ + + + + + + +
+ +

Zu diesem Geraet sind aktuell keine Ports vorhanden.

+ + +

Ports werden nach dem ersten Speichern automatisch aus dem Geraetetyp erzeugt und koennen dann hier gepflegt werden.

+ +
+ @@ -264,34 +338,64 @@ $racks = $sql->get("SELECT id, name FROM racks ORDER BY name", "", []); .button:hover { opacity: 0.8; } + +.device-port-table { + width: 100%; + border-collapse: collapse; + margin-top: 10px; +} + +.device-port-table th, +.device-port-table td { + border-bottom: 1px solid #ddd; + padding: 8px; + text-align: left; +} + +.device-port-table input, +.device-port-table select { + width: 100%; + min-width: 120px; +} diff --git a/app/modules/devices/list.php b/app/modules/devices/list.php index 39ebcdf..c41a448 100644 --- a/app/modules/devices/list.php +++ b/app/modules/devices/list.php @@ -1,7 +1,7 @@ 0) { - $where[] = "d.device_type_id = ?"; - $types .= "i"; + $where[] = 'd.device_type_id = ?'; + $types .= 'i'; $params[] = $typeId; } if ($floorId > 0) { - $where[] = "f.id = ?"; - $types .= "i"; + $where[] = 'f.id = ?'; + $types .= 'i'; $params[] = $floorId; } if ($rackId > 0) { - $where[] = "d.rack_id = ?"; - $types .= "i"; + $where[] = 'd.rack_id = ?'; + $types .= 'i'; $params[] = $rackId; } $whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : ''; // ========================= -// Geräte laden +// Geraete laden // ========================= - $devices = $sql->get( - " - SELECT - d.id, - d.name, - d.serial_number, - d.rack_position_he, - d.rack_height_he, - d.web_config_url, - dt.name AS device_type, - dt.image_path, - f.name AS floor_name, - r.name AS rack_name, - ( - SELECT COUNT(*) - FROM device_ports dp - WHERE dp.device_id = d.id - ) AS port_count, - ( - SELECT COUNT(*) - FROM device_port_modules dpm - JOIN device_ports dp2 ON dp2.id = dpm.device_port_id - WHERE dp2.device_id = d.id - ) AS module_count, - ( - SELECT COUNT(*) - FROM connections c - WHERE (c.port_a_type = 'device' AND c.port_a_id IN ( - SELECT dp3.id FROM device_ports dp3 WHERE dp3.device_id = d.id - )) - OR (c.port_b_type = 'device' AND c.port_b_id IN ( - SELECT dp4.id FROM device_ports dp4 WHERE dp4.device_id = d.id - )) - ) AS connection_count +$devices = $sql->get( + " + SELECT + d.id, + d.name, + d.serial_number, + d.rack_position_he, + d.rack_height_he, + d.web_config_url, + dt.name AS device_type, + dt.image_path, + f.name AS floor_name, + r.name AS rack_name, + ( + SELECT COUNT(*) + FROM device_ports dp + WHERE dp.device_id = d.id + ) AS port_count, + ( + SELECT COUNT(*) + FROM device_ports dp + WHERE dp.device_id = d.id + AND dp.status = 'active' + ) AS active_port_count, + ( + SELECT COUNT(*) + FROM device_ports dp + WHERE dp.device_id = d.id + AND dp.status = 'disabled' + ) AS disabled_port_count, + ( + SELECT COUNT(*) + FROM device_ports dp + WHERE dp.device_id = d.id + AND dp.vlan_config IS NOT NULL + AND dp.vlan_config <> '[]' + ) AS vlan_port_count, + ( + SELECT COUNT(*) + FROM device_port_modules dpm + JOIN device_ports dp2 ON dp2.id = dpm.device_port_id + WHERE dp2.device_id = d.id + ) AS module_count, + ( + SELECT COUNT(*) + FROM connections c + WHERE (c.port_a_type = 'device' AND c.port_a_id IN ( + SELECT dp3.id FROM device_ports dp3 WHERE dp3.device_id = d.id + )) + OR (c.port_b_type = 'device' AND c.port_b_id IN ( + SELECT dp4.id FROM device_ports dp4 WHERE dp4.device_id = d.id + )) + ) AS connection_count FROM devices d JOIN device_types dt ON dt.id = d.device_type_id LEFT JOIN racks r ON r.id = d.rack_id @@ -99,22 +118,19 @@ $whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : ''; // ========================= // Filter-Daten laden // ========================= -$deviceTypes = $sql->get("SELECT id, name FROM device_types ORDER BY name", "", []); -$floors = $sql->get("SELECT id, name FROM floors ORDER BY name", "", []); -$racks = $sql->get("SELECT id, name FROM racks ORDER BY name", "", []); +$deviceTypes = $sql->get('SELECT id, name FROM device_types ORDER BY name', '', []); +$floors = $sql->get('SELECT id, name FROM floors ORDER BY name', '', []); +$racks = $sql->get('SELECT id, name FROM racks ORDER BY name', '', []); ?>
-

Geräte

+

Geraete

-
-