diff --git a/pyproject.toml b/pyproject.toml index 8df3955..83e2fd6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-dist-lists" -version = "0.1.20" +version = "0.1.21" description = "GovOPlaN operational distribution lists and governed audience expansion." readme = "README.md" requires-python = ">=3.12" authors = [{ name = "GovOPlaN" }] dependencies = [ - "govoplan-core>=0.1.18", + "govoplan-core>=0.1.45", ] [tool.setuptools.packages.find] diff --git a/src/govoplan_dist_lists/__init__.py b/src/govoplan_dist_lists/__init__.py index f693781..4d50492 100644 --- a/src/govoplan_dist_lists/__init__.py +++ b/src/govoplan_dist_lists/__init__.py @@ -2,4 +2,4 @@ __all__ = ["__version__"] -__version__ = "0.1.20" +__version__ = "0.1.21" diff --git a/src/govoplan_dist_lists/backend/manifest.py b/src/govoplan_dist_lists/backend/manifest.py index c83f154..5a05777 100644 --- a/src/govoplan_dist_lists/backend/manifest.py +++ b/src/govoplan_dist_lists/backend/manifest.py @@ -57,7 +57,7 @@ from govoplan_dist_lists.backend.dsar_provider import ( MODULE_ID = "dist_lists" MODULE_NAME = "Distribution Lists" -MODULE_VERSION = "0.1.20" +MODULE_VERSION = "0.1.21" READ_SCOPE = "dist_lists:list:read" WRITE_SCOPE = "dist_lists:list:write" @@ -106,6 +106,21 @@ ROLE_TEMPLATES = ( ) DOCUMENTATION = ( + DocumentationTopic( + id="dist_lists.workspace-layout", + title="Distribution Lists workspace actions", + summary="Find collection-wide commands in their consistent workspace position.", + body="Reload and New distribution list use the persistent full-width workspace header at the upper right; Reload sits immediately before creation. Selecting a record, changing filters, or opening an editor does not move these collection-wide commands into the left pane. Member editing and saving stay with the selected list; membership, provenance, and delivery semantics are unchanged. Existing permissions, disabled-state rules, and unsaved-change guards still apply. Administrators configure authority through the existing permission system; no new permission or automatic operation is introduced.", + layer="static", + documentation_types=("user", "admin"), + audience=("user", "module_admin", "operator"), + order=5, + translations={"de": { + "title": "Verteilerlisten: Aktionen im Arbeitsbereich", + "summary": "Sammlungsweite Aktionen an ihrer einheitlichen Position im Arbeitsbereich finden.", + "body": "Neu laden und Neue Verteilerliste stehen oben rechts in der dauerhaft sichtbaren, arbeitsbereichsweiten Leiste; Neu laden steht unmittelbar vor dem Anlegen. Auswahl, Filterwechsel und Bearbeitung verschieben diese sammlungsweiten Aktionen nicht in den linken Bereich. Bearbeiten der Mitglieder und Speichern bleiben bei der ausgewählten Liste; Mitgliedschaft, Herkunftsnachweise und Zustellungssemantik ändern sich nicht. Bestehende Berechtigungen, Deaktivierungsregeln und der Schutz ungespeicherter Änderungen gelten weiterhin. Administratoren konfigurieren Rechte im bestehenden Berechtigungssystem; es entstehen weder neue Rechte noch automatische Vorgänge.", + }}, + ), DocumentationTopic( id=f"{MODULE_ID}.data-subject-requests", title="Distribution-list data-subject requests", @@ -176,7 +191,8 @@ DOCUMENTATION = ( body=( "Distribution Lists owns reusable mixed recipient definitions and expansion snapshots. " "Address lists remain in the addresses module and represent address-domain groupings only. " - "Workflow and Tasks own Umlauf execution state, ordering, deadlines, escalation, and completion." + "Workflow and Tasks own Umlauf execution state, ordering, deadlines, escalation, and completion. " + "Entry editing and result-explanation controls use the shared action-column layout and stay reachable at the right edge when wide tables are scrolled." ), layer="available", documentation_types=("admin", "user"), @@ -212,7 +228,8 @@ DOCUMENTATION = ( "body": ( "Distribution Lists führt wiederverwendbare gemischte Empfängerdefinitionen und Erweiterungsschnappschüsse. " "Adresslisten verbleiben im Modul Addresses und bilden ausschließlich Gruppierungen des Adressbereichs ab. " - "Workflow und Tasks führen Ausführungszustand, Reihenfolge, Fristen, Eskalation und Abschluss von Umläufen." + "Workflow und Tasks führen Ausführungszustand, Reihenfolge, Fristen, Eskalation und Abschluss von Umläufen. " + "Die Steuerelemente zum Bearbeiten von Einträgen und Erläutern von Ergebnissen verwenden das gemeinsame Aktionsspaltenlayout und bleiben beim Scrollen breiter Tabellen am rechten Rand erreichbar." ), } }, diff --git a/webui/package.json b/webui/package.json index f18a64a..bef073d 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/dist-lists-webui", - "version": "0.1.20", + "version": "0.1.21", "private": true, "type": "module", "main": "src/index.ts", @@ -14,10 +14,11 @@ "./styles/dist-lists.css": "./src/styles/dist-lists.css" }, "scripts": { + "test:action-layout": "node scripts/test-action-layout.mjs", "typecheck": "tsc --noEmit" }, "peerDependencies": { - "@govoplan/core-webui": "^0.1.18", + "@govoplan/core-webui": "^0.1.45", "lucide-react": "^1.23.0", "react": ">=19.2.7 <20", "react-dom": ">=19.2.7 <20", diff --git a/webui/scripts/test-action-layout.mjs b/webui/scripts/test-action-layout.mjs new file mode 100644 index 0000000..e4c4efe --- /dev/null +++ b/webui/scripts/test-action-layout.mjs @@ -0,0 +1,9 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; + +const page = readFileSync(new URL("../src/features/distributionLists/DistributionListsPage.tsx", import.meta.url), "utf8"); +assert.match(page, /id: "actions",\s*header: "Actions",\s*columnType: "actions",\s*width: 205,\s*sticky: "end"/); +assert.match(page, /id: "actions",\s*header: "Details",\s*columnType: "actions",\s*width: 90,\s*sticky: "end"/); +assert.match(page, / ( @@ -487,15 +489,16 @@ export default function DistributionListsPage({ settings, auth }: Props) { { id: "actions", header: "Details", + columnType: "actions", width: 90, sticky: "end", render: (row) => ( - } - variant="ghost" - onClick={() => setExplanationTarget(row)} - /> +