From 7a4a2b5fe60b13bf8ded5f9e932f75729e042f99 Mon Sep 17 00:00:00 2001 From: Bkolb Date: Fri, 3 Apr 2026 15:06:58 +0200 Subject: [PATCH] Kursliste und Kurs-Seiten --- app/flask-postgres/app/app.py | 110 ++++++++++++++++++ app/flask-postgres/app/config.py | 10 +- app/flask-postgres/app/permissions.py | 23 +++- app/flask-postgres/app/templates/base.html | 6 + .../app/templates/course/A1_page1.html | 16 +++ .../app/templates/course/A1_page2.html | 16 +++ .../app/templates/course/B1_page1.html | 16 +++ .../app/templates/course/B1_page2.html | 16 +++ .../app/templates/course_list.html | 22 ++++ .../app/templates/course_video.html | 17 +++ app/flask-postgres/styles/site.css | 24 ++++ 11 files changed, 270 insertions(+), 6 deletions(-) create mode 100644 app/flask-postgres/app/templates/course/A1_page1.html create mode 100644 app/flask-postgres/app/templates/course/A1_page2.html create mode 100644 app/flask-postgres/app/templates/course/B1_page1.html create mode 100644 app/flask-postgres/app/templates/course/B1_page2.html create mode 100644 app/flask-postgres/app/templates/course_list.html create mode 100644 app/flask-postgres/app/templates/course_video.html diff --git a/app/flask-postgres/app/app.py b/app/flask-postgres/app/app.py index 45a1c42..65b9197 100644 --- a/app/flask-postgres/app/app.py +++ b/app/flask-postgres/app/app.py @@ -210,7 +210,45 @@ def register_visit(route_name: str) -> int: conn.close() return count +def get_available_courses_for_user(): + mandant_level = session.get("mandant_level") + if mandant_level is None: + current_mandant_id = session.get("mandant_id") + + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT level + FROM mandant + WHERE id = %s + """, (current_mandant_id,)) + row = cur.fetchone() + + cur.close() + conn.close() + + mandant_level = row[0] if row else 0 + session["mandant_level"] = mandant_level + + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT id, code, title, description, video_file, min_level, sort_order + FROM course + WHERE is_active = TRUE + AND min_level <= %s + ORDER BY sort_order, code + """, (mandant_level,)) + + courses = fetchall_dict(cur) + + cur.close() + conn.close() + + return courses @@ -941,4 +979,76 @@ def useradmin_user_edit(user_id): form_error=form_error, success_message=success_message, **get_current_user() + ) + +@app.route("/courses") +@login_required +def course_list(): + courses = get_available_courses_for_user() + + return render_template( + "course_list.html", + page_title="Kurse", + active_page="courses", + courses=courses, + **get_current_user() + ) + +@app.route("/course/") +@login_required +def course_start(course_id): + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT * + FROM course + WHERE id = %s + """, (course_id,)) + course = fetchone_dict(cur) + + cur.close() + conn.close() + + return render_template( + "course_video.html", + course=course, + **get_current_user() + ) + +@app.route("/course//page/") +@login_required +def course_page(course_id, page_number): + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT * + FROM course_page + WHERE course_id = %s + AND page_number = %s + """, (course_id, page_number)) + page = fetchone_dict(cur) + + if not page: + abort(404) + + # Fortschritt speichern + cur.execute(""" + INSERT INTO user_course_progress (user_id, course_id, last_page) + VALUES (%s, %s, %s) + ON CONFLICT (user_id, course_id) + DO UPDATE SET last_page = EXCLUDED.last_page + """, (session["user_id"], course_id, page_number)) + + conn.commit() + + cur.close() + conn.close() + + return render_template( + page["template_name"], + course_id=course_id, + page_number=page_number, + **get_current_user() ) \ No newline at end of file diff --git a/app/flask-postgres/app/config.py b/app/flask-postgres/app/config.py index e434d4e..6ff1983 100644 --- a/app/flask-postgres/app/config.py +++ b/app/flask-postgres/app/config.py @@ -12,8 +12,8 @@ class Config: LOG_DIR = os.getenv("LOG_DIR", "./logs") - COUNTRY_VAT_LABELS = { - "DE": "inkl. 19% USt", - "AT": "inkl. 20% USt", - "CH": "exkl. MwSt", - } \ No newline at end of file +COUNTRY_VAT_LABELS = { + "DE": "inkl. 19% USt", + "AT": "inkl. 20% USt", + "CH": "exkl. MwSt", +} \ No newline at end of file diff --git a/app/flask-postgres/app/permissions.py b/app/flask-postgres/app/permissions.py index b758d40..19854a2 100644 --- a/app/flask-postgres/app/permissions.py +++ b/app/flask-postgres/app/permissions.py @@ -15,4 +15,25 @@ def is_video_allowed_for_level(filename: str, mandant_level: int | None) -> bool if mandant_level == 3: return first_char == "A" - return False \ No newline at end of file + return False + +def get_available_courses_for_user(): + level = session.get("mandant_level", 0) + + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT id, code, title, description, video_file + FROM course + WHERE is_active = TRUE + AND min_level <= %s + ORDER BY sort_order, code + """, (level,)) + + courses = fetchall_dict(cur) + + cur.close() + conn.close() + + return courses \ No newline at end of file diff --git a/app/flask-postgres/app/templates/base.html b/app/flask-postgres/app/templates/base.html index 19a20d1..d992a55 100644 --- a/app/flask-postgres/app/templates/base.html +++ b/app/flask-postgres/app/templates/base.html @@ -23,6 +23,12 @@ Preise Allgemein + {% if is_logged_in %} + + Kurse + + {% endif %} + {% if is_logged_in %}
diff --git a/app/flask-postgres/app/templates/course/A1_page1.html b/app/flask-postgres/app/templates/course/A1_page1.html new file mode 100644 index 0000000..c4d5866 --- /dev/null +++ b/app/flask-postgres/app/templates/course/A1_page1.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} + +

AI Governance Basics

+ +

+ KI-Systeme müssen nachvollziehbar, sicher und kontrollierbar sein... +

+ + + +{% endblock %} \ No newline at end of file diff --git a/app/flask-postgres/app/templates/course/A1_page2.html b/app/flask-postgres/app/templates/course/A1_page2.html new file mode 100644 index 0000000..5e6af97 --- /dev/null +++ b/app/flask-postgres/app/templates/course/A1_page2.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} + +

AI Governance Basics

+ +

+ KI-Systeme müssen einen hübschen Avatar haben sein... +

+ + + +{% endblock %} \ No newline at end of file diff --git a/app/flask-postgres/app/templates/course/B1_page1.html b/app/flask-postgres/app/templates/course/B1_page1.html new file mode 100644 index 0000000..94f315a --- /dev/null +++ b/app/flask-postgres/app/templates/course/B1_page1.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} + +

B1 AI Privacy Basics

+ +

+ KI-Systeme müssen die Privatsphäre schützen sein... +

+ + + +{% endblock %} \ No newline at end of file diff --git a/app/flask-postgres/app/templates/course/B1_page2.html b/app/flask-postgres/app/templates/course/B1_page2.html new file mode 100644 index 0000000..558930a --- /dev/null +++ b/app/flask-postgres/app/templates/course/B1_page2.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} + +

B1 AI Privacy Basics

+ +

+ KI-Systeme müssen die Privatsphäre schützen sein... +

+ + + +{% endblock %} \ No newline at end of file diff --git a/app/flask-postgres/app/templates/course_list.html b/app/flask-postgres/app/templates/course_list.html new file mode 100644 index 0000000..76620ad --- /dev/null +++ b/app/flask-postgres/app/templates/course_list.html @@ -0,0 +1,22 @@ +{% extends "base.html" %} + +{% block content %} + + + +
+ {% for course in courses %} +
+

{{ course.title }}

+

{{ course.description }}

+ + + Starten + +
+ {% endfor %} +
+ +{% endblock %} \ No newline at end of file diff --git a/app/flask-postgres/app/templates/course_video.html b/app/flask-postgres/app/templates/course_video.html new file mode 100644 index 0000000..26b06c8 --- /dev/null +++ b/app/flask-postgres/app/templates/course_video.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block content %} + +

{{ course.title }}

+ + + + + +{% endblock %} \ No newline at end of file diff --git a/app/flask-postgres/styles/site.css b/app/flask-postgres/styles/site.css index ba98114..a152b29 100644 --- a/app/flask-postgres/styles/site.css +++ b/app/flask-postgres/styles/site.css @@ -694,4 +694,28 @@ button { outline: none; border-color: #8fb6e2; box-shadow: 0 0 0 3px rgba(143, 182, 226, 0.2); +} + +/* ========================= + Kurse +========================= */ + + +.course-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px; +} + +.course-card { + background: #fff; + border-radius: 14px; + padding: 20px; + box-shadow: 0 10px 20px rgba(0,0,0,0.08); +} + +.course-nav { + display: flex; + justify-content: space-between; + margin-top: 30px; } \ No newline at end of file