clickup_cli/commands/
tag.rs1use crate::client::ClickUpClient;
2use crate::commands::auth::resolve_token;
3use crate::error::CliError;
4use crate::output::OutputConfig;
5use crate::Cli;
6use clap::Subcommand;
7
8#[derive(Subcommand)]
9pub enum TagCommands {
10 List {
12 #[arg(long)]
14 space: String,
15 },
16 Create {
18 #[arg(long)]
20 space: String,
21 #[arg(long)]
23 name: String,
24 #[arg(long)]
26 fg_color: Option<String>,
27 #[arg(long)]
29 bg_color: Option<String>,
30 },
31 Update {
33 #[arg(long)]
35 space: String,
36 #[arg(long)]
38 tag: String,
39 #[arg(long)]
41 name: Option<String>,
42 #[arg(long)]
44 fg_color: Option<String>,
45 #[arg(long)]
47 bg_color: Option<String>,
48 },
49 Delete {
51 #[arg(long)]
53 space: String,
54 #[arg(long)]
56 tag: String,
57 },
58}
59
60const TAG_FIELDS: &[&str] = &["name", "tag_fg", "tag_bg"];
61
62pub async fn execute(command: TagCommands, cli: &Cli) -> Result<(), CliError> {
63 let token = resolve_token(cli)?;
64 let client = ClickUpClient::new(&token, cli.timeout)?;
65 let output = OutputConfig::from_cli(&cli.output, &cli.fields, cli.no_header, cli.quiet);
66
67 match command {
68 TagCommands::List { space } => {
69 let resp = client.get(&format!("/v2/space/{}/tag", space)).await?;
70 let tags = resp
71 .get("tags")
72 .and_then(|t| t.as_array())
73 .cloned()
74 .unwrap_or_default();
75 output.print_items(&tags, TAG_FIELDS, "name");
76 Ok(())
77 }
78 TagCommands::Create {
79 space,
80 name,
81 fg_color,
82 bg_color,
83 } => {
84 let mut tag_obj = serde_json::json!({ "name": name });
85 if let Some(fg) = fg_color {
86 tag_obj["tag_fg"] = serde_json::Value::String(fg);
87 }
88 if let Some(bg) = bg_color {
89 tag_obj["tag_bg"] = serde_json::Value::String(bg);
90 }
91 let body = serde_json::json!({ "tag": tag_obj });
92 let resp = client
93 .post(&format!("/v2/space/{}/tag", space), &body)
94 .await?;
95 output.print_single(&resp, TAG_FIELDS, "name");
96 Ok(())
97 }
98 TagCommands::Update {
99 space,
100 tag,
101 name,
102 fg_color,
103 bg_color,
104 } => {
105 let mut tag_obj = serde_json::Map::new();
106 if let Some(n) = name {
107 tag_obj.insert("name".into(), serde_json::Value::String(n));
108 }
109 if let Some(fg) = fg_color {
111 tag_obj.insert("fg_color".into(), serde_json::Value::String(fg));
112 }
113 if let Some(bg) = bg_color {
114 tag_obj.insert("bg_color".into(), serde_json::Value::String(bg));
115 }
116 let body = serde_json::json!({ "tag": serde_json::Value::Object(tag_obj) });
117 let resp = client
118 .put(&format!("/v2/space/{}/tag/{}", space, tag), &body)
119 .await?;
120 output.print_single(&resp, TAG_FIELDS, "name");
121 Ok(())
122 }
123 TagCommands::Delete { space, tag } => {
124 client
125 .delete(&format!("/v2/space/{}/tag/{}", space, tag))
126 .await?;
127 output.print_message(&format!("Tag '{}' deleted from space {}", tag, space));
128 Ok(())
129 }
130 }
131}