singularity_cli/models/
tag.rs1use serde::{Deserialize, Serialize};
2
3fn display_opt(o: &Option<String>) -> String {
4 o.as_deref().unwrap_or("-").to_string()
5}
6
7#[derive(Debug, Deserialize)]
8pub struct TagListResponse {
9 pub tags: Vec<Tag>,
10}
11
12#[derive(Debug, Deserialize)]
13pub struct Tag {
14 pub id: String,
15 pub title: String,
16 pub parent: Option<String>,
17 pub order: Option<f64>,
18 #[serde(rename = "modificatedDate")]
19 #[allow(dead_code)]
20 pub modificated_date: Option<String>,
21}
22
23impl Tag {
24 pub fn display_detail(&self) -> String {
25 let mut lines = vec![
26 format!("**ID:** {}", self.id),
27 format!("**Title:** {}", self.title),
28 ];
29 if let Some(ref v) = self.parent {
30 lines.push(format!("**Parent:** {}", v));
31 }
32 if let Some(v) = self.order {
33 lines.push(format!("**Order:** {}", v));
34 }
35 lines.join("\n")
36 }
37
38 pub fn display_list_item(&self) -> String {
39 format!(
40 "- ID: {}\n Tag: {}\n Parent: {}",
41 self.id,
42 self.title,
43 display_opt(&self.parent)
44 )
45 }
46}
47
48#[derive(Debug, Serialize)]
49pub struct TagCreate {
50 pub title: String,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub parent: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub order: Option<f64>,
55}
56
57#[derive(Debug, Serialize, Default)]
58pub struct TagUpdate {
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub title: Option<String>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub parent: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub order: Option<f64>,
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn deserialize_tag_list() {
73 let json = r#"{"tags": [{"id": "tag-1", "title": "urgent", "order": 1.0}]}"#;
74 let resp: TagListResponse = serde_json::from_str(json).unwrap();
75 assert_eq!(resp.tags.len(), 1);
76 assert_eq!(resp.tags[0].id, "tag-1");
77 assert_eq!(resp.tags[0].order, Some(1.0));
78 }
79
80 #[test]
81 fn deserialize_tag_minimal() {
82 let json = r#"{"id": "tag-2", "title": "low"}"#;
83 let t: Tag = serde_json::from_str(json).unwrap();
84 assert_eq!(t.id, "tag-2");
85 assert!(t.parent.is_none());
86 assert!(t.order.is_none());
87 }
88
89 #[test]
90 fn serialize_create_skips_none() {
91 let data = TagCreate {
92 title: "bug".to_string(),
93 parent: None,
94 order: None,
95 };
96 let json = serde_json::to_value(&data).unwrap();
97 assert_eq!(json, serde_json::json!({"title": "bug"}));
98 }
99
100 #[test]
101 fn serialize_update_partial() {
102 let data = TagUpdate {
103 title: Some("renamed".to_string()),
104 ..Default::default()
105 };
106 let json = serde_json::to_value(&data).unwrap();
107 assert_eq!(json, serde_json::json!({"title": "renamed"}));
108 }
109}