Quelltext des aktuellen Standes
<?php
/**
* Dialoge der Rack-Seite: Rack bearbeiten, Geraet einbauen und bearbeiten,
* Verbindung anlegen, Verkabelung importieren, Ports beschriften.
*
* Aufruf nur fuer Aenderungsberechtigte:
* <?= $this->partial('infrastructure-rack-dialogs', [...]) ?>
*
* @var array $rack Das Rack selbst (id, name, doc_page_id, ...).
* @var int $height Hoehe des Racks in HE.
* @var string $numbering 'bottom_up' oder 'top_down'.
* @var string $side Angezeigte Seite ('front'/'rear') – Vorgabe beim Einbauen.
* @var array $mounts Geraete dieses Racks (fuer die Endpunkt-Auswahl).
* @var array $targets Racks der Umgebung mit ihren Geraeten (Endpunkt B).
* @var list<array{0:int,1:string}> $docOptions Dokuseiten zur Auswahl.
* @var float|null $maxLoadKg Hinterlegte Traglast.
* @var int|null $maxPowerW Hinterlegte Leistungsgrenze.
*/
?>
<!-- Modal: Rack bearbeiten -->
<div class="modal-overlay" id="inf-rack-modal" style="display:none;" onclick="if(event.target===this)this.style.display='none'">
<div class="modal-card">
<div class="modal-header"><h2><?= $this->te('Rack bearbeiten') ?></h2>
<button aria-label="<?= $this->te('Schließen') ?>" type="button" class="modal-close" onclick="document.getElementById('inf-rack-modal').style.display='none'">×</button></div>
<form method="POST" action="/infrastructure/racks/<?= (int)$rack['id'] ?>/update">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="modal-body">
<div class="form-group">
<label for="f-f5d6-name"><?= $this->te('Name') ?> <span class="text-danger">*</span></label>
<input id="f-f5d6-name" type="text" name="name" class="form-control form-control-sm" value="<?= $this->e($rack['name']) ?>" required>
</div>
<div class="inf-form-row-2">
<div class="form-group"><label for="f-f5d6-height_u"><?= $this->te('Höhe (HE)') ?></label><input id="f-f5d6-height_u" type="number" name="height_u" class="form-control form-control-sm" value="<?= $height ?>" min="1" max="60"></div>
<div class="form-group"><label for="f-f5d6-numbering"><?= $this->te('Nummerierung') ?></label>
<select id="f-f5d6-numbering" name="numbering" class="form-control form-control-sm" data-searchable>
<option value="bottom_up" <?= $numbering === 'bottom_up' ? 'selected' : '' ?>><?= $this->te('von unten (1 unten)') ?></option>
<option value="top_down" <?= $numbering === 'top_down' ? 'selected' : '' ?>><?= $this->te('von oben (1 oben)') ?></option>
</select>
</div>
</div>
<div class="inf-form-row-2">
<div class="form-group"><label><?= $this->te('Max. Traglast (kg)') ?></label><input type="number" step="0.1" name="max_load_kg" class="form-control form-control-sm" value="<?= $maxLoadKg !== null ? $this->e(rtrim(rtrim(number_format($maxLoadKg, 1, '.', ''), '0'), '.')) : '' ?>" min="0" placeholder="<?= $this->te('optional') ?>"></div>
<div class="form-group"><label><?= $this->te('Max. Leistung (W)') ?></label><input type="number" name="max_power_watt" class="form-control form-control-sm" value="<?= $maxPowerW !== null ? (int)$maxPowerW : '' ?>" min="0" placeholder="<?= $this->te('optional') ?>"></div>
<div class="form-group">
<label for="f-f5d6-doc_page_id"><?= $this->te('Dokumentation') ?></label>
<?php
// Der hinterlegte Eintrag steht als einzige Option im Markup, damit der
// Wert auch ohne das Modul-Skript erhalten bleibt; der Rest kommt beim Oeffnen.
$rackDoc = (int)($rack['doc_page_id'] ?? 0);
$rackDocTitle = '';
foreach ($docOptions as $dp) { if ($dp[0] === $rackDoc) { $rackDocTitle = $dp[1]; break; } }
?>
<select id="f-f5d6-doc_page_id" name="doc_page_id" class="form-control form-control-sm" data-searchable data-inf-fill="docPages">
<option value=""><?= $this->te('— keine —') ?></option>
<?php if ($rackDoc > 0 && $rackDocTitle !== ''): ?>
<option value="<?= $rackDoc ?>" selected><?= $this->e($rackDocTitle) ?></option>
<?php endif; ?>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" onclick="document.getElementById('inf-rack-modal').style.display='none'"><?= $this->te('Abbrechen') ?></button>
<button type="submit" class="btn btn-primary"><?= $this->te('Speichern') ?></button>
</div>
</form>
</div>
</div>
<!-- Modal: Gerät einbauen -->
<div class="modal-overlay" id="inf-mount-modal" style="display:none;" onclick="if(event.target===this)this.style.display='none'">
<div class="modal-card">
<div class="modal-header"><h2><?= $this->te('Gerät einbauen') ?></h2>
<button aria-label="<?= $this->te('Schließen') ?>" type="button" class="modal-close" onclick="document.getElementById('inf-mount-modal').style.display='none'">×</button></div>
<form method="POST" action="/infrastructure/racks/<?= (int)$rack['id'] ?>/mounts">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="modal-body">
<div class="form-group">
<label for="inf-source"><?= $this->te('Quelle') ?></label>
<select name="source_type" class="form-control form-control-sm" id="inf-source" onchange="infSource(this.value)" data-searchable>
<option value="asset"><?= $this->te('Inventar-Gerät') ?></option>
<option value="unifi"><?= $this->te('UniFi-Gerät') ?></option>
<option value="passive"><?= $this->te('Passiv (Patchpanel, PDU …)') ?></option>
</select>
</div>
<div class="form-group" id="inf-f-asset">
<label for="f-f5d6-asset_id"><?= $this->te('Inventar-Gerät') ?></label>
<select id="f-f5d6-asset_id" name="asset_id" class="form-control form-control-sm" data-searchable data-inf-fill="assets">
<option value=""><?= $this->te('— wählen —') ?></option>
</select>
</div>
<div class="form-group" id="inf-f-unifi" style="display:none">
<label for="f-f5d6-unifi_mac"><?= $this->te('UniFi-Gerät') ?></label>
<select id="f-f5d6-unifi_mac" name="unifi_mac" class="form-control form-control-sm" onchange="infUnifiAutofill(this)" data-searchable data-inf-fill="unifi">
<option value=""><?= $this->te('— wählen —') ?></option>
</select>
</div>
<div class="form-group" id="inf-f-label" style="display:none">
<label><?= $this->te('Bezeichnung') ?></label>
<input type="text" name="label" class="form-control form-control-sm" placeholder="<?= $this->te('z. B. Patchpanel P-01') ?>">
</div>
<div class="form-group">
<label class="inf-check"><input type="checkbox" id="inf-add-usecolor" onchange="infToggleColor('add')"> <?= $this->te('Eigene Farbe (überschreibt Hell/Dunkel)') ?></label>
<div class="inf-color-row">
<input type="color" name="color" id="inf-add-color" value="#c0392b" disabled>
<span class="inf-hint"><?= $this->te('z. B. rot für WatchGuard-Firewalls – der Verlauf bleibt erhalten') ?></span>
</div>
</div>
<div class="inf-form-row">
<div class="form-group"><label for="inf-add-start"><?= $this->te('Start-HE') ?></label><input type="number" name="start_u" id="inf-add-start" class="form-control form-control-sm" value="1" min="1" max="<?= $height ?>"></div>
<div class="form-group"><label><?= $this->te('Höhe (HE)') ?></label><input type="number" name="height_u" class="form-control form-control-sm" value="1" min="1" max="20"></div>
<div class="form-group"><label for="inf-add-side"><?= $this->te('Seite') ?></label>
<select name="side" id="inf-add-side" class="form-control form-control-sm" data-searchable>
<option value="front" <?= $side === 'front' ? 'selected' : '' ?>><?= $this->te('Front') ?></option>
<option value="rear" <?= $side === 'rear' ? 'selected' : '' ?>><?= $this->te('Rück') ?></option>
</select>
</div>
</div>
<div class="inf-form-row-2">
<div class="form-group"><label for="inf-add-slot"><?= $this->te('Breite') ?></label>
<select name="slot" id="inf-add-slot" class="form-control form-control-sm" data-searchable>
<option value="full"><?= $this->te('Ganze Breite') ?></option>
<option value="left"><?= $this->te('Linke Hälfte') ?></option>
<option value="right"><?= $this->te('Rechte Hälfte') ?></option>
</select>
</div>
<div class="form-group"><label><?= $this->te('Tiefe') ?></label>
<label class="inf-check"><input type="checkbox" name="full_depth" id="inf-add-fulldepth" value="1" onchange="infAddDepth()"> <?= $this->te('Volle Tiefe (vorne & hinten)') ?></label>
</div>
</div>
<hr>
<div class="form-group">
<label for="inf-portkind"><?= $this->te('Port-Darstellung') ?></label>
<select name="port_kind" class="form-control form-control-sm" id="inf-portkind" onchange="infPortKind(this.value)" data-searchable>
<option value="none"><?= $this->te('Keine (nur Blende)') ?></option>
<option value="switch"><?= $this->te('Switch (RJ45 + SFP)') ?></option>
<option value="firewall"><?= $this->te('Firewall (Ports + SFP)') ?></option>
<option value="patchpanel"><?= $this->te('Patchpanel') ?></option>
<option value="gateway"><?= $this->te('Gateway/Router (WAN/LAN)') ?></option>
<option value="server"><?= $this->te('Server (Laufwerke)') ?></option>
<option value="pbx"><?= $this->te('Telefonanlage (Anschlüsse)') ?></option>
<option value="pdu"><?= $this->te('PDU (Steckdosen)') ?></option>
<option value="ups"><?= $this->te('USV (Ausgänge)') ?></option>
<option value="generic"><?= $this->te('Generisch') ?></option>
</select>
</div>
<div id="inf-portcounts" style="display:none">
<div class="inf-form-row">
<div class="form-group" id="inf-add-pc-wrap"><label for="inf-add-pc" id="inf-add-pc-label"><?= $this->te('Ports') ?></label><input type="number" name="port_count" id="inf-add-pc" class="form-control form-control-sm" value="0" min="0" max="96"></div>
<div class="form-group" id="inf-add-sfp-wrap"><label for="inf-add-sfp">SFP</label><input type="number" name="sfp_count" id="inf-add-sfp" class="form-control form-control-sm" value="0" min="0" max="64"></div>
<div class="form-group" id="inf-add-qsfp-wrap"><label for="inf-add-qsfp">QSFP</label><input type="number" name="qsfp_count" id="inf-add-qsfp" class="form-control form-control-sm" value="0" min="0" max="32"></div>
</div>
<div class="form-group" id="inf-add-layout-wrap">
<label for="inf-add-layout"><?= $this->te('Port-Zählung') ?></label>
<select name="port_layout" id="inf-add-layout" class="form-control form-control-sm" data-searchable>
<option value="zebra"><?= $this->te('Senkrecht paarweise (1 oben, 2 darunter …)') ?></option>
<option value="rows"><?= $this->te('Zeilenweise (obere Reihe, dann untere)') ?></option>
</select>
</div>
<div id="inf-add-rear-wrap" style="display:none">
<div class="inf-subhead"><i class="fas fa-arrows-alt-h"></i> <?= $this->te('Ports auf der Rückseite') ?></div>
<div class="inf-form-row">
<div class="form-group" id="inf-add-rpc-wrap"><label for="f-f5d6-port_count_rear" id="inf-add-rpc-label"><?= $this->te('Ports hinten') ?></label><input id="f-f5d6-port_count_rear" type="number" name="port_count_rear" class="form-control form-control-sm" value="0" min="0" max="96"></div>
<div class="form-group" id="inf-add-rsfp-wrap"><label for="f-f5d6-sfp_count_rear"><?= $this->te('SFP hinten') ?></label><input id="f-f5d6-sfp_count_rear" type="number" name="sfp_count_rear" class="form-control form-control-sm" value="0" min="0" max="64"></div>
<div class="form-group" id="inf-add-rqsfp-wrap"><label for="f-f5d6-qsfp_count_rear"><?= $this->te('QSFP hinten') ?></label><input id="f-f5d6-qsfp_count_rear" type="number" name="qsfp_count_rear" class="form-control form-control-sm" value="0" min="0" max="32"></div>
</div>
</div>
</div>
<div class="inf-form-row-2">
<div class="form-group"><label><?= $this->te('Leistung (W)') ?></label><input type="number" name="power_watt" class="form-control form-control-sm" min="0" placeholder="<?= $this->te('optional') ?>"></div>
<div class="form-group"><label><?= $this->te('Gewicht (kg)') ?></label><input type="number" step="0.1" name="weight_kg" class="form-control form-control-sm" min="0" placeholder="<?= $this->te('optional') ?>"></div>
<div class="form-group"><label for="f-f5d6-power_feed"><?= $this->te('Stromeinspeisung') ?></label>
<select id="f-f5d6-power_feed" name="power_feed" class="form-control form-control-sm">
<option value="none"><?= $this->te('— nicht zugeordnet —') ?></option>
<option value="a"><?= $this->te('Nur A') ?></option>
<option value="b"><?= $this->te('Nur B') ?></option>
<option value="both"><?= $this->te('A und B (redundant)') ?></option>
</select>
</div>
<div class="form-group">
<label><?= $this->te('Dokumentation') ?></label>
<select name="doc_page_id" class="form-control form-control-sm" data-searchable data-inf-fill="docPages">
<option value=""><?= $this->te('— keine —') ?></option>
</select>
</div>
</div>
<div class="form-group" id="inf-add-cap-wrap" style="display:none">
<label><?= $this->te('Nennleistung (W)') ?> <span class="text-muted"><?= $this->te('– Bezug für die Lastbilanz') ?></span></label>
<input type="number" name="capacity_watt" class="form-control form-control-sm" min="0" placeholder="z. B. 1500">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" onclick="document.getElementById('inf-mount-modal').style.display='none'"><?= $this->te('Abbrechen') ?></button>
<button type="submit" class="btn btn-primary"><?= $this->te('Einbauen') ?></button>
</div>
</form>
</div>
</div>
<!-- Modal: Einbau bearbeiten (Identität bleibt, Verkabelung bleibt erhalten) -->
<div class="modal-overlay" id="inf-edit-modal" style="display:none;" onclick="if(event.target===this)this.style.display='none'">
<div class="modal-card">
<div class="modal-header"><h2><?= $this->te('Einbau bearbeiten') ?></h2>
<button aria-label="<?= $this->te('Schließen') ?>" type="button" class="modal-close" onclick="document.getElementById('inf-edit-modal').style.display='none'">×</button></div>
<form method="POST" id="inf-edit-form" action="">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="modal-body">
<div class="form-group" id="inf-edit-f-label">
<label><?= $this->te('Bezeichnung') ?></label>
<input type="text" name="label" class="form-control form-control-sm" placeholder="<?= $this->te('Anzeigename (optional bei Inventar/UniFi)') ?>">
</div>
<div class="form-group">
<label class="inf-check"><input type="checkbox" id="inf-edit-usecolor" onchange="infToggleColor('edit')"> <?= $this->te('Eigene Farbe (überschreibt Hell/Dunkel)') ?></label>
<div class="inf-color-row">
<input type="color" name="color" id="inf-edit-color" value="#c0392b" disabled>
<span class="inf-hint"><?= $this->te('der dezente Verlauf bleibt erhalten') ?></span>
</div>
</div>
<div class="inf-form-row">
<div class="form-group"><label for="f-f5d6-start_u"><?= $this->te('Start-HE') ?></label><input id="f-f5d6-start_u" type="number" name="start_u" class="form-control form-control-sm" value="1" min="1" max="<?= $height ?>"></div>
<div class="form-group"><label><?= $this->te('Höhe (HE)') ?></label><input type="number" name="height_u" class="form-control form-control-sm" value="1" min="1" max="20"></div>
<div class="form-group"><label for="f-f5d6-side"><?= $this->te('Seite') ?></label><select id="f-f5d6-side" name="side" class="form-control form-control-sm" data-searchable><option value="front"><?= $this->te('Front') ?></option><option value="rear"><?= $this->te('Rück') ?></option></select></div>
</div>
<div class="inf-form-row-2">
<div class="form-group"><label for="f-f5d6-slot"><?= $this->te('Breite') ?></label>
<select id="f-f5d6-slot" name="slot" class="form-control form-control-sm" data-searchable>
<option value="full"><?= $this->te('Ganze Breite') ?></option>
<option value="left"><?= $this->te('Linke Hälfte') ?></option>
<option value="right"><?= $this->te('Rechte Hälfte') ?></option>
</select>
</div>
<div class="form-group"><label><?= $this->te('Tiefe') ?></label>
<label class="inf-check"><input type="checkbox" name="full_depth" id="inf-edit-fulldepth" value="1" onchange="infEditDepth()"> <?= $this->te('Volle Tiefe (vorne & hinten)') ?></label>
</div>
</div>
<div class="form-group">
<label for="f-f5d6-port_kind"><?= $this->te('Port-Darstellung') ?></label>
<select id="f-f5d6-port_kind" name="port_kind" class="form-control form-control-sm" onchange="infEditPortKind(this.value)" data-searchable>
<option value="none"><?= $this->te('Keine (nur Blende)') ?></option>
<option value="switch"><?= $this->te('Switch (RJ45 + SFP)') ?></option>
<option value="firewall"><?= $this->te('Firewall (Ports + SFP)') ?></option>
<option value="patchpanel"><?= $this->te('Patchpanel') ?></option>
<option value="gateway"><?= $this->te('Gateway/Router (WAN/LAN)') ?></option>
<option value="server"><?= $this->te('Server (Laufwerke)') ?></option>
<option value="pbx"><?= $this->te('Telefonanlage (Anschlüsse)') ?></option>
<option value="pdu"><?= $this->te('PDU (Steckdosen)') ?></option>
<option value="ups"><?= $this->te('USV (Ausgänge)') ?></option>
<option value="generic"><?= $this->te('Generisch') ?></option>
</select>
</div>
<div id="inf-edit-portcounts" style="display:none">
<div class="inf-form-row">
<div class="form-group" id="inf-edit-pc-wrap"><label for="f-f5d6-port_count" id="inf-edit-pc-label"><?= $this->te('Ports') ?></label><input id="f-f5d6-port_count" type="number" name="port_count" class="form-control form-control-sm" value="0" min="0" max="96"></div>
<div class="form-group" id="inf-edit-sfp-wrap"><label for="f-f5d6-sfp_count">SFP</label><input id="f-f5d6-sfp_count" type="number" name="sfp_count" class="form-control form-control-sm" value="0" min="0" max="64"></div>
<div class="form-group" id="inf-edit-qsfp-wrap"><label for="f-f5d6-qsfp_count">QSFP</label><input id="f-f5d6-qsfp_count" type="number" name="qsfp_count" class="form-control form-control-sm" value="0" min="0" max="32"></div>
</div>
<div class="form-group" id="inf-edit-layout-wrap">
<label for="f-f5d6-port_layout"><?= $this->te('Port-Zählung') ?></label>
<select id="f-f5d6-port_layout" name="port_layout" class="form-control form-control-sm" data-searchable>
<option value="zebra"><?= $this->te('Senkrecht paarweise (1 oben, 2 darunter …)') ?></option>
<option value="rows"><?= $this->te('Zeilenweise (obere Reihe, dann untere)') ?></option>
</select>
</div>
<div id="inf-edit-rear-wrap" style="display:none">
<div class="inf-subhead"><i class="fas fa-arrows-alt-h"></i> <?= $this->te('Ports auf der Rückseite') ?></div>
<div class="inf-form-row">
<div class="form-group" id="inf-edit-rpc-wrap"><label id="inf-edit-rpc-label"><?= $this->te('Ports hinten') ?></label><input type="number" name="port_count_rear" class="form-control form-control-sm" value="0" min="0" max="96"></div>
<div class="form-group" id="inf-edit-rsfp-wrap"><label><?= $this->te('SFP hinten') ?></label><input type="number" name="sfp_count_rear" class="form-control form-control-sm" value="0" min="0" max="64"></div>
<div class="form-group" id="inf-edit-rqsfp-wrap"><label><?= $this->te('QSFP hinten') ?></label><input type="number" name="qsfp_count_rear" class="form-control form-control-sm" value="0" min="0" max="32"></div>
</div>
</div>
</div>
<div class="inf-form-row-2">
<div class="form-group"><label><?= $this->te('Leistung (W)') ?></label><input type="number" name="power_watt" class="form-control form-control-sm" min="0" placeholder="<?= $this->te('optional') ?>"></div>
<div class="form-group"><label><?= $this->te('Gewicht (kg)') ?></label><input type="number" step="0.1" name="weight_kg" class="form-control form-control-sm" min="0" placeholder="<?= $this->te('optional') ?>"></div>
<div class="form-group"><label><?= $this->te('Stromeinspeisung') ?></label>
<select name="power_feed" class="form-control form-control-sm">
<option value="none"><?= $this->te('— nicht zugeordnet —') ?></option>
<option value="a"><?= $this->te('Nur A') ?></option>
<option value="b"><?= $this->te('Nur B') ?></option>
<option value="both"><?= $this->te('A und B (redundant)') ?></option>
</select>
</div>
<div class="form-group">
<label><?= $this->te('Dokumentation') ?></label>
<select name="doc_page_id" class="form-control form-control-sm" data-searchable data-inf-fill="docPages">
<option value=""><?= $this->te('— keine —') ?></option>
</select>
</div>
</div>
<div class="form-group" id="inf-edit-cap-wrap" style="display:none">
<label><?= $this->te('Nennleistung (W)') ?> <span class="text-muted"><?= $this->te('– Bezug für die Lastbilanz') ?></span></label>
<input type="number" name="capacity_watt" class="form-control form-control-sm" min="0" placeholder="z. B. 1500">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" onclick="document.getElementById('inf-edit-modal').style.display='none'"><?= $this->te('Abbrechen') ?></button>
<button type="submit" class="btn btn-primary"><?= $this->te('Speichern') ?></button>
</div>
</form>
</div>
</div>
<!-- Modal: Verbindung anlegen -->
<div class="modal-overlay" id="inf-conn-modal" style="display:none;" onclick="if(event.target===this)this.style.display='none'">
<div class="modal-card">
<div class="modal-header"><h2 id="inf-conn-title"><?= $this->te('Verbindung anlegen') ?></h2>
<button aria-label="<?= $this->te('Schließen') ?>" type="button" class="modal-close" onclick="document.getElementById('inf-conn-modal').style.display='none'">×</button></div>
<form method="POST" id="inf-conn-form" action="/infrastructure/racks/<?= (int)$rack['id'] ?>/connections">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="modal-body">
<div class="inf-form-row-2">
<div class="form-group">
<label for="inf-a-mount"><?= $this->te('Gerät A') ?> <span class="text-danger">*</span></label>
<select name="a_mount_id" class="form-control form-control-sm" id="inf-a-mount" data-searchable>
<option value=""><?= $this->te('— wählen —') ?></option>
<?php foreach ($mounts as $m): ?>
<option value="<?= (int)$m['id'] ?>"><?= $this->te('{name} (HE {he})', ['name' => $m['name'], 'he' => (int)$m['start_u']]) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label><?= $this->te('Port A') ?> <span class="text-danger">*</span></label>
<input type="text" name="a_port" class="form-control form-control-sm" list="inf-a-portlist" placeholder="<?= $this->te('z. B. 5, SFP1, WAN1') ?>">
<datalist id="inf-a-portlist"></datalist>
</div>
</div>
<div class="form-group">
<label for="inf-b-kind"><?= $this->te('Endpunkt B') ?></label>
<select class="form-control form-control-sm" id="inf-b-kind" name="b_kind" onchange="infBKind(this.value)" data-searchable>
<option value="mount"><?= $this->te('Gerät im System (auch anderes Rack/Standort)') ?></option>
<option value="external"><?= $this->te('Externes Ziel (frei)') ?></option>
</select>
</div>
<div id="inf-b-mount-wrap">
<div class="inf-form-row-2">
<div class="form-group">
<label for="inf-b-mount"><?= $this->te('Gerät B') ?></label>
<select name="b_mount_id" class="form-control form-control-sm" id="inf-b-mount" data-searchable onchange="infBPorts(this.value)">
<option value=""><?= $this->te('— wählen —') ?></option>
<?php foreach ($targets as $g): ?>
<?php $ctx = ($g['location'] ? $g['location'] . ' › ' : '') . $g['rack']; ?>
<?php foreach ($g['mounts'] as $tm): ?>
<option value="<?= (int)$tm['id'] ?>"><?= $this->e($ctx . ' · ' . $tm['name']) ?></option>
<?php endforeach; ?>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label><?= $this->te('Port B') ?></label>
<input type="text" name="b_port" class="form-control form-control-sm" list="inf-b-portlist" placeholder="<?= $this->te('z. B. 24, SFP1, Core-Uplink') ?>">
<datalist id="inf-b-portlist"></datalist>
</div>
</div>
</div>
<div id="inf-b-ext-wrap" style="display:none">
<div class="form-group">
<label><?= $this->te('Externes Ziel') ?></label>
<input type="text" name="b_external" class="form-control form-control-sm" placeholder="<?= $this->te('z. B. Provider-Übergabe, ISP-Modem') ?>">
</div>
</div>
<div class="inf-form-row-2">
<div class="form-group">
<label for="f-f5d6-cable_type"><?= $this->te('Kabeltyp') ?></label>
<select id="f-f5d6-cable_type" name="cable_type" class="form-control form-control-sm" data-searchable>
<option value="copper"><?= $this->te('Kupfer (Cat)') ?></option>
<option value="fiber"><?= $this->te('Fiber') ?></option>
<option value="dac">DAC</option>
<option value="wan">WAN/VPN</option>
<option value="power"><?= $this->te('Strom') ?></option>
<option value="other"><?= $this->te('Sonstige') ?></option>
</select>
</div>
<div class="form-group">
<label><?= $this->te('Bezeichnung') ?></label>
<input type="text" name="label" class="form-control form-control-sm" placeholder="<?= $this->te('optional, z. B. DAC 1m') ?>">
</div>
</div>
<div class="inf-form-row-2">
<div class="form-group">
<label><?= $this->te('Länge (m)') ?></label>
<input type="number" step="0.1" min="0" name="length_m" class="form-control form-control-sm" placeholder="<?= $this->te('optional') ?>">
</div>
<div class="form-group">
<label class="inf-check"><input type="checkbox" id="inf-conn-usecolor" onchange="infToggleCableColor()"> <?= $this->te('Kabelfarbe') ?></label>
<div class="inf-color-row">
<input type="color" name="color" id="inf-conn-color" value="#3c8dbc" disabled>
<span class="inf-hint"><?= $this->te('hilft beim Wiederfinden im Rack') ?></span>
</div>
</div>
</div>
<div class="form-group">
<label for="f-f5d6-installed_on"><?= $this->te('Verlegt am') ?></label>
<input id="f-f5d6-installed_on" type="date" name="installed_on" class="form-control form-control-sm">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" onclick="document.getElementById('inf-conn-modal').style.display='none'"><?= $this->te('Abbrechen') ?></button>
<button type="submit" class="btn btn-primary"><?= $this->te('Speichern') ?></button>
</div>
</form>
</div>
</div>
<!-- Modal: Einbauten aus CSV übernehmen -->
<div class="modal-overlay" id="inf-import-modal" style="display:none;" onclick="if(event.target===this)this.style.display='none'">
<div class="modal-card">
<form method="POST" action="/infrastructure/racks/<?= (int)$rack['id'] ?>/mounts/import" enctype="multipart/form-data">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="modal-header">
<h2><?= $this->te('Einbauten aus CSV übernehmen') ?></h2>
<button aria-label="<?= $this->te('Schließen') ?>" type="button" class="modal-close" onclick="document.getElementById('inf-import-modal').style.display='none'">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="inf-import-file"><?= $this->te('CSV-Datei') ?> <span class="text-danger">*</span></label>
<input type="file" name="csv" id="inf-import-file" accept=".csv,text/csv" required class="form-control form-control-sm">
</div>
<p class="inf-hint" style="margin:0;">
<?= $this->t('Spalten, mit Semikolon getrennt:<br> <code>Bezeichnung;Start-HE;Höhe-HE;Seite;Port-Typ;Ports;SFP;Watt;kg</code><br> Beispiel: <code>Patchpanel EG;12;1;front;patchpanel;24;0;;3.2</code><br> Eine Kopfzeile wird erkannt und übersprungen. Zeilen auf belegten Positionen werden ausgelassen und danach benannt.') ?>
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" onclick="document.getElementById('inf-import-modal').style.display='none'"><?= $this->te('Abbrechen') ?></button>
<button type="submit" class="btn btn-primary"><?= $this->te('Übernehmen') ?></button>
</div>
</form>
</div>
</div>
<!-- Modal: Ports beschriften -->
<div class="modal-overlay" id="inf-portlabel-modal" style="display:none;" onclick="if(event.target===this)this.style.display='none'">
<div class="modal-card">
<div class="modal-header"><h2 id="inf-portlabel-title"><?= $this->te('Ports beschriften') ?></h2>
<button aria-label="<?= $this->te('Schließen') ?>" type="button" class="modal-close" onclick="document.getElementById('inf-portlabel-modal').style.display='none'">×</button></div>
<form method="POST" id="inf-portlabel-form" action="">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="modal-body">
<p class="inf-hint" style="margin:0 0 .6rem"><?= $this->te('Hinterlege je Port, wohin er führt (z. B. „Büro 1.02"). Leere Felder werden nicht gespeichert.') ?></p>
<div id="inf-portlabel-body" class="inf-pl-grid"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" onclick="document.getElementById('inf-portlabel-modal').style.display='none'"><?= $this->te('Abbrechen') ?></button>
<button type="submit" class="btn btn-primary"><?= $this->te('Speichern') ?></button>
</div>
</form>
</div>
</div>