import { useEffect, useMemo, useState } from "react"; import { Link, useLocation } from "react-router-dom"; import { ChevronDown, ChevronRight, RefreshCw } from "lucide-react"; import { Button, DataGrid, DismissibleAlert, ExplorerTree, LoadingFrame, PageTitle, SegmentedControl, StatusBadge, adminErrorMessage, useGuardedNavigate, usePlatformLanguage, type ApiSettings, type DataGridColumn } from "@govoplan/core-webui"; import { fetchDocsContext, type DocsContext, type DocsDocumentationTopic, type DocsModule, type DocsOptionalModuleEvidence, type DocsRoute, type DocsSource } from "../../api/docs"; type DocumentationType = "admin" | "user"; type DocsPageNode = | { id: string; title: string; kind: "topic"; topic: DocsDocumentationTopic; } | { id: string; title: string; kind: "topic-list"; topics: DocsDocumentationTopic[]; emptyText: string; } | { id: string; title: string; kind: "admin-reference"; }; type DocsTreeNode = { id: string; title: string; page: DocsPageNode; children: DocsTreeNode[]; }; type OutlineItem = { id: string; label: string; }; export default function DocsPage({ settings }: { settings: ApiSettings }) { const location = useLocation(); const navigate = useGuardedNavigate(); const { language } = usePlatformLanguage(); const [context, setContext] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [documentationType, setDocumentationType] = useState(() => documentationTypeFromSearch(location.search)); const [expandedNodes, setExpandedNodes] = useState>(() => new Set()); const locale = localeFromSearch(location.search) ?? language; const adminDocs = documentationType === "admin"; async function load() { setLoading(true); setError(""); try { setContext(await fetchDocsContext(settings, { documentationType, locale })); } catch (err) { setError(adminErrorMessage(err)); } finally { setLoading(false); } } useEffect(() => { const nextType = documentationTypeFromSearch(location.search); setDocumentationType((current) => current === nextType ? current : nextType); }, [location.search]); useEffect(() => { void load(); }, [settings.apiBaseUrl, settings.apiKey, settings.accessToken, documentationType, locale]); const treeNodes = useMemo(() => docsTreeNodes(context, adminDocs), [context, adminDocs]); const pages = useMemo(() => flattenTreePages(treeNodes), [treeNodes]); const selectedPage = selectedPageFromSearch(location.search, pages); const topicById = useMemo(() => topicIndex(context), [context]); const visibleRoutes = context?.layers.configured.routes ?? []; const availableRoutes = context?.layers.available.routes ?? []; const grantedPermissions = context?.layers.configured.permissions.filter((item) => item.granted) ?? []; const moduleRows = useMemo(() => context?.layers.configured.modules ?? [], [context]); const outlineItems = outlineForPage(selectedPage, adminDocs); useEffect(() => { setExpandedNodes(new Set(defaultExpandedNodeIds(treeNodes))); }, [treeNodes]); useEffect(() => { if (!selectedPage) return; const ancestorIds = ancestorNodeIdsForPage(treeNodes, selectedPage.id); if (!ancestorIds.length) return; setExpandedNodes((current) => { const next = new Set(current); for (const nodeId of ancestorIds) { next.add(nodeId); } return next; }); }, [treeNodes, selectedPage?.id]); return (
i18n:govoplan-docs.help_center.f3f3a34b

{adminDocs ? "i18n:govoplan-docs.technical_documentation_for_the_modules_and_conf.267e739e" : "i18n:govoplan-docs.guidance_for_the_functions_available_in_this_ins.723b7cad"}

{error && {error}}
); function selectDocumentationType(type: DocumentationType) { const params = new URLSearchParams(location.search); params.set("type", type); navigate(`${location.pathname}?${params.toString()}`, { replace: true }); } function selectPage(page: DocsPageNode) { const params = new URLSearchParams(location.search); params.set("topic", page.id); navigate(`${location.pathname}?${params.toString()}`, { replace: true }); } function toggleNode(nodeId: string) { setExpandedNodes((current) => { const next = new Set(current); if (next.has(nodeId)) { next.delete(nodeId); } else { next.add(nodeId); } return next; }); } } function AudienceToggle({ selected, onSelect, canViewAdmin }: { selected: DocumentationType; onSelect: (type: DocumentationType) => void; canViewAdmin: boolean }) { const options: Array<{ id: DocumentationType; label: string }> = [ { id: "user", label: "i18n:govoplan-docs.user_docs.1e38e8d3" } ]; if (canViewAdmin) { options.unshift({ id: "admin", label: "i18n:govoplan-docs.admin_docs.bf504a56" }); } return ( ); } function PageOutline({ items }: { items: OutlineItem[] }) { return ( ); } function SelectedPageContent({ page, adminDocs, documentationType, topicById, moduleRows, visibleRoutes, availableRoutes, grantedPermissions, evidenceModules, evidenceSources }: { page: DocsPageNode | null; adminDocs: boolean; documentationType: DocumentationType; topicById: Map; moduleRows: DocsModule[]; visibleRoutes: DocsRoute[]; availableRoutes: DocsRoute[]; grantedPermissions: Array<{ scope: string; label: string; category: string }>; evidenceModules: DocsOptionalModuleEvidence[]; evidenceSources: DocsSource[]; }) { if (!page) { return (

i18n:govoplan-docs.help_center.f3f3a34b

i18n:govoplan-docs.no_system_topics_found.d01a8068

); } if (page.kind === "topic") { return ; } if (page.kind === "admin-reference") { return (

{page.title}

i18n:govoplan-docs.modules.04e9462c

i18n:govoplan-docs.visible_routes.6c9b1605

i18n:govoplan-docs.available_routes.c2635868

i18n:govoplan-docs.granted_permissions.0a232e78

); } return (

{page.title}

); } function TopicPage({ topic, showTechnical, documentationType, topicById }: { topic: DocsDocumentationTopic; showTechnical: boolean; documentationType: DocumentationType; topicById: Map }) { return (
{topic.source_module_id} {showTechnical && {topic.i18n_key} · {topic.translation_locale}}

{topic.title}

{topic.summary &&

{topic.summary}

}
{!topic.active && }
{!!topic.unlocks.length &&

i18n:govoplan-docs.unlocks.67d569db {topic.unlocks.join(" ")}

} {!!topic.links.length && }
); } function DocumentationTopicList({ topics, emptyText, showTechnical = false, documentationType, topicById }: { topics: DocsDocumentationTopic[]; emptyText: string; showTechnical?: boolean; documentationType: DocumentationType; topicById: Map }) { if (!topics.length) return

{emptyText}

; return (
{topics.map((topic) =>
{topic.source_module_id} {showTechnical && {topic.i18n_key} · {topic.translation_locale}}

{topic.title}

{topic.summary &&

{topic.summary}

} {!topic.active && } {!!topic.unlocks.length &&

i18n:govoplan-docs.unlocks.67d569db {topic.unlocks.join(" ")}

} {!!topic.links.length && }
)}
); } function TopicMetadata({ topic, showTechnical, documentationType, topicById }: { topic: DocsDocumentationTopic; showTechnical: boolean; documentationType: DocumentationType; topicById: Map }) { const configuredDetails = ; if (topic.kind === "workflow") return <>{configuredDetails}; if (topic.kind === "reference") return <>{configuredDetails}; if (topic.kind === "pattern") return <>{configuredDetails}; return <>{configuredDetails}; } function ConfiguredDetails({ topic }: { topic: DocsDocumentationTopic }) { const currentConfiguration = metadataList(topic.metadata, "current_configuration"); const limitations = metadataList(topic.metadata, "limitations"); const constraints = metadataRecords(topic.metadata, "constraints"); const prefix = topicAnchorId(topic); if (!currentConfiguration.length && !limitations.length && !constraints.length) return null; return (
{!!currentConfiguration.length && } {!!constraints.length && } {!!limitations.length && }
); } function WorkflowDetails({ topic, documentationType, topicById }: { topic: DocsDocumentationTopic; documentationType: DocumentationType; topicById: Map }) { const prerequisites = metadataList(topic.metadata, "prerequisites"); const steps = metadataList(topic.metadata, "steps"); const outcome = metadataString(topic.metadata, "outcome"); const result = metadataString(topic.metadata, "result"); const verification = metadataString(topic.metadata, "verification"); const prefix = topicAnchorId(topic); return (
{outcome && } {!!prerequisites.length && } {!!steps.length &&

i18n:govoplan-docs.steps.6041435e

    {steps.map((step) =>
  1. {step}
  2. )}
} {result && } {verification && }
); } function ConstraintDetails({ id, constraints }: { id: string; constraints: Record[] }) { return (

i18n:govoplan-docs.requirements.09a428f9

{constraints.map((constraint, index) => { const label = metadataString(constraint, "label"); const description = metadataString(constraint, "description"); const values = metadataList(constraint, "values"); return (
{label}
{description} {!!values.length && {values.join(", ")}}
); })}
); } function ReferenceDetails({ topic, showTechnical, documentationType, topicById }: { topic: DocsDocumentationTopic; showTechnical: boolean; documentationType: DocumentationType; topicById: Map }) { const route = metadataString(topic.metadata, "route"); const screen = metadataString(topic.metadata, "screen"); const section = metadataString(topic.metadata, "section"); const fields = metadataRecords(topic.metadata, "fields"); return (
{(route || screen || section) &&
{screen &&
i18n:govoplan-docs.screen.c4878ec4
{screen}
} {section &&
i18n:govoplan-docs.section.5e498158
{section}
} {showTechnical && route &&
i18n:govoplan-docs.route.4999528e
{route}
}
} {!!fields.length && }
); } function ReferenceFieldTable({ id, fields, showTechnical }: { id: string; fields: Record[]; showTechnical: boolean }) { const columns: DataGridColumn>[] = [ { id: "field", header: "i18n:govoplan-docs.field.7558c082", width: "minmax(180px, .8fr)", minWidth: 160, resizable: true, sortable: true, filterable: true, value: (field) => metadataString(field, "label"), render: (field) => {metadataString(field, "label")} }, { id: "meaning", header: "i18n:govoplan-docs.meaning.584d8aa0", width: "minmax(260px, 1.3fr)", minWidth: 220, resizable: true, filterable: true, value: (field) => [metadataString(field, "user_description"), metadataString(field, "admin_description"), metadataString(field, "provenance")].join(" "), render: (field) =>
{metadataString(field, "user_description")}{showTechnical && metadataString(field, "admin_description") && {metadataString(field, "admin_description")}}{showTechnical && metadataString(field, "provenance") && {metadataString(field, "provenance")}}
}, ...(showTechnical ? [ { id: "api", header: "i18n:govoplan-docs.api_mapping.e969f6f7", width: "minmax(190px, .8fr)", minWidth: 170, resizable: true, filterable: true, value: (field: Record) => `${metadataString(field, "api_path")} ${metadataString(field, "api_field")}`, render: (field: Record) =>
{metadataString(field, "api_path")}{metadataString(field, "api_field")}
}, { id: "permission", header: "i18n:govoplan-docs.permission.d71c9448", width: 190, filterable: true, value: (field: Record) => metadataString(field, "permission_scope") || "-", render: (field: Record) => metadataString(field, "permission_scope") || "-" } ] satisfies DataGridColumn>[] : []), { id: "validation", header: "i18n:govoplan-docs.validation.ef7f6d9c", width: "minmax(180px, .7fr)", minWidth: 160, resizable: true, filterable: true, value: (field) => metadataString(field, "validation") || "-", render: (field) => metadataString(field, "validation") || "-" } ]; return (
metadataString(field, "field_id") || metadataString(field, "label")} />
); } function PatternDetails({ topic, showTechnical, documentationType, topicById }: { topic: DocsDocumentationTopic; showTechnical: boolean; documentationType: DocumentationType; topicById: Map }) { const purpose = metadataString(topic.metadata, "purpose"); const whenUsed = metadataString(topic.metadata, "when_used"); const explanation = showTechnical ? metadataString(topic.metadata, "admin_explanation") : metadataString(topic.metadata, "user_explanation"); const componentRefs = metadataList(topic.metadata, "component_refs"); const prefix = topicAnchorId(topic); return (
{purpose && } {whenUsed && } {explanation && } {showTechnical && !!componentRefs.length && }
); } function DetailBlock({ id, title, value }: { id: string; title: string; value: string }) { return (

{title}

{value}

); } function DetailList({ id, title, items }: { id: string; title: string; items: string[] }) { return (

{title}

    {items.map((item) =>
  • {item}
  • )}
); } function RelatedTopics({ topic, documentationType, topicById }: { topic: DocsDocumentationTopic; documentationType: DocumentationType; topicById: Map }) { const related = metadataList(topic.metadata, "related_topic_ids") .map((id) => topicById.get(id)) .filter((item): item is DocsDocumentationTopic => Boolean(item)); if (!related.length) return null; return (

i18n:govoplan-docs.related_topics.d5eb8b74 {related.map((item, index) => {index > 0 && " | "} {item.title} )}

); } function TopicLinks({ topic }: { topic: DocsDocumentationTopic }) { return (

{topic.links.map((link, index) => {index > 0 && " | "} {link.label} )}

); } function BodyText({ value }: { value: string }) { if (!value) return null; return ( <> {value.split("\n").filter(Boolean).map((line) =>

{line}

)} ); } function UnavailableDocumentationReason({ topic }: { topic: DocsDocumentationTopic }) { const rows = [ ["i18n:govoplan-docs.modules.04e9462c", topic.blockers.modules], ["i18n:govoplan-docs.capabilities.ca09c54b", topic.blockers.capabilities], ["i18n:govoplan-docs.permissions.d06d5557", topic.blockers.scopes] ].filter(([, values]) => Array.isArray(values) && values.length); return (

{topic.reason}

{!!rows.length &&
{rows.map(([label, values]) =>
{label}
{(values as string[]).join(", ")}
)}
}
); } function docsTreeNodes(context: DocsContext | null, adminDocs: boolean): DocsTreeNode[] { const allTopics = allDocumentationTopics(context); const systemTopics = context?.topic_groups.system ?? []; const workflowTopics = context?.topic_groups.workflow ?? []; const referenceTopics = context?.topic_groups.reference ?? []; const patternTopics = context?.topic_groups.pattern ?? []; const systemTopicIds = new Set(systemTopics.map((topic) => topic.id)); const moduleTopics = allTopics.filter((topic) => !systemTopicIds.has(topic.id)); const workingTopics = uniqueTopics([...patternTopics, ...workflowTopics]); const troubleshootingTopics = allTopics.filter((topic) => !topic.active || topic.layer === "evidence"); const basicsNode = categoryTreeNode( "basics", "i18n:govoplan-docs.basics.5fcebeef", patternTopics, "i18n:govoplan-docs.no_basic_topics_found.ee5ec3c6" ); const commonTasksNode = categoryTreeNode( "common-tasks", "i18n:govoplan-docs.common_tasks.9f825c48", workflowTopics, "i18n:govoplan-docs.no_common_task_topics_found.c17814cf" ); const nodes: DocsTreeNode[] = [ categoryTreeNode( "about-govoplan", "i18n:govoplan-docs.about_govoplan.6b2d7127", systemTopics, "i18n:govoplan-docs.no_about_topics_found.7cd8af6d" ), { id: "tree:working-with-govoplan", title: "i18n:govoplan-docs.working_with_govoplan.81908ef4", page: { id: "working-with-govoplan:overview", title: "i18n:govoplan-docs.working_with_govoplan.81908ef4", kind: "topic-list", topics: workingTopics, emptyText: "i18n:govoplan-docs.no_working_with_govoplan_topics_found.b6db8384" }, children: [basicsNode, commonTasksNode] }, categoryTreeNode( "advanced", "i18n:govoplan-docs.advanced.203a8d6b", referenceTopics, "i18n:govoplan-docs.no_advanced_topics_found.271166c9" ), { id: "tree:modules", title: "i18n:govoplan-docs.modules.04e9462c", page: { id: "modules:overview", title: "i18n:govoplan-docs.modules.04e9462c", kind: "topic-list", topics: moduleTopics, emptyText: "i18n:govoplan-docs.no_module_topics_found.0cbbdc9b" }, children: moduleTreeNodes(moduleTopics, context) } ]; if (adminDocs) { nodes.push({ id: "tree:administration", title: "i18n:govoplan-docs.administration.101aedaf", page: { id: "administration:overview", title: "i18n:govoplan-docs.administration.101aedaf", kind: "topic-list", topics: referenceTopics, emptyText: "i18n:govoplan-docs.no_administration_topics_found.6213dff2" }, children: [ ...referenceTopics.map(topicTreeNode), { id: "tree:administration:technical-reference", title: "i18n:govoplan-docs.technical_reference.f271430d", page: { id: "system:technical-reference", title: "i18n:govoplan-docs.technical_reference.f271430d", kind: "admin-reference" }, children: [] } ] }); } if (troubleshootingTopics.length) { nodes.push(categoryTreeNode( "troubleshooting", "i18n:govoplan-docs.troubleshooting_and_support.3d42f434", troubleshootingTopics, "i18n:govoplan-docs.no_troubleshooting_topics_found.8c275468" )); } return nodes; } function categoryTreeNode(id: string, title: string, topics: DocsDocumentationTopic[], emptyText: string): DocsTreeNode { const sortedTopics = [...topics].sort((left, right) => left.order - right.order || left.title.localeCompare(right.title)); return { id: `tree:${id}`, title, page: { id: `${id}:overview`, title, kind: "topic-list", topics: sortedTopics, emptyText }, children: nestedTopicNodes(sortedTopics) }; } function topicPage(topic: DocsDocumentationTopic): DocsPageNode { return { id: topic.id, title: topic.title, kind: "topic", topic }; } function topicTreeNode(topic: DocsDocumentationTopic): DocsTreeNode { return { id: `tree:topic:${topic.id}`, title: topic.title, page: topicPage(topic), children: [] }; } function moduleTreeNodes(topics: DocsDocumentationTopic[], context: DocsContext | null): DocsTreeNode[] { const topicsByModule = new Map(); for (const topic of topics) { const moduleTopics = topicsByModule.get(topic.source_module_id) ?? []; moduleTopics.push(topic); topicsByModule.set(topic.source_module_id, moduleTopics); } const configuredModules = context?.layers.configured.modules ?? []; const moduleOrder = new Map(configuredModules.map((module, index) => [module.id, index])); return Array.from(topicsByModule.entries()) .sort(([left], [right]) => (moduleOrder.get(left) ?? 999) - (moduleOrder.get(right) ?? 999) || moduleTitle(left, context).localeCompare(moduleTitle(right, context))) .map(([moduleId, moduleTopics]) => { const sortedTopics = [...moduleTopics].sort((left, right) => left.order - right.order || left.title.localeCompare(right.title)); const title = moduleTitle(moduleId, context); return { id: `tree:module:${moduleId}`, title, page: { id: `module:${moduleId}`, title, kind: "topic-list", topics: sortedTopics, emptyText: "i18n:govoplan-docs.no_system_topics_found.d01a8068" }, children: nestedTopicNodes(sortedTopics) }; }); } function nestedTopicNodes(topics: DocsDocumentationTopic[]): DocsTreeNode[] { const nodes = new Map(topics.map((topic) => [topic.id, topicTreeNode(topic)])); const roots: DocsTreeNode[] = []; for (const topic of topics) { const node = nodes.get(topic.id); if (!node) continue; const parentId = topicParentId(topic); const parent = parentId ? nodes.get(parentId) : undefined; if (parent && parentId !== topic.id) { parent.children.push(node); } else { roots.push(node); } } return roots; } function topicParentId(topic: DocsDocumentationTopic): string { return metadataString(topic.metadata, "tree_parent_id") || metadataString(topic.metadata, "parent_topic_id") || metadataString(topic.metadata, "parent_id"); } function moduleTitle(moduleId: string, context: DocsContext | null): string { const module = context?.layers.configured.modules.find((item) => item.id === moduleId); if (module) return module.name; return moduleId .replace(/^govoplan[-_]/, "") .split(/[-_]+/) .filter(Boolean) .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) .join(" ") || moduleId; } function flattenTreePages(nodes: DocsTreeNode[]): DocsPageNode[] { return nodes.flatMap((node) => [node.page, ...flattenTreePages(node.children)]); } function defaultExpandedNodeIds(nodes: DocsTreeNode[]): string[] { return nodes.filter((node) => node.children.length).map((node) => node.id); } function ancestorNodeIdsForPage(nodes: DocsTreeNode[], pageId: string, ancestors: string[] = []): string[] { for (const node of nodes) { if (node.page.id === pageId) return ancestors; const match = ancestorNodeIdsForPage(node.children, pageId, [...ancestors, node.id]); if (match.length) return match; } return []; } function activeNodeIdForPage(nodes: DocsTreeNode[], pageId: string): string { if (!pageId) return ""; for (const node of nodes) { if (node.page.id === pageId) return node.id; const childId = activeNodeIdForPage(node.children, pageId); if (childId) return childId; } return ""; } function allDocumentationTopics(context: DocsContext | null): DocsDocumentationTopic[] { const topics = Object.values(context?.topic_groups ?? {}).flat(); return uniqueTopics(topics).sort((left, right) => left.order - right.order || left.title.localeCompare(right.title)); } function uniqueTopics(topics: DocsDocumentationTopic[]): DocsDocumentationTopic[] { const seen = new Set(); return topics.filter((topic) => { if (seen.has(topic.id)) return false; seen.add(topic.id); return true; }); } function selectedPageFromSearch(search: string, pages: DocsPageNode[]): DocsPageNode | null { if (!pages.length) return null; const params = new URLSearchParams(search); const requested = params.get("topic") || ""; if (requested) return pages.find((page) => page.id === requested) ?? pages[0]; const helpContext = params.get("context") || ""; if (helpContext) { const exact = pages.find((page) => page.kind === "topic" && metadataList(page.topic.metadata, "help_contexts").includes(helpContext)); if (exact) return exact; const moduleId = helpContextModuleId(helpContext); const moduleTopic = pages.find((page) => page.kind === "topic" && page.topic.source_module_id === moduleId); if (moduleTopic) return moduleTopic; } return pages[0]; } function helpContextModuleId(value: string): string { const prefix = value.split(".", 1)[0]; if (prefix === "campaign") return "campaigns"; if (prefix === "address-book") return "addresses"; return prefix; } function outlineForPage(page: DocsPageNode | null, showTechnical: boolean): OutlineItem[] { if (!page) return []; if (page.kind === "admin-reference") { return [ { id: page.id, label: page.title }, { id: "docs-admin-modules", label: "i18n:govoplan-docs.modules.04e9462c" }, { id: "docs-admin-routes", label: "i18n:govoplan-docs.routes.03730e58" }, { id: "docs-admin-permissions", label: "i18n:govoplan-docs.permissions.d06d5557" } ]; } if (page.kind === "topic-list") { return [ { id: page.id, label: page.title }, ...page.topics.map((topic) => ({ id: topicAnchorId(topic), label: topic.title })) ]; } const topic = page.topic; const prefix = topicAnchorId(topic); const items: OutlineItem[] = [{ id: prefix, label: topic.title }]; if (topic.summary) items.push({ id: `${prefix}-summary`, label: "i18n:govoplan-docs.summary.d6b9936d" }); if (metadataList(topic.metadata, "current_configuration").length) items.push({ id: `${prefix}-current-configuration`, label: "i18n:govoplan-docs.this_system.b13a51ad" }); if (metadataRecords(topic.metadata, "constraints").length) items.push({ id: `${prefix}-constraints`, label: "i18n:govoplan-docs.requirements.09a428f9" }); if (metadataList(topic.metadata, "limitations").length) items.push({ id: `${prefix}-limitations`, label: "i18n:govoplan-docs.details.a6b3c45f" }); if (topic.kind === "workflow") { if (metadataString(topic.metadata, "outcome")) items.push({ id: `${prefix}-outcome`, label: "i18n:govoplan-docs.outcome.10172bd3" }); if (metadataList(topic.metadata, "prerequisites").length) items.push({ id: `${prefix}-prerequisites`, label: "i18n:govoplan-docs.prerequisites.fdf2407f" }); if (metadataList(topic.metadata, "steps").length) items.push({ id: `${prefix}-steps`, label: "i18n:govoplan-docs.steps.6041435e" }); if (metadataString(topic.metadata, "result")) items.push({ id: `${prefix}-result`, label: "i18n:govoplan-docs.result.1f4fbf43" }); if (metadataString(topic.metadata, "verification")) items.push({ id: `${prefix}-verification`, label: "i18n:govoplan-docs.verification.4b5f10dd" }); } if (topic.kind === "reference" && metadataRecords(topic.metadata, "fields").length) { items.push({ id: `${prefix}-fields`, label: "i18n:govoplan-docs.field.7558c082" }); } if (topic.kind === "pattern") { if (metadataString(topic.metadata, "purpose")) items.push({ id: `${prefix}-purpose`, label: "i18n:govoplan-docs.purpose.4af40581" }); if (metadataString(topic.metadata, "when_used")) items.push({ id: `${prefix}-when-used`, label: "i18n:govoplan-docs.when_used.b870b361" }); if (showTechnical && metadataList(topic.metadata, "component_refs").length) items.push({ id: `${prefix}-components`, label: "i18n:govoplan-docs.components.e81e57d8" }); } return items; } function documentationTypeFromSearch(search: string): DocumentationType { return new URLSearchParams(search).get("type") === "admin" ? "admin" : "user"; } function localeFromSearch(search: string): string | null { const value = new URLSearchParams(search).get("locale"); if (!value) return null; return value.toLowerCase().startsWith("de") ? "de" : "en"; } function topicAnchorId(topic: DocsDocumentationTopic): string { return topic.anchor_id || `docs-topic-${topic.source_module_id}-${topic.id}`.replace(/[^a-z0-9_-]+/gi, "-").toLowerCase(); } function topicPageHref(topic: DocsDocumentationTopic, documentationType: DocumentationType): string { const params = new URLSearchParams(); params.set("type", documentationType); params.set("topic", topic.id); return `?${params.toString()}#${topicAnchorId(topic)}`; } function topicIndex(context: DocsContext | null): Map { const index = new Map(); for (const topic of allDocumentationTopics(context)) { index.set(topic.id, topic); } return index; } function metadataString(metadata: Record, key: string): string { const value = metadata[key]; return typeof value === "string" ? value : ""; } function metadataList(metadata: Record, key: string): string[] { const value = metadata[key]; if (!Array.isArray(value)) return []; return value.filter((item): item is string => typeof item === "string"); } function metadataRecords(metadata: Record, key: string): Record[] { const value = metadata[key]; if (!Array.isArray(value)) return []; return value.filter((item): item is Record => Boolean(item) && typeof item === "object" && !Array.isArray(item)); } function ModuleTable({ modules }: { modules: DocsModule[] }) { if (!modules.length) return

i18n:govoplan-docs.no_configured_modules_found.f6f9ce24

; const columns: DataGridColumn[] = [ { id: "module", header: "i18n:govoplan-docs.module.b8ff0289", width: "minmax(220px, 1fr)", minWidth: 190, resizable: true, sortable: true, filterable: true, value: (module) => `${module.name} ${module.id} ${module.version}`, render: (module) =>
{module.name}{module.id} {module.version}
}, { id: "routes", header: "i18n:govoplan-docs.routes.03730e58", width: 170, sortable: true, value: (module) => module.route_count, render: (module) => <>{module.route_count} i18n:govoplan-docs.route.200e2a66 {module.nav_count} nav }, { id: "permissions", header: "i18n:govoplan-docs.permissions.d06d5557", width: 130, sortable: true, value: (module) => module.permission_count }, { id: "frontend", header: "i18n:govoplan-docs.frontend.152d1cf2", width: "minmax(180px, .8fr)", minWidth: 160, resizable: true, sortable: true, filterable: true, value: (module) => module.frontend_package || "-", render: (module) => module.frontend_package || "-" }, { id: "capabilities", header: "i18n:govoplan-docs.capabilities.ca09c54b", width: "minmax(260px, 1.2fr)", minWidth: 220, resizable: true, filterable: true, value: (module) => module.capabilities.join(" "), render: (module) =>
{module.capabilities.length ? module.capabilities.join(", ") : "-"}{module.documentation_count || module.documentation_provider_count ? {module.documentation_count} i18n:govoplan-docs.docs.5dc1e9b8 {module.documentation_provider_count} provider : null}
} ]; return ( module.id} /> ); } function RouteTable({ routes, emptyText }: { routes: DocsRoute[]; emptyText: string }) { if (!routes.length) return

{emptyText}

; const columns: DataGridColumn[] = [ { id: "route", header: "i18n:govoplan-docs.route.4999528e", width: "minmax(240px, 1fr)", minWidth: 200, resizable: true, sortable: true, filterable: true, value: (route) => `${route.label} ${route.path}`, render: (route) =>
{route.label}{route.path}
}, { id: "module", header: "i18n:govoplan-docs.module.b8ff0289", width: 160, sortable: true, filterable: true, value: (route) => route.module_id }, { id: "source", header: "i18n:govoplan-docs.source.6da13add", width: 160, sortable: true, filterable: true, value: (route) => route.source }, { id: "requirements", header: "i18n:govoplan-docs.requirements.09a428f9", width: "minmax(220px, 1fr)", minWidth: 180, resizable: true, filterable: true, value: (route) => routeRequirements(route) }, { id: "status", header: "i18n:govoplan-docs.status.bae7d5be", width: 160, sortable: true, filterable: true, value: (route) => route.visible ? "visible" : route.reason, render: (route) => } ]; return ( `${route.source}-${route.module_id}-${route.path}`} /> ); } function PermissionList({ permissions }: { permissions: Array<{ scope: string; label: string; category: string }> }) { if (!permissions.length) return

i18n:govoplan-docs.no_granted_platform_permissions_found.36010898

; return (
{permissions.slice(0, 24).map((permission) =>
{permission.category}
{permission.label} · {permission.scope}
)} {permissions.length > 24 &&
i18n:govoplan-docs.more.4bab2d8f
{permissions.length - 24} i18n:govoplan-docs.additional_permissions.8042cb01
}
); } function EvidenceList({ modules, sources }: { modules: DocsOptionalModuleEvidence[]; sources: DocsSource[] }) { if (!modules.length && !sources.length) return

i18n:govoplan-docs.no_evidence_sources_found.be3bb2f6

; return (
{modules.map((item) =>
{item.module_id} · {item.reason}
)} {sources.map((item) =>
{item.layer}
{item.label} · {item.source}
)}
); } function routeRequirements(route: DocsRoute): string { const parts = []; if (route.required_all.length) parts.push(`all: ${route.required_all.join(", ")}`); if (route.required_any.length) parts.push(`any: ${route.required_any.join(", ")}`); return parts.join(" | ") || "-"; }