@@ -63,30 +60,8 @@
{% endif %}
-
-
-
-
-
- {% for course in courses %}
- -
-
-
- {% endfor %}
-
-
-
-
-
-
+ {# ── Password Form ─────────────────────────────────────────── #}
@@ -100,68 +75,66 @@
autofocus
class="w-full px-4 py-3 rounded-md bg-background border border-border text-text placeholder-muted focus:outline-none focus:ring-2 focus:ring-primary"
/>
-
-
+ {# ── Deck Cards ────────────────────────────────────────────── #}
{% if decks %}
-
+
{% for deck in decks %}
{% endfor %}
-
+
{% else %}
No decks unlocked yet.
{% endif %}
-
-
-
-
-
+{% endblock body %}
diff --git a/app/templates/macros/ui.html b/app/templates/macros/ui.html
new file mode 100644
index 0000000..79db418
--- /dev/null
+++ b/app/templates/macros/ui.html
@@ -0,0 +1,133 @@
+{#
+ Reusable UI macros for Tutortool templates.
+ Usage: {% from "macros/ui.html" import flash_messages, styled_field, text_input %}
+#}
+
+
+{# Renders all flashed messages with colour-coded styling. #}
+{% macro flash_messages() %}
+ {% with messages = get_flashed_messages(with_categories=true) %}
+ {% if messages %}
+
+ {% for category, message in messages %}
+ {% if category == 'error' %}
+ {% set alert_class = 'bg-red-900 border-red-400 text-red-100' %}
+ {% elif category == 'expired' %}
+ {% set alert_class = 'bg-orange-900 border-orange-400 text-orange-100' %}
+ {% else %}
+ {% set alert_class = 'bg-green-900 border-green-400 text-green-100' %}
+ {% endif %}
+
+ {{ message }}
+
+ {% endfor %}
+
+ {% endif %}
+ {% endwith %}
+{% endmacro %}
+
+
+{#
+ Renders a WTForms field with a label and standard Tailwind styling.
+ Pass extra_kwargs as a dict for additional HTML attributes (e.g. type, multiple).
+#}
+{% macro styled_field(field, extra_kwargs={}) %}
+
+
+ {{ field(
+ class="w-full rounded-lg p-3 bg-background border border-border text-text placeholder-muted focus:outline-none focus:ring-2 focus:ring-primary",
+ **extra_kwargs
+ ) }}
+ {% for error in field.errors %}
+
{{ error }}
+ {% endfor %}
+
+{% endmacro %}
+
+
+{#
+ Renders a plain
(not WTForms) with standard styling.
+ `type` defaults to 'text'.
+#}
+{% macro text_input(name, label, placeholder='', type='text', required=true, autofocus=false) %}
+
+
+
+
+{% endmacro %}
+
+
+{# Renders a delete button wrapped in a form. #}
+{% macro delete_button(action_url, label='Delete') %}
+
+{% endmacro %}
+
+
+{# Course-switcher dropdown (used in admin and index pages). #}
+{% macro course_switcher(courses, active_course_name, switch_url_prefix) %}
+
+
+ {{ active_course_name }}
+
+
+
+
+ {% for course in courses %}
+
+ {% endfor %}
+
+
+
+
+{% endmacro %}
diff --git a/app/templates/register.html b/app/templates/register.html
index 02e7482..60bda3c 100644
--- a/app/templates/register.html
+++ b/app/templates/register.html
@@ -1,61 +1,42 @@
-
-
-
-
-
-
Register for Tutortool
-
-
-
-
-
-
-
Create an Account
-
Choose a username to get started.
-
+{% extends "centered_layout.html" %}
+{% from "macros/ui.html" import flash_messages, text_input %}
- {% with messages = get_flashed_messages(with_categories=true) %}
- {% if messages %}
-
- {% for category, message in messages %}
- {% set alert_class = 'bg-red-900 border-red-400 text-red-100' if category == 'error' else 'bg-green-900 border-green-400 text-green-100' %}
-
- {{ message }}
-
- {% endfor %}
-
- {% endif %}
- {% endwith %}
+{% set title = 'Register – Tutortool' %}
-
+ {{ flash_messages() }}
-
- Already have an account? Log In
-
+
+
+
+ Already have an account?
+ Log In
+
+{% endblock %}
diff --git a/app/templates/set_token.html b/app/templates/set_token.html
index 3d2b81f..0833c82 100644
--- a/app/templates/set_token.html
+++ b/app/templates/set_token.html
@@ -1,47 +1,26 @@
-
-
-
-
-
-
Register for Tutortool
-
-
-
-
-
-
-
Login
-
+{% extends "centered_layout.html" %}
+{% from "macros/ui.html" import flash_messages, text_input %}
- {% with messages = get_flashed_messages(with_categories=true) %}
- {% if messages %}
-
- {% for category, message in messages %}
- {% set alert_class = 'bg-red-900 border-red-400 text-red-100' if category == 'error' else 'bg-green-900 border-green-400 text-green-100' %}
-
- {{ message }}
-
- {% endfor %}
-
- {% endif %}
- {% endwith %}
-
-
+{% set title = 'Login – Tutortool' %}
-
- Do not have an Account? Create one
-
-
-
-
+{% block card_content %}
+
+
Login
+
+ {{ flash_messages() }}
+
+
+
+
+ Do not have an Account?
+ Create one
+
+{% endblock %}
diff --git a/docker-compose.yml b/docker-compose.yml
index 29b375f..0d4a7ab 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -69,8 +69,9 @@ services:
- ./grafana/provisioning:/etc/grafana/provisioning
environment:
- GF_USERS_ALLOW_SIGN_UP=false
- # Only allow access from localhost/reverse proxy
- - GF_SERVER_ROOT_URL=https://tutor.cato447.de/dashboard
+ - GF_SERVER_ROOT_URL=https://tutor.cato447.de/dashboard/
+ - GF_SERVER_SERVE_FROM_SUB_PATH=true
+ - GF_SECURITY_ALLOW_EMBEDDING=true
depends_on:
- prometheus
- db