Volle Mindflux-App ins Deploy-Repo übernehmen

Ersetzt das Hello-World-Gerüst durch die vollständige Anwendung
(com.example.mindflux: 64 Klassen, Thymeleaf-Templates, Static-Assets,
Flyway V1–V6). Deploy-Infrastruktur (.gitea, Dockerfile) bleibt erhalten.

- pom: volle Abhängigkeiten (Security, Thymeleaf, JPA, Flyway), Spring Boot 3.4.4 / Java 17
- docker-compose: SPRING_DATASOURCE_* unverändert; App lauscht auf 8080
  (nginx -> mindflux:8080); Uploads-Volume; Admin-Passwörter via Gitea-Secrets
- Workflow: Deploy-Step injiziert MINDFLUX_ADMIN*_PASSWORD aus Secrets
- .dockerignore ergänzt; Hello-World (com.mindflux) und Test-Datei 'main' entfernt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
AliceDarkest
2026-06-26 14:51:30 +02:00
parent f3309c1574
commit 9022961762
185 changed files with 22772 additions and 142 deletions
@@ -0,0 +1,139 @@
<!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 th:text="${category.title} + ' – TechTacular'">TechTacular-Kategorie</title>
<link rel="stylesheet" href="/css/theme.css">
<script src="/js/theme.js"></script>
<style>
.ttcat { max-width: 1000px; margin: 0 auto; padding: 0 1rem; width: 100%; }
.ttcat .q {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px; padding: 0.9rem 1.1rem; margin-bottom: 0.7rem;
box-shadow: var(--g-soft);
}
.ttcat .q-head { display: flex; align-items: center; gap: 0.6rem; justify-content: space-between; }
.ttcat .points {
background: var(--glow-w); color: var(--accent); font-weight: 800;
border: 1px solid var(--border-accent);
border-radius: 7px; padding: 0.14rem 0.5rem; font-size: 0.85rem;
}
.ttcat .q-text { color: var(--heading); font-weight: 600; margin: 0.2rem 0 0.5rem; }
.ttcat ul.ans { list-style: none; padding: 0; margin: 0; }
.ttcat ul.ans li { color: var(--text); padding: 0.15rem 0; }
.ttcat ul.ans li.correct { color: var(--accent); font-weight: 700; }
.ttcat ul.ans li.correct::before { content: "✓ "; }
.ttcat .expl { color: var(--muted); font-size: 0.85rem; margin-top: 0.4rem; }
.ttcat .addbox { margin-top: 1.6rem; }
.ttcat .field { margin-bottom: 0.7rem; display: flex; flex-direction: column; gap: 0.35rem; }
.ttcat .field > label { color: var(--accent); font-weight: 700; font-size: 0.85rem; }
.ttcat .ans-row { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.5rem; }
.ttcat .ans-row input[type="text"] { flex: 1; }
.ttcat .ans-row label { color: var(--accent); font-size: 0.82rem; white-space: nowrap; display: flex; align-items: center; gap: 0.3rem; }
.ttcat .hint { color: var(--muted); font-size: 0.82rem; margin-bottom: 0.8rem; line-height: 1.5; }
.ttcat .hint strong { color: var(--text); }
.ttcat .empty { color: var(--danger); }
</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/techtacular}" class="mf-back">⟵ Zurück zur Kategorienliste</a>
</div>
<header style="margin-bottom:1.4rem">
<div class="mf-eyebrow">TechTacular · Kategorie</div>
<h1 style="color:var(--heading); font-size:1.75rem; font-weight:800; margin-top:.35rem" th:text="'🎯 ' + ${category.title}">Kategorie</h1>
</header>
<main class="ttcat">
<!-- Vorhandene Fragen -->
<div class="q" th:each="q : ${category.questions}">
<div class="q-head">
<span class="points" th:text="${q.points} + ' Pkt'">100 Pkt</span>
<form th:action="@{'/admin/techtacular/questions/' + ${q.id} + '/delete'}" method="post"
onsubmit="return confirm('Frage löschen?');">
<input type="hidden" name="categoryId" th:value="${category.id}">
<button type="submit" class="mf-btn danger">✕ Frage löschen</button>
</form>
</div>
<p class="q-text" th:text="${q.text}">Fragetext</p>
<ul class="ans">
<li th:each="a : ${q.answers}" th:text="${a.text}" th:classappend="${a.correct} ? 'correct' : ''">Antwort</li>
</ul>
<p class="expl" th:if="${q.explanation}" th:text="'Erklärung: ' + ${q.explanation}">Erklärung</p>
</div>
<p th:if="${category.questions.isEmpty()}" class="empty">Noch keine Fragen – unten hinzufügen.</p>
<!-- Frage hinzufügen -->
<div class="mf-panel accent addbox">
<h4>Hinweis hinzufügen</h4>
<p class="hint">Jeopardy umgekehrt: Der <strong>Hinweis</strong> ist eine Aussage. Trage die gesuchten
<strong>Begriffe</strong> ein und markiere die <strong>Lösung</strong> mit „richtig“. Im Spiel
erscheinen die Begriffe als „Was ist …?“. Mindestens zwei Begriffe.</p>
<form th:action="@{'/admin/techtacular/categories/' + ${category.id} + '/questions'}" method="post">
<div class="field">
<label>Hinweis (Aussage)</label>
<input class="mf-input" type="text" name="text" placeholder="z. B. Dieses Protokoll übersetzt Domainnamen in IP-Adressen." required>
</div>
<div class="field">
<label>Erklärung (optional)</label>
<input class="mf-input" type="text" name="explanation" placeholder="kurze Begründung">
</div>
<div class="field">
<label>Punkte (Schwierigkeit)</label>
<select class="mf-select" name="points">
<option value="100">100</option>
<option value="200">200</option>
<option value="300">300</option>
<option value="400">400</option>
<option value="500">500</option>
</select>
</div>
<div class="ans-row">
<label><input type="radio" name="correct" value="0" checked> Lösung</label>
<input class="mf-input" type="text" name="answer1" placeholder="Begriff 1 (z. B. DNS)" required>
</div>
<div class="ans-row">
<label><input type="radio" name="correct" value="1"> Lösung</label>
<input class="mf-input" type="text" name="answer2" placeholder="Begriff 2" required>
</div>
<div class="ans-row">
<label><input type="radio" name="correct" value="2"> Lösung</label>
<input class="mf-input" type="text" name="answer3" placeholder="Begriff 3 (optional)">
</div>
<div class="ans-row">
<label><input type="radio" name="correct" value="3"> Lösung</label>
<input class="mf-input" type="text" name="answer4" placeholder="Begriff 4 (optional)">
</div>
<button type="submit" class="mf-btn" style="margin-top:.4rem">➕ Hinweis speichern</button>
</form>
</div>
</main>
</div>
<footer class="mf-footer">
<a href="#">Support</a>
<a href="#">Feedback</a>
<a href="#">Nutzungsbedingungen</a>
<a href="#">Richtlinien</a>
<a href="#">Datenschutz</a>
<a href="#">Impressum</a>
</footer>
</body>
</html>