Files
mindflux/src/main/resources/templates/admin/devlab.html
T
AliceDarkest 501ecc0c1e AP3 A11y-Widget perfektioniert (Focus-Trap, aria-Semantik, tote CSS, Cache)
- accessibility.js: Focus-Trap im Panel (Tab/Shift+Tab zyklisch ueber Close + 9
  Optionen), aria-modal="true" beim Oeffnen, Klick-ausserhalb schliesst (Escape +
  Fokus-Rueckgabe bestehen). Font-Button: aria-pressed ersetzt durch dynamisches
  aria-label ("... aktuell 115 %") + .is-active ab >100 %; Reset-Button ohne
  aria-pressed (Aktion statt Toggle). Hochkontrast-Untertitel "immer dunkel".
- accessibility.css: toten Legacy-Dock-Code entfernt (72px body-padding, .mf-a11y-dock,
  Fixed-Trigger, Dock-Media-Query); .is-active am Aktiv-Styling; Kommentar, dass
  Hochkontrast bewusst immer dunkel bleibt.
- accessibility-placement.css: obsoleten Padding-Reset entfernt; .is-active ergaenzt.
- Cache-Buster: theme.js injiziert accessibility.css v6 / placement v10 /
  accessibility.js v9 / fluxtimer.css v5; theme.css?v=4 und theme.js?v=5 in allen
  80 Templates/Finalflux-Seiten vereinheitlicht.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WFxcjtc9HNP4VECT6Ur1tE
2026-07-21 00:16:05 +02:00

97 lines
5.2 KiB
HTML
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.
<!DOCTYPE html>
<html lang="de" data-theme="dark"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dev-Lab-Verwaltung – Admin</title>
<link rel="stylesheet" href="/css/theme.css?v=4">
<script src="/js/theme.js?v=5"></script>
<style>
.dla { max-width: 1000px; margin: 0 auto; padding: 0 1rem; width: 100%; }
.dla .new-game { margin-bottom: 1.6rem; }
.dla .grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
.dla .game {
display: flex; align-items: center; flex-wrap: wrap; gap: 0.6rem; justify-content: space-between;
background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--accent);
border-radius: 12px; padding: 0.9rem 1.1rem; margin-bottom: 0.7rem; box-shadow: var(--g-soft);
}
.dla .game.inactive { border-left-color: var(--danger); opacity: 0.7; }
.dla .game h2 { color: var(--heading); margin: 0; font-size: 1.05rem; }
.dla .slug { color: var(--accent); font-size: 0.78rem; font-family: monospace; }
.dla .badge { font-size: 0.66rem; text-transform: uppercase; padding: 0.14rem 0.45rem; border-radius: 7px; border: 1px solid var(--border-accent); color: var(--secondary); border-color: var(--secondary); }
.dla .badge.on { background: var(--glow-w); color: var(--accent); border-color: var(--border-accent); }
.dla .badge.off { background: rgba(255,95,107,.12); color: var(--danger); border-color: var(--danger); }
.dla .count { color: var(--muted); font-size: 0.85rem; }
.dla .actions { display: flex; gap: 0.45rem; flex-wrap: wrap; align-items: center; }
.dla .field { margin-bottom: 0.7rem; display: flex; flex-direction: column; gap: 0.35rem; }
.dla .field > label { color: var(--accent); font-weight: 700; font-size: 0.85rem; }
.dla .empty { color: var(--muted); }
@media (max-width: 600px) { .dla .grid2 { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<div class="mf-theme-float"><button class="mf-theme"></button></div>
<div class="mf-container" style="max-width:1040px">
<div class="mf-page-head">
<a th:href="@{/admin}" class="mf-back">⟵ Zurück zum Admin-Dashboard</a>
</div>
<header style="margin-bottom:1.4rem">
<div class="mf-eyebrow">Dev Lab</div>
<h1 style="color:var(--heading); font-size:1.75rem; font-weight:800; margin-top:.35rem">⚗️ Dev-Lab-Verwaltung</h1>
</header>
<main class="dla">
<div class="mf-panel accent new-game">
<h4>Neues Spiel anlegen</h4>
<form th:action="@{/admin/devlab/games}" method="post">
<div class="grid2">
<div class="field"><label>Titel</label><input class="mf-input" type="text" name="title" placeholder="z. B. SQL Detective" required></div>
<div class="field"><label>Sprache/Domäne</label><input class="mf-input" type="text" name="language" placeholder="SQL / CSS / Git …"></div>
</div>
<div class="grid2">
<div class="field"><label>Pfad</label>
<select class="mf-select" name="path">
<option value="syntax">Syntax &amp; Grundlagen</option>
<option value="debugging">Debugging &amp; Problemlösung</option>
<option value="visual">Praxis &amp; Visualisierung</option>
</select>
</div>
<div class="field"><label>Beschreibung</label><input class="mf-input" type="text" name="description" placeholder="kurze Beschreibung"></div>
</div>
<button type="submit" class="mf-btn">➕ Spiel anlegen &amp; Aufgaben hinzufügen</button>
</form>
</div>
<div class="game" th:each="g : ${games}" th:classappend="${g.active} ? '' : 'inactive'">
<div>
<h2 th:text="${g.title}">Spiel</h2>
<span class="slug" th:text="'/' + ${g.slug}">/slug</span>
<span class="badge" th:text="${g.path}">syntax</span>
<span class="badge" th:if="${g.language}" th:text="${g.language}">SQL</span>
<span class="badge on" th:if="${g.active}">aktiv</span>
<span class="badge off" th:unless="${g.active}">inaktiv</span>
<span class="count" th:text="'· ' + ${g.taskCount} + ' Aufgaben'">· 0 Aufgaben</span>
</div>
<div class="actions">
<a class="mf-btn" th:href="@{'/admin/devlab/games/' + ${g.id}}">Aufgaben verwalten</a>
<form th:action="@{'/admin/devlab/games/' + ${g.id} + '/toggle'}" method="post">
<button type="submit" class="mf-btn outline" th:text="${g.active} ? 'Deaktivieren' : 'Aktivieren'">Toggle</button>
</form>
<form th:action="@{'/admin/devlab/games/' + ${g.id} + '/delete'}" method="post" onsubmit="return confirm('Spiel inkl. aller Aufgaben löschen?');">
<button type="submit" class="mf-btn danger">Löschen</button>
</form>
</div>
</div>
<p th:if="${games.isEmpty()}" class="empty">Noch keine Spiele. Lege oben das erste an.</p>
</main>
</div>
<footer class="mf-footer">
<a href="#">Support</a><a href="#">Feedback</a>
<a href="/nutzungsbedingungen">Nutzungsbedingungen</a><a href="/richtlinien">Richtlinien</a>
<a href="/datenschutz">Datenschutz</a><a href="/impressum">Impressum</a>
</footer>
</body>
</html>