Files
urlshort-qr-gen/templates/dashboard/index.php
T
florian.wilde c65c02cda5 feat(setup): Systemcheck und Upload-Paket fuer klassisches Webhosting
Auf Shared Hosting gibt es keine Kommandozeile - ohne Anzeige laesst
sich dort nicht feststellen, ob etwa gd fehlt, die PHP-Version zu alt
ist oder data/ nicht beschreibbar ist. Der Setup-Assistent prueft das
jetzt und listet es auf; im Dashboard meldet sich die Pruefung spaeter
nur noch, wenn etwas nicht stimmt. Fehlende Pflichtbausteine sind
Fehler, fehlende Kuer (intl, imagick, cURL) nur Hinweise mit Angabe,
was dadurch entfaellt.

build-release.sh erzeugt das Upload-Paket: Abhaengigkeiten ohne
Entwicklungspakete, ohne Tests und Docker-Dateien. Dabei faellt eine
16 MB grosse Schriftart aus endroid/qr-code weg, die ausschliesslich
fuer Beschriftungen unter dem QR-Code gebraucht wird - die erzeugt
diese Anwendung nicht. Das Paket schrumpft damit von 18 MB auf 1 MB.
Sollte spaeter doch eine Beschriftung dazukommen, erkennt das Skript
das und behaelt die Datei.

Die Variante ohne eigenen Webroot (alles liegt im Domainverzeichnis,
die .htaccess im Stammverzeichnis leitet nach public/ um) war bisher
gebaut, aber nie erprobt. Sie ist jetzt gegen eine Hoster-Simulation
getestet: Ersteinrichtung, Kurzlinks, Weiterleitung, QR-Codes,
Statistik und die Sperren fuer src/, vendor/, data/ und .env.
2026-08-10 15:32:13 +02:00

136 lines
5.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* @var array{links:int,clicks:int,active:int} $summary
* @var list<array<string,mixed>> $recentLinks
* @var list<array<string,mixed>> $topLinks
* @var list<array{date:string,clicks:int}> $series
* @var int $domainCount
* @var App\Config $config
*/
use App\Repository\LinkRepository;
use App\Service\SystemCheck;
use App\Support\ShortDomain;
$fallbackBase = rtrim($config->baseUrl(), '/');
?>
<?php if (($systemProblems ?? []) !== []):
$hatFehler = false;
foreach ($systemProblems as $problem) {
if ($problem['status'] === SystemCheck::ERROR) {
$hatFehler = true;
}
}
?>
<section class="card check-result check-result--<?= $hatFehler ? 'error' : 'warn' ?>">
<div class="check-result__head">
<span class="check-result__icon" aria-hidden="true"><?= $hatFehler ? '×' : '!' ?></span>
<div>
<h2>Hinweise zum Server</h2>
<p class="check-result__summary">
<?= $hatFehler
? 'Es fehlt etwas, das die Anwendung braucht.'
: 'Alles läuft – einzelne Zusatzfunktionen stehen aber nicht zur Verfügung.' ?>
</p>
</div>
</div>
<ul class="check-list">
<?php foreach ($systemProblems as $problem): ?>
<li class="check-list__item check-list__item--<?= $problem['status'] === SystemCheck::ERROR ? 'error' : 'warn' ?>">
<span class="check-list__icon" aria-hidden="true"><?= $problem['status'] === SystemCheck::ERROR ? '×' : '!' ?></span>
<span class="check-list__label"><?= $e($problem['label']) ?></span>
<span class="check-list__text"><?= $e($problem['text']) ?></span>
</li>
<?php endforeach; ?>
</ul>
</section>
<?php endif; ?>
<div class="page-head">
<div>
<h1>Übersicht</h1>
<p class="muted">Alle Kurzlinks und Klicks auf einen Blick.</p>
</div>
<a href="<?= $e($url('/admin/links/new')) ?>" class="btn btn--primary">Neuer Kurzlink</a>
</div>
<div class="stats-grid">
<div class="stat">
<span class="stat__label">Kurzlinks</span>
<span class="stat__value"><?= (int) $summary['links'] ?></span>
</div>
<div class="stat">
<span class="stat__label">davon aktiv</span>
<span class="stat__value"><?= (int) $summary['active'] ?></span>
</div>
<div class="stat">
<span class="stat__label">Klicks gesamt</span>
<span class="stat__value"><?= number_format((int) $summary['clicks'], 0, ',', '.') ?></span>
</div>
<div class="stat">
<span class="stat__label">Klicks (30 Tage)</span>
<span class="stat__value"><?= number_format(array_sum(array_column($series, 'clicks')), 0, ',', '.') ?></span>
</div>
<div class="stat">
<span class="stat__label">Domains</span>
<span class="stat__value">
<a href="<?= $e($url('/admin/domains')) ?>"><?= (int) $domainCount ?></a>
</span>
</div>
</div>
<section class="card">
<h2>Klicks der letzten 30 Tage</h2>
<div class="chart" data-chart="line" data-series="<?= $e(json_encode($series, JSON_UNESCAPED_SLASHES)) ?>">
<canvas height="120" aria-label="Liniendiagramm der Klicks pro Tag"></canvas>
<noscript><p class="muted">Für das Diagramm wird JavaScript benötigt.</p></noscript>
</div>
</section>
<div class="grid grid--2">
<section class="card">
<h2>Zuletzt angelegt</h2>
<?php if ($recentLinks === []): ?>
<p class="muted">Noch keine Kurzlinks vorhanden.
<a href="<?= $e($url('/admin/links/new')) ?>">Jetzt den ersten anlegen.</a></p>
<?php else: ?>
<ul class="list">
<?php foreach ($recentLinks as $link): ?>
<li class="list__item">
<div class="list__main">
<a class="mono" href="<?= $e($url('/admin/links/' . $link['id'] . '/stats')) ?>"><?php
if ($domainCount > 1 && $link['domain_base_url'] !== null): ?><span class="linkcopy__domain"><?=
$e(ShortDomain::displayName((string) $link['domain_base_url'])) ?></span><?php
endif; ?>/<?= $e($link['slug']) ?></a>
<span class="muted small truncate"><?= $e($link['target_url']) ?></span>
</div>
<span class="badge"><?= (int) $link['click_count'] ?> Klicks</span>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</section>
<section class="card">
<h2>Meistgeklickt</h2>
<?php if ($topLinks === [] || (int) $summary['clicks'] === 0): ?>
<p class="muted">Noch keine Klicks erfasst.</p>
<?php else: ?>
<ul class="list">
<?php foreach ($topLinks as $link): ?>
<li class="list__item">
<div class="list__main">
<a class="mono" href="<?= $e($url('/admin/links/' . $link['id'] . '/stats')) ?>"><?php
if ($domainCount > 1 && $link['domain_base_url'] !== null): ?><span class="linkcopy__domain"><?=
$e(ShortDomain::displayName((string) $link['domain_base_url'])) ?></span><?php
endif; ?>/<?= $e($link['slug']) ?></a>
<span class="muted small truncate"><?= $e($link['target_url']) ?></span>
</div>
<span class="badge"><?= (int) $link['click_count'] ?> Klicks</span>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</section>
</div>