Coverage for src/lexigram/admin/layout/layout_manager.py: 0%
67 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:18 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-24 23:18 +0800
1"""Layout manager for lexigram-admin.
3Provides layout types and configuration for resource views.
4"""
6from __future__ import annotations
8from dataclasses import dataclass, field
9from enum import Enum, auto
10from typing import TYPE_CHECKING, Any
12if TYPE_CHECKING:
13 from collections.abc import Callable
16class LayoutType(str, Enum):
17 """Available layout types for resource views."""
19 LIST = auto() # Standard list/table view
20 GRID = auto() # Grid/card view
21 CALENDAR = auto() # Calendar view for date-based data
22 KANBAN = auto() # Kanban board view
23 TIMELINE = auto() # Timeline view
24 MAP = auto() # Map view for geo-data
25 TREE = auto() # Tree/hierarchical view
26 CUSTOM = auto() # User-defined custom layout
29@dataclass
30class LayoutConfig:
31 """Configuration for a layout type."""
33 type: LayoutType = LayoutType.LIST
34 label: str = ""
35 icon: str = "list"
36 enabled: bool = True
37 default: bool = False
39 # Layout-specific options
40 options: dict[str, Any] = field(default_factory=dict)
42 # Grid-specific
43 columns: int = 3
44 card_template: Callable[..., Any] | None = None
46 # Calendar-specific
47 date_field: str = "date"
48 title_field: str = "title"
50 # Kanban-specific
51 status_field: str = "status"
52 statuses: list[str] = field(default_factory=list)
54 def with_option(self, key: str, value: Any) -> LayoutConfig:
55 """Add an option and return self for chaining."""
56 self.options[key] = value
57 return self
60@dataclass
61class LayoutViewConfig:
62 """Configuration for multiple layout views on a resource."""
64 layouts: list[LayoutConfig] = field(default_factory=list)
65 default: LayoutType = LayoutType.LIST
67 def add(self, layout: LayoutConfig) -> LayoutViewConfig:
68 """Add a layout configuration."""
69 self.layouts.append(layout)
70 return self
72 def set_default(self, layout_type: LayoutType) -> LayoutViewConfig:
73 """Set the default layout type."""
74 self.default = layout_type
75 return self
78class LayoutManager:
79 """Manages layout configurations for a resource.
81 Handles switching between different view layouts (list, grid, calendar, etc.)
82 and provides view rendering.
83 """
85 def __init__(self, default_layout: LayoutType = LayoutType.LIST):
86 """Initialize layout manager.
88 Args:
89 default_layout: Default layout type
90 """
91 self._layouts: dict[LayoutType, LayoutConfig] = {}
92 self._default = default_layout
93 self._current = default_layout
95 def register(self, config: LayoutConfig) -> LayoutManager:
96 """Register a layout configuration.
98 Args:
99 config: Layout configuration to register
101 Returns:
102 Self for chaining
103 """
104 self._layouts[config.type] = config
105 if config.default:
106 self._default = config.type
107 return self
109 def set_default(self, layout_type: LayoutType) -> LayoutManager:
110 """Set the default layout type.
112 Args:
113 layout_type: Layout type to set as default
115 Returns:
116 Self for chaining
117 """
118 self._default = layout_type
119 return self
121 def get_config(self, layout_type: LayoutType) -> LayoutConfig | None:
122 """Get configuration for a layout type.
124 Args:
125 layout_type: Layout type to get config for
127 Returns:
128 LayoutConfig or None if not registered
129 """
130 return self._layouts.get(layout_type)
132 def get_available(self) -> list[LayoutConfig]:
133 """Get all available layout configurations.
135 Returns:
136 List of enabled layout configurations
137 """
138 return list(filter(lambda c: c.enabled, self._layouts.values()))
140 def get_current(self) -> LayoutType:
141 """Get the current active layout type.
143 Returns:
144 Current layout type
145 """
146 return self._current
148 def set_current(self, layout_type: LayoutType) -> None:
149 """Set the current active layout type.
151 Args:
152 layout_type: Layout type to set as current
153 """
154 if layout_type in self._layouts:
155 self._current = layout_type
157 def get_default(self) -> LayoutType:
158 """Get the default layout type.
160 Returns:
161 Default layout type
162 """
163 return self._default
165 @property
166 def has_multiple_layouts(self) -> bool:
167 """Check if multiple layouts are available.
169 Returns:
170 True if more than one layout is enabled
171 """
172 return len(self.get_available()) > 1