Eigenes CSS statt Framework, Vanilla-JavaScript, heller und dunkler Modus. Ohne JavaScript bleibt alles bedienbar; das Liniendiagramm faellt auf eine selbst gezeichnete Balkendarstellung zurueck, wenn das CDN nicht erreichbar ist. Chart.js ist auf eine Version festgelegt und per Subresource Integrity an seinen Hash gebunden. Die Domain-Seite enthaelt eine Schritt-fuer-Schritt-Anleitung fuer DNS, Hosting-Panel und Zertifikat samt Fehlersuche.
104 lines
4.3 KiB
PHP
104 lines
4.3 KiB
PHP
<?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\Support\ShortDomain;
|
|
|
|
$fallbackBase = rtrim($config->baseUrl(), '/');
|
|
?>
|
|
<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>
|