feat(monitoring): complete monitoring pipeline and fix presentation flag persistence

add superadmin monitoring dashboard with protected route, menu entry, and monitoring data client
add monitoring overview API endpoint and improve log serialization/aggregation for dashboard use
extend listener health/log handling with robust status/event/timestamp normalization and screenshot payload extraction
improve screenshot persistence and retrieval (timestamp-aware uploads, latest screenshot endpoint fallback)
fix page_progress and auto_progress persistence/serialization across create, update, and detached occurrence flows
align technical and project docs to reflect implemented monitoring and no-version-bump backend changes
add documentation sync log entry and include minor compose env indentation cleanup
This commit is contained in:
2026-03-24 11:18:33 +00:00
parent 3107d0f671
commit 9c330f984f
18 changed files with 2095 additions and 104 deletions

View File

@@ -104,6 +104,9 @@ def get_events():
"end_time": e.end.isoformat() if e.end else None,
"is_all_day": False,
"media_id": e.event_media_id,
"slideshow_interval": e.slideshow_interval,
"page_progress": e.page_progress,
"auto_progress": e.auto_progress,
"type": e.event_type.value if e.event_type else None,
"icon": get_icon_for_type(e.event_type.value if e.event_type else None),
# Recurrence metadata
@@ -267,6 +270,8 @@ def detach_event_occurrence(event_id, occurrence_date):
'event_type': master.event_type,
'event_media_id': master.event_media_id,
'slideshow_interval': getattr(master, 'slideshow_interval', None),
'page_progress': getattr(master, 'page_progress', None),
'auto_progress': getattr(master, 'auto_progress', None),
'created_by': master.created_by,
}
@@ -318,6 +323,8 @@ def detach_event_occurrence(event_id, occurrence_date):
event_type=master_data['event_type'],
event_media_id=master_data['event_media_id'],
slideshow_interval=master_data['slideshow_interval'],
page_progress=data.get("page_progress", master_data['page_progress']),
auto_progress=data.get("auto_progress", master_data['auto_progress']),
recurrence_rule=None,
recurrence_end=None,
skip_holidays=False,
@@ -361,11 +368,15 @@ def create_event():
event_type = data["event_type"]
event_media_id = None
slideshow_interval = None
page_progress = None
auto_progress = None
# Präsentation: event_media_id und slideshow_interval übernehmen
if event_type == "presentation":
event_media_id = data.get("event_media_id")
slideshow_interval = data.get("slideshow_interval")
page_progress = data.get("page_progress")
auto_progress = data.get("auto_progress")
if not event_media_id:
return jsonify({"error": "event_media_id required for presentation"}), 400
@@ -443,6 +454,8 @@ def create_event():
is_active=True,
event_media_id=event_media_id,
slideshow_interval=slideshow_interval,
page_progress=page_progress,
auto_progress=auto_progress,
autoplay=autoplay,
loop=loop,
volume=volume,
@@ -519,6 +532,10 @@ def update_event(event_id):
event.event_type = data.get("event_type", event.event_type)
event.event_media_id = data.get("event_media_id", event.event_media_id)
event.slideshow_interval = data.get("slideshow_interval", event.slideshow_interval)
if "page_progress" in data:
event.page_progress = data.get("page_progress")
if "auto_progress" in data:
event.auto_progress = data.get("auto_progress")
# Video-specific fields
if "autoplay" in data:
event.autoplay = data.get("autoplay")