diff --git a/app/modules/device_types/edit.php b/app/modules/device_types/edit.php index a89b4d6..7ac02f0 100644 --- a/app/modules/device_types/edit.php +++ b/app/modules/device_types/edit.php @@ -22,7 +22,7 @@ if ($deviceTypeId > 0) { [$deviceTypeId] ); - if ($deviceType) { +if ($deviceType) { $ports = $sql->get( "SELECT * FROM device_type_ports WHERE device_type_id = ? ORDER BY name", "i", @@ -31,6 +31,11 @@ if ($deviceTypeId > 0) { } } +$shapeDefinition = $deviceType['shape_definition'] ?? '[]'; +if (trim($shapeDefinition) === '') { + $shapeDefinition = '[]'; +} + $isEdit = !empty($deviceType); $pageTitle = $isEdit ? "Gerätetyp bearbeiten: " . htmlspecialchars($deviceType['name']) : "Neuer Gerätetyp"; @@ -104,6 +109,77 @@ $pageTitle = $isEdit ? "Gerätetyp bearbeiten: " . htmlspecialchars($deviceType[ +
+ Gerätedesign (Rechtecke, Kreise, Text) + + + +
+
+ + + +
+
+
+ + +
+ +
+ + + + + + + + + +
+ + +

Shapes werden als JSON gespeichert und können jederzeit angepasst werden.

+
+
+ +
+

Shapes

+ +
+
+ @@ -246,6 +322,89 @@ $pageTitle = $isEdit ? "Gerätetyp bearbeiten: " . htmlspecialchars($deviceType[ margin-top: 30px; } +.shape-editor { + display: flex; + gap: 18px; + flex-wrap: wrap; + margin-top: 20px; +} + +.shape-editor-canvas { + flex: 1 1 320px; + min-width: 280px; + border: 1px solid #ddd; + border-radius: 6px; + background: white; + padding: 10px; +} + +.shape-editor-canvas svg { + width: 100%; + height: 200px; + display: block; + font-family: inherit; +} + +.shape-editor-controls { + flex: 1 1 220px; + min-width: 220px; +} + +.shape-control-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); + gap: 8px; + margin: 12px 0; +} + +.shape-control-grid label { + font-size: 0.8rem; + display: flex; + flex-direction: column; + gap: 4px; +} + +.shape-control-grid input, +.shape-control-grid select { + padding: 6px 8px; + border: 1px solid #ccc; + border-radius: 4px; + font-family: inherit; +} + +.shape-list { + margin-top: 12px; +} + +.shape-list ul { + list-style: none; + padding: 0; + margin: 6px 0 0; + border: 1px solid #eee; + border-radius: 4px; + background: #fafafa; + max-height: 130px; + overflow-y: auto; +} + +.shape-list li { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 12px; + border-bottom: 1px solid #eee; + font-size: 0.85rem; +} + +.shape-list li:last-child { + border-bottom: none; +} + +.shape-list button { + padding: 4px 8px; + font-size: 0.75rem; +} + .button { padding: 10px 15px; background: #007bff; @@ -294,3 +453,173 @@ function confirmDelete(id) { } } + + diff --git a/app/modules/device_types/save.php b/app/modules/device_types/save.php index 5d12688..75ffed1 100644 --- a/app/modules/device_types/save.php +++ b/app/modules/device_types/save.php @@ -22,6 +22,14 @@ $name = trim($_POST['name'] ?? ''); $category = $_POST['category'] ?? 'other'; $comment = trim($_POST['comment'] ?? ''); $seedPortCount = max(0, (int)($_POST['seed_ports'] ?? 0)); +$rawShapes = trim($_POST['shape_definition'] ?? ''); +$shapeDefinition = '[]'; +if ($rawShapes !== '') { + $decoded = json_decode($rawShapes, true); + if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) { + $shapeDefinition = json_encode($decoded, JSON_UNESCAPED_UNICODE); + } +} // ========================= // Validierung @@ -88,31 +96,31 @@ if ($deviceTypeId > 0) { // UPDATE if ($imagePath) { $sql->set( - "UPDATE device_types SET name = ?, category = ?, comment = ?, image_path = ?, image_type = ? WHERE id = ?", - "sssisi", - [$name, $category, $comment, $imagePath, $imageType, $deviceTypeId] + "UPDATE device_types SET name = ?, category = ?, comment = ?, image_path = ?, image_type = ?, shape_definition = ? WHERE id = ?", + "ssssssi", + [$name, $category, $comment, $imagePath, $imageType, $shapeDefinition, $deviceTypeId] ); } else { $sql->set( - "UPDATE device_types SET name = ?, category = ?, comment = ? WHERE id = ?", - "sssi", - [$name, $category, $comment, $deviceTypeId] + "UPDATE device_types SET name = ?, category = ?, comment = ?, shape_definition = ? WHERE id = ?", + "ssssi", + [$name, $category, $comment, $shapeDefinition, $deviceTypeId] ); } } else { // INSERT if ($imagePath) { $deviceTypeId = $sql->set( - "INSERT INTO device_types (name, category, comment, image_path, image_type) VALUES (?, ?, ?, ?, ?)", - "sssss", - [$name, $category, $comment, $imagePath, $imageType], + "INSERT INTO device_types (name, category, comment, image_path, image_type, shape_definition) VALUES (?, ?, ?, ?, ?, ?)", + "ssssss", + [$name, $category, $comment, $imagePath, $imageType, $shapeDefinition], true ); } else { $deviceTypeId = $sql->set( - "INSERT INTO device_types (name, category, comment, image_path, image_type) VALUES (?, ?, ?, NULL, ?)", - "ssss", - [$name, $category, $comment, 'bitmap'], + "INSERT INTO device_types (name, category, comment, image_path, image_type, shape_definition) VALUES (?, ?, ?, NULL, ?, ?)", + "sssss", + [$name, $category, $comment, 'bitmap', $shapeDefinition], true ); } diff --git a/doc/DATABASE.md b/doc/DATABASE.md index 3e5ff32..0bf31ad 100644 --- a/doc/DATABASE.md +++ b/doc/DATABASE.md @@ -119,6 +119,9 @@ Definiert eine Gerätevorlage. - Unterstützt SVG und Bitmap (PNG/JPG) - Grundlage für alle grafischen Ansichten +**Technische Attribute** +- `shape_definition`: JSON-Array mit einfachen Formen (rect/circle/text) für die integrierte Zeichenfläche. + --- ### `device_type_ports` diff --git a/init.sql b/init.sql index d698807..0d967d9 100644 --- a/init.sql +++ b/init.sql @@ -74,7 +74,8 @@ CREATE TABLE device_types ( category ENUM('switch','server','patchpanel','other') NOT NULL, image_path VARCHAR(255), image_type ENUM('svg','bitmap') NOT NULL, - comment TEXT + comment TEXT, + shape_definition JSON ) ENGINE=InnoDB; CREATE TABLE device_type_ports (