docs/dev: sync backend rework, MQTT, and devcontainer hygiene
README: add Versioning (unified SemVer, pre-releases, build metadata); emphasize UTC handling and streaming endpoint; add Dev Container notes (UI-only Remote Containers, npm ci, idempotent aliases) TECH-CHANGELOG: backend rework notes (serialization camelCase, UTC normalization, streaming metadata); add component build metadata template (image tags/SHAs) Copilot instructions: integrate maintenance guardrails; reinforce UTC and camelCase conventions; document MQTT topics and scheduler retained payload behavior Devcontainer: map Remote Containers to UI; remove in-container install; switch to npm ci; make aliases idempotent
This commit is contained in:
19
.github/copilot-instructions.md
vendored
19
.github/copilot-instructions.md
vendored
@@ -15,6 +15,8 @@ Small multi-service digital signage app (Flask API, React dashboard, MQTT schedu
|
||||
- "Refactor `scheduler/db_utils.py` to prefer precomputed EventMedia metadata and fall back to a HEAD probe."
|
||||
- "Add an ffprobe-based worker that extracts duration/resolution/bitrate and stores them on `EventMedia`."
|
||||
|
||||
Keep docs synced with code. When you change services/MQTT/API/UTC/env or dev/prod run steps, update this file in the same commit (see `AI-INSTRUCTIONS-MAINTENANCE.md`).
|
||||
|
||||
### When not to change
|
||||
- Avoid editing generated assets under `dashboard/dist/` and compiled bundles. Don't modify files produced by CI or Docker builds (unless intentionally updating build outputs).
|
||||
|
||||
@@ -40,6 +42,8 @@ Small multi-service digital signage app (Flask API, React dashboard, MQTT schedu
|
||||
- Scheduler: Publishes only currently active events (per group, at "now") to MQTT retained topics in `scheduler/scheduler.py`. It queries a future window (default: 7 days) to expand recurring events using RFC 5545 rules and applies event exceptions, but only publishes events that are active at the current time. When a group has no active events, the scheduler clears its retained topic by publishing an empty list. All time comparisons are UTC; any naive timestamps are normalized. Logging is concise; conversion lookups are cached and logged only once per media.
|
||||
- Nginx: Reverse proxy routes `/api/*` and `/screenshots/*` to API; everything else to dashboard (`nginx.conf`).
|
||||
|
||||
- Dev Container (hygiene): UI-only `Dev Containers` extension runs on host UI via `remote.extensionKind`; do not install it in-container. Dashboard installs use `npm ci`; shell aliases in `postStartCommand` are appended idempotently.
|
||||
|
||||
## Recent changes since last commit
|
||||
|
||||
### Latest (November 2025)
|
||||
@@ -57,6 +61,7 @@ Small multi-service digital signage app (Flask API, React dashboard, MQTT schedu
|
||||
- Frontend: Dashboard and appointments automatically append 'Z' to parse as UTC and display in user's local timezone
|
||||
- Time formatting functions use `toLocaleTimeString('de-DE')` for German locale display
|
||||
- All time comparisons use UTC; `new Date().toISOString()` sends UTC back to API
|
||||
- API returns ISO strings without `Z`; frontend must append `Z` before parsing to ensure UTC
|
||||
|
||||
- **Dashboard Enhancements**:
|
||||
- New card-based design for Raumgruppen (room groups) with Syncfusion components
|
||||
@@ -84,6 +89,11 @@ Small multi-service digital signage app (Flask API, React dashboard, MQTT schedu
|
||||
|
||||
Note: these edits are intentionally backwards-compatible — if the probe fails, the scheduler still emits the stream URL and the client should fallback to a direct play attempt or request richer metadata when available.
|
||||
|
||||
Backend rework notes (no version bump):
|
||||
- Dev container hygiene: UI-only Remote Containers; reproducible dashboard installs (`npm ci`); idempotent shell aliases.
|
||||
- Serialization consistency: snake_case internal → camelCase external via `server/serializers.py` for all JSON.
|
||||
- UTC normalization across routes/scheduler; enums and datetimes serialize consistently.
|
||||
|
||||
## Service boundaries & data flow
|
||||
- Database connection string is passed as `DB_CONN` (mysql+pymysql) to Python services.
|
||||
- API builds its engine in `server/database.py` (loads `.env` only in development).
|
||||
@@ -96,6 +106,8 @@ Small multi-service digital signage app (Flask API, React dashboard, MQTT schedu
|
||||
- Per-client group assignment (retained): `infoscreen/{uuid}/group_id` via `server/mqtt_helper.py`.
|
||||
- Screenshots: server-side folders `server/received_screenshots/` and `server/screenshots/`; Nginx exposes `/screenshots/{uuid}.jpg` via `server/wsgi.py` route.
|
||||
|
||||
- Dev Container guidance: If extensions reappear inside the container, remove UI-only extensions from `devcontainer.json` `extensions` and map them in `remote.extensionKind` as `"ui"`.
|
||||
|
||||
- Presentation conversion (PPT/PPTX/ODP → PDF):
|
||||
- Trigger: on upload in `server/routes/eventmedia.py` for media types `ppt|pptx|odp` (compute sha256, upsert `Conversion`, enqueue job).
|
||||
- Worker: RQ worker runs `server.worker.convert_event_media_to_pdf`, calls Gotenberg LibreOffice endpoint, writes to `server/media/converted/`.
|
||||
@@ -141,12 +153,16 @@ Small multi-service digital signage app (Flask API, React dashboard, MQTT schedu
|
||||
- `POST /api/academic_periods/active` — set active period (deactivates others)
|
||||
- `GET /api/academic_periods/for_date?date=YYYY-MM-DD` — period covering given date
|
||||
|
||||
Documentation maintenance: keep this file aligned with real patterns; update when routes/session/UTC rules change. Avoid long prose; link exact paths.
|
||||
|
||||
## Frontend patterns (dashboard)
|
||||
- Vite React app; proxies `/api` and `/screenshots` to API in dev (`vite.config.ts`).
|
||||
- Uses Syncfusion components; Vite config pre-bundles specific packages to avoid alias issues.
|
||||
- Environment: `VITE_API_URL` provided at build/run; in dev compose, proxy handles `/api` so local fetches can use relative `/api/...` paths.
|
||||
- **API Response Format**: All API endpoints return camelCase JSON (e.g., `startTime`, `endTime`, `groupId`). Frontend consumes camelCase directly.
|
||||
- **UTC Time Parsing**: API returns ISO strings without 'Z' suffix. Frontend appends 'Z' before parsing to ensure UTC interpretation: `const utcString = dateStr.endsWith('Z') ? dateStr : dateStr + 'Z'; new Date(utcString);`. Display uses `toLocaleTimeString('de-DE')` for German format.
|
||||
|
||||
- Dev Container: When adding frontend deps, prefer `npm ci` and, if using named volumes, recreate dashboard `node_modules` volume so installs occur inside the container.
|
||||
- Theming: Syncfusion Material 3 theme is used. All component CSS is imported centrally in `dashboard/src/main.tsx` (base, navigations, buttons, inputs, dropdowns, popups, kanban, grids, schedule, filemanager, notifications, layouts, lists, calendars, splitbuttons, icons). Tailwind CSS has been removed.
|
||||
- Scheduler (appointments page): top bar includes Group and Academic Period selectors (Syncfusion DropDownList). Selecting a period calls `POST /api/academic_periods/active`, moves the calendar to today’s month/day within the period year, and refreshes a right-aligned indicator row showing:
|
||||
- Holidays present in the current view (count)
|
||||
@@ -252,6 +268,7 @@ Note: Syncfusion usage in the dashboard is already documented above; if a UI for
|
||||
- Frontend **must** append 'Z' before parsing: `const utcStr = dateStr.endsWith('Z') ? dateStr : dateStr + 'Z'; new Date(utcStr);`
|
||||
- Display in local timezone using `toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })`
|
||||
- When sending to API, use `date.toISOString()` which includes 'Z' and is UTC
|
||||
- Frontend must append `Z` to API strings before parsing; backend compares in UTC and returns ISO without `Z`.
|
||||
- **JSON Naming Convention**:
|
||||
- Backend uses snake_case internally (Python convention)
|
||||
- API returns camelCase JSON (web standard): `startTime`, `endTime`, `groupId`, etc.
|
||||
@@ -268,6 +285,8 @@ Note: Syncfusion usage in the dashboard is already documented above; if a UI for
|
||||
3) Manage `Session()` lifecycle,
|
||||
4) Return JSON-safe values (serialize enums and datetimes), and
|
||||
5) Use `dict_to_camel_case()` for camelCase JSON responses
|
||||
|
||||
Docs maintenance guardrails (solo-friendly): Update this file alongside code changes (services/MQTT/API/UTC/env). Keep it concise (20–50 lines per section). Never include secrets.
|
||||
- When extending media types, update `MediaType` and any logic in `eventmedia` and dashboard that depends on it.
|
||||
- Academic periods: Events/media can be optionally associated with periods for educational organization. Only one period should be active at a time (`is_active=True`).
|
||||
- Initialization scripts: legacy DB init scripts were removed; use Alembic and `initialize_database.py` going forward.
|
||||
|
||||
Reference in New Issue
Block a user