From 64f55a8b1f6801c825947d060e6253c31c195b38 Mon Sep 17 00:00:00 2001 From: Florian Heinz Date: Mon, 26 Oct 2026 09:35:19 +0100 Subject: [PATCH] Complete 0.7.1 fixes --- docs/ACCEPTANCE.md | 16 +- docs/ARCHITECTURE.md | 13 +- docs/DECISIONS.md | 14 ++ docs/RELEASE_NOTES.md | 24 ++- docs/STATUS.md | 27 +-- migrations/0019_usage_preparation.sql | 17 ++ src/app.css | 78 ++++++++- src/app.html | 6 +- src/lib/components/IconPicker.svelte | 9 +- src/lib/components/PresentationDisplay.svelte | 1 - src/lib/components/ShareManagement.svelte | 43 +++-- src/lib/components/UsageEditorDialog.svelte | 126 +++++++++----- src/lib/server/database.spec.ts | 2 +- src/lib/server/live.spec.ts | 34 ++++ src/lib/server/live.ts | 28 ++-- src/lib/server/shows.spec.ts | 34 +++- src/lib/server/shows.ts | 156 ++++++++++++++---- src/routes/freigabe/[token]/+page.svelte | 2 +- src/routes/fundus/[id]/+page.svelte | 17 +- .../fundus/[id]/praesentation/+page.svelte | 12 +- .../praesentation/preview-image/+server.ts | 4 +- src/routes/sendungen/[id]/+page.server.ts | 5 +- src/routes/sendungen/[id]/+page.svelte | 2 +- src/routes/verwaltung/+page.svelte | 4 +- static/manifest.webmanifest | 11 ++ tests/ui.e2e.ts | 93 ++++++++++- 26 files changed, 610 insertions(+), 168 deletions(-) create mode 100644 migrations/0019_usage_preparation.sql create mode 100644 static/manifest.webmanifest diff --git a/docs/ACCEPTANCE.md b/docs/ACCEPTANCE.md index efc48c7..3a5f860 100644 --- a/docs/ACCEPTANCE.md +++ b/docs/ACCEPTANCE.md @@ -4,19 +4,19 @@ | Bereich | Nachweis | Stand | | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -| Abschnittsdauer und Rückkehr zu früheren Pieces (#1) | Live-Verhaltenstests für geänderte Plandauer, Wiederaufnahme, Abschnittslaufzeit und Gesamtzeit; Chromium-Ablauf | erfüllt am 25.10.2026 | -| Mobiler Live-Ablauf und Metadaten (#3, #13) | kleine Live-Regie bei 390 x 700 ohne horizontalen Überlauf; Sheet, Fokus und Viewportgrenzen im Chromium-Ablauf | Chromium erfüllt; Safari und installierte iOS-Webapp offen | -| Mobile Sendungskarten (#5) | responsive Karten im vollständigen Chromium-Lauf bei 390 Pixeln geöffnet | erfüllt am 25.10.2026 | -| Vorbereitung nach Einplanung (#6, #15) | Servertest schließt ungeplante Pieces aus und liefert konkrete Usage-Snapshots priorisiert mit Themenicons | erfüllt am 25.10.2026 | -| Kontextabhängige Präsentation (#8) | Fundus- und Usage-Editor im Chromium-Lauf; Text-, Bild-, Link- und Videozustände durch bestehende Verhaltenstests gedeckt | erfüllt am 25.10.2026 | -| Gastansicht und Freigaben (#11, #12) | Gastansicht mobil/desktop, erneut geöffnete Dialogergebnisse und Tokenersatz mit Invalidierungstest | erfüllt am 25.10.2026 | -| Iconsuche (#14) | Chromium prüft sichtbares und unmittelbar fokussiertes Suchfeld bei 390, 960 und 1280 Pixeln | erfüllt am 25.10.2026 | +| Abschnittsdauer und Rückkehr zu früheren Pieces (#1) | Live-Verhaltenstests für geänderte Plandauer, Wiederaufnahme, Abschnittslaufzeit und Gesamtzeit; Chromium-Ablauf | erfüllt am 26.10.2026 | +| Mobiler Live-Ablauf und Metadaten (#3, #13) | mobile Live-Regie ohne horizontalen Überlauf; viewportgebundenes Sheet, Safe-Area-/Standalone-Basis und Fokus in Chromium | Chromium erfüllt; Safari und installierte iOS-Webapp offen | +| Mobile Sendungskarten (#5) | responsive Karten im vollständigen Chromium-Lauf bei 390 Pixeln geöffnet | erfüllt am 26.10.2026 | +| Vorbereitung nach Einplanung (#6, #15) | Migration und Servertest für konkrete Usage-Snapshots; Chromium öffnet die Usage und entfernt sie nach „sendefertig“ | erfüllt am 26.10.2026 | +| Kontextabhängige Präsentation (#8) | vier serverseitig getrennte Modi; Fundus-/Usage-Vorschauen sowie Link-, Video-, Text-/Bildausgabe in Chromium | erfüllt am 26.10.2026 | +| Gastansicht und Freigaben (#11, #12) | gestalteter Einzeldialog, Verwaltungsreihenfolge und Kartenpadding per Chromium; Tokenersatz mit Invalidierungstest | erfüllt am 26.10.2026 | +| Iconsuche (#14) | Suchfokus innerhalb der öffnenden Bedienaktion; Chromium bei mobilen und breiten Ansichten | erfüllt am 26.10.2026 | - `npm test`: 60 von 60 Verhaltenstests erfolgreich. - `npm run lint`: erfolgreich. - `npm run check`: 0 Fehler und 0 Warnungen. - `npm run build`: erfolgreich mit `@sveltejs/adapter-node`. -- `npm run test:e2e`: 18 von 18 Chromium-Abläufen erfolgreich. +- `npm run test:e2e`: 19 von 19 Chromium-Abläufen erfolgreich. - Safari auf echtem iOS-Gerät: offen. - Installierte Webapp auf echtem iOS-Gerät: separat offen. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 876c947..918cf62 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -453,12 +453,13 @@ Präsentationsmedium. ## Wartungskorrekturen 0.7.1 -Die Vorbereitungsliste projiziert bestehende Daten statt einen zweiten -Vorbereitungszustand einzuführen: Sie verbindet aktive Sendungen mit ihren -Usage-Snapshots und berücksichtigt nur Originale im Zustand `preparing`. -Dadurch erscheinen Mehrfachplanungen als getrennte Sendungsfassungen, während -ungeplante Fundus-Pieces ausgeschlossen bleiben. Der Link adressiert die Usage -direkt; Titel und Themenicons stammen aus dem stabilen Snapshot. +Migration `0019` ergänzt `preparation_status_snapshot` und +`preparation_effort_snapshot` an `piece_usages` und übernimmt für vorhandene +Einplanungen einmalig die damaligen Originalwerte. Danach ist ausschließlich die +konkrete Sendungsfassung maßgeblich. Einplanen, Duplizieren und bewusstes +Aktualisieren aus dem Fundus kopieren beide Werte; der Usage-Editor ändert sie +unabhängig. Die Übersicht berücksichtigt vorbereitende Nicht-Reserve-Usages +aktiver Sendungen, priorisiert zuerst deren Termin und führt direkt zum Editor. Ein Freigabe-Ersatzlink rotiert ausschließlich den gehashten Token derselben Freigabe. Umfang, Passwort-Hash und Ablauf bleiben erhalten, der alte Token und diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 25e71e2..e6b9c8c 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -504,3 +504,17 @@ Weil Freigabetokens nur gehasht gespeichert werden, kann ein bestehender Link nicht erneut angezeigt werden. Ein Ersatzlink rotiert deshalb den Token derselben Freigabe transaktional und löscht alle Gastsitzungen; Sichtumfang, Passwort und Ablauf werden nicht stillschweigend verändert. + +## D-032: Vorbereitung als Eigenschaft der konkreten Einplanung + +Die erste 0.7.1-Umsetzung aus D-031 leitete den Vorbereitungszustand noch vom +veränderlichen Fundus-Original ab. Das widerspricht der bestehenden Kopierregel +für Sendungsfassungen und verhindert unterschiedliche Arbeitsstände bei +Mehrfachverwendung. D-032 ersetzt deshalb diesen Teil von D-031: Status und +Aufwand werden mit Migration `0019` additiv an `piece_usages` gespeichert. + +Vorbereitende und sendefertige Originale dürfen eingeplant werden. Einplanung, +Duplikation und ausdrückliches Aktualisieren kopieren den Zustand, während der +Usage-Editor ihn danach unabhängig ändert. `piece_usages.status` bleibt davon +getrennt und beschreibt weiterhin ausschließlich den Livezustand `open`, +`current`, `done` oder `skipped`. diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md index 2e34696..6fc2a9f 100644 --- a/docs/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -2,26 +2,32 @@ ## 0.7.1 - Bedienung und Live-Korrekturen -Veröffentlicht am 25. Oktober 2026 +Veröffentlicht am 25. Oktober 2026, Korrekturstand 26. Oktober 2026 - Live-Abschnittszeiten übernehmen geänderte Plandauern. Frühere erledigte oder übersprungene Pieces können offiziell wiederaufgenommen werden, ohne ihre Abschnittslaufzeit oder die Gesamtzeit zurückzusetzen (#1). - Mobiler Live-Ablauf, lange Metadaten und Sendungskarten halten ihre verfügbare Breite ein. Der Ablauf bleibt als fokussierbares Sheet bedienbar (#3, #5, #13). -- „Noch vorzubereiten“ zeigt nur tatsächlich eingeplante unfertige Fassungen - aktiver Sendungen, priorisiert sie und verlinkt sie mit ihren Themenicons direkt - in den Usage-Editor (#6, #15). +- „Noch vorzubereiten“ speichert Status und Aufwand an der konkreten Einplanung, + priorisiert aktive Sendungen nach Termin und verlinkt mit den Themenicons direkt + in den Usage-Editor. Vorbereitende Originale können regulär eingeplant werden; + Mehrfachverwendungen bleiben unabhängig (#6, #15). - Fundus- und Usage-Editor unterscheiden Text, Nur Bild, Linkvorschau und Video durch kontextsensitive Eingaben und passende Vorschauen (#8). -- Gastabschnitte verzichten auf unnötige äußere Karten. Freigabedialoge zeigen - den einmaligen Link nach dem Anlegen sofort wieder an, bieten Kopieren und - können einen alten Token sicher durch einen neuen ersetzen (#11, #12). +- Gast- und historische Abschnitte besitzen klar gepolsterte äußere Glaskarten. + Die Freigabeverwaltung liegt direkt vor dem Werkzeugkatalog; der gemeinsame + Dialog und seine Formfelder folgen ohne nativen Doppelrahmen dem Sendewerk- + Design. Einmalige Links lassen sich kopieren und sicher ersetzen (#11, #12). - Die Iconsuche ist nach dem Öffnen sofort sichtbar und fokussiert (#14). - RSS-Feeds und technische Zugänge verwenden in der Verwaltung kompakte Hinzufügen-Einstiege und dieselbe visuelle Listenlogik wie der Werkzeugkatalog. -- Paket, Lockdatei und Cloudron-Manifest tragen Version `0.7.1`. Es gibt keine - neue Datenbankmigration. 60 Verhaltenstests und 18 Chromium-Abläufe sind +- Mobiles Live-Sheet und Backdrop sind am Viewport verankert. Viewport-Fit, + Standalone-Metadaten und Web-App-Manifest aktivieren iOS-Safe-Areas; ein echter + Safari-/Home-Bildschirm-Test bleibt mangels Gerät offen (#3, #13). +- Paket, Lockdatei und Cloudron-Manifest tragen Version `0.7.1`. Migration + `0019_usage_preparation.sql` ergänzt additive Usage-Snapshots. 60 + Verhaltenstests und 19 Chromium-Abläufe sind erfolgreich; echtes Safari und die installierte Webapp auf iOS bleiben offen. ## 0.7.0 - RSS-Import und externe Assistenz diff --git a/docs/STATUS.md b/docs/STATUS.md index 1619827..15c5d96 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -13,24 +13,29 @@ dokumentiert. - Explizite Abschnittsdauern werden während der Live-Regie nach Änderungen synchronisiert. Erledigte oder übersprungene Pieces lassen sich bewusst wiederaufnehmen; frühere Abschnitts- und Gesamtzeiten bleiben dabei erhalten. -- Der mobile Ablauf liegt innerhalb eines isolierten Live-Containers, und lange - Metadaten verbreitern die Regie nicht mehr. Sendungskarten stapeln ihre Inhalte - auf kleinen Bildschirmen eindeutig. -- Die Vorbereitung zeigt nur konkrete Einplanungen aktiver Sendungen, deren - Fundus-Original noch in Vorbereitung ist. Usage-Titel, Sendung, Abschnitt, - Priorität und gespeicherte Themenicons führen direkt zur Sendungsfassung. +- Der mobile Ablauf liegt innerhalb eines isolierten Live-Containers, lange + Metadaten verbreitern die Regie nicht mehr und das Sheet ist am mobilen + Viewport verankert. `viewport-fit=cover`, Standalone-Metadaten und Manifest + aktivieren Safe Areas auch beim Start vom Home-Bildschirm. Sendungskarten + stapeln ihre Inhalte auf kleinen Bildschirmen eindeutig. +- Die Vorbereitung liegt als eigener Status- und Aufwandsnapshot an der konkreten + Einplanung. Vorbereitende Fundus-Pieces lassen sich planen; Originaländerungen, + Duplikation und bewusste Aktualisierung folgen der bestehenden Snapshotregel. + Usage-Titel, Sendung, Abschnitt, Termin und Themenicons führen direkt in den + Usage-Editor; „sendefertig“ entfernt die Fassung aus der Übersicht. - Text, Nur Bild, Linkvorschau und Video besitzen in Fundus- und Usage-Editor kontextsensitive Felder und Vorschauen. Ausgeblendete Werte bleiben beim Moduswechsel erhalten. -- Die Iconsuche fokussiert beim Öffnen sofort das Suchfeld. RSS-Feeds und - technische Zugänge folgen in der Verwaltung dem kompakten Katalogmuster. +- Die Iconsuche fokussiert innerhalb der öffnenden Klick-/Tastaturaktion das + Suchfeld. RSS-Feeds und technische Zugänge verwenden gestaltete Formfelder. - Lesefreigaben öffnen nach Serverantworten wieder mit dem einmalig sichtbaren Link, bieten Kopieren und sichere Ersatzlinks. Ersatzlinks invalidieren den - alten Token und dessen Gastsitzungen. Die Gastansicht trennt Abschnitte ohne - zusätzliche äußere Karten. + alten Token und dessen Gastsitzungen. Die Verwaltung zeigt Freigaben direkt + vor dem Werkzeugkatalog; der Dialog besitzt nur eine gestaltete Glasfläche. + Gast- und historische Abschnitte besitzen äußere Karten mit Innenabstand. Geprüft wurden 60 von 60 Verhaltenstests, Lint, Typprüfung, Produktionsbuild und -18 von 18 Chromium-Abläufe. Die Browsermatrix öffnete beide Piece-Editoren, +19 von 19 Chromium-Abläufe. Die Browsermatrix öffnete beide Piece-Editoren, Sendungsübersicht, Verwaltung und Freigabedialoge, Gastansicht sowie Live-Regie bei Desktop- und Mobilbreiten. Safari und die installierte Webapp auf einem echten iOS-Gerät bleiben mangels Gerät getrennt offen. diff --git a/migrations/0019_usage_preparation.sql b/migrations/0019_usage_preparation.sql new file mode 100644 index 0000000..7dcb4b0 --- /dev/null +++ b/migrations/0019_usage_preparation.sql @@ -0,0 +1,17 @@ +ALTER TABLE piece_usages ADD COLUMN preparation_status_snapshot TEXT NOT NULL DEFAULT 'ready' + CHECK (preparation_status_snapshot IN ('preparing', 'ready')); + +ALTER TABLE piece_usages ADD COLUMN preparation_effort_snapshot TEXT + CHECK (preparation_effort_snapshot IS NULL OR preparation_effort_snapshot IN ('low', 'medium', 'high')); + +UPDATE piece_usages +SET preparation_status_snapshot = CASE + WHEN EXISTS ( + SELECT 1 FROM pieces p + WHERE p.id = piece_usages.original_piece_id AND p.status = 'preparing' + ) THEN 'preparing' + ELSE 'ready' + END, + preparation_effort_snapshot = ( + SELECT p.preparation_effort FROM pieces p WHERE p.id = piece_usages.original_piece_id + ); diff --git a/src/app.css b/src/app.css index b35eb44..9c51c7c 100644 --- a/src/app.css +++ b/src/app.css @@ -113,10 +113,51 @@ } .share-management { - margin-bottom: 1.5rem; + max-height: min(82dvh, 54rem); + padding: clamp(1rem, 2.5vw, 1.4rem); + overflow-y: auto; +} + +.share-management-dialog { + width: min(64rem, calc(100% - 2rem)); + max-width: none; + max-height: none; + margin: auto; + padding: 0; + border: 1px solid var(--line-strong); + border-radius: var(--radius-large); + background: color-mix(in srgb, var(--bg-elevated) 94%, transparent); + box-shadow: var(--shadow); + color: var(--text); + overflow: hidden; + backdrop-filter: blur(24px) saturate(1.12); +} + +.share-management-dialog::backdrop { + background: rgb(3 8 16 / 58%); + backdrop-filter: blur(5px); +} + +.share-catalog-panel { + display: grid; + gap: 0.75rem; + margin-bottom: 0.75rem; padding: 1rem; } +.share-catalog-panel .panel-heading { + margin: 0; +} + +.share-catalog-panel h2 { + margin: 0.15rem 0 0; + font-size: 1rem; +} + +.share-catalog-panel .catalog-note { + margin: 0; +} + .share-create-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); @@ -133,6 +174,28 @@ font-weight: 700; } +.share-create-form :is(input, select), +.share-edit-form :is(input, select), +.integration-form :is(input, select) { + width: 100%; + min-width: 0; + min-height: 2.65rem; + padding: 0.55rem 0.7rem; + border: 1px solid var(--line-strong); + border-radius: var(--radius-small); + background: var(--field); + color: var(--text); + font: inherit; +} + +.share-create-form :is(input, select):focus-visible, +.share-edit-form :is(input, select):focus-visible, +.integration-form :is(input, select):focus-visible { + border-color: var(--accent); + outline: 2px solid color-mix(in srgb, var(--accent) 30%, transparent); + outline-offset: 1px; +} + .share-create-form button { align-self: end; } @@ -302,8 +365,11 @@ } .shared-section { - padding: 0 0 1.25rem; - border-bottom: 1px solid var(--line); + padding: clamp(1rem, 2.5vw, 1.35rem); +} + +.historical-section { + padding: clamp(1rem, 2.5vw, 1.35rem); } .shared-section > header, @@ -1328,6 +1394,7 @@ textarea:focus { } .live-controller-shell { + height: 100vh; height: 100dvh; min-height: 0; margin-left: 0 !important; @@ -1340,6 +1407,7 @@ textarea:focus { position: relative; isolation: isolate; width: 100%; + height: 100vh; height: 100dvh; grid-template-rows: auto auto minmax(0, 1fr) auto; gap: 0.55rem; @@ -2405,7 +2473,7 @@ textarea:focus { .live-page.without-rail .live-rail, .live-rail { display: grid; - position: absolute; + position: fixed; z-index: 80; inset: max(0.4rem, env(safe-area-inset-top)) max(0.4rem, env(safe-area-inset-right)) max(0.4rem, env(safe-area-inset-bottom)) auto; @@ -2429,7 +2497,7 @@ textarea:focus { .live-rail-backdrop.visible { display: block; - position: absolute; + position: fixed; z-index: 70; inset: 0; border: 0; diff --git a/src/app.html b/src/app.html index 4320f5e..bfc534d 100644 --- a/src/app.html +++ b/src/app.html @@ -2,8 +2,12 @@ - + + + + +
@@ -25,7 +32,7 @@ if (menu.open) queueMicrotask(() => searchInput.focus()); }} > - Icon auswählen + Icon auswählen