diff --git a/src/govoplan_scheduling/backend/manifest.py b/src/govoplan_scheduling/backend/manifest.py index b371b06..c54f7ca 100644 --- a/src/govoplan_scheduling/backend/manifest.py +++ b/src/govoplan_scheduling/backend/manifest.py @@ -115,7 +115,10 @@ DOCUMENTATION = ( id="scheduling.workspace-layout", title="Scheduling workspace layout", summary="Find workspace actions and read consistently arranged content.", - body="The workspace always keeps Reload and New scheduling request at the upper right, including empty, detail, and editor states. Reload sits immediately before New. Creation remains visible but disabled while saving or without creation/write permission; it never disappears inside the request-list card. An open editor keeps its own Save and Discard actions and the unsaved-change guard applies before switching requests. Administrators grant existing Scheduling permissions; this layout adds no permission or automatic invitation or Calendar action.", + body="Documentation books sit immediately beside the visible heading or contextual label for " + "Scheduling, the selected request and public participation details, not among operational " + "action buttons. Field help remains beside its label. " + "The workspace always keeps Reload and New scheduling request at the upper right, including empty, detail, and editor states. Reload sits immediately before New. Creation remains visible but disabled while saving or without creation/write permission; it never disappears inside the request-list card. An open editor keeps its own Save and Discard actions and the unsaved-change guard applies before switching requests. Administrators grant existing Scheduling permissions; this layout adds no permission or automatic invitation or Calendar action.", layer="static", documentation_types=("user", "admin"), audience=("user", "module_admin", "operator"), @@ -123,7 +126,11 @@ DOCUMENTATION = ( translations={"de": { "title": "Terminfindung: Aufbau des Arbeitsbereichs", "summary": "Arbeitsbereichsaktionen finden und einheitlich angeordnete Inhalte lesen.", - "body": "Der Arbeitsbereich zeigt Neu laden und Neue Terminanfrage immer oben rechts, auch in leerem Zustand, Detailansicht und Bearbeitung. Neu laden steht unmittelbar vor Neu. Das Anlegen bleibt beim Speichern oder ohne Schreibrecht sichtbar, aber deaktiviert; es verschwindet nicht innerhalb der Anfragekartenleiste. Ein geöffneter Editor behält Speichern und Verwerfen; beim Wechsel schützt die Rückfrage ungespeicherte Änderungen. Administratoren vergeben bestehende Scheduling-Rechte; dieses Layout fügt weder Rechte noch automatische Einladungen oder Kalenderaktionen hinzu.", + "body": "Dokumentationsbücher stehen unmittelbar neben der sichtbaren Überschrift oder " + "Kontextbezeichnung für Terminfindung, die ausgewählte Anfrage und öffentliche " + "Teilnahmedetails, nicht zwischen ausführbaren Aktionsschaltflächen. Feldhilfe bleibt neben " + "der Feldbezeichnung. " + "Der Arbeitsbereich zeigt Neu laden und Neue Terminanfrage immer oben rechts, auch in leerem Zustand, Detailansicht und Bearbeitung. Neu laden steht unmittelbar vor Neu. Das Anlegen bleibt beim Speichern oder ohne Schreibrecht sichtbar, aber deaktiviert; es verschwindet nicht innerhalb der Anfragekartenleiste. Ein geöffneter Editor behält Speichern und Verwerfen; beim Wechsel schützt die Rückfrage ungespeicherte Änderungen. Administratoren vergeben bestehende Scheduling-Rechte; dieses Layout fügt weder Rechte noch automatische Einladungen oder Kalenderaktionen hinzu.", }}, ), DocumentationTopic( diff --git a/tests/test_manifest.py b/tests/test_manifest.py index 4c5ce2b..bd903f5 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -1,12 +1,23 @@ from __future__ import annotations import unittest +from pathlib import Path from govoplan_core.core.modules import ModuleManifest from govoplan_scheduling.backend.manifest import get_manifest class SchedulingManifestTests(unittest.TestCase): + def test_widget_documentation_is_contributed_for_its_dashboard_title(self) -> None: + root = Path(__file__).resolve().parents[1] + contribution = (root / "webui/src/module.ts").read_text(encoding="utf-8") + widget = (root / "webui/src/features/scheduling/SchedulingRequestsWidget.tsx").read_text(encoding="utf-8") + self.assertIn( + 'documentation: { topicId: "scheduling.find-and-decide-meeting-time", documentationType: "user" }', + contribution, + ) + self.assertNotIn("DocumentationHelpLink", widget) + def test_all_static_topics_have_complete_german_content(self) -> None: manifest = get_manifest() for topic in manifest.documentation: diff --git a/webui/scripts/test-scheduling-page-structure.mjs b/webui/scripts/test-scheduling-page-structure.mjs index 69dc9ca..15a10f3 100644 --- a/webui/scripts/test-scheduling-page-structure.mjs +++ b/webui/scripts/test-scheduling-page-structure.mjs @@ -201,7 +201,8 @@ assert.match(enrollmentPage, /topicId: "scheduling\.public-self-enrollment"/); assert.doesNotMatch(enrollmentPage, /window\.(?:alert|confirm)\(/); assert.doesNotMatch(enrollmentPage, /(?:localStorage|sessionStorage).*(?:token|proof)|(?:token|proof).*(?:localStorage|sessionStorage)/); -assert.match(widget, /DocumentationHelpLink/); +assert.doesNotMatch(widget, /DocumentationHelpLink/, "widget help belongs to the host card title, not a detached footer"); +assert.match(moduleSource, /documentation: \{ topicId: "scheduling\.find-and-decide-meeting-time", documentationType: "user" \}/); assert.match(widget, /to: `\/scheduling\?request_id=\$\{encodeURIComponent\(request\.id\)\}`/); assert.match(widget, /label=\{request\.status === "collecting" \? I18N\.open : I18N\.draft\}/); assert.doesNotMatch(widget, /Loading scheduling requests|Open scheduling|No scheduling requests are awaiting responses/); diff --git a/webui/src/features/scheduling/SchedulingEnrollmentPage.tsx b/webui/src/features/scheduling/SchedulingEnrollmentPage.tsx index ce54843..df259a2 100644 --- a/webui/src/features/scheduling/SchedulingEnrollmentPage.tsx +++ b/webui/src/features/scheduling/SchedulingEnrollmentPage.tsx @@ -202,11 +202,11 @@ export default function SchedulingEnrollmentPage({ settings, auth }: SchedulingE {enrollment ? (