Kursverwaltung
This commit is contained in:
parent
452a3219ea
commit
aa0767f790
@ -1488,3 +1488,118 @@ def admin_checklist():
|
||||
form_values=form_values,
|
||||
**get_current_user()
|
||||
)
|
||||
|
||||
@app.route("/admin/courses", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def admin_courses():
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
form_error = None
|
||||
form_values = None
|
||||
|
||||
video_dir = os.path.join("/app/images/videos")
|
||||
video_files = []
|
||||
if os.path.isdir(video_dir):
|
||||
video_files = sorted([
|
||||
f for f in os.listdir(video_dir)
|
||||
if f.lower().endswith(".mp4")
|
||||
])
|
||||
|
||||
if request.method == "POST":
|
||||
action = request.form.get("action")
|
||||
|
||||
code = request.form.get("code", "").strip().upper()
|
||||
title = request.form.get("title", "").strip()
|
||||
description = request.form.get("description", "").strip()
|
||||
min_level = request.form.get("min_level", "").strip()
|
||||
video_file = request.form.get("video_file", "").strip()
|
||||
sort_order = request.form.get("sort_order", "0").strip()
|
||||
|
||||
form_values = {
|
||||
"code": code,
|
||||
"title": title,
|
||||
"description": description,
|
||||
"min_level": min_level,
|
||||
"video_file": video_file,
|
||||
"sort_order": sort_order
|
||||
}
|
||||
|
||||
if action == "create":
|
||||
if not code:
|
||||
form_error = "Code ist Pflicht."
|
||||
elif not title:
|
||||
form_error = "Titel ist Pflicht."
|
||||
elif not min_level:
|
||||
form_error = "Level ist Pflicht."
|
||||
elif not video_file:
|
||||
form_error = "Video-Datei ist Pflicht."
|
||||
else:
|
||||
cur.execute("""
|
||||
INSERT INTO course (code, title, description, min_level, video_file, sort_order)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
""", (
|
||||
code,
|
||||
title,
|
||||
description or None,
|
||||
int(min_level),
|
||||
video_file,
|
||||
int(sort_order or 0)
|
||||
))
|
||||
conn.commit()
|
||||
|
||||
elif action == "update":
|
||||
course_id = request.form.get("id")
|
||||
|
||||
if not code:
|
||||
form_error = "Code ist Pflicht."
|
||||
elif not title:
|
||||
form_error = "Titel ist Pflicht."
|
||||
elif not min_level:
|
||||
form_error = "Level ist Pflicht."
|
||||
elif not video_file:
|
||||
form_error = "Video-Datei ist Pflicht."
|
||||
else:
|
||||
cur.execute("""
|
||||
UPDATE course
|
||||
SET code=%s,
|
||||
title=%s,
|
||||
description=%s,
|
||||
min_level=%s,
|
||||
video_file=%s,
|
||||
sort_order=%s
|
||||
WHERE id=%s
|
||||
""", (
|
||||
code,
|
||||
title,
|
||||
description or None,
|
||||
int(min_level),
|
||||
video_file,
|
||||
int(sort_order or 0),
|
||||
int(course_id)
|
||||
))
|
||||
conn.commit()
|
||||
|
||||
elif action == "delete":
|
||||
course_id = request.form.get("id")
|
||||
cur.execute("DELETE FROM course WHERE id=%s", (int(course_id),))
|
||||
conn.commit()
|
||||
|
||||
cur.execute("""
|
||||
SELECT id, code, title, description, min_level, video_file, sort_order
|
||||
FROM course
|
||||
ORDER BY min_level, sort_order, id
|
||||
""")
|
||||
courses = fetchall_dict(cur)
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
return render_template(
|
||||
"admin_courses.html",
|
||||
courses=courses,
|
||||
video_files=video_files,
|
||||
form_error=form_error,
|
||||
form_values=form_values,
|
||||
**get_current_user()
|
||||
)
|
||||
131
app/flask-postgres/app/templates/admin_courses.html
Normal file
131
app/flask-postgres/app/templates/admin_courses.html
Normal file
@ -0,0 +1,131 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>Kursverwaltung</h1>
|
||||
|
||||
{% if form_error %}
|
||||
<div class="error-box">{{ form_error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="admin-panel">
|
||||
<h2>Neuen Kurs anlegen</h2>
|
||||
|
||||
<form method="post" class="admin-grid-form">
|
||||
<input type="hidden" name="action" value="create">
|
||||
|
||||
<div class="form-row">
|
||||
<label>Code</label>
|
||||
<input type="text" name="code" value="{{ form_values.code if form_values else '' }}" placeholder="z.B. A1" required>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label>Titel</label>
|
||||
<input type="text" name="title" value="{{ form_values.title if form_values else '' }}" required>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label>Level</label>
|
||||
<select name="min_level" required>
|
||||
<option value="1" {% if form_values and form_values.min_level == '1' %}selected{% endif %}>1 - Gold</option>
|
||||
<option value="2" {% if form_values and form_values.min_level == '2' %}selected{% endif %}>2 - Silber</option>
|
||||
<option value="3" {% if form_values and form_values.min_level == '3' %}selected{% endif %}>3 - Bronze</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label>Video-Datei</label>
|
||||
<select name="video_file" required>
|
||||
<option value="">Bitte wählen</option>
|
||||
{% for v in video_files %}
|
||||
<option value="{{ v }}" {% if form_values and form_values.video_file == v %}selected{% endif %}>
|
||||
{{ v }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label>Sortierung</label>
|
||||
<input type="number" name="sort_order" value="{{ form_values.sort_order if form_values else '0' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-row form-row-full">
|
||||
<label>Beschreibung</label>
|
||||
<textarea name="description">{{ form_values.description if form_values else '' }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-row form-row-full">
|
||||
<button class="btn-primary">Kurs anlegen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="admin-panel">
|
||||
<h2>Bestehende Kurse</h2>
|
||||
|
||||
<table class="mandanten-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Code</th>
|
||||
<th>Titel</th>
|
||||
<th>Level</th>
|
||||
<th>Video</th>
|
||||
<th>Sort</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for c in courses %}
|
||||
<tr>
|
||||
<form method="post">
|
||||
<input type="hidden" name="id" value="{{ c.id }}">
|
||||
|
||||
<td>{{ c.id }}</td>
|
||||
|
||||
<td>
|
||||
<input type="text" name="code" value="{{ c.code }}">
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type="text" name="title" value="{{ c.title }}">
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<select name="min_level">
|
||||
<option value="1" {% if c.min_level == 1 %}selected{% endif %}>1 - Gold</option>
|
||||
<option value="2" {% if c.min_level == 2 %}selected{% endif %}>2 - Silber</option>
|
||||
<option value="3" {% if c.min_level == 3 %}selected{% endif %}>3 - Bronze</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<select name="video_file">
|
||||
{% for v in video_files %}
|
||||
<option value="{{ v }}" {% if c.video_file == v %}selected{% endif %}>
|
||||
{{ v }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type="number" name="sort_order" value="{{ c.sort_order }}">
|
||||
</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="delete" class="btn-danger btn-small">Löschen</button>
|
||||
</td>
|
||||
</form>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@ -37,6 +37,7 @@
|
||||
{% if is_admin %}
|
||||
<a href="/admin/mandanten">Mandanten</a>
|
||||
<a href="/admin/checklist">Checklist</a>
|
||||
<a href="/admin/courses">Kurse</a>
|
||||
{% endif %}
|
||||
{% if is_user_admin %}
|
||||
<a href="/useradmin/mandant">Useradministration</a>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user