Mindflux: Sicherheit, Datenintegrität und Navigation härten
This commit is contained in:
@@ -30,12 +30,14 @@
|
||||
<div class="mf-container">
|
||||
|
||||
<div class="mf-page-head">
|
||||
<a href="/profile" class="mf-back">⟵ Zurück zum Profil</a>
|
||||
<a th:href="@{/dashboard}" class="mf-back">⟵ Zurück zum Dashboard</a>
|
||||
</div>
|
||||
<span class="mf-eyebrow">Deine Trophäen</span>
|
||||
<h1 style="color:var(--heading); font-size:1.9rem; font-weight:800; margin:.3rem 0 .25rem;">🏆 Deine Trophäen</h1>
|
||||
<span class="mf-eyebrow">Deine Erfolge</span>
|
||||
<h1 style="color:var(--heading); font-size:1.9rem; font-weight:800; margin:.3rem 0 .25rem;">🏆 Deine Erfolge</h1>
|
||||
<p style="color:var(--muted); margin-bottom:1.4rem;">Sammle sie alle und werde zur Legende!</p>
|
||||
|
||||
<nav th:replace="~{fragments/layout :: profileTabs('erfolge')}"></nav>
|
||||
|
||||
<div class="mf-panel">
|
||||
<div class="mf-ach-grid">
|
||||
<div class="achievement-card"
|
||||
|
||||
@@ -35,68 +35,8 @@
|
||||
<body>
|
||||
<div class="mf-shell">
|
||||
|
||||
<!-- ===== Sidebar ===== -->
|
||||
<aside class="mf-sidebar">
|
||||
<a th:href="@{/dashboard}" class="mf-logo">
|
||||
<span class="mark"></span>
|
||||
<span class="txt"><b>MINDFLUX</b><span>KNOWLEDGE. CODE. WIN.</span></span>
|
||||
</a>
|
||||
|
||||
<nav class="mf-nav">
|
||||
<a th:href="@{/dashboard}" class="active">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>
|
||||
Dashboard
|
||||
</a>
|
||||
<a th:href="@{/admin}" sec:authorize="hasRole('ADMIN')">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l8 4v6c0 5-3.5 8-8 10-4.5-2-8-5-8-10V6z"/><path d="M9 12l2 2 4-4"/></svg>
|
||||
Admin-Dashboard
|
||||
</a>
|
||||
<a th:href="@{/profile/knowledge}">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3 3 15 0 18M12 3c-3 3-3 15 0 18"/></svg>
|
||||
Knowledge Core
|
||||
</a>
|
||||
<a th:href="@{/progress}">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 20V10M10 20V4M16 20v-8M22 20H2"/></svg>
|
||||
Statistiken
|
||||
</a>
|
||||
<a th:href="@{/profile/achievements}">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="9" r="6"/><path d="M9 14l-2 8 5-3 5 3-2-8"/></svg>
|
||||
Achievements
|
||||
</a>
|
||||
<a th:href="@{/profile/settings}">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3.2"/><path d="M19 12a7 7 0 0 0-.1-1l2-1.6-2-3.4-2.4 1a7 7 0 0 0-1.7-1L14.5 2h-4l-.3 2.5a7 7 0 0 0-1.7 1l-2.4-1-2 3.4 2 1.6a7 7 0 0 0 0 2l-2 1.6 2 3.4 2.4-1a7 7 0 0 0 1.7 1l.3 2.5h4l.3-2.5a7 7 0 0 0 1.7-1l2.4 1 2-3.4-2-1.6c.1-.3.1-.7.1-1z"/></svg>
|
||||
Einstellungen
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<a th:href="@{/profile}" class="mf-profile" style="text-decoration:none">
|
||||
<div class="row">
|
||||
<span class="mf-avatar" th:text="${#authentication.name != null ? #authentication.name.substring(0,1).toUpperCase() : 'U'}">A</span>
|
||||
<div>
|
||||
<b sec:authentication="name">Alice Darkest</b>
|
||||
<span class="role" sec:authorize="hasRole('ADMIN')">Administrator</span>
|
||||
<span class="role" sec:authorize="!hasRole('ADMIN')">Mitglied</span>
|
||||
</div>
|
||||
<svg style="margin-left:auto;color:var(--muted);width:18px;height:18px" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="mf-meta">
|
||||
<div class="lvl">LEVEL <b>12</b></div>
|
||||
<div class="xp">3250 / 5000 XP</div>
|
||||
<div class="mf-bar"><i style="width:65%"></i></div>
|
||||
</div>
|
||||
<div class="mf-streak">
|
||||
<span class="fire">🔥</span><span><b>STREAK</b><small>7 Tage in Folge</small></span>
|
||||
</div>
|
||||
|
||||
<div class="mf-brain">
|
||||
<svg viewBox="0 0 120 110" fill="none" stroke="var(--accent)" stroke-width="1.4">
|
||||
<path d="M60 12c-14-8-34-2-36 14-10 4-12 18-4 26-4 10 2 22 14 24 4 8 18 10 26 4 8 6 22 4 26-4 12-2 18-14 14-24 8-8 6-22-4-26-2-16-22-22-36-14z"/>
|
||||
<path d="M60 16v82M40 30c8 4 8 14 0 18M80 30c-8 4-8 14 0 18M34 60c10 0 14 8 14 16M86 60c-10 0-14 8-14 16M48 44h24M44 76h32"/>
|
||||
</svg>
|
||||
</div>
|
||||
</aside>
|
||||
<!-- ===== Sidebar (gemeinsames Fragment) ===== -->
|
||||
<aside th:replace="~{fragments/layout :: sidebar('dashboard')}"></aside>
|
||||
|
||||
<!-- ===== Topbar ===== -->
|
||||
<header class="mf-topbar">
|
||||
@@ -111,7 +51,9 @@
|
||||
<button class="mf-iconbtn" aria-label="Benachrichtigungen"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.7 21a2 2 0 0 1-3.4 0"/></svg></button>
|
||||
<div class="mf-search"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4-4"/></svg><input placeholder="Suche..."></div>
|
||||
<button class="mf-theme"></button>
|
||||
<a class="mf-iconbtn" href="/logout" aria-label="Logout" style="color:var(--danger)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg></a>
|
||||
<form th:action="@{/logout}" method="post" style="display:inline">
|
||||
<button type="submit" class="mf-iconbtn" aria-label="Logout" style="color:var(--danger)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg></button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -186,12 +128,12 @@
|
||||
const GAMES = [
|
||||
['MindMatch','brain','Trainiere dein Gedächtnis mit IT-Begriffen in einem klassischen Memory-Spiel.','/mindmatch'],
|
||||
['TechTacular','code','Das IT-Quizduell im Jeopardy-Stil – teste dein Wissen in verschiedenen Kategorien.','/techtacular'],
|
||||
['Dev Lab','lab','Das Entwicklerlabor bündelt Java, SQL, CSS, PHP, HTML, Git, REST und Regex.','/devlab'],
|
||||
['Syntax Saga','terminal','Interaktive IT-Geschichten mit Lückentexten – wie ein Textadventure zum Mitdenken.','/syntaxsaga'],
|
||||
['Code Escape Room','lock','Entkomme mit IT-Rätseln aus digitalen Räumen – sei schnell und clever.','/comingsoon'],
|
||||
['Service Clash','sword','Der chaotische Admin-Alltag als Spiel – meistere Anfragen & halte Systeme am Laufen!','/comingsoon'],
|
||||
['Bug Hunter','bug','Finde Fehler im Code, denke wie ein Debugger und löse knifflige Bugs.','/comingsoon'],
|
||||
['Netzwerker – Das Router-Rätselspiel','network','Verbinde Netzwerke, konfiguriere IPs und löse Routing-Herausforderungen.','/comingsoon'],
|
||||
['DevLab','lab','Das Entwicklerlabor bündelt Java, SQL, CSS, PHP, HTML, Git, REST und Regex.','/devlab'],
|
||||
['SyntaxSaga','terminal','Interaktive IT-Geschichten mit Lückentexten – wie ein Textadventure zum Mitdenken.','/syntaxsaga'],
|
||||
['CodeEscape','lock','Entkomme mit IT-Rätseln aus digitalen Räumen – sei schnell und clever.','/comingsoon'],
|
||||
['ServiceClash','sword','Der chaotische Admin-Alltag als Spiel – meistere Anfragen & halte Systeme am Laufen!','/comingsoon'],
|
||||
['BugHunter','bug','Finde Fehler im Code, denke wie ein Debugger und löse knifflige Bugs.','/comingsoon'],
|
||||
['NetWorker','network','Verbinde Netzwerke, konfiguriere IPs und löse Routing-Herausforderungen.','/comingsoon'],
|
||||
['FinalFlux','trophy','Dein Power-Modul für die Prüfung – gezielt lernen, strukturiert trainieren, sicher bestehen.','/finalflux']
|
||||
];
|
||||
document.getElementById('grid').innerHTML = GAMES.map(([t,ic,d,href])=>`
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
</div>
|
||||
<div class="dlg-header-tools">
|
||||
<button type="button" class="mf-theme"></button>
|
||||
<a href="/logout" class="dlg-logout">Logout</a>
|
||||
<form th:action="@{/logout}" method="post" style="display:inline">
|
||||
<button type="submit" class="dlg-logout" style="background:none;border:0;cursor:pointer;font:inherit">Logout</button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -41,12 +41,14 @@
|
||||
<header class="mf-topbar dl-topbar">
|
||||
<div class="mf-hello">
|
||||
<p class="mf-eyebrow">Entwicklerlabor</p>
|
||||
<h1>Dev Lab</h1>
|
||||
<h1>DevLab</h1>
|
||||
<p>Ein zentraler Hub für die Spiele aus Syntax, Debugging und visueller Praxis.</p>
|
||||
</div>
|
||||
<div class="mf-tools">
|
||||
<button type="button" class="mf-theme"></button>
|
||||
<a class="mf-iconbtn" href="/logout" aria-label="Logout" style="color:var(--danger)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg></a>
|
||||
<form th:action="@{/logout}" method="post" style="display:inline">
|
||||
<button type="submit" class="mf-iconbtn" aria-label="Logout" style="color:var(--danger)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg></button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" data-theme="dark" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mindflux – Fehler</title>
|
||||
<link rel="stylesheet" href="/css/theme.css">
|
||||
<script src="/js/theme.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mf-theme-float"><button class="mf-theme"></button></div>
|
||||
|
||||
<div class="mf-container" style="max-width:640px; margin:10vh auto 0;">
|
||||
<div class="mf-panel" style="text-align:center; padding:2.5rem 2rem;">
|
||||
<div style="font-size:2.6rem; margin-bottom:.6rem;">⚡</div>
|
||||
<h1 style="color:var(--heading); font-size:1.6rem; font-weight:800; margin-bottom:.4rem;">
|
||||
Ups – da ist etwas schiefgelaufen
|
||||
</h1>
|
||||
<p style="color:var(--muted); margin-bottom:1rem;">
|
||||
<span th:if="${status != null}" th:text="'Fehlercode ' + ${status}">Fehlercode</span>
|
||||
<span th:unless="${status != null}">Unerwarteter Fehler</span>
|
||||
</p>
|
||||
<p th:if="${friendlyMessage != null}" th:text="${friendlyMessage}"
|
||||
style="color:var(--text); margin-bottom:1.4rem;"></p>
|
||||
<a th:href="@{/dashboard}" class="mf-btn">Zum Dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -16,9 +16,9 @@
|
||||
<button class="mf-theme"></button>
|
||||
</div>
|
||||
<h1>FinalFlux</h1>
|
||||
<p>AP1 Informatik nach aktueller IHK-Ausbildungsordnung.</p>
|
||||
<p>AP1 & AP2 nach aktueller IHK-Ausbildungsordnung – die gesamte Fachinformatiker-Ausbildung.</p>
|
||||
|
||||
<nav class="finalflux-nav" aria-label="FinalFlux AP1 Navigation">
|
||||
<nav class="finalflux-nav" aria-label="FinalFlux Navigation">
|
||||
<section>
|
||||
<h2>Grundlagen</h2>
|
||||
<a href="/finalflux/ap1/zahlensysteme.html">Zahlensysteme & Speicher</a>
|
||||
@@ -58,6 +58,16 @@
|
||||
<a href="/finalflux/wirtschaft/harvard_konzept.html">Harvard-Konzept</a>
|
||||
<a href="/finalflux/wirtschaft/win_win_strategie.html">Win-Win-Strategie</a>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>AP2 Anwendungsentwicklung</h2>
|
||||
<a href="/finalflux/ap2-fiae/entwurfsmuster.html">Entwurfsmuster</a>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>AP2 Systemintegration</h2>
|
||||
<a href="/finalflux/ap2-fisi/hochverfuegbarkeit.html">Hochverfügbarkeit</a>
|
||||
</section>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Gemeinsame Layout-Fragmente: App-Sidebar, Profil-Tab-Leiste, Footer.
|
||||
Einbinden mit th:replace="~{fragments/layout :: sidebar('dashboard')}" usw. -->
|
||||
<html lang="de" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<body>
|
||||
|
||||
<!-- ===== App-Sidebar (Dashboard-Shell). 'active' markiert den aktuellen Eintrag.
|
||||
Die XP/Streak-Widgets erscheinen nur, wenn die Seite 'overall' (ProgressData) liefert. ===== -->
|
||||
<aside class="mf-sidebar" th:fragment="sidebar(active)">
|
||||
<a th:href="@{/dashboard}" class="mf-logo">
|
||||
<span class="mark"></span>
|
||||
<span class="txt"><b>MINDFLUX</b><span>KNOWLEDGE. CODE. WIN.</span></span>
|
||||
</a>
|
||||
|
||||
<nav class="mf-nav">
|
||||
<a th:href="@{/dashboard}" th:classappend="${active == 'dashboard'} ? 'active'">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>
|
||||
Dashboard
|
||||
</a>
|
||||
<a th:href="@{/admin}" sec:authorize="hasRole('ADMIN')" th:classappend="${active == 'admin'} ? 'active'">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l8 4v6c0 5-3.5 8-8 10-4.5-2-8-5-8-10V6z"/><path d="M9 12l2 2 4-4"/></svg>
|
||||
Admin-Dashboard
|
||||
</a>
|
||||
<a th:href="@{/profile}" th:classappend="${active == 'profil'} ? 'active'">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4 3.6-6.5 8-6.5S20 17 20 21"/></svg>
|
||||
Profil
|
||||
</a>
|
||||
<a th:href="@{/profile/knowledge}" th:classappend="${active == 'knowledge'} ? 'active'">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3 3 15 0 18M12 3c-3 3-3 15 0 18"/></svg>
|
||||
Knowledge Core
|
||||
</a>
|
||||
<a th:href="@{/progress}" th:classappend="${active == 'statistiken'} ? 'active'">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 20V10M10 20V4M16 20v-8M22 20H2"/></svg>
|
||||
Statistiken
|
||||
</a>
|
||||
<a th:href="@{/profile/achievements}" th:classappend="${active == 'erfolge'} ? 'active'">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="9" r="6"/><path d="M9 14l-2 8 5-3 5 3-2-8"/></svg>
|
||||
Erfolge
|
||||
</a>
|
||||
<a th:href="@{/profile/settings}" th:classappend="${active == 'einstellungen'} ? 'active'">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3.2"/><path d="M19 12a7 7 0 0 0-.1-1l2-1.6-2-3.4-2.4 1a7 7 0 0 0-1.7-1L14.5 2h-4l-.3 2.5a7 7 0 0 0-1.7 1l-2.4-1-2 3.4 2 1.6a7 7 0 0 0 0 2l-2 1.6 2 3.4 2.4-1a7 7 0 0 0 1.7 1l.3 2.5h4l.3-2.5a7 7 0 0 0 1.7-1l2.4 1 2-3.4-2-1.6c.1-.3.1-.7.1-1z"/></svg>
|
||||
Einstellungen
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<!-- Profil-Shortcut (ohne Dropdown-Pfeil – es gibt kein Dropdown) -->
|
||||
<a th:href="@{/profile}" class="mf-profile" style="text-decoration:none">
|
||||
<div class="row">
|
||||
<span class="mf-avatar" th:text="${#authentication.name != null ? #authentication.name.substring(0,1).toUpperCase() : 'U'}">A</span>
|
||||
<div>
|
||||
<b sec:authentication="name">Benutzer</b>
|
||||
<span class="role" sec:authorize="hasRole('ADMIN')">Administrator</span>
|
||||
<span class="role" sec:authorize="!hasRole('ADMIN')">Mitglied</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="mf-meta" th:if="${overall != null}">
|
||||
<div class="lvl">LEVEL <b th:text="${overall.userLevel}">1</b></div>
|
||||
<div class="xp" th:text="${overall.currentXp} + ' / ' + ${overall.xpForNextLevel} + ' XP'">0 / 1000 XP</div>
|
||||
<div class="mf-bar"><i th:style="'width:' + ${overall.progressPercent} + '%'"></i></div>
|
||||
</div>
|
||||
<div class="mf-streak" th:if="${overall != null}">
|
||||
<span class="fire">🔥</span>
|
||||
<span><b>STREAK</b><small th:text="${overall.streakDays} + (${overall.streakDays == 1} ? ' Tag' : ' Tage') + ' in Folge'">0 Tage in Folge</small></span>
|
||||
</div>
|
||||
|
||||
<div class="mf-brain">
|
||||
<svg viewBox="0 0 120 110" fill="none" stroke="var(--accent)" stroke-width="1.4">
|
||||
<path d="M60 12c-14-8-34-2-36 14-10 4-12 18-4 26-4 10 2 22 14 24 4 8 18 10 26 4 8 6 22 4 26-4 12-2 18-14 14-24 8-8 6-22-4-26-2-16-22-22-36-14z"/>
|
||||
<path d="M60 16v82M40 30c8 4 8 14 0 18M80 30c-8 4-8 14 0 18M34 60c10 0 14 8 14 16M86 60c-10 0-14 8-14 16M48 44h24M44 76h32"/>
|
||||
</svg>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- ===== Profilbereich: Tab-Leiste, auf ALLEN Unterseiten identisch ===== -->
|
||||
<nav class="mf-tab-nav" th:fragment="profileTabs(active)">
|
||||
<a th:href="@{/profile}" class="mf-tab" th:classappend="${active == 'profil'} ? ' active'">Profil</a>
|
||||
<a th:href="@{/progress}" class="mf-tab" th:classappend="${active == 'statistiken'} ? ' active'">Statistiken</a>
|
||||
<a th:href="@{/profile/achievements}" class="mf-tab" th:classappend="${active == 'erfolge'} ? ' active'">Erfolge</a>
|
||||
<a th:href="@{/soziales}" class="mf-tab" th:classappend="${active == 'soziales'} ? ' active'">Soziales</a>
|
||||
<a th:href="@{/profile/settings}" class="mf-tab" th:classappend="${active == 'einstellungen'} ? ' active'">Einstellungen</a>
|
||||
</nav>
|
||||
|
||||
<!-- ===== Footer ===== -->
|
||||
<footer class="mf-footer" th:fragment="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>
|
||||
@@ -59,6 +59,8 @@
|
||||
|
||||
<div th:if="${param.registerError}" class="mf-alert err">Benutzername bereits vergeben.</div>
|
||||
<div th:if="${param.passwordMismatch}" class="mf-alert err">Die Passwörter stimmen nicht überein. Bitte erneut eingeben.</div>
|
||||
<div th:if="${param.passwordPolicy}" class="mf-alert err">Das Passwort muss mindestens 8 Zeichen lang sein.</div>
|
||||
<div th:if="${param.emailInvalid}" class="mf-alert err">Bitte gib eine gültige E-Mail-Adresse an.</div>
|
||||
|
||||
<form th:action="@{/register}" method="post">
|
||||
<div class="mf-field">
|
||||
@@ -71,7 +73,7 @@
|
||||
</div>
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="reg-password">Passwort</label>
|
||||
<input id="reg-password" class="mf-input" type="password" name="password" placeholder="Passwort" required>
|
||||
<input id="reg-password" class="mf-input" type="password" name="password" placeholder="Passwort (min. 8 Zeichen)" required minlength="8">
|
||||
</div>
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="reg-password2">Passwort wiederholen</label>
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login – Mindflux</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 400px;
|
||||
margin: 50px auto;
|
||||
padding: 2rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
label {
|
||||
display: block;
|
||||
margin: 1rem 0 0.3rem;
|
||||
}
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
button {
|
||||
margin-top: 1rem;
|
||||
width: 100%;
|
||||
padding: 0.7rem;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.message {
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Login</h2>
|
||||
|
||||
<form th:action="@{/login}" method="post">
|
||||
<label for="username">Benutzername</label>
|
||||
<input type="text" id="username" name="username" required th:value="${param.username}"/>
|
||||
|
||||
<label for="password">Passwort</label>
|
||||
<input type="password" id="password" name="password" required/>
|
||||
|
||||
<div class="message error" th:if="${param.error}">
|
||||
Benutzername oder Passwort sind falsch.
|
||||
</div>
|
||||
|
||||
<div class="message" th:if="${param.logout}">
|
||||
Du hast dich erfolgreich abgemeldet.
|
||||
</div>
|
||||
|
||||
<button type="submit">Einloggen</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -18,7 +18,9 @@
|
||||
<h1 class="mm-title">MindMatch</h1>
|
||||
<div class="mm-header-tools">
|
||||
<button type="button" class="mf-theme"></button>
|
||||
<a href="/logout" class="mm-logout">Logout</a>
|
||||
<form th:action="@{/logout}" method="post" style="display:inline">
|
||||
<button type="submit" class="mm-logout" style="background:none;border:0;cursor:pointer;font:inherit">Logout</button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
<link rel="stylesheet" href="/css/theme.css">
|
||||
<script src="/js/theme.js"></script>
|
||||
<style>
|
||||
.mf-tab-nav { display:flex; flex-wrap:wrap; gap:.4rem; margin-bottom:1.4rem; }
|
||||
.mf-tab { padding:.55rem .95rem; border-radius:10px; border:1px solid var(--border); color:var(--muted); text-decoration:none; font-size:.85rem; font-weight:700; transition:all .18s ease; }
|
||||
.mf-tab:hover { color:var(--text); background:var(--surface-2); }
|
||||
.mf-tab.active { color:var(--accent-ink); background:linear-gradient(100deg,var(--accent),var(--accent-2)); box-shadow:0 0 18px var(--glow-s); border-color:transparent; }
|
||||
.mf-profile-pic { display:flex; justify-content:center; margin-bottom:1.3rem; }
|
||||
.mf-profile-pic img { width:140px; height:140px; border-radius:50%; object-fit:cover; border:2px solid var(--border-accent); box-shadow:0 0 22px var(--glow-w); }
|
||||
.mf-success { margin-bottom:1.2rem; transition:opacity 1.5s ease; }
|
||||
@@ -32,13 +28,7 @@
|
||||
<h1 style="color:var(--heading); font-size:1.9rem; font-weight:800; margin:.3rem 0 .25rem;">👤 Mein Profil</h1>
|
||||
<p style="color:var(--muted); margin-bottom:1.4rem;">Alles rund um dich und deinen Fortschritt</p>
|
||||
|
||||
<nav class="mf-tab-nav">
|
||||
<a th:href="@{/profile}" class="mf-tab active">Profil</a>
|
||||
<a th:href="@{/progress}" class="mf-tab">Fortschritt</a>
|
||||
<a th:href="@{/profile/achievements}" class="mf-tab">Erfolge</a>
|
||||
<a th:href="@{/soziales}" class="mf-tab">Soziales</a>
|
||||
<a th:href="@{/profile/settings}" class="mf-tab">Einstellungen</a>
|
||||
</nav>
|
||||
<nav th:replace="~{fragments/layout :: profileTabs('profil')}"></nav>
|
||||
|
||||
<!-- Erfolgsmeldung -->
|
||||
<div th:if="${message}" class="mf-panel accent mf-success" id="successMessage">
|
||||
|
||||
@@ -33,12 +33,14 @@
|
||||
<div class="mf-container">
|
||||
|
||||
<div class="mf-page-head">
|
||||
<a href="/profile" class="mf-back">⟵ Zurück zum Profil</a>
|
||||
<a th:href="@{/dashboard}" class="mf-back">⟵ Zurück zum Dashboard</a>
|
||||
</div>
|
||||
<span class="mf-eyebrow">Dein Fortschritt</span>
|
||||
<h1 style="color:var(--heading); font-size:2.1rem; font-weight:800; margin:.3rem 0 .25rem;">Dein Fortschritt</h1>
|
||||
<span class="mf-eyebrow">Deine Statistiken</span>
|
||||
<h1 style="color:var(--heading); font-size:2.1rem; font-weight:800; margin:.3rem 0 .25rem;">Deine Statistiken</h1>
|
||||
<p style="color:var(--muted); margin-bottom:1.4rem;">Bleib am Ball – jeder Schritt zählt!</p>
|
||||
|
||||
<nav th:replace="~{fragments/layout :: profileTabs('statistiken')}"></nav>
|
||||
|
||||
<!-- Gesamtfortschritt -->
|
||||
<section class="mf-panel accent" style="margin-bottom:1.2rem;">
|
||||
<div class="mf-progress-summary">
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" data-theme="dark" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mindflux – Registrieren</title>
|
||||
<link rel="stylesheet" href="/css/theme.css">
|
||||
<script src="/js/theme.js"></script>
|
||||
<style>
|
||||
.mf-authlogo { display:flex; flex-direction:column; align-items:center; gap:.5rem; margin-bottom:1.4rem; text-align:center; }
|
||||
.mf-authlogo .mark { width:60px; height:60px; background:var(--accent);
|
||||
-webkit-mask:url("/img/mindflux-emblem.png") center/contain no-repeat; mask:url("/img/mindflux-emblem.png") center/contain no-repeat;
|
||||
filter:drop-shadow(0 0 12px var(--glow-s)); }
|
||||
.mf-authlogo b { color:var(--accent); font-weight:800; letter-spacing:.16em; font-size:1.15rem; text-shadow:0 0 14px var(--glow-s); }
|
||||
.mf-authlogo span { color:var(--muted); font-size:.62rem; letter-spacing:.24em; }
|
||||
.mf-cardbox h2 { color:var(--heading); font-size:1.15rem; font-weight:800; margin-bottom:1.1rem; text-align:center; }
|
||||
.mf-cardbox .mf-btn { width:100%; }
|
||||
.mf-alert { padding:.7rem .9rem; border-radius:10px; font-size:.86rem; margin-bottom:1rem; }
|
||||
.mf-alert.err { color:var(--danger); border:1px solid var(--danger); background:rgba(255,95,107,.08); }
|
||||
.mf-alert.ok { color:var(--accent); border:1px solid var(--border-accent); background:var(--surface-2); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mf-theme-float"><button class="mf-theme"></button></div>
|
||||
|
||||
<div class="mf-center">
|
||||
<div class="mf-cardbox">
|
||||
<div class="mf-authlogo">
|
||||
<span class="mark"></span>
|
||||
<b>MINDFLUX</b>
|
||||
<span>REGISTRIERUNG</span>
|
||||
</div>
|
||||
|
||||
<h2>📝 Account erstellen</h2>
|
||||
|
||||
<!-- Fehler anzeigen -->
|
||||
<div th:if="${error}" class="mf-alert err">
|
||||
<span th:text="${error}"></span>
|
||||
</div>
|
||||
|
||||
<!-- Erfolgreiche Registrierung anzeigen -->
|
||||
<div th:if="${param.registerSuccess}" class="mf-alert ok">
|
||||
Registrierung erfolgreich! Du kannst dich jetzt einloggen.
|
||||
</div>
|
||||
|
||||
<form th:action="@{/register}" method="post">
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="username">Benutzername</label>
|
||||
<input id="username" class="mf-input" type="text" name="username" placeholder="Benutzername" required>
|
||||
</div>
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="password">Passwort</label>
|
||||
<input id="password" class="mf-input" type="password" name="password" placeholder="Passwort" required>
|
||||
</div>
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="email">E-Mail</label>
|
||||
<input id="email" class="mf-input" type="email" name="email" placeholder="E-Mail" required>
|
||||
</div>
|
||||
<button type="submit" class="mf-btn">Registrieren</button>
|
||||
</form>
|
||||
|
||||
<p style="text-align:center;margin-top:1.1rem">
|
||||
<a href="/" class="mf-back">⟵ Zurück zum Login</a>
|
||||
</p>
|
||||
</div>
|
||||
</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>
|
||||
@@ -23,50 +23,33 @@
|
||||
<div class="mf-container">
|
||||
|
||||
<div class="mf-page-head">
|
||||
<a th:href="@{/profile}" class="mf-back">⟵ Zurück zum Profil</a>
|
||||
<a th:href="@{/dashboard}" class="mf-back">⟵ Zurück zum Dashboard</a>
|
||||
</div>
|
||||
<span class="mf-eyebrow">Einstellungen</span>
|
||||
<h1 style="color:var(--heading); font-size:1.9rem; font-weight:800; margin:.3rem 0 .25rem;">⚙️ Einstellungen</h1>
|
||||
<p style="color:var(--muted); margin-bottom:1.4rem;">Passe Mindflux nach deinen Wünschen an</p>
|
||||
|
||||
<nav th:replace="~{fragments/layout :: profileTabs('einstellungen')}"></nav>
|
||||
|
||||
<!-- Flash-Meldungen (z. B. nach Passwortänderung) -->
|
||||
<div th:if="${message}" class="mf-panel accent mf-success" style="margin-bottom:1.2rem;">
|
||||
<p th:text="${message}" style="color:var(--accent); margin:0;"></p>
|
||||
</div>
|
||||
<div th:if="${error}" class="mf-panel mf-error" style="margin-bottom:1.2rem;">
|
||||
<p th:text="${error}" style="color:#c0392b; margin:0;"></p>
|
||||
<p th:text="${error}" style="color:var(--danger); margin:0;"></p>
|
||||
</div>
|
||||
|
||||
<!-- Theme-Einstellung (Dummy) -->
|
||||
<!-- Theme-Einstellung (an theme.js gekoppelt, wird in localStorage gespeichert) -->
|
||||
<section class="mf-panel" style="margin-bottom:1.2rem;">
|
||||
<h2 class="mf-section-title">Theme wechseln</h2>
|
||||
<div class="mf-field">
|
||||
<label class="mf-label">Modus auswählen:</label>
|
||||
<select class="mf-select">
|
||||
<option>Standard (Dark)</option>
|
||||
<option>Hell (Light)</option>
|
||||
<label class="mf-label" for="theme-select">Modus auswählen:</label>
|
||||
<select class="mf-select" id="theme-select">
|
||||
<option value="dark">Standard (Dark)</option>
|
||||
<option value="light">Hell (Light)</option>
|
||||
</select>
|
||||
</div>
|
||||
<small class="mf-hint">Hinweis: Nutze den Umschalter oben rechts, um zwischen Dark (Grün) und Light (Magenta) zu wechseln.</small>
|
||||
</section>
|
||||
|
||||
<!-- Spracheinstellung (Dummy) -->
|
||||
<section class="mf-panel" style="margin-bottom:1.2rem;">
|
||||
<h2 class="mf-section-title">Sprache</h2>
|
||||
<div class="mf-field">
|
||||
<label class="mf-label">Sprache auswählen:</label>
|
||||
<select class="mf-select">
|
||||
<option>Deutsch</option>
|
||||
<option>Englisch</option>
|
||||
</select>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Benachrichtigungen (Dummy) -->
|
||||
<section class="mf-panel" style="margin-bottom:1.2rem;">
|
||||
<h2 class="mf-section-title">Benachrichtigungen</h2>
|
||||
<label class="mf-check"><input type="checkbox" checked> E-Mail-Benachrichtigungen erhalten</label>
|
||||
<label class="mf-check"><input type="checkbox"> Erinnerungen an Lernziele aktivieren</label>
|
||||
<small class="mf-hint">Die Auswahl gilt sofort und wird auf diesem Gerät gespeichert.</small>
|
||||
</section>
|
||||
|
||||
<!-- Passwort ändern -->
|
||||
@@ -88,6 +71,18 @@
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Theme-Select mit dem zentralen Umschalter (theme.js) koppeln.
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var select = document.getElementById('theme-select');
|
||||
if (!select || !window.MindfluxTheme) return;
|
||||
select.value = window.MindfluxTheme.current() === 'light' ? 'light' : 'dark';
|
||||
select.addEventListener('change', function () {
|
||||
window.MindfluxTheme.set(select.value);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<footer class="mf-footer">
|
||||
<a href="#">Support</a>
|
||||
<a href="#">Feedback</a>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" data-theme="dark">
|
||||
<html lang="de" data-theme="dark" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@@ -21,9 +21,11 @@
|
||||
<div class="mf-container">
|
||||
|
||||
<div class="mf-page-head">
|
||||
<a href="/profile" class="mf-back">⟵ Zurück zum Profil</a>
|
||||
<a th:href="@{/dashboard}" class="mf-back">⟵ Zurück zum Dashboard</a>
|
||||
</div>
|
||||
|
||||
<nav th:replace="~{fragments/layout :: profileTabs('soziales')}"></nav>
|
||||
|
||||
<div class="mf-panel accent mf-soziales">
|
||||
<h1>„Straßen? Wo wir hingehen, brauchen wir keine Straßen!“ 🚀</h1>
|
||||
<p>Das soziale Netzwerk für Mindflux-User befindet sich noch in Entwicklung.<br>
|
||||
|
||||
@@ -13,10 +13,12 @@
|
||||
<div class="ss-shell">
|
||||
<header class="ss-header">
|
||||
<a href="/dashboard" class="ss-back">⟵ Dashboard</a>
|
||||
<h1 class="ss-title">Syntax Saga</h1>
|
||||
<h1 class="ss-title">SyntaxSaga</h1>
|
||||
<div class="ss-header-tools">
|
||||
<button type="button" class="mf-theme"></button>
|
||||
<a href="/logout" class="ss-logout">Logout</a>
|
||||
<form th:action="@{/logout}" method="post" style="display:inline">
|
||||
<button type="submit" class="ss-logout" style="background:none;border:0;cursor:pointer;font:inherit">Logout</button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
<h1 class="tt-title">TechTacular</h1>
|
||||
<div class="tt-header-tools">
|
||||
<button type="button" class="mf-theme"></button>
|
||||
<a href="/logout" class="tt-logout">Logout</a>
|
||||
<form th:action="@{/logout}" method="post" style="display:inline">
|
||||
<button type="submit" class="tt-logout" style="background:none;border:0;cursor:pointer;font:inherit">Logout</button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" data-theme="dark" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Benutzer anlegen</title>
|
||||
<link rel="stylesheet" href="/css/theme.css">
|
||||
<script src="/js/theme.js"></script>
|
||||
<style>
|
||||
.mf-cardbox { max-width:480px; }
|
||||
.mf-cardbox h1 { color:var(--heading); font-size:1.3rem; font-weight:800; margin-bottom:1.3rem; text-align:center; }
|
||||
.mf-cardbox .mf-btn { width:100%; margin-top:.4rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mf-theme-float"><button class="mf-theme"></button></div>
|
||||
|
||||
<div class="mf-center">
|
||||
<div class="mf-cardbox">
|
||||
<h1>Neuen Benutzer erstellen</h1>
|
||||
|
||||
<form th:action="@{/users/save}" th:object="${user}" method="post">
|
||||
<!-- CSRF-Token für Spring Security -->
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
|
||||
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="username">Benutzername</label>
|
||||
<input id="username" class="mf-input" type="text" th:field="*{username}" placeholder="Benutzername" required />
|
||||
</div>
|
||||
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="password">Passwort</label>
|
||||
<input id="password" class="mf-input" type="password" th:field="*{password}" placeholder="Passwort" required />
|
||||
</div>
|
||||
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="email">E-Mail</label>
|
||||
<input id="email" class="mf-input" type="email" th:field="*{email}" placeholder="E-Mail" required />
|
||||
</div>
|
||||
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="role">Rolle</label>
|
||||
<select id="role" class="mf-select" th:field="*{role}">
|
||||
<option value="USER">USER</option>
|
||||
<option value="ADMIN">ADMIN</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Optionales Profilbild-Feld, falls gewünscht -->
|
||||
<!--
|
||||
<div class="mf-field">
|
||||
<label class="mf-label" for="profilePicture">Profilbild-URL</label>
|
||||
<input id="profilePicture" class="mf-input" type="text" th:field="*{profilePicture}" placeholder="Profilbild-URL" />
|
||||
</div>
|
||||
-->
|
||||
|
||||
<button type="submit" class="mf-btn">Speichern</button>
|
||||
</form>
|
||||
</div>
|
||||
</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>
|
||||
@@ -1,46 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" data-theme="dark" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Benutzer erfolgreich erstellt</title>
|
||||
<link rel="stylesheet" href="/css/theme.css">
|
||||
<script src="/js/theme.js"></script>
|
||||
<style>
|
||||
.mf-cardbox { max-width:480px; text-align:center; }
|
||||
.mf-check { width:64px; height:64px; margin:0 auto 1rem; color:var(--accent); filter:drop-shadow(0 0 10px var(--glow-s)); }
|
||||
.mf-cardbox h1 { color:var(--heading); font-size:1.3rem; font-weight:800; margin-bottom:.6rem; }
|
||||
.mf-cardbox p { color:var(--muted); font-size:.92rem; line-height:1.55; margin-bottom:1.4rem; }
|
||||
.mf-actions { display:flex; gap:.7rem; justify-content:center; flex-wrap:wrap; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mf-theme-float"><button class="mf-theme"></button></div>
|
||||
|
||||
<div class="mf-center">
|
||||
<div class="mf-cardbox">
|
||||
<svg class="mf-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"/><path d="M8 12l3 3 5-6"/>
|
||||
</svg>
|
||||
<h1>Benutzer gespeichert!</h1>
|
||||
<p>Der neue Benutzer wurde erfolgreich in der Datenbank gespeichert.</p>
|
||||
|
||||
<div class="mf-actions">
|
||||
<a href="/users/form" class="mf-btn">Neuen Benutzer anlegen</a>
|
||||
<a href="/api/users" class="mf-btn outline">Alle Benutzer anzeigen (JSON)</a>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
Reference in New Issue
Block a user