Quelltext des aktuellen Standes
<?php $this->layout('layouts/main', [
'page_title' => 'DNS-Zone',
'current_route' => 'dns',
'full_width' => true,
]); ?>
<?php
$zone = $zone ?? [];
$records = $records ?? [];
$typeCounts = $type_counts ?? [];
$filterQ = $filter_q ?? '';
$filterType = $filter_type ?? '';
$zoneId = (int)($zone['id'] ?? 0);
?>
<div class="page-body">
<div class="content-header">
<div>
<h1><?= $this->e($zone['name'] ?? '') ?></h1>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/"><?= $this->te('Home') ?></a></li>
<li class="breadcrumb-item"><a href="/dns">DNS</a></li>
<li class="breadcrumb-item active"><?= $this->e($zone['name'] ?? '') ?></li>
</ol>
</div>
<?php if (!empty($can_manage)): ?>
<div>
<form action="/dns/zones/<?= $zoneId ?>" method="POST" style="display:inline;">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<input type="hidden" name="_method" value="DELETE">
<button type="button" class="btn btn-sm btn-danger"
onclick="itConfirmSubmit(this, 'Zone entfernen?', 'Die Zone „<?= $this->e(addslashes((string)($zone['name'] ?? ''))) ?>“ wird mit allen Records und ihrem Änderungsverlauf aus OpenNIT entfernt. Der DNS-Server selbst bleibt unberührt – meldet ein Agent die Zone erneut, taucht sie wieder auf.', 'Entfernen')">
<i class="fas fa-trash"></i> <?= $this->te('Zone entfernen') ?>
</button>
</form>
</div>
<?php endif; ?>
</div>
<!-- Zonen-Metadaten -->
<section class="detail-card" style="margin-bottom:1.25rem;">
<div class="detail-card-body" style="display:flex;flex-wrap:wrap;gap:2rem;">
<div><div style="font-size:.75rem;color:var(--gray-500);text-transform:uppercase;"><?= $this->te('Typ') ?></div><div style="font-weight:600;"><?= $this->e($zone['zone_type'] ?: '–') ?></div></div>
<div><div style="font-size:.75rem;color:var(--gray-500);text-transform:uppercase;"><?= $this->te('DNS-Server') ?></div><div style="font-weight:600;"><?= $this->e($zone['dns_server'] ?: '–') ?></div></div>
<div><div style="font-size:.75rem;color:var(--gray-500);text-transform:uppercase;"><?= $this->te('AD-integriert') ?></div><div style="font-weight:600;"><?= !empty($zone['is_ad_integrated']) ? 'Ja' : 'Nein' ?></div></div>
<div><div style="font-size:.75rem;color:var(--gray-500);text-transform:uppercase;"><?= $this->te('Reverse-Zone') ?></div><div style="font-weight:600;"><?= !empty($zone['is_reverse']) ? 'Ja' : 'Nein' ?></div></div>
<div><div style="font-size:.75rem;color:var(--gray-500);text-transform:uppercase;"><?= $this->te('Records') ?></div><div style="font-weight:600;"><?= (int)($zone['record_count'] ?? 0) ?></div></div>
<div><div style="font-size:.75rem;color:var(--gray-500);text-transform:uppercase;"><?= $this->te('Letzter Sync') ?></div><div style="font-weight:600;"><?= !empty($zone['last_synced_at']) ? $this->e(date('d.m.Y H:i', strtotime($zone['last_synced_at']))) : '–' ?></div></div>
</div>
</section>
<!-- Filter -->
<div class="card card-outline card-primary">
<div class="filter-card-body">
<form method="get" action="/dns/zones/<?= $zoneId ?>" style="display:flex;gap:.5rem;flex-wrap:wrap;align-items:center;">
<input type="search" name="q" value="<?= $this->e($filterQ) ?>" class="form-control form-control-sm" placeholder="<?= $this->te('Record suchen…') ?>" autocomplete="off" style="max-width:240px;">
<select name="type" class="form-control form-control-sm" style="max-width:160px;">
<option value=""><?= $this->te('Alle Typen') ?></option>
<?php foreach ($typeCounts as $t => $c): ?>
<option value="<?= $this->e($t) ?>" <?= $filterType === $t ? 'selected' : '' ?>><?= $this->e($t) ?> (<?= (int)$c ?>)</option>
<?php endforeach; ?>
</select>
<button type="submit" class="btn btn-sm btn-primary"><?= $this->te('Filtern') ?></button>
<?php if ($filterQ !== '' || $filterType !== ''): ?><a href="/dns/zones/<?= $zoneId ?>" class="btn btn-sm btn-default"><?= $this->te('Zurücksetzen') ?></a><?php endif; ?>
</form>
<a href="/dns" class="btn btn-sm btn-default" style="margin-left:auto;"><?= $this->te('« Alle Zonen') ?></a>
</div>
</div>
<!-- Records -->
<?php if (empty($records)): ?>
<div class="empty-state">
<span class="empty-icon"><i class="fas fa-search"></i></span>
<strong><?= $this->te(($filterQ !== '' || $filterType !== '') ? 'Keine Records für den Filter' : 'Keine Records') ?></strong>
</div>
<?php else: ?>
<div class="table-wrapper">
<table class="data-table">
<thead><tr><th scope="col"><?= $this->te('Name') ?></th><th scope="col"><?= $this->te('Typ') ?></th><th scope="col"><?= $this->te('Daten') ?></th><th scope="col"><?= $this->t('TTL') ?></th></tr></thead>
<tbody>
<?php foreach ($records as $r): ?>
<tr>
<td style="font-family:monospace;"><?= $this->e($r['name']) ?></td>
<td><span class="badge"><?= $this->e($r['type']) ?></span></td>
<td style="font-family:monospace;word-break:break-all;"><?= $this->e($r['data'] ?? '') ?></td>
<td style="color:var(--gray-500);"><?= $r['ttl'] !== null ? (int)$r['ttl'] : '–' ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php
$changes = $changes ?? [];
$historyDays = (int)($history_days ?? 0);
$artLabel = ['added' => 'Hinzugefügt', 'changed' => 'Geändert', 'removed' => 'Entfernt'];
$artPill = ['added' => 'status-pill--success', 'changed' => 'status-pill--warning', 'removed' => 'status-pill--danger'];
?>
<h2 style="margin-top:2rem;font-size:1.05rem;"><?= $this->te('Änderungen') ?></h2>
<?php if (empty($changes)): ?>
<div class="empty-state">
<span class="empty-icon"><i class="fas fa-history"></i></span>
<strong><?= $this->te('Noch keine Änderungen aufgezeichnet') ?></strong>
<p><?= $this->te('Der Verlauf beginnt mit dem zweiten Import dieser Zone – der erste legt den Ausgangsstand fest.') ?></p>
</div>
<?php else: ?>
<div class="table-wrapper">
<table class="data-table">
<thead><tr><th scope="col"><?= $this->te('Zeitpunkt') ?></th><th scope="col"><?= $this->te('Art') ?></th><th scope="col"><?= $this->te('Name') ?></th><th scope="col"><?= $this->te('Typ') ?></th><th scope="col"><?= $this->te('Vorher') ?></th><th scope="col"><?= $this->te('Nachher') ?></th></tr></thead>
<tbody>
<?php foreach ($changes as $c): ?>
<tr>
<td style="white-space:nowrap;color:var(--gray-500);">
<?= $this->e(date('d.m.Y H:i', strtotime((string)$c['changed_at']))) ?>
</td>
<td>
<span class="status-pill <?= $artPill[$c['change_type']] ?? 'status-pill--neutral' ?>">
<?= $artLabel[$c['change_type']] ?? $this->e($c['change_type']) ?>
</span>
</td>
<td style="font-family:monospace;"><?= $this->e($c['record_name']) ?></td>
<td><span class="badge"><?= $this->e($c['record_type']) ?></span></td>
<td style="font-family:monospace;word-break:break-all;color:var(--gray-500);">
<?= $c['old_data'] !== null ? $this->e($c['old_data']) : '—' ?>
<?php if ($c['old_ttl'] !== null && $c['old_ttl'] !== $c['new_ttl']): ?>
<small><?= $this->t('(TTL') ?> <?= (int)$c['old_ttl'] ?>)</small>
<?php endif; ?>
</td>
<td style="font-family:monospace;word-break:break-all;">
<?= $c['new_data'] !== null ? $this->e($c['new_data']) : '—' ?>
<?php if ($c['new_ttl'] !== null && $c['old_ttl'] !== $c['new_ttl']): ?>
<small><?= $this->t('(TTL') ?> <?= (int)$c['new_ttl'] ?>)</small>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<small class="form-hint" style="display:block;margin-top:.5rem;">
<?php if ($historyDays > 0): ?>
<?= $this->t('Der Verlauf wird {tage} Tage aufbewahrt.', ['tage' => $this->e($historyDays)]) ?>
<?php else: ?>
<?= $this->te('Der Verlauf wird unbegrenzt aufbewahrt.') ?>
<?php endif; ?>
<?= $this->t('Aufgezeichnet wird, was sich zwischen zwei Importen unterscheidet – nicht, wer die Änderung am DNS-Server vorgenommen hat.') ?>
</small>
<?php endif; ?>
</div>
<?php if (!empty($can_manage)): ?><?= $this->partial('confirm_modal') ?><?php endif; ?>