Every installation now reports address and version to sites.kant-it.de every 15 minutes and picks up update orders there (ADR 123). Reports and answers are HMAC-signed with a per-installation key sent on first contact; an order can only install a published release with checksum. The next request after the file swap runs the migrations, so a remote update finishes without anyone in the admin. The platform itself lives in zentrale/ (plain PHP + SQLite, not part of the release archive): overview with outdated, silent and unassigned installations, single and bulk updates, per-site detail and history. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
101 lines
5.5 KiB
PHP
101 lines
5.5 KiB
PHP
<?php /** @var Zentrale\Ansicht $v */ ?>
|
||
<p class="zurueck"><a href="/">← Alle Installationen</a></p>
|
||
<div class="titelzeile">
|
||
<h1><?= $v->e($i['domain']) ?></h1>
|
||
<?php if ($i['unbekannt']) { ?><span class="marke-fremd">Unbekannt</span><?php } ?>
|
||
</div>
|
||
|
||
<div class="raster">
|
||
<section class="karte" aria-labelledby="t-stand">
|
||
<h2 id="t-stand">Stand</h2>
|
||
<dl class="fakten">
|
||
<dt>Adresse</dt><dd><a href="<?= $v->e($i['adresse']) ?>" rel="noopener noreferrer"><?= $v->e($i['adresse']) ?></a></dd>
|
||
<?php if (null !== $i['domain_vorher']) { ?><dt>Vorher gemeldet als</dt><dd><?= $v->e($i['domain_vorher']) ?></dd><?php } ?>
|
||
<dt>Fassung</dt><dd><span class="fassung <?= $i['veraltet'] ? 'f-alt' : 'f-ok' ?>"><?= $v->e($i['fassung']) ?></span><?= $i['veraltet'] && null !== $neueste ? ' – neueste ist '.$v->e($neueste['version']) : '' ?></dd>
|
||
<dt>Aktualisiert über</dt><dd><?= 'git' === $i['art'] ? 'Git-Arbeitskopie' : 'Releasearchiv' ?></dd>
|
||
<dt>PHP</dt><dd><?= $v->e($i['php'] ?: '–') ?></dd>
|
||
<dt>Datenbank</dt><dd><?= $v->e($i['datenbank'] ?: '–') ?></dd>
|
||
<dt>Wartungsseite</dt><dd><?= $i['wartung'] ? 'an' : 'aus' ?></dd>
|
||
<dt>Letzte Meldung</dt><dd><?= $v->e($v->zeit($i['letzte_meldung'])) ?> (<?= $v->e($v->vor($i['alter'])) ?>)<?= $i['still'] ? ' – <strong>seit über 48 Stunden still</strong>' : '' ?></dd>
|
||
<dt>Erste Meldung</dt><dd><?= $v->e($v->zeit($i['erste_meldung'])) ?></dd>
|
||
<dt>IP-Adresse</dt><dd><?= $v->e($i['ip'] ?: '–') ?></dd>
|
||
<?php if (null !== $i['update_phase']) { ?>
|
||
<dt>Letztes Update</dt><dd><?= $v->e($i['update_meldung']) ?> <span class="klein">(<?= $v->e($v->zeit($i['update_zeit'])) ?>)</span></dd>
|
||
<?php } ?>
|
||
</dl>
|
||
</section>
|
||
|
||
<section class="karte" aria-labelledby="t-update">
|
||
<h2 id="t-update">Update</h2>
|
||
<?php if (null !== $i['auftrag_zustand']) { ?>
|
||
<p><span class="pille p-<?= $v->e($i['auftrag_zustand']['art']) ?>"><?= $v->e($i['auftrag_zustand']['text']) ?></span></p>
|
||
<?php } ?>
|
||
<?php if ('wartet' === ($i['auftrag_zustand']['art'] ?? null)) { ?>
|
||
<p>Die Website holt den Auftrag mit ihrer nächsten Meldung ab – meist innerhalb von 15 Minuten.</p>
|
||
<?php } elseif ($i['kann_update'] && null !== $neueste) { ?>
|
||
<form method="post" action="/auftrag">
|
||
<?= $v->csrf() ?>
|
||
<input type="hidden" name="id" value="<?= $v->e($i['id']) ?>">
|
||
<input type="hidden" name="zurueck" value="detail">
|
||
<p>Die Website holt den Auftrag mit ihrer nächsten Meldung ab, legt eine Sicherung an, spielt <?= $v->e($neueste['version']) ?> ein und schaltet bei einem Fehler zurück.</p>
|
||
<button type="submit" class="knopf">Auf <?= $v->e($neueste['version']) ?> aktualisieren</button>
|
||
</form>
|
||
<?php } else { ?>
|
||
<p><?= $v->e($i['kein_update_grund']) ?></p>
|
||
<?php } ?>
|
||
<?php if (null !== $i['auftrag'] && null === $i['auftrag']['abgeholt'] && null === $i['auftrag']['erledigt']) { ?>
|
||
<form method="post" action="/auftrag/zurueckziehen" class="abstand">
|
||
<?= $v->csrf() ?>
|
||
<input type="hidden" name="id" value="<?= $v->e($i['id']) ?>">
|
||
<button type="submit" class="knopf knopf-leise">Auftrag zurückziehen</button>
|
||
</form>
|
||
<?php } ?>
|
||
</section>
|
||
|
||
<section class="karte" aria-labelledby="t-kunde">
|
||
<h2 id="t-kunde">Kunde</h2>
|
||
<form method="post" action="/notiz">
|
||
<?= $v->csrf() ?>
|
||
<input type="hidden" name="id" value="<?= $v->e($i['id']) ?>">
|
||
<label for="notiz">Kunde oder Notiz</label>
|
||
<p class="feldhilfe" id="notiz-hilfe">Installationen ohne Eintrag stehen in der Übersicht als „Unbekannt“ – so fällt eine fremde Nutzung auf.</p>
|
||
<input id="notiz" name="notiz" type="text" maxlength="200" value="<?= $v->e($i['notiz']) ?>" aria-describedby="notiz-hilfe">
|
||
<button type="submit" class="knopf abstand">Speichern</button>
|
||
</form>
|
||
</section>
|
||
</div>
|
||
|
||
<section class="karte" aria-labelledby="t-verlauf">
|
||
<h2 id="t-verlauf">Aufträge</h2>
|
||
<?php if ([] === $i['verlauf']) { ?>
|
||
<p>Noch kein Auftrag.</p>
|
||
<?php } else { ?>
|
||
<div class="tabelle-rahmen">
|
||
<table class="tabelle">
|
||
<thead><tr><th scope="col">Beauftragt</th><th scope="col">Fassung</th><th scope="col">Abgeholt</th><th scope="col">Ergebnis</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($i['verlauf'] as $a) { ?>
|
||
<tr>
|
||
<td data-label="Beauftragt"><?= $v->e($v->zeit($a['erstellt'])) ?></td>
|
||
<td data-label="Fassung"><?= $v->e($a['fassung']) ?></td>
|
||
<td data-label="Abgeholt"><?= $v->e($v->zeit($a['abgeholt'])) ?></td>
|
||
<td data-label="Ergebnis"><span class="pille p-<?= $v->e($a['zustand']['art']) ?>"><?= $v->e($a['zustand']['text']) ?></span><?php if ('' !== (string) $a['meldung']) { ?><span class="klein block"><?= $v->e($a['meldung']) ?></span><?php } ?></td>
|
||
</tr>
|
||
<?php } ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php } ?>
|
||
</section>
|
||
|
||
<details class="karte gefahr">
|
||
<summary>Eintrag entfernen</summary>
|
||
<form method="post" action="/entfernen">
|
||
<?= $v->csrf() ?>
|
||
<input type="hidden" name="id" value="<?= $v->e($i['id']) ?>">
|
||
<p>Entfernt die Installation und ihre Aufträge aus dieser Liste. An der Website ändert sich nichts; meldet sie sich wieder, erscheint sie neu.</p>
|
||
<label class="bestaetigen"><input type="checkbox" name="bestaetigt" value="ja" required> Ja, <?= $v->e($i['domain']) ?> aus der Liste entfernen</label>
|
||
<button type="submit" class="knopf knopf-gefahr">Entfernen</button>
|
||
</form>
|
||
</details>
|