Kursfortschrittsanzeige
This commit is contained in:
parent
bc3b2505b6
commit
989422a4a7
@ -1119,9 +1119,20 @@ def course_start(course_id):
|
|||||||
cur.close()
|
cur.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
show_course_progress = True
|
||||||
|
course_progress_title = f"{course['code']} – {course['title']}"
|
||||||
|
course_progress_current = 1
|
||||||
|
course_progress_total = 8
|
||||||
|
course_progress_percent = int((course_progress_current / course_progress_total) * 100)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"course_video.html",
|
"course_video.html",
|
||||||
course=course,
|
course=course,
|
||||||
|
show_course_progress=show_course_progress,
|
||||||
|
course_progress_title=course_progress_title,
|
||||||
|
course_progress_current=course_progress_current,
|
||||||
|
course_progress_total=course_progress_total,
|
||||||
|
course_progress_percent=course_progress_percent,
|
||||||
**get_current_user()
|
**get_current_user()
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1142,6 +1153,13 @@ def course_page(course_id, page_number):
|
|||||||
if not page:
|
if not page:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
cur.execute("""
|
||||||
|
SELECT *
|
||||||
|
FROM course
|
||||||
|
WHERE id = %s
|
||||||
|
""", (course_id,))
|
||||||
|
course = fetchone_dict(cur)
|
||||||
|
|
||||||
# Fortschritt speichern
|
# Fortschritt speichern
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
INSERT INTO user_course_progress (user_id, course_id, last_page)
|
INSERT INTO user_course_progress (user_id, course_id, last_page)
|
||||||
@ -1155,10 +1173,21 @@ def course_page(course_id, page_number):
|
|||||||
cur.close()
|
cur.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
show_course_progress = True
|
||||||
|
course_progress_title = f"{course['code']} – {course['title']}"
|
||||||
|
course_progress_current = page_number+1
|
||||||
|
course_progress_total = 8
|
||||||
|
course_progress_percent = int((course_progress_current / course_progress_total) * 100)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
page["template_name"],
|
page["template_name"],
|
||||||
course_id=course_id,
|
course_id=course_id,
|
||||||
page_number=page_number,
|
page_number=page_number,
|
||||||
|
show_course_progress=show_course_progress,
|
||||||
|
course_progress_title=course_progress_title,
|
||||||
|
course_progress_current=course_progress_current,
|
||||||
|
course_progress_total=course_progress_total,
|
||||||
|
course_progress_percent=course_progress_percent,
|
||||||
**get_current_user()
|
**get_current_user()
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1591,7 +1620,7 @@ def admin_courses():
|
|||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT id, code, title, description, min_level, video_file, sort_order
|
SELECT id, code, title, description, min_level, video_file, sort_order
|
||||||
FROM course
|
FROM course
|
||||||
ORDER BY min_level, sort_order, id
|
ORDER BY code
|
||||||
""")
|
""")
|
||||||
courses = fetchall_dict(cur)
|
courses = fetchall_dict(cur)
|
||||||
|
|
||||||
|
|||||||
@ -68,12 +68,12 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th>Code</th>
|
<th style="width:60px;">Code</th>
|
||||||
<th>Titel</th>
|
<th>Titel</th>
|
||||||
<th>Level</th>
|
<th style="width:120px;">Level</th>
|
||||||
<th>Video</th>
|
<th>Video</th>
|
||||||
<th>Sort</th>
|
<th style="width:80px;">Sort</th>
|
||||||
<th>Aktionen</th>
|
<th style="width:160px;">Aktionen</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
@ -81,26 +81,34 @@
|
|||||||
{% for c in courses %}
|
{% for c in courses %}
|
||||||
<tr>
|
<tr>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="hidden" name="id" value="{{ c.id }}">
|
<td>
|
||||||
|
<input type="hidden" name="id" value="{{ c.id }}">
|
||||||
<td>{{ c.id }}</td>
|
{{ c.id }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<!-- CODE -->
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="code" value="{{ c.code }}">
|
<input type="text" name="code" value="{{ c.code }}" maxlength="5" class="input-small">
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<!-- TITEL + BESCHREIBUNG -->
|
||||||
<td>
|
<td>
|
||||||
<input type="text" name="title" value="{{ c.title }}">
|
<input type="text" name="title" value="{{ c.title }}" class="input-full">
|
||||||
|
|
||||||
|
<textarea name="description" class="textarea-inline"
|
||||||
|
placeholder="Beschreibung">{{ c.description or '' }}</textarea>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<!-- LEVEL -->
|
||||||
<td>
|
<td>
|
||||||
<select name="min_level">
|
<select name="min_level">
|
||||||
<option value="1" {% if c.min_level == 1 %}selected{% endif %}>1 - Gold</option>
|
<option value="1" {% if c.min_level == 1 %}selected{% endif %}>Gold</option>
|
||||||
<option value="2" {% if c.min_level == 2 %}selected{% endif %}>2 - Silber</option>
|
<option value="2" {% if c.min_level == 2 %}selected{% endif %}>Silber</option>
|
||||||
<option value="3" {% if c.min_level == 3 %}selected{% endif %}>3 - Bronze</option>
|
<option value="3" {% if c.min_level == 3 %}selected{% endif %}>Bronze</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<!-- VIDEO -->
|
||||||
<td>
|
<td>
|
||||||
<select name="video_file">
|
<select name="video_file">
|
||||||
{% for v in video_files %}
|
{% for v in video_files %}
|
||||||
@ -111,15 +119,17 @@
|
|||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<!-- SORT -->
|
||||||
<td>
|
<td>
|
||||||
<input type="number" name="sort_order" value="{{ c.sort_order }}">
|
<input type="number" name="sort_order" value="{{ c.sort_order }}" class="input-small">
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<!-- ACTIONS -->
|
||||||
<td>
|
<td>
|
||||||
<input type="hidden" name="description" value="{{ c.description or '' }}">
|
|
||||||
<button name="action" value="update" class="btn-primary btn-small">Speichern</button>
|
<button name="action" value="update" class="btn-primary btn-small">Speichern</button>
|
||||||
<button name="action" value="delete" class="btn-danger btn-small">Löschen</button>
|
<button name="action" value="delete" class="btn-danger btn-small">Löschen</button>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -72,6 +72,23 @@
|
|||||||
<main class="content-area">
|
<main class="content-area">
|
||||||
<section class="content-box">
|
<section class="content-box">
|
||||||
|
|
||||||
|
{% if show_course_progress %}
|
||||||
|
<div class="course-progress-box">
|
||||||
|
|
||||||
|
<div class="course-progress-header">
|
||||||
|
<strong>{{ course_progress_title }}</strong>
|
||||||
|
<span>{{ course_progress_current }} / {{ course_progress_total }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="course-progress-bar">
|
||||||
|
<div class="course-progress-fill"
|
||||||
|
style="width: {{ course_progress_percent }}%;">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
45
app/flask-postgres/app/templates/course/A1_page0.html
Normal file
45
app/flask-postgres/app/templates/course/A1_page0.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>AI Governance Basics</h2>
|
||||||
|
|
||||||
|
<section class="content-section ai-explainer">
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<h2 class="section-title">Willkommen zu Compliance Verification und zum Modul A1 – AI Governance Basics</h2>
|
||||||
|
|
||||||
|
<p class="lead">
|
||||||
|
In diesem Kurs lernen Sie die Grundlagen dafür, wie moderne KI-Systeme funktionieren,
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
warum sie so leistungsfähig – aber gleichzeitig fehleranfällig – sind,
|
||||||
|
in welchen Unternehmensbereichen KI eingesetzt wird,
|
||||||
|
und welche Mindestregeln für einen sicheren und verantwortungsvollen Umgang gelten.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Unser Ziel ist nicht,
|
||||||
|
Sie zu Programmiererinnen oder Technikern zu machen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Unser Ziel ist,
|
||||||
|
dass Sie ein realistisches Grundverständnis entwickeln:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="key-points">
|
||||||
|
<li>Was KI kann.</li>
|
||||||
|
<li>Was KI nicht kann.</li>
|
||||||
|
<li>Und welche Verantwortung Sie im Alltag tragen.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="course-nav">
|
||||||
|
<a href="/course/{{ course_id }}" class="btn-secondary">Zurück</a>
|
||||||
|
<a href="/course/{{ course_id }}/page/2" class="btn-primary">Weiter</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@ -41,8 +41,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/1" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/page/2" class="btn-primary">Weiter</a>
|
<a href="/course/{{ course_id }}/page/3" class="btn-secondary">Weiter</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -56,8 +56,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/1" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/2" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/page/3" class="btn-secondary">Weiter</a>
|
<a href="/course/{{ course_id }}/page/4" class="btn-secondary">Weiter</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -75,8 +75,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/2" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/3" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/page/4" class="btn-secondary">Weiter</a>
|
<a href="/course/{{ course_id }}/page/5" class="btn-secondary">Weiter</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -42,8 +42,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/3" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/4" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/page/5" class="btn-secondary">Weiter</a>
|
<a href="/course/{{ course_id }}/page/6" class="btn-secondary">Weiter</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -85,8 +85,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/4" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/5" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/assessment" class="btn-primary">Zum Assessment</a>
|
<a href="/course/{{ course_id }}/page/7" class="btn-secondary">Weiter</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -31,7 +31,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/5" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/6" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/assessment" class="btn-primary">Zum Assessment</a>
|
<a href="/course/{{ course_id }}/assessment" class="btn-primary">Zum Assessment</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -58,8 +58,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/4" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/5" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/page/6" class="btn-primary">Weiter</a>
|
<a href="/course/{{ course_id }}/page/7" class="btn-primary">Weiter</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -50,8 +50,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/1" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/3" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/page/3" class="btn-primary">Weiter</a>
|
<a href="/course/{{ course_id }}/page/5" class="btn-primary">Weiter</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -52,8 +52,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/1" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/4" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/page/3" class="btn-primary">Weiter</a>
|
<a href="/course/{{ course_id }}/page/6" class="btn-primary">Weiter</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -54,8 +54,8 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/1" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/5" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/page/3" class="btn-primary">Weiter</a>
|
<a href="/course/{{ course_id }}/page/7" class="btn-primary">Weiter</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -31,7 +31,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="course-nav">
|
<div class="course-nav">
|
||||||
<a href="/course/{{ course_id }}/page/1" class="btn-secondary">Zurück</a>
|
<a href="/course/{{ course_id }}/page/6" class="btn-secondary">Zurück</a>
|
||||||
<a href="/course/{{ course_id }}/assessment" class="btn-primary">Zum Assessment</a>
|
<a href="/course/{{ course_id }}/assessment" class="btn-primary">Zum Assessment</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1020,4 +1020,74 @@ button {
|
|||||||
.highlight-quote {
|
.highlight-quote {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mandanten-table textarea {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 70px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid #cfd8e3;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
resize: vertical;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===============================
|
||||||
|
Kursverwaltung Tabelle
|
||||||
|
=============================== */
|
||||||
|
|
||||||
|
.input-small {
|
||||||
|
width: 60px;
|
||||||
|
padding: 6px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-full {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textarea-inline {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 60px;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border: 1px solid #cfd8e3;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
resize: vertical;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===============================
|
||||||
|
Kursfortschritt (grün/grau)
|
||||||
|
=============================== */
|
||||||
|
|
||||||
|
.course-progress-box {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-progress-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hintergrund = grau */
|
||||||
|
.course-progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
height: 12px;
|
||||||
|
background: #e5e7eb; /* grau */
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fortschritt = grün */
|
||||||
|
.course-progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: #22c55e; /* grün */
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: width 0.3s ease;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user