2 Commits
Author SHA1 Message Date
zemion 1d6eef386d fix(ui): align contextual documentation with headings
Verified with the coordinated workspace changes by devkit full run
2026-09-08T225814-186389-0000-3e3ed7cd (all seven phases passed).
This shared UI pass does not mark the individual module reviews complete.
2026-09-09 02:03:35 +02:00
zemion 96c48a7f2d refactor(committee): reuse exact Core actor selection contract
Module Package Release / publish-packages (push) Successful in 13s
Release v0.1.22. Coordinated integrity review: GovOPlaN/govoplan-core#298.
2026-09-08 12:19:37 +02:00
8 changed files with 16 additions and 24 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@govoplan/committee-webui", "name": "@govoplan/committee-webui",
"version": "0.1.21", "version": "0.1.22",
"private": true, "private": true,
"description": "GovOPlaN Committee platform module seed.", "description": "GovOPlaN Committee platform module seed.",
"type": "module", "type": "module",
+2 -2
View File
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "govoplan-committee" name = "govoplan-committee"
version = "0.1.21" version = "0.1.22"
description = "GovOPlaN committee governance and formal-decision integration module." description = "GovOPlaN committee governance and formal-decision integration module."
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
license = { file = "LICENSE" } license = { file = "LICENSE" }
authors = [{ name = "GovOPlaN" }] authors = [{ name = "GovOPlaN" }]
dependencies = [ dependencies = [
"govoplan-core>=0.1.18", "govoplan-core>=0.1.46",
"govoplan-access>=0.1.18", "govoplan-access>=0.1.18",
] ]
+7 -3
View File
@@ -59,7 +59,7 @@ from govoplan_core.db.base import Base
MODULE_ID = "committee" MODULE_ID = "committee"
MODULE_NAME = "Committee" MODULE_NAME = "Committee"
MODULE_VERSION = "0.1.21" MODULE_VERSION = "0.1.22"
READ_SCOPE = "committee:workspace:read" READ_SCOPE = "committee:workspace:read"
WRITE_SCOPE = "committee:workspace:write" WRITE_SCOPE = "committee:workspace:write"
BALLOT_SCOPE = "committee:ballot:finalize" BALLOT_SCOPE = "committee:ballot:finalize"
@@ -558,7 +558,9 @@ manifest = ModuleManifest(
id="committee.workspace-layout", id="committee.workspace-layout",
title="Committee workspace layout", title="Committee workspace layout",
summary="Find workspace actions and read consistently arranged content.", summary="Find workspace actions and read consistently arranged content.",
body="Reload and New body share the workspace-wide action bar at the upper right; Reload sits directly before New. Searching and selecting a body, meeting, or agenda item leaves those workspace actions in place. Item editing, ballots, and finalization remain scoped to the selected record. Disabled controls explain missing authority; administrators grant the existing management permissions rather than changing layouts.", body="Documentation books sit beside the Committee workspace heading and beside record or ballot "
"dialog titles; field help stays with its label. "
"Reload and New body share the workspace-wide action bar at the upper right; Reload sits directly before New. Searching and selecting a body, meeting, or agenda item leaves those workspace actions in place. Item editing, ballots, and finalization remain scoped to the selected record. Disabled controls explain missing authority; administrators grant the existing management permissions rather than changing layouts.",
layer="static", layer="static",
documentation_types=("user", "admin"), documentation_types=("user", "admin"),
audience=("user", "module_admin", "operator"), audience=("user", "module_admin", "operator"),
@@ -566,7 +568,9 @@ manifest = ModuleManifest(
translations={"de": { translations={"de": {
"title": "Gremien: Aufbau des Arbeitsbereichs", "title": "Gremien: Aufbau des Arbeitsbereichs",
"summary": "Arbeitsbereichsaktionen finden und einheitlich angeordnete Inhalte lesen.", "summary": "Arbeitsbereichsaktionen finden und einheitlich angeordnete Inhalte lesen.",
"body": "Neu laden und Neues Gremium stehen oben rechts in der gemeinsamen Arbeitsbereichsleiste; Neu laden steht unmittelbar vor Neu. Suche und Auswahl eines Gremiums, einer Sitzung oder eines Tagesordnungspunkts verändern diese Positionen nicht. Bearbeitung, Abstimmungen und Abschluss bleiben dem ausgewählten Datensatz zugeordnet. Deaktivierte Aktionen erklären fehlende Berechtigungen; Administratoren vergeben die bestehenden Verwaltungsrechte, statt das Layout zu ändern.", "body": "Dokumentationsbücher stehen neben der Überschrift des Gremienarbeitsbereichs sowie neben den "
"Titeln der Eintrags- und Abstimmungsdialoge; Feldhilfe bleibt bei der Feldbezeichnung. "
"Neu laden und Neues Gremium stehen oben rechts in der gemeinsamen Arbeitsbereichsleiste; Neu laden steht unmittelbar vor Neu. Suche und Auswahl eines Gremiums, einer Sitzung oder eines Tagesordnungspunkts verändern diese Positionen nicht. Bearbeitung, Abstimmungen und Abschluss bleiben dem ausgewählten Datensatz zugeordnet. Deaktivierte Aktionen erklären fehlende Berechtigungen; Administratoren vergeben die bestehenden Verwaltungsrechte, statt das Layout zu ändern.",
}}, }},
), ),
DocumentationTopic( DocumentationTopic(
+1 -14
View File
@@ -11,6 +11,7 @@ import uuid
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from govoplan_core.core.principal_helpers import principal_user_first_actor as _principal_actor
from govoplan_core.core.events import ( from govoplan_core.core.events import (
EventActorRef, EventActorRef,
EventObjectRef, EventObjectRef,
@@ -1001,20 +1002,6 @@ def _principal_tenant(principal: object) -> str:
return tenant_id return tenant_id
def _principal_actor(principal: object) -> str | None:
user = getattr(principal, "user", None)
for value in (
getattr(user, "id", None),
getattr(principal, "account_id", None),
getattr(principal, "identity_id", None),
getattr(principal, "membership_id", None),
):
candidate = str(value or "").strip()
if candidate:
return candidate
return None
def _session(value: object) -> Session: def _session(value: object) -> Session:
if not hasattr(value, "query"): if not hasattr(value, "query"):
raise InstitutionalContextError( raise InstitutionalContextError(
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@govoplan/committee-webui", "name": "@govoplan/committee-webui",
"version": "0.1.21", "version": "0.1.22",
"private": true, "private": true,
"type": "module", "type": "module",
"main": "src/index.ts", "main": "src/index.ts",
@@ -102,6 +102,7 @@ export default function CommitteeBallotDialog({
<Dialog <Dialog
open={open} open={open}
title={votingBallotId ? "Finalize Voting ballot" : "Finalize provider ballot"} title={votingBallotId ? "Finalize Voting ballot" : "Finalize provider ballot"}
titleHelp={<DocumentationHelpLink reference={COMMITTEE_FIELD_DOCUMENTATION} />}
onClose={requestClose} onClose={requestClose}
closeDisabled={busy} closeDisabled={busy}
portal portal
@@ -121,7 +122,6 @@ export default function CommitteeBallotDialog({
} }
> >
<div className="committee-record-form"> <div className="committee-record-form">
<div className="committee-dialog-help"><DocumentationHelpLink reference={COMMITTEE_FIELD_DOCUMENTATION} /></div>
{error ? <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert> : null} {error ? <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert> : null}
<p className="committee-dialog-note"> <p className="committee-dialog-note">
{votingBallotId {votingBallotId
@@ -186,6 +186,8 @@ export default function CommitteePage({ settings, auth }: PlatformRouteContext)
<main className="committee-page"> <main className="committee-page">
<WorkspaceFrame className="committee-shell" label="Committee workspace" interfaceId="committee.workspace" helpContextId="committee.page.workspace" helpModuleId="committee"> <WorkspaceFrame className="committee-shell" label="Committee workspace" interfaceId="committee.workspace" helpContextId="committee.page.workspace" helpModuleId="committee">
<WorkspaceActionBar <WorkspaceActionBar
title="Committee"
titleHelp={<DocumentationHelpLink reference={COMMITTEE_DOCUMENTATION} />}
scope="workspace" scope="workspace"
variant="collection" variant="collection"
refreshable refreshable
@@ -204,7 +206,6 @@ export default function CommitteePage({ settings, auth }: PlatformRouteContext)
<Plus size={16} aria-hidden="true" /> <Plus size={16} aria-hidden="true" />
New body New body
</Button>} </Button>}
helpAction={<DocumentationHelpLink reference={COMMITTEE_DOCUMENTATION} />}
/> />
{error ? <DismissibleAlert tone="danger" resetKey={error} className="committee-alert">{error}</DismissibleAlert> : null} {error ? <DismissibleAlert tone="danger" resetKey={error} className="committee-alert">{error}</DismissibleAlert> : null}
@@ -155,6 +155,7 @@ export default function CommitteeRecordDialog({
action: translateText(record ? "Edit" : "New"), action: translateText(record ? "Edit" : "New"),
kind: translateText(kindLabel(kind)) kind: translateText(kindLabel(kind))
})} })}
titleHelp={<DocumentationHelpLink reference={COMMITTEE_FIELD_DOCUMENTATION} />}
onClose={requestClose} onClose={requestClose}
closeDisabled={busy} closeDisabled={busy}
portal portal
@@ -174,7 +175,6 @@ export default function CommitteeRecordDialog({
} }
> >
<div className="committee-record-form"> <div className="committee-record-form">
<div className="committee-dialog-help"><DocumentationHelpLink reference={COMMITTEE_FIELD_DOCUMENTATION} /></div>
{error ? <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert> : null} {error ? <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert> : null}
<FormGrid columns={2} gap="compact" collapseAt="narrow"> <FormGrid columns={2} gap="compact" collapseAt="narrow">
<FormField label="Title" documentation={COMMITTEE_FIELD_DOCUMENTATION}> <FormField label="Title" documentation={COMMITTEE_FIELD_DOCUMENTATION}>