Some checks failed
release-tag / release-image (push) Failing after 38s
build-binaries / build (, amd64, linux) (push) Has been skipped
build-binaries / build (, arm, 7, linux) (push) Has been skipped
build-binaries / build (, arm64, linux) (push) Has been skipped
build-binaries / build (.exe, amd64, windows) (push) Has been skipped
build-binaries / release (push) Has been skipped
80 lines
2.7 KiB
HTML
80 lines
2.7 KiB
HTML
{{- /* templates/index.html */ -}}
|
|
<!doctype html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
<title>{{ .Title }}</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="/static/styles.css">
|
|
</head>
|
|
<body>
|
|
<header class="container">
|
|
<h1>{{ .Title }}</h1>
|
|
<div class="controls">
|
|
<input id="search" type="search" placeholder="Suchen…" aria-label="Suchen" />
|
|
<select id="category">
|
|
<option value="">Alle Kategorien</option>
|
|
{{- range .Categories }}
|
|
<option value="{{ . }}">{{ . }}</option>
|
|
{{- end }}
|
|
</select>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="container">
|
|
<div id="grid" class="grid">
|
|
{{- range .Apps }}
|
|
<a class="tile" href="{{ .URL | safeURL }}" target="_blank" rel="noopener noreferrer"
|
|
data-title="{{ .Title }}" data-category="{{ .Category }}">
|
|
<div class="tile-inner" style="{{ if .Color }}--tile-color: {{ .Color }};{{ end }}">
|
|
<div class="icon" aria-hidden="true">
|
|
{{- /* Falls Icon eine URL ist, Bild anzeigen. Sonst Emoji/Text. */ -}}
|
|
{{- if or (hasPrefix .Icon "http://") (hasPrefix .Icon "https://") -}}
|
|
<img src="{{ .Icon }}" alt="" loading="lazy" />
|
|
{{- else -}}
|
|
<span>{{ .Icon }}</span>
|
|
{{- end -}}
|
|
</div>
|
|
<div class="title">{{ .Title }}</div>
|
|
{{- if .Category }}<div class="badge">{{ .Category }}</div>{{ end }}
|
|
</div>
|
|
</a>
|
|
{{- end }}
|
|
</div>
|
|
</main>
|
|
|
|
<footer class="container footer">
|
|
<small>Stand: {{ .Now.Format "02.01.2006 15:04" }}</small>
|
|
</footer>
|
|
|
|
<script>
|
|
// kleine Hilfsfunktionen
|
|
const el = (sel) => document.querySelector(sel);
|
|
const els = (sel) => Array.from(document.querySelectorAll(sel));
|
|
const norm = (s) => (s || "").toLowerCase().normalize("NFKD");
|
|
|
|
// Suche & Kategorie-Filter
|
|
const search = el('#search');
|
|
const cat = el('#category');
|
|
const tiles = els('.tile');
|
|
|
|
function applyFilter() {
|
|
const q = norm(search.value);
|
|
const c = cat.value;
|
|
tiles.forEach(t => {
|
|
const title = norm(t.dataset.title);
|
|
const category = t.dataset.category || "";
|
|
const matchQ = !q || title.includes(q);
|
|
const matchC = !c || category === c;
|
|
t.style.display = (matchQ && matchC) ? "" : "none";
|
|
});
|
|
}
|
|
|
|
search.addEventListener('input', applyFilter);
|
|
cat.addEventListener('change', applyFilter);
|
|
</script>
|
|
</body>
|
|
</html>
|