armature_admin/
registry.rs1use crate::model::ModelDefinition;
4use std::collections::HashMap;
5
6#[derive(Debug, Default)]
8pub struct ModelRegistry {
9 models: HashMap<String, ModelDefinition>,
11 order: Vec<String>,
13 groups: HashMap<String, Vec<String>>,
15}
16
17impl ModelRegistry {
18 pub fn new() -> Self {
20 Self {
21 models: HashMap::new(),
22 order: Vec::new(),
23 groups: HashMap::new(),
24 }
25 }
26
27 pub fn register(&mut self, model: ModelDefinition) {
29 let name = model.name.clone();
30 self.order.push(name.clone());
31 self.models.insert(name, model);
32 }
33
34 pub fn register_in_group(&mut self, group: impl Into<String>, model: ModelDefinition) {
36 let group = group.into();
37 let name = model.name.clone();
38
39 self.models.insert(name.clone(), model);
40
41 if !self.order.contains(&name) {
42 self.order.push(name.clone());
43 }
44
45 self.groups.entry(group).or_default().push(name);
46 }
47
48 pub fn get(&self, name: &str) -> Option<&ModelDefinition> {
50 self.models.get(name)
51 }
52
53 pub fn all(&self) -> Vec<&ModelDefinition> {
55 self.order
56 .iter()
57 .filter_map(|name| self.models.get(name))
58 .collect()
59 }
60
61 pub fn names(&self) -> &[String] {
63 &self.order
64 }
65
66 pub fn group(&self, name: &str) -> Vec<&ModelDefinition> {
68 self.groups
69 .get(name)
70 .map(|names| names.iter().filter_map(|n| self.models.get(n)).collect())
71 .unwrap_or_default()
72 }
73
74 pub fn groups(&self) -> &HashMap<String, Vec<String>> {
76 &self.groups
77 }
78
79 pub fn contains(&self, name: &str) -> bool {
81 self.models.contains_key(name)
82 }
83
84 pub fn count(&self) -> usize {
86 self.models.len()
87 }
88
89 pub fn unregister(&mut self, name: &str) -> Option<ModelDefinition> {
91 self.order.retain(|n| n != name);
92 for group in self.groups.values_mut() {
93 group.retain(|n| n != name);
94 }
95 self.models.remove(name)
96 }
97
98 pub fn sidebar_items(&self) -> Vec<SidebarItem> {
100 if !self.groups.is_empty() {
102 let mut items = Vec::new();
103 let mut ungrouped = Vec::new();
104
105 for (group_name, model_names) in &self.groups {
107 let models: Vec<_> = model_names
108 .iter()
109 .filter_map(|n| self.models.get(n))
110 .map(|m| SidebarItem::Model {
111 name: m.name.clone(),
112 label: m.verbose_name.clone(),
113 icon: m.icon.clone(),
114 })
115 .collect();
116
117 if !models.is_empty() {
118 items.push(SidebarItem::Group {
119 name: group_name.clone(),
120 items: models,
121 });
122 }
123 }
124
125 for name in &self.order {
127 let in_group = self.groups.values().any(|g| g.contains(name));
128 if !in_group && let Some(model) = self.models.get(name) {
129 ungrouped.push(SidebarItem::Model {
130 name: model.name.clone(),
131 label: model.verbose_name.clone(),
132 icon: model.icon.clone(),
133 });
134 }
135 }
136
137 items.extend(ungrouped);
138 items
139 } else {
140 self.order
142 .iter()
143 .filter_map(|name| self.models.get(name))
144 .map(|m| SidebarItem::Model {
145 name: m.name.clone(),
146 label: m.verbose_name.clone(),
147 icon: m.icon.clone(),
148 })
149 .collect()
150 }
151 }
152}
153
154#[derive(Debug, Clone)]
156pub enum SidebarItem {
157 Model {
159 name: String,
160 label: String,
161 icon: Option<String>,
162 },
163 Group {
165 name: String,
166 items: Vec<SidebarItem>,
167 },
168 Divider,
170 Link {
172 label: String,
173 url: String,
174 icon: Option<String>,
175 },
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181 use crate::field::{FieldDefinition, FieldType};
182
183 #[test]
184 fn test_registry() {
185 let mut registry = ModelRegistry::new();
186
187 let user = ModelDefinition::builder("user")
188 .id_field()
189 .field(FieldDefinition::new("name", FieldType::String))
190 .build();
191
192 let post = ModelDefinition::builder("post")
193 .id_field()
194 .field(FieldDefinition::new("title", FieldType::String))
195 .build();
196
197 registry.register(user);
198 registry.register(post);
199
200 assert_eq!(registry.count(), 2);
201 assert!(registry.contains("user"));
202 assert!(registry.contains("post"));
203 assert!(!registry.contains("comment"));
204 }
205
206 #[test]
207 fn test_registry_groups() {
208 let mut registry = ModelRegistry::new();
209
210 let user = ModelDefinition::builder("user").id_field().build();
211
212 let role = ModelDefinition::builder("role").id_field().build();
213
214 registry.register_in_group("Auth", user);
215 registry.register_in_group("Auth", role);
216
217 let auth_models = registry.group("Auth");
218 assert_eq!(auth_models.len(), 2);
219 }
220}