feat: publish case launch context and product area

This commit is contained in:
2026-08-18 21:32:25 +02:00
parent 83e69565fe
commit 2efe574f18
3 changed files with 65 additions and 4 deletions
+50
View File
@@ -26,6 +26,7 @@ from govoplan_core.core.modules import (
ModuleManifest, ModuleManifest,
NavItem, NavItem,
PermissionDefinition, PermissionDefinition,
ProductAreaContribution,
RoleTemplate, RoleTemplate,
) )
from govoplan_core.core.views import ViewSurface from govoplan_core.core.views import ViewSurface
@@ -216,6 +217,17 @@ manifest = ModuleManifest(
order=35, order=35,
), ),
), ),
product_areas=(
ProductAreaContribution(
id="services-cases",
module_id=MODULE_ID,
label="i18n:govoplan-core.product_area.services_cases",
icon="landmark",
description="i18n:govoplan-core.product_area.services_cases_description",
surface_ids=("cases.nav.cases", "cases.route.cases", "cases.route.cases.caseid"),
order=20,
),
),
view_surfaces=( view_surfaces=(
ViewSurface( ViewSurface(
id="cases.navigation", id="cases.navigation",
@@ -388,6 +400,44 @@ manifest = ModuleManifest(
), ),
tenant_summary_providers=(_tenant_summary,), tenant_summary_providers=(_tenant_summary,),
documentation=( documentation=(
DocumentationTopic(
id="cases.workflow.quick-access-context",
title="Use task-local tools from an active Case",
summary="Launch an authorized full-page tool and return to the exact Case route and context.",
body=(
"After an exact Case revision loads, the Case detail page publishes a bounded active-object reference to Core. "
"Quick Access may carry that reference together with the current tenant, acting assignment, temporal selection, "
"View revision, and route when opening an owning module's full page. It never carries Case content or an access "
"decision. The destination reauthorizes its data and effects. Unsaved Case edits use the shared save/discard guard "
"before navigation, and the shell provides an explicit return action."
),
layer="available",
documentation_types=("admin", "user"),
audience=("case_manager", "operator", "module_admin"),
related_modules=("quick_access", "views", "access"),
order=13,
links=(
DocumentationLink(label="Cases", href="/cases", kind="runtime"),
DocumentationLink(
label="Quick Access architecture",
href="govoplan/docs/architecture/QUICK_ACCESS_AND_PRODUCT_AREAS.md",
kind="repository",
),
),
translations={
"de": {
"title": "Aufgabenbezogene Werkzeuge aus einem aktiven Vorgang verwenden",
"summary": "Ein berechtigtes Werkzeug oeffnen und zum genauen Vorgangskontext zurueckkehren.",
"body": (
"Nach dem Laden einer genauen Vorgangsrevision veroeffentlicht die Detailseite einen begrenzten Objektverweis an Core. "
"Der Schnellzugriff darf diesen Verweis zusammen mit Mandant, handelnder Zuordnung, Zeitbezug, Ansichtsversion und Ruecksprungort uebergeben. "
"Vorgangsinhalte oder Zugriffsentscheidungen werden nicht uebertragen. Das Ziel prueft Daten und Wirkungen erneut; ungespeicherte Aenderungen "
"werden vor dem Wechsel durch den gemeinsamen Speichern-Verwerfen-Dialog geschuetzt."
),
}
},
metadata={"help_contexts": ["cases.detail.quick-access"]},
),
DocumentationTopic( DocumentationTopic(
id="cases.workflow.record-formal-decision", id="cases.workflow.record-formal-decision",
title="Record a formal Decision from a Case", title="Record a formal Decision from a Case",
@@ -14,6 +14,7 @@ import { ActionToolbar,
hasScope, hasScope,
usePlatformModuleInstalled, usePlatformModuleInstalled,
useGuardedNavigate, useGuardedNavigate,
useRegisterActiveObject,
useUnsavedDraftGuard, useUnsavedDraftGuard,
type PlatformRouteContext type PlatformRouteContext
} from "@govoplan/core-webui"; } from "@govoplan/core-webui";
@@ -74,6 +75,16 @@ export default function CaseDetailPage({ settings, auth }: PlatformRouteContext)
? "Enable Mandates to verify formal authority." ? "Enable Mandates to verify formal authority."
: undefined; : undefined;
const canFileRecords = recordsAvailable && hasScope(auth, "records:workspace:write"); const canFileRecords = recordsAvailable && hasScope(auth, "records:workspace:write");
const activeCase = useMemo(() => record ? {
ownerModule: record.reference.owner_module,
kind: record.reference.kind,
objectId: record.reference.object_id,
tenantId: record.reference.tenant_id,
label: `${record.case_number} · ${record.title}`,
version: record.reference.version ?? String(record.revision),
path: `/cases/${encodeURIComponent(record.reference.object_id)}`
} : null, [record]);
useRegisterActiveObject(activeCase);
const load = useCallback((signal?: AbortSignal) => { const load = useCallback((signal?: AbortSignal) => {
setLoading(true); setLoading(true);
+4 -4
View File
@@ -97,7 +97,7 @@
margin-top: 16px; margin-top: 16px;
padding: 14px; padding: 14px;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 6px; border-radius: var(--radius-compact);
background: var(--surface-raised); background: var(--surface-raised);
} }
@@ -128,7 +128,7 @@
margin-top: 18px; margin-top: 18px;
background: var(--border); background: var(--border);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 6px; border-radius: var(--radius-compact);
overflow: hidden; overflow: hidden;
} }
@@ -233,7 +233,7 @@
.case-decision-list > article { .case-decision-list > article {
padding: 12px; padding: 12px;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 6px; border-radius: var(--radius-compact);
background: var(--surface-raised); background: var(--surface-raised);
} }
@@ -326,7 +326,7 @@
font-size: 0.76rem; font-size: 0.76rem;
} }
@media (max-width: 860px) { @media (max-width: 900px) {
.cases-count { .cases-count {
margin-left: 0; margin-left: 0;
} }