240 lines
9.9 KiB
PHP
240 lines
9.9 KiB
PHP
<?php
|
|
/**
|
|
* app/modules/floor_infrastructure/list.php
|
|
*
|
|
* Uebersicht ueber Patchpanels und Netzwerkbuchsen auf Stockwerken.
|
|
*/
|
|
|
|
$floorId = (int)($_GET['floor_id'] ?? 0);
|
|
|
|
$floors = $sql->get(
|
|
"SELECT id, name, svg_path
|
|
FROM floors
|
|
ORDER BY name",
|
|
"",
|
|
[]
|
|
);
|
|
|
|
$where = '';
|
|
$types = '';
|
|
$params = [];
|
|
|
|
if ($floorId > 0) {
|
|
$where = "WHERE p.floor_id = ?";
|
|
$types = 'i';
|
|
$params[] = $floorId;
|
|
}
|
|
|
|
$patchPanels = $sql->get(
|
|
"SELECT p.*, f.name AS floor_name
|
|
FROM floor_patchpanels p
|
|
LEFT JOIN floors f ON f.id = p.floor_id
|
|
$where
|
|
ORDER BY f.name, p.name",
|
|
$types,
|
|
$params
|
|
);
|
|
|
|
$networkOutlets = $sql->get(
|
|
"SELECT o.id, o.room_id, o.name, o.x, o.y, o.comment,
|
|
r.name AS room_name, r.number AS room_number,
|
|
f.name AS floor_name, f.id AS floor_id,
|
|
GROUP_CONCAT(nop.name ORDER BY nop.name SEPARATOR ', ') AS port_names
|
|
FROM network_outlets o
|
|
LEFT JOIN rooms r ON r.id = o.room_id
|
|
LEFT JOIN floors f ON f.id = r.floor_id
|
|
LEFT JOIN network_outlet_ports nop ON nop.outlet_id = o.id
|
|
GROUP BY o.id
|
|
ORDER BY f.name, r.name, o.name",
|
|
"",
|
|
[]
|
|
);
|
|
|
|
$floorMap = [];
|
|
foreach ($floors as $floor) {
|
|
$id = (int)$floor['id'];
|
|
$svgPath = trim((string)($floor['svg_path'] ?? ''));
|
|
$floorMap[$id] = [
|
|
'id' => $id,
|
|
'name' => (string)($floor['name'] ?? ''),
|
|
'svg_url' => $svgPath !== '' ? '/' . ltrim($svgPath, '/\\') : ''
|
|
];
|
|
}
|
|
|
|
$editorFloor = ($floorId > 0 && isset($floorMap[$floorId])) ? $floorMap[$floorId] : null;
|
|
$editorPatchPanels = [];
|
|
$editorOutlets = [];
|
|
|
|
if ($editorFloor) {
|
|
foreach ($patchPanels as $panel) {
|
|
if ((int)$panel['floor_id'] !== $floorId) {
|
|
continue;
|
|
}
|
|
$editorPatchPanels[] = [
|
|
'id' => (int)$panel['id'],
|
|
'name' => (string)$panel['name'],
|
|
'x' => (int)$panel['pos_x'],
|
|
'y' => (int)$panel['pos_y'],
|
|
'width' => max(1, (int)$panel['width']),
|
|
'height' => max(1, (int)$panel['height']),
|
|
'port_count' => (int)$panel['port_count'],
|
|
'comment' => (string)($panel['comment'] ?? '')
|
|
];
|
|
}
|
|
|
|
foreach ($networkOutlets as $outlet) {
|
|
if ((int)$outlet['floor_id'] !== $floorId) {
|
|
continue;
|
|
}
|
|
$editorOutlets[] = [
|
|
'id' => (int)$outlet['id'],
|
|
'name' => (string)$outlet['name'],
|
|
'x' => (int)$outlet['x'],
|
|
'y' => (int)$outlet['y'],
|
|
'room_name' => (string)($outlet['room_name'] ?? ''),
|
|
'room_number' => (string)($outlet['room_number'] ?? ''),
|
|
'port_names' => (string)($outlet['port_names'] ?? ''),
|
|
'comment' => (string)($outlet['comment'] ?? '')
|
|
];
|
|
}
|
|
}
|
|
?>
|
|
|
|
<div class="floor-infra">
|
|
<link rel="stylesheet" href="/assets/css/floor-infrastructure-list.css">
|
|
<script src="/assets/js/floor-infrastructure-list.js" defer></script>
|
|
|
|
<h1>Stockwerksinfrastruktur</h1>
|
|
|
|
<div class="toolbar">
|
|
<a href="?module=floor_infrastructure&action=edit&type=patchpanel" class="button button-primary">
|
|
+ Patchpanel hinzufuegen
|
|
</a>
|
|
<a href="?module=floor_infrastructure&action=edit&type=outlet" class="button">
|
|
+ Wandbuchse hinzufuegen
|
|
</a>
|
|
</div>
|
|
|
|
<form method="get" class="filter-form" id="infra-filter-form">
|
|
<input type="hidden" name="module" value="floor_infrastructure">
|
|
<input type="hidden" name="action" value="list">
|
|
|
|
<select name="floor_id" id="infra-floor-select">
|
|
<option value="">- Stockwerk waehlen -</option>
|
|
<?php foreach ($floors as $floor): ?>
|
|
<option value="<?php echo (int)$floor['id']; ?>" <?php echo ((int)$floor['id'] === $floorId) ? 'selected' : ''; ?>>
|
|
<?php echo htmlspecialchars((string)$floor['name']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
|
|
<button class="button" type="submit">Filter</button>
|
|
<a href="?module=floor_infrastructure&action=list" class="button">Zuruecksetzen</a>
|
|
</form>
|
|
|
|
<section class="infra-plan">
|
|
<h2>Stockwerkskarte</h2>
|
|
<?php if ($floorId <= 0): ?>
|
|
<p class="empty-state">Bitte ein Stockwerk auswaehlen, um die Karte anzuzeigen.</p>
|
|
<?php elseif (!$editorFloor): ?>
|
|
<p class="empty-state">Gewaehltes Stockwerk wurde nicht gefunden.</p>
|
|
<?php elseif (($editorFloor['svg_url'] ?? '') === ''): ?>
|
|
<p class="empty-state">Das gewaehlte Stockwerk hat keinen SVG-Plan hinterlegt.</p>
|
|
<?php else: ?>
|
|
<p>
|
|
Read-only Vorschau fuer <strong><?php echo htmlspecialchars((string)$editorFloor['name']); ?></strong>.
|
|
Alle Objekte werden angezeigt; Hover zeigt Details.
|
|
</p>
|
|
<div id="infra-floor-canvas"
|
|
class="infra-floor-canvas"
|
|
data-patchpanels="<?php echo htmlspecialchars(json_encode($editorPatchPanels, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ENT_QUOTES, 'UTF-8'); ?>"
|
|
data-outlets="<?php echo htmlspecialchars(json_encode($editorOutlets, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), ENT_QUOTES, 'UTF-8'); ?>">
|
|
<img src="<?php echo htmlspecialchars((string)$editorFloor['svg_url']); ?>" class="infra-floor-svg" alt="Stockwerksplan">
|
|
<svg id="infra-floor-overlay" class="infra-floor-overlay" viewBox="0 0 1 1" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
|
|
</div>
|
|
<p class="floor-plan-hint">Blau: Patchpanel | Gruen: Wandbuchse. Hover zeigt Name, Raum und Ports (Browser-Tooltip).</p>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="infra-section">
|
|
<h2>Patchpanels</h2>
|
|
<?php if (!empty($patchPanels)): ?>
|
|
<table class="infra-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Stockwerk</th>
|
|
<th>Position</th>
|
|
<th>Groesse</th>
|
|
<th>Ports</th>
|
|
<th>Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($patchPanels as $panel): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars((string)$panel['name']); ?></td>
|
|
<td><?php echo htmlspecialchars((string)($panel['floor_name'] ?? '-')); ?></td>
|
|
<td><?php echo (int)$panel['pos_x'] . ' x ' . (int)$panel['pos_y']; ?></td>
|
|
<td><?php echo (int)$panel['width'] . ' x ' . (int)$panel['height']; ?></td>
|
|
<td><?php echo (int)$panel['port_count']; ?></td>
|
|
<td class="actions">
|
|
<a href="?module=floor_infrastructure&action=edit&type=patchpanel&id=<?php echo (int)$panel['id']; ?>" class="button button-small">Bearbeiten</a>
|
|
<a href="?module=floor_infrastructure&action=delete&type=patchpanel&id=<?php echo (int)$panel['id']; ?>" class="button button-small button-danger" onclick="return confirm('Patchpanel wirklich loeschen?');">Loeschen</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php else: ?>
|
|
<p class="empty-state">Noch keine Patchpanels definiert.</p>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="infra-section">
|
|
<h2>Wandbuchsen</h2>
|
|
<?php if (!empty($networkOutlets)): ?>
|
|
<table class="infra-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Stockwerk</th>
|
|
<th>Raum</th>
|
|
<th>Koordinaten</th>
|
|
<th>Ports</th>
|
|
<th>Kommentar</th>
|
|
<th>Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($networkOutlets as $outlet): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars((string)$outlet['name']); ?></td>
|
|
<td><?php echo htmlspecialchars((string)($outlet['floor_name'] ?? '-')); ?></td>
|
|
<td>
|
|
<?php
|
|
$roomLabel = (string)($outlet['room_name'] ?? '-');
|
|
$roomNumber = trim((string)($outlet['room_number'] ?? ''));
|
|
if ($roomNumber !== '') {
|
|
$roomLabel .= ' (' . $roomNumber . ')';
|
|
}
|
|
echo htmlspecialchars($roomLabel);
|
|
?>
|
|
</td>
|
|
<td><?php echo (int)$outlet['x'] . ' x ' . (int)$outlet['y']; ?></td>
|
|
<td><?php echo htmlspecialchars((string)($outlet['port_names'] ?? '-')); ?></td>
|
|
<td><?php echo htmlspecialchars((string)($outlet['comment'] ?? '')); ?></td>
|
|
<td class="actions">
|
|
<a href="?module=floor_infrastructure&action=edit&type=outlet&id=<?php echo (int)$outlet['id']; ?>" class="button button-small">Bearbeiten</a>
|
|
<a href="?module=floor_infrastructure&action=delete&type=outlet&id=<?php echo (int)$outlet['id']; ?>" class="button button-small button-danger" onclick="return confirm('Wandbuchse wirklich loeschen?');">Loeschen</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php else: ?>
|
|
<p class="empty-state">Noch keine Wandbuchsen angelegt.</p>
|
|
<?php endif; ?>
|
|
</section>
|
|
</div>
|