From b973d2857b8661ca679918a3e714ce32d09af504 Mon Sep 17 00:00:00 2001 From: fixclean Date: Thu, 19 Feb 2026 10:31:53 +0100 Subject: [PATCH] Bearbeite Issues #22 bis #24 closes #22 closes #23 closes #24 --- NEXT.md | 3 ++ app/assets/css/floor-infrastructure-edit.css | 19 ++----- app/assets/js/floor-infrastructure-edit.js | 57 +++++++++----------- app/modules/connections/edit.php | 12 +++-- app/modules/connections/save.php | 39 +++----------- app/modules/floor_infrastructure/edit.php | 16 +----- 6 files changed, 49 insertions(+), 97 deletions(-) diff --git a/NEXT.md b/NEXT.md index f36171d..29d2ad1 100644 --- a/NEXT.md +++ b/NEXT.md @@ -1,6 +1,9 @@ # NEXT_STEPS ## Aktive Aufgaben (priorisiert) +- [x] [#24] infrastruktur stockerkkarte zoomen wird die grundrisskarten overlay nicht mitgezoomt +- [x] [#23] netzwerkdosen haben nur port 1 und brauche in den auswahlen nicht mit port 1 angezeigt zu werden +- [x] [#22] für neue verbindungen nur ports anbieten die noch keine verbingung haben - [x] [#20] Gesamt-Topologie-Wand im dashboard ist schwarze - [x] [#19] gerät nicht löschbar wegen ports, ports sind aber nicht löschbar - [x] [#18] wandbuchsen direkt beim erstellen schon an patchpanel bindfen diff --git a/app/assets/css/floor-infrastructure-edit.css b/app/assets/css/floor-infrastructure-edit.css index 240cfdb..12cb2fc 100644 --- a/app/assets/css/floor-infrastructure-edit.css +++ b/app/assets/css/floor-infrastructure-edit.css @@ -30,10 +30,6 @@ flex-direction: column; gap: 6px; } -.floor-plan-toolbar { - display: flex; - gap: 6px; -} .floor-plan-canvas { position: relative; width: 100%; @@ -48,17 +44,6 @@ cursor: crosshair; overflow: hidden; } -.floor-plan-svg { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - object-fit: contain; - pointer-events: none; - z-index: 0; - opacity: 0.75; - border-radius: 6px; -} .floor-plan-overlay { position: absolute; inset: 0; @@ -67,6 +52,10 @@ z-index: 2; touch-action: none; } +.floor-plan-overlay .floor-plan-background { + opacity: 0.75; + pointer-events: none; +} .floor-plan-overlay .active-marker { cursor: move; } diff --git a/app/assets/js/floor-infrastructure-edit.js b/app/assets/js/floor-infrastructure-edit.js index 0802c15..942e98e 100644 --- a/app/assets/js/floor-infrastructure-edit.js +++ b/app/assets/js/floor-infrastructure-edit.js @@ -38,6 +38,18 @@ document.addEventListener('DOMContentLoaded', () => { let viewWidth = DEFAULT_PLAN_SIZE.width; let viewHeight = DEFAULT_PLAN_SIZE.height; + overlay.setAttribute('preserveAspectRatio', 'none'); + + const backgroundImage = document.createElementNS(SVG_NS, 'image'); + backgroundImage.classList.add('floor-plan-background'); + backgroundImage.setAttribute('x', '0'); + backgroundImage.setAttribute('y', '0'); + backgroundImage.setAttribute('width', String(DEFAULT_PLAN_SIZE.width)); + backgroundImage.setAttribute('height', String(DEFAULT_PLAN_SIZE.height)); + backgroundImage.setAttribute('preserveAspectRatio', 'none'); + backgroundImage.setAttribute('display', 'none'); + overlay.appendChild(backgroundImage); + const activeMarker = document.createElementNS(SVG_NS, 'rect'); activeMarker.classList.add('active-marker'); if (markerType === 'patchpanel') { @@ -237,7 +249,6 @@ document.addEventListener('DOMContentLoaded', () => { const panelBuildingSelect = document.getElementById('panel-building-select'); const panelFloorSelect = document.getElementById('panel-floor-select'); const outletRoomSelect = document.getElementById('outlet-room-select'); - const floorPlanSvg = document.getElementById('floor-plan-svg'); const panelPlacementFields = document.getElementById('panel-placement-fields'); const panelFloorPlanGroup = document.getElementById('panel-floor-plan-group'); const panelFloorMissingHint = document.getElementById('panel-floor-missing-hint'); @@ -312,21 +323,19 @@ document.addEventListener('DOMContentLoaded', () => { }; const updateFloorPlanImage = () => { - if (!floorPlanSvg) { - return; - } - const floorOption = panelFloorSelect?.selectedOptions?.[0]; const roomOption = outletRoomSelect?.selectedOptions?.[0]; const svgUrl = floorOption?.dataset?.svgUrl || roomOption?.dataset?.floorSvgUrl || ''; if (svgUrl) { - floorPlanSvg.src = svgUrl; - floorPlanSvg.hidden = false; + backgroundImage.setAttribute('href', svgUrl); + backgroundImage.setAttribute('width', String(planSize.width)); + backgroundImage.setAttribute('height', String(planSize.height)); + backgroundImage.setAttribute('display', 'block'); loadPlanDimensions(svgUrl); } else { - floorPlanSvg.removeAttribute('src'); - floorPlanSvg.hidden = true; + backgroundImage.removeAttribute('href'); + backgroundImage.setAttribute('display', 'none'); planSize.width = DEFAULT_PLAN_SIZE.width; planSize.height = DEFAULT_PLAN_SIZE.height; resetView(); @@ -335,13 +344,6 @@ document.addEventListener('DOMContentLoaded', () => { filterPatchpanelBindOptions(); }; - if (floorPlanSvg) { - floorPlanSvg.addEventListener('error', () => { - floorPlanSvg.removeAttribute('src'); - floorPlanSvg.hidden = true; - }); - } - const loadPlanDimensions = async (svgUrl) => { if (!svgUrl) { return; @@ -365,6 +367,8 @@ document.addEventListener('DOMContentLoaded', () => { if (parts.length === 4 && parts.every((value) => Number.isFinite(value))) { planSize.width = Math.max(1, parts[2]); planSize.height = Math.max(1, parts[3]); + backgroundImage.setAttribute('width', String(planSize.width)); + backgroundImage.setAttribute('height', String(planSize.height)); resetView(); renderReferenceMarkers(); updateFromInputs(); @@ -381,12 +385,16 @@ document.addEventListener('DOMContentLoaded', () => { planSize.width = DEFAULT_PLAN_SIZE.width; planSize.height = DEFAULT_PLAN_SIZE.height; } + backgroundImage.setAttribute('width', String(planSize.width)); + backgroundImage.setAttribute('height', String(planSize.height)); resetView(); renderReferenceMarkers(); updateFromInputs(); } catch (error) { planSize.width = DEFAULT_PLAN_SIZE.width; planSize.height = DEFAULT_PLAN_SIZE.height; + backgroundImage.setAttribute('width', String(planSize.width)); + backgroundImage.setAttribute('height', String(planSize.height)); resetView(); renderReferenceMarkers(); updateFromInputs(); @@ -584,23 +592,6 @@ document.addEventListener('DOMContentLoaded', () => { }); } - document.querySelectorAll('[data-floor-plan-zoom]').forEach((button) => { - button.addEventListener('click', () => { - const action = button.getAttribute('data-floor-plan-zoom'); - if (action === 'in') { - const rect = overlay.getBoundingClientRect(); - zoomAt(rect.left + (rect.width / 2), rect.top + (rect.height / 2), 0.85); - return; - } - if (action === 'out') { - const rect = overlay.getBoundingClientRect(); - zoomAt(rect.left + (rect.width / 2), rect.top + (rect.height / 2), 1.15); - return; - } - resetView(); - }); - }); - updateOverlayViewBox(); updateFromInputs(); filterPatchpanelBindOptions(); diff --git a/app/modules/connections/edit.php b/app/modules/connections/edit.php index 40fe688..68006a6 100644 --- a/app/modules/connections/edit.php +++ b/app/modules/connections/edit.php @@ -77,9 +77,6 @@ $isEndpointAllowed = static function (string $type, int $id) use ($occupiedByTyp if ($id <= 0) { return false; } - if ($type === 'outlet') { - return true; - } if ($type === $portAType && $id === $portAId) { return true; } @@ -173,7 +170,14 @@ foreach ($outletPorts as $row) { if (!$isEndpointAllowed('outlet', $id)) { continue; } - $parts = array_filter([(string)($row['floor_name'] ?? ''), (string)($row['room_name'] ?? ''), (string)$row['outlet_name'], (string)$row['name']]); + $portName = trim((string)($row['name'] ?? '')); + $includePortName = ($portName !== '' && strcasecmp($portName, 'Port 1') !== 0); + $parts = array_filter([ + (string)($row['floor_name'] ?? ''), + (string)($row['room_name'] ?? ''), + (string)$row['outlet_name'], + $includePortName ? $portName : '', + ]); $endpointOptions['outlet'][] = [ 'id' => $id, 'label' => implode(' / ', $parts), diff --git a/app/modules/connections/save.php b/app/modules/connections/save.php index c6f3aa9..68faebb 100644 --- a/app/modules/connections/save.php +++ b/app/modules/connections/save.php @@ -75,25 +75,16 @@ $otherConnections = $sql->get( ); $endpointUsage = []; -$trackUsage = static function (string $endpointType, int $endpointId, string $otherType) use (&$endpointUsage): void { +$trackUsage = static function (string $endpointType, int $endpointId) use (&$endpointUsage): void { if ($endpointId <= 0) { return; } if (!isset($endpointUsage[$endpointType][$endpointId])) { $endpointUsage[$endpointType][$endpointId] = [ 'total' => 0, - 'patchpanel' => 0, - 'other' => 0, ]; } $endpointUsage[$endpointType][$endpointId]['total']++; - if ($endpointType === 'outlet') { - if ($otherType === 'patchpanel') { - $endpointUsage[$endpointType][$endpointId]['patchpanel']++; - } else { - $endpointUsage[$endpointType][$endpointId]['other']++; - } - } }; foreach ((array)$otherConnections as $row) { @@ -102,43 +93,29 @@ foreach ((array)$otherConnections as $row) { $idA = (int)($row['port_a_id'] ?? 0); $idB = (int)($row['port_b_id'] ?? 0); - $trackUsage($typeA, $idA, $typeB); - $trackUsage($typeB, $idB, $typeA); + $trackUsage($typeA, $idA); + $trackUsage($typeB, $idB); } -$validateEndpointUsage = static function (string $endpointType, int $endpointId, string $otherType, string $label) use ($endpointUsage): ?string { +$validateEndpointUsage = static function (string $endpointType, int $endpointId, string $label) use ($endpointUsage): ?string { if ($endpointId <= 0) { return null; } - $stats = $endpointUsage[$endpointType][$endpointId] ?? ['total' => 0, 'patchpanel' => 0, 'other' => 0]; + $stats = $endpointUsage[$endpointType][$endpointId] ?? ['total' => 0]; if ((int)$stats['total'] <= 0) { return null; } - if ($endpointType !== 'outlet') { - return $label . " ist bereits in Verwendung"; - } - - if ($otherType === 'patchpanel') { - if ((int)$stats['patchpanel'] > 0) { - return $label . " hat bereits eine Patchpanel-Verbindung"; - } - return null; - } - - if ((int)$stats['other'] > 0) { - return $label . " hat bereits eine Endgeraete-Verbindung"; - } - return null; + return $label . " ist bereits in Verwendung"; }; -$errorA = $validateEndpointUsage($portAType, $portAId, $portBType, 'Port an Endpunkt A'); +$errorA = $validateEndpointUsage($portAType, $portAId, 'Port an Endpunkt A'); if ($errorA !== null) { $errors[] = $errorA; } -$errorB = $validateEndpointUsage($portBType, $portBId, $portAType, 'Port an Endpunkt B'); +$errorB = $validateEndpointUsage($portBType, $portBId, 'Port an Endpunkt B'); if ($errorB !== null) { $errors[] = $errorB; } diff --git a/app/modules/floor_infrastructure/edit.php b/app/modules/floor_infrastructure/edit.php index ee6e4fb..85c97fe 100644 --- a/app/modules/floor_infrastructure/edit.php +++ b/app/modules/floor_infrastructure/edit.php @@ -248,11 +248,6 @@ if ($type === 'outlet' && $id > 0) {
>
-
- - - -
0) { data-active-id="" data-reference-panels="" data-reference-outlets=""> - Stockwerksplan
-

Nur das aktuell bearbeitete Patchpanel ist verschiebbar. Andere Objekte werden als Referenz halbtransparent angezeigt. Neue Objekte starten bei Position 30 x 30. Zoom per Mausrad, verschieben mit Shift + Drag.

+

Nur das aktuell bearbeitete Patchpanel ist verschiebbar. Andere Objekte werden als Referenz halbtransparent angezeigt. Neue Objekte starten bei Position 30 x 30. Zoom mit Mausrad, verschieben mit Shift + Drag.

Koordinate:

@@ -350,11 +344,6 @@ if ($type === 'outlet' && $id > 0) {
-
- - - -
0) { data-active-id="" data-reference-panels="" data-reference-outlets=""> - Stockwerksplan
-

Nur die aktuell bearbeitete Wandbuchse ist verschiebbar. Blau = Patchpanel, Gruen = Dosen-Referenz, Orange = gewaehlter Raum. Netzwerkdosen sind immer 10 x 10. Zoom per Mausrad, verschieben mit Shift + Drag.

+

Nur die aktuell bearbeitete Wandbuchse ist verschiebbar. Blau = Patchpanel, Gruen = Dosen-Referenz, Orange = gewaehlter Raum. Netzwerkdosen sind immer 10 x 10. Zoom mit Mausrad, verschieben mit Shift + Drag.

Koordinate: