613 lines
22 KiB
PHP
613 lines
22 KiB
PHP
<?php
|
|
/**
|
|
* app/modules/floor_infrastructure/edit.php
|
|
*
|
|
* Formular zum Anlegen/Bearbeiten von Patchpanels und Wandbuchsen
|
|
*/
|
|
|
|
$type = $_GET['type'] ?? 'patchpanel';
|
|
$id = (int)($_GET['id'] ?? 0);
|
|
|
|
$locations = $sql->get("SELECT id, name FROM locations ORDER BY name", "", []);
|
|
$buildings = $sql->get("SELECT id, name, location_id FROM buildings ORDER BY name", "", []);
|
|
$floors = $sql->get(
|
|
"SELECT f.*, b.name AS building_name, b.location_id, l.name AS location_name
|
|
FROM floors f
|
|
LEFT JOIN buildings b ON b.id = f.building_id
|
|
LEFT JOIN locations l ON l.id = b.location_id
|
|
ORDER BY l.name, b.name, f.level, f.name",
|
|
"",
|
|
[]
|
|
);
|
|
$rooms = $sql->get(
|
|
"SELECT r.id, r.name, r.floor_id, f.name AS floor_name, f.svg_path, b.id AS building_id, l.id AS location_id
|
|
FROM rooms r
|
|
LEFT JOIN floors f ON f.id = r.floor_id
|
|
LEFT JOIN buildings b ON b.id = f.building_id
|
|
LEFT JOIN locations l ON l.id = b.location_id
|
|
ORDER BY l.name, b.name, f.level, f.name, r.name",
|
|
"",
|
|
[]
|
|
);
|
|
|
|
$locationMap = [];
|
|
foreach ($locations as $location) {
|
|
$locationMap[$location['id']] = $location['name'];
|
|
}
|
|
|
|
foreach ($floors as &$floor) {
|
|
$paths = trim((string)($floor['svg_path'] ?? ''));
|
|
$floor['svg_url'] = $paths !== '' ? '/' . ltrim($paths, '/\\') : '';
|
|
}
|
|
unset($floor);
|
|
|
|
foreach ($rooms as &$room) {
|
|
$roomPath = trim((string)($room['svg_path'] ?? ''));
|
|
$room['floor_svg_url'] = $roomPath !== '' ? '/' . ltrim($roomPath, '/\\') : '';
|
|
}
|
|
unset($room);
|
|
|
|
$floorIndex = [];
|
|
foreach ($floors as $floor) {
|
|
$floorIndex[$floor['id']] = $floor;
|
|
}
|
|
|
|
$panel = null;
|
|
$outlet = null;
|
|
$pageTitle = $type === 'outlet' ? 'Wandbuchse bearbeiten' : 'Patchpanel bearbeiten';
|
|
|
|
if ($type === 'patchpanel' && $id > 0) {
|
|
$panel = $sql->single(
|
|
"SELECT * FROM floor_patchpanels WHERE id = ?",
|
|
"i",
|
|
[$id]
|
|
);
|
|
if ($panel) {
|
|
$pageTitle = "Patchpanel bearbeiten: " . htmlspecialchars($panel['name']);
|
|
}
|
|
}
|
|
|
|
if ($type === 'outlet' && $id > 0) {
|
|
$outlet = $sql->single(
|
|
"SELECT * FROM network_outlets WHERE id = ?",
|
|
"i",
|
|
[$id]
|
|
);
|
|
if ($outlet) {
|
|
$pageTitle = "Wandbuchse bearbeiten: " . htmlspecialchars($outlet['name']);
|
|
}
|
|
}
|
|
|
|
$panel = $panel ?? [];
|
|
$outlet = $outlet ?? [];
|
|
|
|
$selectedLocationId = 0;
|
|
$selectedBuildingId = 0;
|
|
$selectedFloorId = 0;
|
|
if ($type === 'patchpanel') {
|
|
$selectedFloorId = (int)($panel['floor_id'] ?? 0);
|
|
if ($selectedFloorId && isset($floorIndex[$selectedFloorId])) {
|
|
$selectedBuildingId = (int)($floorIndex[$selectedFloorId]['building_id'] ?? 0);
|
|
$selectedLocationId = (int)($floorIndex[$selectedFloorId]['location_id'] ?? 0);
|
|
}
|
|
}
|
|
|
|
$defaultPanelSize = ['width' => 140, 'height' => 40];
|
|
$defaultOutletSize = 32;
|
|
$showPanelPlacementFields = $type === 'patchpanel' && $selectedFloorId > 0;
|
|
|
|
if ($type === 'patchpanel') {
|
|
$panel['width'] = $panel['width'] ?? $defaultPanelSize['width'];
|
|
$panel['height'] = $panel['height'] ?? $defaultPanelSize['height'];
|
|
}
|
|
|
|
$markerWidth = $type === 'patchpanel' ? $panel['width'] : $defaultOutletSize;
|
|
$markerHeight = $type === 'patchpanel' ? $panel['height'] : $defaultOutletSize;
|
|
?>
|
|
|
|
<div class="floor-infra-edit">
|
|
<h1><?php echo $pageTitle; ?></h1>
|
|
|
|
<form method="post" action="?module=floor_infrastructure&action=save" class="infra-edit-form">
|
|
<input type="hidden" name="type" value="<?php echo htmlspecialchars($type); ?>">
|
|
<input type="hidden" name="id" value="<?php echo $type === 'patchpanel' ? ($panel['id'] ?? $id) : ($outlet['id'] ?? $id); ?>">
|
|
|
|
<?php if ($type === 'patchpanel'): ?>
|
|
<div class="form-group">
|
|
<label>Name</label>
|
|
<input type="text" name="name" value="<?php echo htmlspecialchars($panel['name'] ?? ''); ?>" required>
|
|
</div>
|
|
|
|
<div class="form-grid">
|
|
<div class="form-group">
|
|
<label>Location</label>
|
|
<select id="panel-location-select">
|
|
<option value="">- Location wählen -</option>
|
|
<?php foreach ($locations as $location): ?>
|
|
<option value="<?php echo $location['id']; ?>" <?php echo $selectedLocationId === $location['id'] ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($location['name']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Gebäude</label>
|
|
<select id="panel-building-select">
|
|
<option value="">- Gebäude wählen -</option>
|
|
<?php foreach ($buildings as $building): ?>
|
|
<?php $buildingLocation = $locationMap[$building['location_id']] ?? ''; ?>
|
|
<option value="<?php echo $building['id']; ?>"
|
|
data-location-id="<?php echo $building['location_id'] ?? 0; ?>"
|
|
<?php echo $selectedBuildingId === $building['id'] ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($building['name'] . ($buildingLocation ? ' · ' . $buildingLocation : '')); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Stockwerk</label>
|
|
<select id="panel-floor-select" name="floor_id" required>
|
|
<option value="">- Stockwerk wählen -</option>
|
|
<?php foreach ($floors as $floor): ?>
|
|
<option value="<?php echo $floor['id']; ?>"
|
|
data-building-id="<?php echo $floor['building_id'] ?? 0; ?>"
|
|
data-location-id="<?php echo $floor['location_id'] ?? 0; ?>"
|
|
data-svg-url="<?php echo htmlspecialchars($floor['svg_url']); ?>"
|
|
<?php echo $selectedFloorId === $floor['id'] ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($floor['name']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="panel-placement-fields" class="form-grid" <?php echo $showPanelPlacementFields ? '' : 'hidden'; ?>>
|
|
<div class="form-group">
|
|
<label>X</label>
|
|
<input type="number" name="pos_x" value="<?php echo $panel['pos_x'] ?? 0; ?>">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Y</label>
|
|
<input type="number" name="pos_y" value="<?php echo $panel['pos_y'] ?? 0; ?>">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Breite</label>
|
|
<input type="number" name="width" value="<?php echo $panel['width']; ?>" readonly title="Breite wird automatisch nach Standardwerten vorgegeben.">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Höhe</label>
|
|
<input type="number" name="height" value="<?php echo $panel['height']; ?>" readonly title="Höhe wird automatisch nach Standardwerten vorgegeben.">
|
|
</div>
|
|
</div>
|
|
|
|
<div id="panel-floor-plan-group" class="form-group" <?php echo $showPanelPlacementFields ? '' : 'hidden'; ?>>
|
|
<label>Stockwerkskarte</label>
|
|
<div class="floor-plan-block">
|
|
<div id="floor-plan-canvas" class="floor-plan-canvas"
|
|
data-marker-width="<?php echo $markerWidth; ?>"
|
|
data-marker-height="<?php echo $markerHeight; ?>"
|
|
data-marker-type="patchpanel"
|
|
data-x-field="pos_x"
|
|
data-y-field="pos_y">
|
|
<img id="floor-plan-svg" class="floor-plan-svg" alt="Stockwerksplan">
|
|
<div id="floor-plan-marker" class="floor-plan-marker panel-marker"
|
|
style="--marker-width: <?php echo $markerWidth; ?>px; --marker-height: <?php echo $markerHeight; ?>px;"></div>
|
|
</div>
|
|
<p class="floor-plan-hint">Ziehe das Patchpanel oder klicke auf den Plan, um die Position zu setzen.</p>
|
|
<p class="floor-plan-position">Koordinate: <span id="floor-plan-position"></span></p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Port-Anzahl</label>
|
|
<input type="number" name="port_count" value="<?php echo $panel['port_count'] ?? 0; ?>" min="0">
|
|
</div>
|
|
|
|
<p id="panel-floor-missing-hint" class="info" <?php echo $showPanelPlacementFields ? 'hidden' : ''; ?>>
|
|
Position, Groesse und Stockwerkskarte werden erst angezeigt, sobald ein Stockwerk ausgewaehlt ist.
|
|
</p>
|
|
|
|
<div class="form-group">
|
|
<label>Kommentar</label>
|
|
<textarea name="comment"><?php echo htmlspecialchars($panel['comment'] ?? ''); ?></textarea>
|
|
</div>
|
|
|
|
<p class="info">Position und Größe folgen dem Drag-&-Drop auf dem Plan, damit alle Patchpanels einheitlich bleiben.</p>
|
|
|
|
<?php else: ?>
|
|
<div class="form-group">
|
|
<label>Name</label>
|
|
<input type="text" name="name" value="<?php echo htmlspecialchars($outlet['name'] ?? ''); ?>" required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Raum</label>
|
|
<select name="room_id" id="outlet-room-select" required>
|
|
<option value="">- Raum wählen -</option>
|
|
<?php foreach ($rooms as $room): ?>
|
|
<option value="<?php echo $room['id']; ?>"
|
|
data-floor-id="<?php echo $room['floor_id'] ?? 0; ?>"
|
|
data-floor-svg-url="<?php echo htmlspecialchars($room['floor_svg_url']); ?>"
|
|
<?php echo ($outlet['room_id'] ?? 0) === $room['id'] ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars($room['floor_name'] . ' / ' . $room['name']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>X</label>
|
|
<input type="number" name="x" value="<?php echo $outlet['x'] ?? 0; ?>">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Y</label>
|
|
<input type="number" name="y" value="<?php echo $outlet['y'] ?? 0; ?>">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Stockwerkskarte</label>
|
|
<div class="floor-plan-block">
|
|
<div id="floor-plan-canvas" class="floor-plan-canvas"
|
|
data-marker-width="<?php echo $markerWidth; ?>"
|
|
data-marker-height="<?php echo $markerHeight; ?>"
|
|
data-marker-type="outlet"
|
|
data-x-field="x"
|
|
data-y-field="y">
|
|
<img id="floor-plan-svg" class="floor-plan-svg" alt="Stockwerksplan">
|
|
<div id="floor-plan-marker" class="floor-plan-marker outlet-marker"
|
|
style="--marker-width: <?php echo $markerWidth; ?>px; --marker-height: <?php echo $markerHeight; ?>px;"></div>
|
|
</div>
|
|
<p class="floor-plan-hint">Klicke oder ziehe die Wandbuchse auf dem Plan. Die Größe bleibt quadratisch.</p>
|
|
<p class="floor-plan-position">Koordinate: <span id="floor-plan-position"></span></p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Kommentar</label>
|
|
<textarea name="comment"><?php echo htmlspecialchars($outlet['comment'] ?? ''); ?></textarea>
|
|
</div>
|
|
|
|
<p class="info">Wandbuchsen bleiben quadratisch, ihre Position wird über die Karte festgelegt.</p>
|
|
<?php endif; ?>
|
|
|
|
<div class="form-actions">
|
|
<button type="submit" class="button button-primary">Speichern</button>
|
|
<a href="?module=floor_infrastructure&action=list" class="button">Abbrechen</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<?php
|
|
//TODO drag an drop auf der stockwerkskarte für die patchfelder und wandbuchsen. buchsen haben eine einheitliche größe, und sind quadratisch, patchfelder sind auch für sich einheitlich, sind rechteckig und breiter als hoch
|
|
//TODO style in css files einsortieren
|
|
?>
|
|
<style>
|
|
.floor-infra-edit {
|
|
padding: 25px;
|
|
max-width: 700px;
|
|
}
|
|
.infra-edit-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
.form-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
.form-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
gap: 12px;
|
|
}
|
|
.form-actions {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
.info {
|
|
font-size: 0.9em;
|
|
color: #555;
|
|
}
|
|
.floor-plan-block {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
.floor-plan-canvas {
|
|
position: relative;
|
|
width: 100%;
|
|
min-height: 260px;
|
|
border: 1px solid #d4d4d4;
|
|
border-radius: 8px;
|
|
background-color: #fff;
|
|
background-image:
|
|
linear-gradient(90deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px),
|
|
linear-gradient(rgba(0, 0, 0, 0.05) 1px, transparent 1px);
|
|
background-size: 40px 40px;
|
|
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-marker {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: var(--marker-width, 32px);
|
|
height: var(--marker-height, 32px);
|
|
transition: left 0.1s ease, top 0.1s ease;
|
|
touch-action: none;
|
|
z-index: 2;
|
|
}
|
|
.floor-plan-marker.panel-marker {
|
|
background: rgba(13, 110, 253, 0.25);
|
|
border: 2px solid #0d6efd;
|
|
border-radius: 6px;
|
|
}
|
|
.floor-plan-marker.outlet-marker {
|
|
background: rgba(25, 135, 84, 0.25);
|
|
border: 2px solid #198754;
|
|
border-radius: 4px;
|
|
}
|
|
.floor-plan-hint {
|
|
font-size: 0.85em;
|
|
color: #444;
|
|
margin: 0;
|
|
}
|
|
.floor-plan-position {
|
|
margin: 0;
|
|
font-size: 0.85em;
|
|
color: #666;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const canvas = document.getElementById('floor-plan-canvas');
|
|
const marker = document.getElementById('floor-plan-marker');
|
|
const positionLabel = document.getElementById('floor-plan-position');
|
|
if (!canvas || !marker) {
|
|
return;
|
|
}
|
|
|
|
const xFieldName = canvas.dataset.xField;
|
|
const yFieldName = canvas.dataset.yField;
|
|
const xField = xFieldName ? document.querySelector(`input[name="${xFieldName}"]`) : null;
|
|
const yField = yFieldName ? document.querySelector(`input[name="${yFieldName}"]`) : null;
|
|
if (!xField || !yField) {
|
|
return;
|
|
}
|
|
|
|
const markerWidth = Math.max(1, Number(canvas.dataset.markerWidth) || marker.offsetWidth);
|
|
const markerHeight = Math.max(1, Number(canvas.dataset.markerHeight) || marker.offsetHeight);
|
|
|
|
const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
|
|
const updatePositionLabel = (x, y) => {
|
|
if (positionLabel) {
|
|
positionLabel.textContent = `${Math.round(x)} x ${Math.round(y)}`;
|
|
}
|
|
};
|
|
|
|
const setMarkerPosition = (rawX, rawY) => {
|
|
const rect = canvas.getBoundingClientRect();
|
|
const maxX = Math.max(0, rect.width - markerWidth);
|
|
const maxY = Math.max(0, rect.height - markerHeight);
|
|
const left = clamp(rawX, 0, maxX);
|
|
const top = clamp(rawY, 0, maxY);
|
|
marker.style.left = `${left}px`;
|
|
marker.style.top = `${top}px`;
|
|
xField.value = Math.round(left);
|
|
yField.value = Math.round(top);
|
|
updatePositionLabel(left, top);
|
|
};
|
|
|
|
const updateFromInputs = () => {
|
|
setMarkerPosition(Number(xField.value) || 0, Number(yField.value) || 0);
|
|
};
|
|
|
|
updateFromInputs();
|
|
|
|
let dragging = false;
|
|
let offsetX = 0;
|
|
let offsetY = 0;
|
|
|
|
const startDrag = (clientX, clientY) => {
|
|
const markerRect = marker.getBoundingClientRect();
|
|
offsetX = clientX - markerRect.left;
|
|
offsetY = clientY - markerRect.top;
|
|
};
|
|
|
|
marker.addEventListener('pointerdown', (event) => {
|
|
event.preventDefault();
|
|
dragging = true;
|
|
startDrag(event.clientX, event.clientY);
|
|
marker.setPointerCapture(event.pointerId);
|
|
});
|
|
|
|
marker.addEventListener('pointermove', (event) => {
|
|
if (!dragging) {
|
|
return;
|
|
}
|
|
const rect = canvas.getBoundingClientRect();
|
|
setMarkerPosition(event.clientX - rect.left - offsetX, event.clientY - rect.top - offsetY);
|
|
});
|
|
|
|
const stopDrag = (event) => {
|
|
if (!dragging) {
|
|
return;
|
|
}
|
|
dragging = false;
|
|
if (marker.hasPointerCapture(event.pointerId)) {
|
|
marker.releasePointerCapture(event.pointerId);
|
|
}
|
|
};
|
|
|
|
['pointerup', 'pointercancel', 'pointerleave'].forEach((evt) => {
|
|
marker.addEventListener(evt, stopDrag);
|
|
});
|
|
|
|
canvas.addEventListener('pointerdown', (event) => {
|
|
if (event.target !== canvas) {
|
|
return;
|
|
}
|
|
const rect = canvas.getBoundingClientRect();
|
|
setMarkerPosition(event.clientX - rect.left - markerWidth / 2, event.clientY - rect.top - markerHeight / 2);
|
|
});
|
|
|
|
[xField, yField].forEach((input) => {
|
|
input.addEventListener('input', () => {
|
|
updateFromInputs();
|
|
});
|
|
});
|
|
|
|
window.addEventListener('resize', () => {
|
|
updateFromInputs();
|
|
});
|
|
|
|
const panelLocationSelect = document.getElementById('panel-location-select');
|
|
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');
|
|
|
|
const buildingOptions = panelBuildingSelect ? Array.from(panelBuildingSelect.options).filter((option) => option.value !== '') : [];
|
|
const floorOptions = panelFloorSelect ? Array.from(panelFloorSelect.options).filter((option) => option.value !== '') : [];
|
|
|
|
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;
|
|
} else {
|
|
floorPlanSvg.removeAttribute('src');
|
|
floorPlanSvg.hidden = true;
|
|
}
|
|
};
|
|
|
|
if (floorPlanSvg) {
|
|
floorPlanSvg.addEventListener('error', () => {
|
|
floorPlanSvg.removeAttribute('src');
|
|
floorPlanSvg.hidden = true;
|
|
});
|
|
}
|
|
|
|
const updatePanelPlacementVisibility = () => {
|
|
if (!panelFloorSelect || !panelPlacementFields || !panelFloorPlanGroup) {
|
|
return;
|
|
}
|
|
|
|
const hasFloor = !!panelFloorSelect.value;
|
|
panelPlacementFields.hidden = !hasFloor;
|
|
panelFloorPlanGroup.hidden = !hasFloor;
|
|
if (panelFloorMissingHint) {
|
|
panelFloorMissingHint.hidden = hasFloor;
|
|
}
|
|
};
|
|
|
|
const filterFloorOptions = () => {
|
|
if (!panelFloorSelect) {
|
|
return;
|
|
}
|
|
const buildingValue = panelBuildingSelect?.value || '';
|
|
let firstMatch = '';
|
|
floorOptions.forEach((option) => {
|
|
const matches = !buildingValue || option.dataset.buildingId === buildingValue;
|
|
option.hidden = !matches;
|
|
option.disabled = !matches;
|
|
if (matches && !firstMatch) {
|
|
firstMatch = option.value;
|
|
}
|
|
});
|
|
|
|
const selectedOption = panelFloorSelect.querySelector(`option[value="${panelFloorSelect.value}"]`);
|
|
const isSelectedHidden = selectedOption ? selectedOption.hidden : true;
|
|
if (buildingValue && (!panelFloorSelect.value || isSelectedHidden) && firstMatch) {
|
|
panelFloorSelect.value = firstMatch;
|
|
}
|
|
|
|
updatePanelPlacementVisibility();
|
|
updateFloorPlanImage();
|
|
};
|
|
|
|
const filterBuildingOptions = () => {
|
|
if (!panelBuildingSelect) {
|
|
return;
|
|
}
|
|
const locationValue = panelLocationSelect?.value || '';
|
|
let firstMatch = '';
|
|
buildingOptions.forEach((option) => {
|
|
const matches = !locationValue || option.dataset.locationId === locationValue;
|
|
option.hidden = !matches;
|
|
option.disabled = !matches;
|
|
if (matches && !firstMatch) {
|
|
firstMatch = option.value;
|
|
}
|
|
});
|
|
|
|
const selectedOption = panelBuildingSelect.querySelector(`option[value="${panelBuildingSelect.value}"]`);
|
|
const isSelectedHidden = selectedOption ? selectedOption.hidden : true;
|
|
if (locationValue && (!panelBuildingSelect.value || isSelectedHidden) && firstMatch) {
|
|
panelBuildingSelect.value = firstMatch;
|
|
}
|
|
};
|
|
|
|
if (panelLocationSelect) {
|
|
panelLocationSelect.addEventListener('change', () => {
|
|
filterBuildingOptions();
|
|
filterFloorOptions();
|
|
});
|
|
}
|
|
|
|
if (panelBuildingSelect) {
|
|
panelBuildingSelect.addEventListener('change', () => {
|
|
filterFloorOptions();
|
|
});
|
|
}
|
|
|
|
if (panelFloorSelect) {
|
|
panelFloorSelect.addEventListener('change', () => {
|
|
updatePanelPlacementVisibility();
|
|
updateFloorPlanImage();
|
|
});
|
|
}
|
|
|
|
if (outletRoomSelect) {
|
|
outletRoomSelect.addEventListener('change', () => {
|
|
updateFloorPlanImage();
|
|
});
|
|
}
|
|
|
|
if (panelLocationSelect) {
|
|
filterBuildingOptions();
|
|
filterFloorOptions();
|
|
} else {
|
|
updateFloorPlanImage();
|
|
}
|
|
|
|
updatePanelPlacementVisibility();
|
|
});
|
|
</script>
|
|
|