2 Commits
Author SHA1 Message Date
zemion f8d3190b4c fix(packaging): expose immutable WebUI Git package for v0.1.21
Module Package Release / publish-packages (push) Successful in 11s
2026-09-08 02:06:09 +02:00
zemion c337f2f1fa Release govoplan-dist-lists v0.1.21: unify interface contracts and documentation 2026-09-08 01:32:32 +02:00
8 changed files with 111 additions and 29 deletions
+18
View File
@@ -87,3 +87,21 @@ PYTHONPATH=src:/mnt/DATA/git/govoplan-core/src /mnt/DATA/git/govoplan/.venv/bin/
- [Distribution lists architecture](docs/DISTRIBUTION_LISTS_ARCHITECTURE.md) - [Distribution lists architecture](docs/DISTRIBUTION_LISTS_ARCHITECTURE.md)
- [Implementation plan](docs/IMPLEMENTATION_PLAN.md) - [Implementation plan](docs/IMPLEMENTATION_PLAN.md)
- [AdreMa capability assessment](docs/ADREMA_CAPABILITY_ASSESSMENT.md) - [AdreMa capability assessment](docs/ADREMA_CAPABILITY_ASSESSMENT.md)
## Git-source WebUI package
The repository root exposes `@govoplan/dist-lists-webui` for Git-tagged release
dependencies. It mirrors the owning `webui/package.json` version, public
TypeScript/CSS exports and peer requirements, with entry paths under
`webui/src`. Consumers provide the shared Core/React peers; the facade runs no
development or install scripts. The source archive contains `webui/src`, this
README and any repository license file. Run module development checks from `webui/`; Python
installation remains governed by `pyproject.toml`.
Das Repository stellt `@govoplan/dist-lists-webui` am Wurzelpfad für versionierte
Git-Abhängigkeiten bereit. Version, öffentliche TypeScript-/CSS-Exporte und
Peer-Anforderungen entsprechen `webui/package.json`; die Einstiegspfade liegen
unter `webui/src`. Gemeinsame Core-/React-Peers stellt die einbindende Anwendung
bereit. Die Fassade führt keine Entwicklungs- oder Installationsskripte aus.
Entwicklungsprüfungen bleiben in `webui/`, die Python-Installation weiterhin in
`pyproject.toml` definiert.
+34
View File
@@ -0,0 +1,34 @@
{
"name": "@govoplan/dist-lists-webui",
"version": "0.1.21",
"private": true,
"type": "module",
"main": "webui/src/index.ts",
"module": "webui/src/index.ts",
"types": "webui/src/index.ts",
"exports": {
".": {
"types": "./webui/src/index.ts",
"import": "./webui/src/index.ts"
},
"./styles/dist-lists.css": "./webui/src/styles/dist-lists.css"
},
"peerDependencies": {
"@govoplan/core-webui": "^0.1.45",
"lucide-react": "^1.23.0",
"react": ">=19.2.7 <20",
"react-dom": ">=19.2.7 <20",
"react-router": ">=8.3.0 <9",
"typescript": "^5.7.2"
},
"peerDependenciesMeta": {
"@govoplan/core-webui": {
"optional": true
}
},
"files": [
"webui/src",
"README.md",
"LICENSE"
]
}
+2 -2
View File
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "govoplan-dist-lists" name = "govoplan-dist-lists"
version = "0.1.20" version = "0.1.21"
description = "GovOPlaN operational distribution lists and governed audience expansion." description = "GovOPlaN operational distribution lists and governed audience expansion."
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
authors = [{ name = "GovOPlaN" }] authors = [{ name = "GovOPlaN" }]
dependencies = [ dependencies = [
"govoplan-core>=0.1.18", "govoplan-core>=0.1.45",
] ]
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
+1 -1
View File
@@ -2,4 +2,4 @@
__all__ = ["__version__"] __all__ = ["__version__"]
__version__ = "0.1.20" __version__ = "0.1.21"
+20 -3
View File
@@ -57,7 +57,7 @@ from govoplan_dist_lists.backend.dsar_provider import (
MODULE_ID = "dist_lists" MODULE_ID = "dist_lists"
MODULE_NAME = "Distribution Lists" MODULE_NAME = "Distribution Lists"
MODULE_VERSION = "0.1.20" MODULE_VERSION = "0.1.21"
READ_SCOPE = "dist_lists:list:read" READ_SCOPE = "dist_lists:list:read"
WRITE_SCOPE = "dist_lists:list:write" WRITE_SCOPE = "dist_lists:list:write"
@@ -106,6 +106,21 @@ ROLE_TEMPLATES = (
) )
DOCUMENTATION = ( 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( DocumentationTopic(
id=f"{MODULE_ID}.data-subject-requests", id=f"{MODULE_ID}.data-subject-requests",
title="Distribution-list data-subject requests", title="Distribution-list data-subject requests",
@@ -176,7 +191,8 @@ DOCUMENTATION = (
body=( body=(
"Distribution Lists owns reusable mixed recipient definitions and expansion snapshots. " "Distribution Lists owns reusable mixed recipient definitions and expansion snapshots. "
"Address lists remain in the addresses module and represent address-domain groupings only. " "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", layer="available",
documentation_types=("admin", "user"), documentation_types=("admin", "user"),
@@ -212,7 +228,8 @@ DOCUMENTATION = (
"body": ( "body": (
"Distribution Lists führt wiederverwendbare gemischte Empfängerdefinitionen und Erweiterungsschnappschüsse. " "Distribution Lists führt wiederverwendbare gemischte Empfängerdefinitionen und Erweiterungsschnappschüsse. "
"Adresslisten verbleiben im Modul Addresses und bilden ausschließlich Gruppierungen des Adressbereichs ab. " "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."
), ),
} }
}, },
+3 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@govoplan/dist-lists-webui", "name": "@govoplan/dist-lists-webui",
"version": "0.1.20", "version": "0.1.21",
"private": true, "private": true,
"type": "module", "type": "module",
"main": "src/index.ts", "main": "src/index.ts",
@@ -14,10 +14,11 @@
"./styles/dist-lists.css": "./src/styles/dist-lists.css" "./styles/dist-lists.css": "./src/styles/dist-lists.css"
}, },
"scripts": { "scripts": {
"test:action-layout": "node scripts/test-action-layout.mjs",
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit"
}, },
"peerDependencies": { "peerDependencies": {
"@govoplan/core-webui": "^0.1.18", "@govoplan/core-webui": "^0.1.45",
"lucide-react": "^1.23.0", "lucide-react": "^1.23.0",
"react": ">=19.2.7 <20", "react": ">=19.2.7 <20",
"react-dom": ">=19.2.7 <20", "react-dom": ">=19.2.7 <20",
+9
View File
@@ -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, /<TableActionGroup actions=\{\[\{\s*id: "explain"/);
assert.match(page, /<DataGridRowActions/);
console.log("Distribution List controls use the shared action-column contract.");
@@ -37,6 +37,7 @@ import { DialogSection, FormGrid, ActionToolbar,
SelectionListItemContent, SelectionListItemContent,
StatePanel, StatePanel,
StatusBadge, StatusBadge,
TableActionGroup,
ToggleSwitch, ToggleSwitch,
WorkspaceActionBar, WorkspaceActionBar,
WorkspaceFrame, WorkspaceFrame,
@@ -412,6 +413,7 @@ export default function DistributionListsPage({ settings, auth }: Props) {
{ {
id: "actions", id: "actions",
header: "Actions", header: "Actions",
columnType: "actions",
width: 205, width: 205,
sticky: "end", sticky: "end",
render: (entry, index) => ( render: (entry, index) => (
@@ -487,15 +489,16 @@ export default function DistributionListsPage({ settings, auth }: Props) {
{ {
id: "actions", id: "actions",
header: "Details", header: "Details",
columnType: "actions",
width: 90, width: 90,
sticky: "end", sticky: "end",
render: (row) => ( render: (row) => (
<IconButton <TableActionGroup actions={[{
label="Explain this result" id: "explain",
icon={<Eye size={16} />} label: "Explain this result",
variant="ghost" icon: <Eye size={16} aria-hidden="true" />,
onClick={() => setExplanationTarget(row)} onClick: () => setExplanationTarget(row)
/> }]} />
) )
} }
], []); ], []);
@@ -540,18 +543,8 @@ export default function DistributionListsPage({ settings, auth }: Props) {
return ( return (
<WorkspaceFrame as="main" height="viewport" surface="plain" className="dist-lists-page" label="Distribution lists workspace"> <WorkspaceFrame as="main" height="viewport" surface="plain" className="dist-lists-page" label="Distribution lists workspace">
<WorkspaceLayout
variant="split"
primarySize="compact"
surface="contained"
primaryScrollable={false}
contentScrollable={false}
primaryLabel="Distribution lists"
contentLabel="Distribution list workspace"
contentClassName="dist-lists-workspace"
primary={<>
<WorkspaceActionBar <WorkspaceActionBar
scope="collection-pane" scope="workspace"
variant="collection" variant="collection"
refreshable refreshable
reloadAction={{ onReload: () => void reload(selectedId), loading: loading || busy }} reloadAction={{ onReload: () => void reload(selectedId), loading: loading || busy }}
@@ -565,6 +558,16 @@ export default function DistributionListsPage({ settings, auth }: Props) {
onClick={() => requestDiscard(() => setCreateOpen(true))} onClick={() => requestDiscard(() => setCreateOpen(true))}
/>} />}
/> />
<WorkspaceLayout
variant="split"
primarySize="compact"
surface="contained"
primaryScrollable={false}
contentScrollable={false}
primaryLabel="Distribution lists"
contentLabel="Distribution list workspace"
contentClassName="dist-lists-workspace"
primary={<>
<FilterBar surface="panel"> <FilterBar surface="panel">
<input <input
type="search" type="search"