Coverage for src/lexigram/admin/navigation/types.py: 98%
60 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 14:56 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 14:56 +0800
1"""Navigation type definitions for admin sidebar construction."""
3from __future__ import annotations
5from dataclasses import dataclass, field
8@dataclass
9class NavItem:
10 """Navigation item."""
12 name: str
13 label: str
14 url: str
15 icon: str | None = None
16 badge: str | None = None
17 badge_variant: str = "primary"
18 active: bool = False
19 external: bool = False
21 children: list[NavItem] | None = None
23 resource_name: str | None = None
24 permission: str | None = None
27@dataclass
28class NavGroup:
29 """Navigation group containing multiple items."""
31 name: str
32 label: str
33 icon: str | None = None
34 order: int = 0
35 collapsible: bool = True
36 collapsed: bool = False
38 items: list[NavItem] = field(default_factory=list)
40 permission: str | None = None
41 feature_flag: str | None = None
44@dataclass
45class SidebarNavItem:
46 """Normalized sidebar navigation item.
48 Converts ``NavigationContribution`` and resource nav entries into one
49 shell-ready shape consumed by ``AdminShell._prepare_navigation()``.
50 """
52 label: str
53 href: str
54 icon: str | None = None
55 badge: str | None = None
56 active: bool = False
57 is_group: bool = False
58 permission: str | None = None
59 feature: str | None = None
61 def to_dict(self) -> dict[str, str | bool | None]:
62 """Convert to dict for backward-compatible shell consumption."""
63 d: dict[str, str | bool | None] = {
64 "label": self.label,
65 "href": self.href,
66 "icon": self.icon,
67 "badge": self.badge,
68 "active": self.active,
69 }
70 if self.is_group:
71 d["is_group"] = True
72 if self.permission:
73 d["permission"] = self.permission
74 if self.feature:
75 d["feature"] = self.feature
76 return d
79@dataclass(frozen=True)
80class MenuItem:
81 """User-menu entry rendered in the shell's user dropdown.
83 ``action`` is an optional semantic marker (e.g. ``"logout"``); plain
84 entries are plain links to ``href``.
85 """
87 label: str
88 href: str
89 icon: str | None = None
90 action: str | None = None
92 def to_dict(self) -> dict[str, str | None]:
93 """Convert to a shell-compatible dict."""
94 return {
95 "label": self.label,
96 "href": self.href,
97 "icon": self.icon,
98 "action": self.action,
99 }
102@dataclass
103class NavigationConfig:
104 """Configuration for navigation assembly."""
106 prefix: str = "/admin"
108 groups: dict[str, NavGroup] = field(default_factory=dict)
110 default_icons: dict[str, str] = field(
111 default_factory=lambda: {
112 "users": "users",
113 "products": "cube",
114 "orders": "shopping-cart",
115 "settings": "cog",
116 "reports": "chart-bar",
117 "logs": "document-text",
118 },
119 )
121 show_counts: bool = False
124__all__ = ["NavGroup", "NavItem", "NavigationConfig", "SidebarNavItem"]