Dashboard (dashboard/src/dashboard.tsx, settings.tsx, apiAcademicPeriods.ts): - Refactor loadHolidayStatus to useCallback with stable empty-deps reference; removes location.pathname dependency that caused overlapping API calls at mount and left the banner unresolved via request-sequence cancellation - Add key prop derived from severity:text to Syncfusion MessageComponent to force remount on state change, fixing stale banner that ignored React prop/children updates - Correct German transliterated text to proper Umlauts throughout visible UI strings (fuer -> für, oe -> ö, ae -> ä etc. across dashboard and settings views) Backend (server/init_academic_periods.py): - Refactor to idempotent two-phase flow: seed default periods only when table is empty; on every run activate exactly the non-archived period covering date.today() - Enforces single-active invariant by deactivating all periods before promoting match - Emits explicit warning when no period covers current date instead of doing nothing Deployment (docker-compose.prod.yml): - Add init_academic_periods.py to server startup chain after migrations and defaults; eliminates manual post-deploy step to set an active academic period Release docs: - program-info.json: bump to 2026.1.0-alpha.16; fix JSON parse error caused by typographic curly quotes in the new changelog entry - TECH-CHANGELOG.md: detailed alpha.16 section with root-cause motivation for both dashboard refactoring decisions (unstable callback ref + Syncfusion stale render) - DEV-CHANGELOG.md: document dashboard refactor, Syncfusion key fix, Umlaut changes, and program-info JSON regression and fix - README.md: add Latest Release Highlights section for alpha.16 - .github/copilot-instructions.md: sync file map, prod bootstrap note, backend and frontend pattern additions for academic period init and Syncfusion remount pattern
5.4 KiB
5.4 KiB
Copilot instructions for infoscreen_2025
Purpose
This file is a concise, high-signal brief for coding agents. It is not a changelog and not a full architecture handbook.
TL;DR
- Stack: Flask API + MariaDB, React/Vite dashboard, MQTT listener, scheduler, worker.
- Main areas:
- API logic in
server/ - Scheduler logic in
scheduler/ - UI logic in
dashboard/src/
- API logic in
- Keep changes minimal, match existing patterns, and update docs in the same commit when behavior changes.
Fast file map
scheduler/scheduler.py- scheduler loop, MQTT event publishing, TV power intent publishingscheduler/db_utils.py- event formatting and power-intent helper logiclistener/listener.py- discovery/heartbeat/log/screenshot MQTT consumptionserver/init_academic_periods.py- idempotent academic-period seeding + auto-activation for current dateserver/initialize_database.py- migration + bootstrap orchestration for local/manual setupserver/routes/events.py- event CRUD, recurrence handling, UTC normalizationserver/routes/eventmedia.py- file manager, media upload/stream endpointsserver/routes/groups.py- group lifecycle, alive status, order persistenceserver/routes/system_settings.py- system settings CRUD and supplement-table endpointdashboard/src/settings.tsx- settings UX and system-defaults integrationdashboard/src/components/CustomEventModal.tsx- event creation/editing UXdashboard/src/monitoring.tsx- superadmin monitoring pageTV_POWER_INTENT_SERVER_CONTRACT_V1.md- Phase 1 TV power contract
Service picture
- API:
server/on:8000(health:/health) - Dashboard:
dashboard/(dev:5173, proxied API calls) - MQTT broker: Mosquitto (
mosquitto/config/mosquitto.conf) - Listener: MQTT consumer that updates server-side state
- Scheduler: publishes active events and group-level TV power intents
- Nginx: routes
/api/*and/screenshots/*to API, dashboard otherwise - Prod bootstrap:
docker-compose.prod.ymlserver command runs migrations, defaults init, and academic-period init before Gunicorn start
Non-negotiable conventions
- Datetime:
- Store/compare in UTC.
- API returns ISO strings without
Zin many routes. - Frontend must append
Zbefore parsing if needed.
- JSON naming:
- Backend internals use snake_case.
- API responses use camelCase (via
server/serializers.py).
- DB host in containers:
db(not localhost). - Never put secrets in docs.
MQTT contracts
- Event list topic (retained):
infoscreen/events/{group_id} - Group assignment topic (retained):
infoscreen/{uuid}/group_id - Heartbeat topic:
infoscreen/{uuid}/heartbeat - Logs topic family:
infoscreen/{uuid}/logs/{error|warn|info} - Health topic:
infoscreen/{uuid}/health - Dashboard screenshot topic:
infoscreen/{uuid}/dashboard - TV power intent Phase 1 topic (retained, QoS1):
infoscreen/groups/{group_id}/power/intent
TV power intent Phase 1 rules:
- Schema version is
"1.0". - Group-only scope in Phase 1.
- Heartbeat publish keeps
intent_id; semantic transition rotatesintent_id. - Expiry rule:
expires_at = issued_at + max(3 x poll_interval_sec, 90s). - Canonical contract is
TV_POWER_INTENT_SERVER_CONTRACT_V1.md.
Backend patterns
- Routes in
server/routes/*, registered inserver/wsgi.py. - Use one request-scoped DB session, commit on mutation, always close session.
- Keep enum/datetime serialization JSON-safe.
- Maintain UTC-safe comparisons in scheduler and routes.
- Keep recurrence handling backend-driven and consistent with exceptions.
- Academic periods bootstrap is idempotent and should auto-activate period covering
date.today()when available.
Frontend patterns
- Use Syncfusion-based patterns already present in dashboard.
- Keep API requests relative (
/api/...) to use Vite proxy in dev. - Respect
FRONTEND_DESIGN_RULES.mdfor component and styling conventions. - Keep role-gated UI behavior aligned with backend authorization.
- Holiday status banner in dashboard should render from computed state and avoid stale message reuse in 3rd-party UI components.
Environment variables (high-value)
- Scheduler:
POLL_INTERVAL_SECONDS,REFRESH_SECONDS - Power intent:
POWER_INTENT_PUBLISH_ENABLED,POWER_INTENT_HEARTBEAT_ENABLED,POWER_INTENT_EXPIRY_MULTIPLIER,POWER_INTENT_MIN_EXPIRY_SECONDS - Monitoring:
PRIORITY_SCREENSHOT_TTL_SECONDS - Core:
DB_CONN,DB_USER,DB_PASSWORD,DB_HOST,DB_NAME,ENV
Edit guardrails
- Do not edit generated assets in
dashboard/dist/. - Do not change CI/build outputs unless explicitly intended.
- Preserve existing API behavior unless task explicitly requires a change.
- Prefer links to canonical docs instead of embedding long historical notes here.
Documentation sync rule
When services/MQTT/API/UTC/env behavior changes:
- Update this file (concise deltas only).
- Update canonical docs where details live.
- Update changelogs separately (
TECH-CHANGELOG.md,DEV-CHANGELOG.md,dashboard/public/program-info.jsonas appropriate).
Canonical docs map
- Repo entry:
README.md - Instruction governance:
AI-INSTRUCTIONS-MAINTENANCE.md - Technical release details:
TECH-CHANGELOG.md - Workspace/development notes:
DEV-CHANGELOG.md - MQTT payload details:
MQTT_EVENT_PAYLOAD_GUIDE.md - TV power contract:
TV_POWER_INTENT_SERVER_CONTRACT_V1.md - Frontend patterns:
FRONTEND_DESIGN_RULES.md - Archived historical docs:
docs/archive/