metabase_api_rs/core/models/
collection.rs1use super::common::CollectionId;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Collection {
8 pub id: Option<CollectionId>,
9 pub name: String,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub description: Option<String>,
12 #[serde(skip_serializing_if = "Option::is_none")]
13 pub color: Option<String>,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub parent_id: Option<i32>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub personal_owner_id: Option<i64>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub namespace: Option<String>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub slug: Option<String>,
22 #[serde(default, skip_serializing_if = "Option::is_none")]
23 pub archived: Option<bool>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub can_write: Option<bool>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub created_at: Option<DateTime<Utc>>,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub updated_at: Option<DateTime<Utc>>,
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub authority_level: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub collection_position: Option<i32>,
35}
36
37impl Collection {
38 pub fn new(id: Option<CollectionId>, name: String) -> Self {
40 Self {
41 id,
42 name,
43 description: None,
44 color: None,
45 parent_id: None,
46 personal_owner_id: None,
47 namespace: None,
48 slug: None,
49 archived: Some(false),
50 can_write: None,
51 created_at: None,
52 updated_at: None,
53 authority_level: None,
54 collection_position: None,
55 }
56 }
57
58 pub fn id(&self) -> Option<CollectionId> {
60 self.id
61 }
62
63 pub fn name(&self) -> &str {
64 &self.name
65 }
66
67 pub fn description(&self) -> Option<&str> {
68 self.description.as_deref()
69 }
70
71 pub fn color(&self) -> Option<&str> {
72 self.color.as_deref()
73 }
74
75 pub fn parent_id(&self) -> Option<i32> {
76 self.parent_id
77 }
78
79 pub fn personal_owner_id(&self) -> Option<i64> {
80 self.personal_owner_id
81 }
82
83 pub fn namespace(&self) -> Option<&str> {
84 self.namespace.as_deref()
85 }
86
87 pub fn slug(&self) -> Option<&str> {
88 self.slug.as_deref()
89 }
90
91 pub fn archived(&self) -> Option<bool> {
92 self.archived
93 }
94
95 pub fn can_write(&self) -> Option<bool> {
96 self.can_write
97 }
98
99 pub fn authority_level(&self) -> Option<&str> {
100 self.authority_level.as_deref()
101 }
102
103 pub fn collection_position(&self) -> Option<i32> {
104 self.collection_position
105 }
106
107 pub fn is_personal(&self) -> bool {
109 self.personal_owner_id.is_some()
110 }
111
112 pub fn is_root(&self) -> bool {
114 self.parent_id.is_none() && !self.is_personal()
115 }
116}
117
118pub struct CollectionBuilder {
120 id: Option<CollectionId>,
121 name: String,
122 description: Option<String>,
123 color: Option<String>,
124 parent_id: Option<i32>,
125 personal_owner_id: Option<i64>,
126 namespace: Option<String>,
127 slug: Option<String>,
128 archived: Option<bool>,
129 can_write: Option<bool>,
130 created_at: Option<DateTime<Utc>>,
131 updated_at: Option<DateTime<Utc>>,
132 authority_level: Option<String>,
133 collection_position: Option<i32>,
134}
135
136impl CollectionBuilder {
137 pub fn new(id: Option<CollectionId>, name: String) -> Self {
139 Self {
140 id,
141 name,
142 description: None,
143 color: None,
144 parent_id: None,
145 personal_owner_id: None,
146 namespace: None,
147 slug: None,
148 archived: Some(false),
149 can_write: None,
150 created_at: None,
151 updated_at: None,
152 authority_level: None,
153 collection_position: None,
154 }
155 }
156
157 pub fn new_collection(name: impl Into<String>) -> Self {
159 Self::new(None, name.into())
160 }
161
162 pub fn description<S: Into<String>>(mut self, desc: S) -> Self {
163 self.description = Some(desc.into());
164 self
165 }
166
167 pub fn color<S: Into<String>>(mut self, color: S) -> Self {
168 self.color = Some(color.into());
169 self
170 }
171
172 pub fn parent_id(mut self, id: i32) -> Self {
173 self.parent_id = Some(id);
174 self
175 }
176
177 pub fn personal_owner_id(mut self, id: i64) -> Self {
178 self.personal_owner_id = Some(id);
179 self
180 }
181
182 pub fn namespace<S: Into<String>>(mut self, ns: S) -> Self {
183 self.namespace = Some(ns.into());
184 self
185 }
186
187 pub fn slug<S: Into<String>>(mut self, slug: S) -> Self {
188 self.slug = Some(slug.into());
189 self
190 }
191
192 pub fn archived(mut self, archived: bool) -> Self {
193 self.archived = Some(archived);
194 self
195 }
196
197 pub fn can_write(mut self, can_write: bool) -> Self {
198 self.can_write = Some(can_write);
199 self
200 }
201
202 pub fn created_at(mut self, dt: DateTime<Utc>) -> Self {
203 self.created_at = Some(dt);
204 self
205 }
206
207 pub fn updated_at(mut self, dt: DateTime<Utc>) -> Self {
208 self.updated_at = Some(dt);
209 self
210 }
211
212 pub fn authority_level<S: Into<String>>(mut self, level: S) -> Self {
213 self.authority_level = Some(level.into());
214 self
215 }
216
217 pub fn collection_position(mut self, position: i32) -> Self {
218 self.collection_position = Some(position);
219 self
220 }
221
222 pub fn build(self) -> Collection {
224 Collection {
225 id: self.id,
226 name: self.name,
227 description: self.description,
228 color: self.color,
229 parent_id: self.parent_id,
230 personal_owner_id: self.personal_owner_id,
231 namespace: self.namespace,
232 slug: self.slug,
233 archived: self.archived,
234 can_write: self.can_write,
235 created_at: self.created_at,
236 updated_at: self.updated_at,
237 authority_level: self.authority_level,
238 collection_position: self.collection_position,
239 }
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use super::*;
246
247 #[test]
248 fn test_collection_creation() {
249 let collection = Collection::new(Some(CollectionId(1)), "Test Collection".to_string());
250
251 assert_eq!(collection.id(), Some(CollectionId(1)));
252 assert_eq!(collection.name(), "Test Collection");
253 assert!(collection.description().is_none());
254 assert!(collection.parent_id().is_none());
255 assert!(!collection.is_personal());
256 }
257
258 #[test]
259 fn test_collection_hierarchy() {
260 let _parent = Collection::new(Some(CollectionId(1)), "Parent Collection".to_string());
261
262 let child = CollectionBuilder::new(Some(CollectionId(2)), "Child Collection".to_string())
263 .parent_id(1)
264 .description("A child collection")
265 .build();
266
267 assert_eq!(child.parent_id(), Some(1));
268 assert_eq!(child.description(), Some("A child collection"));
269 }
270
271 #[test]
272 fn test_personal_collection() {
273 let personal = CollectionBuilder::new(
274 Some(CollectionId(100)),
275 "My Personal Collection".to_string(),
276 )
277 .personal_owner_id(42)
278 .build();
279
280 assert_eq!(personal.personal_owner_id(), Some(42));
281 assert!(personal.is_personal());
282 }
283
284 #[test]
285 fn test_collection_with_authority_level() {
286 let collection =
287 CollectionBuilder::new(Some(CollectionId(10)), "Admin Collection".to_string())
288 .authority_level("admin")
289 .collection_position(1)
290 .build();
291
292 assert_eq!(collection.authority_level(), Some("admin"));
293 assert_eq!(collection.collection_position(), Some(1));
294 }
295}