diff --git a/src/govoplan_docs/backend/api/v1/routes.py b/src/govoplan_docs/backend/api/v1/routes.py index 4d788d5..5ecc00d 100644 --- a/src/govoplan_docs/backend/api/v1/routes.py +++ b/src/govoplan_docs/backend/api/v1/routes.py @@ -47,77 +47,167 @@ def docs_context( visible_route_items = [item for item in route_items if item["visible"]] documentation_layers = _documentation_layers(request, registry, principal, documentation_type=documentation_type, locale=resolved_locale) if documentation_type == "admin": - visible_routes = visible_route_items - modules = [_module_payload(manifest, technical=True) for manifest in registry.manifests()] - permissions = [_permission_payload(permission, principal) for permission in registry.permissions()] - available_routes = [item for item in route_items if not item["visible"]] - optional_modules = _optional_module_evidence(registry.manifests()) + catalog = _admin_documentation_catalog( + registry, + principal, + route_items=route_items, + visible_route_items=visible_route_items, + ) else: - visible_module_ids = { - *(str(item["module_id"]) for item in visible_route_items), - *(str(topic["source_module_id"]) for topic in _all_documentation_topics(documentation_layers)), - } - modules = [ + catalog = _user_documentation_catalog( + registry, + visible_route_items=visible_route_items, + documentation_layers=documentation_layers, + ) + topic_groups = _documentation_topic_groups(documentation_layers) + return { + "actor": _documentation_actor( + principal, + documentation_type=documentation_type, + locale=resolved_locale, + can_read_admin=can_read_admin_documentation, + ), + "summary": _documentation_summary( + catalog, + documentation_layers=documentation_layers, + topic_groups=topic_groups, + ), + "topic_groups": topic_groups, + "layers": _documentation_layer_payload( + catalog, + documentation_layers=documentation_layers, + include_evidence_sources=documentation_type == "admin", + ), + } + + +def _admin_documentation_catalog( + registry: PlatformRegistry, + principal: ApiPrincipal, + *, + route_items: list[dict[str, Any]], + visible_route_items: list[dict[str, Any]], +) -> dict[str, list[dict[str, Any]]]: + return { + "modules": [ + _module_payload(manifest, technical=True) + for manifest in registry.manifests() + ], + "permissions": [ + _permission_payload(permission, principal) + for permission in registry.permissions() + ], + "visible_routes": visible_route_items, + "available_routes": [item for item in route_items if not item["visible"]], + "optional_modules": _optional_module_evidence(registry.manifests()), + } + + +def _user_documentation_catalog( + registry: PlatformRegistry, + *, + visible_route_items: list[dict[str, Any]], + documentation_layers: Mapping[str, list[dict[str, Any]]], +) -> dict[str, list[dict[str, Any]]]: + visible_module_ids = { + *(str(item["module_id"]) for item in visible_route_items), + *( + str(topic["source_module_id"]) + for topic in _all_documentation_topics(documentation_layers) + ), + } + return { + "modules": [ _module_payload(manifest, technical=False) for manifest in registry.manifests() if manifest.id in visible_module_ids - ] - permissions = [] - visible_routes = _user_route_payloads(visible_route_items) - available_routes = [] - optional_modules = [] - documentation_count = sum(len(layer) for layer in documentation_layers.values()) - topic_groups = _documentation_topic_groups(documentation_layers) + ], + "permissions": [], + "visible_routes": _user_route_payloads(visible_route_items), + "available_routes": [], + "optional_modules": [], + } - actor_payload: dict[str, Any] = { + +def _documentation_actor( + principal: ApiPrincipal, + *, + documentation_type: DocumentationType, + locale: str, + can_read_admin: bool, +) -> dict[str, Any]: + actor: dict[str, Any] = { "documentation_type": documentation_type, - "locale": resolved_locale, - "available_documentation_types": ["user", *(["admin"] if can_read_admin_documentation else [])], + "locale": locale, + "available_documentation_types": [ + "user", + *(["admin"] if can_read_admin else []), + ], } if documentation_type == "admin": - actor_payload.update( + actor.update( tenant_id=principal.tenant_id, user_id=principal.user.id, scope_count=len(principal.scopes), ) + return actor + +def _documentation_summary( + catalog: Mapping[str, list[dict[str, Any]]], + *, + documentation_layers: Mapping[str, list[dict[str, Any]]], + topic_groups: Mapping[str, list[dict[str, Any]]], +) -> dict[str, int]: + permissions = catalog["permissions"] return { - "actor": actor_payload, - "summary": { - "module_count": len(modules), - "visible_route_count": len(visible_routes), - "available_route_count": len(available_routes), - "permission_count": len(permissions), - "granted_permission_count": sum(1 for item in permissions if item["granted"]), - "optional_module_count": len(optional_modules), - "documentation_topic_count": documentation_count, - "configured_documentation_topic_count": len(documentation_layers["configured"]), - "workflow_topic_count": len(topic_groups["workflow"]), - "reference_topic_count": len(topic_groups["reference"]), - "pattern_topic_count": len(topic_groups["pattern"]), - "system_topic_count": len(topic_groups["system"]), + "module_count": len(catalog["modules"]), + "visible_route_count": len(catalog["visible_routes"]), + "available_route_count": len(catalog["available_routes"]), + "permission_count": len(permissions), + "granted_permission_count": sum( + 1 for item in permissions if item["granted"] + ), + "optional_module_count": len(catalog["optional_modules"]), + "documentation_topic_count": sum( + len(layer) for layer in documentation_layers.values() + ), + "configured_documentation_topic_count": len( + documentation_layers["configured"] + ), + "workflow_topic_count": len(topic_groups["workflow"]), + "reference_topic_count": len(topic_groups["reference"]), + "pattern_topic_count": len(topic_groups["pattern"]), + "system_topic_count": len(topic_groups["system"]), + } + + +def _documentation_layer_payload( + catalog: Mapping[str, list[dict[str, Any]]], + *, + documentation_layers: Mapping[str, list[dict[str, Any]]], + include_evidence_sources: bool, +) -> dict[str, dict[str, object]]: + permissions = catalog["permissions"] + return { + "always": { + "documentation": documentation_layers["always"], }, - "topic_groups": topic_groups, - "layers": { - "always": { - "documentation": documentation_layers["always"], - }, - "configured": { - "modules": modules, - "routes": visible_routes, - "permissions": permissions, - "documentation": documentation_layers["configured"], - }, - "available": { - "routes": available_routes, - "permissions": [item for item in permissions if not item["granted"]], - "documentation": documentation_layers["available"], - }, - "evidence": { - "optional_modules": optional_modules, - "sources": _evidence_sources() if documentation_type == "admin" else [], - "documentation": documentation_layers["evidence"], - }, + "configured": { + "modules": catalog["modules"], + "routes": catalog["visible_routes"], + "permissions": permissions, + "documentation": documentation_layers["configured"], + }, + "available": { + "routes": catalog["available_routes"], + "permissions": [item for item in permissions if not item["granted"]], + "documentation": documentation_layers["available"], + }, + "evidence": { + "optional_modules": catalog["optional_modules"], + "sources": _evidence_sources() if include_evidence_sources else [], + "documentation": documentation_layers["evidence"], }, } diff --git a/webui/package.json b/webui/package.json index f9fa89d..9fab480 100644 --- a/webui/package.json +++ b/webui/package.json @@ -17,7 +17,7 @@ "lucide-react": "^1.23.0", "react": "^19.0.0", "react-dom": "^19.0.0", - "react-router-dom": "^7.1.1", + "react-router-dom": ">=7.18.2 <8", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5.7.2", "vite": "^6.0.6"