Skip to main content

clickup_cli/commands/
checklist.rs

1use clap::Subcommand;
2use crate::client::ClickUpClient;
3use crate::commands::auth::resolve_token;
4use crate::error::CliError;
5use crate::output::OutputConfig;
6use crate::Cli;
7
8#[derive(Subcommand)]
9pub enum ChecklistCommands {
10    /// Create a checklist on a task
11    Create {
12        /// Task ID
13        #[arg(long)]
14        task: String,
15        /// Checklist name
16        #[arg(long)]
17        name: String,
18    },
19    /// Update a checklist
20    Update {
21        /// Checklist ID
22        id: String,
23        /// New name
24        #[arg(long)]
25        name: Option<String>,
26        /// Position
27        #[arg(long)]
28        position: Option<i64>,
29    },
30    /// Delete a checklist
31    Delete {
32        /// Checklist ID
33        id: String,
34    },
35    /// Add an item to a checklist
36    AddItem {
37        /// Checklist ID
38        id: String,
39        /// Item name
40        #[arg(long)]
41        name: String,
42        /// Assignee user ID
43        #[arg(long)]
44        assignee: Option<i64>,
45    },
46    /// Update a checklist item
47    UpdateItem {
48        /// Checklist ID
49        id: String,
50        /// Item ID
51        item_id: String,
52        /// New name
53        #[arg(long)]
54        name: Option<String>,
55        /// Mark as resolved
56        #[arg(long)]
57        resolved: bool,
58        /// Assignee user ID
59        #[arg(long)]
60        assignee: Option<i64>,
61        /// Parent item ID (nest under another item)
62        #[arg(long)]
63        parent: Option<String>,
64    },
65    /// Delete a checklist item
66    DeleteItem {
67        /// Checklist ID
68        id: String,
69        /// Item ID
70        item_id: String,
71    },
72}
73
74pub async fn execute(command: ChecklistCommands, cli: &Cli) -> Result<(), CliError> {
75    let token = resolve_token(cli)?;
76    let client = ClickUpClient::new(&token, cli.timeout)?;
77    let output = OutputConfig::from_cli(&cli.output, &cli.fields, cli.no_header, cli.quiet);
78
79    match command {
80        ChecklistCommands::Create { task, name } => {
81            let body = serde_json::json!({ "name": name });
82            let resp = client
83                .post(&format!("/v2/task/{}/checklist", task), &body)
84                .await?;
85            let checklist = resp.get("checklist").cloned().unwrap_or(resp);
86            output.print_single(&checklist, &["id", "name", "task_id", "orderindex"], "id");
87            Ok(())
88        }
89        ChecklistCommands::Update { id, name, position } => {
90            let mut body = serde_json::Map::new();
91            if let Some(n) = name {
92                body.insert("name".into(), serde_json::Value::String(n));
93            }
94            if let Some(p) = position {
95                body.insert("position".into(), serde_json::json!(p));
96            }
97            let resp = client
98                .put(&format!("/v2/checklist/{}", id), &serde_json::Value::Object(body))
99                .await?;
100            let checklist = resp.get("checklist").cloned().unwrap_or(resp);
101            output.print_single(&checklist, &["id", "name", "orderindex"], "id");
102            Ok(())
103        }
104        ChecklistCommands::Delete { id } => {
105            client.delete(&format!("/v2/checklist/{}", id)).await?;
106            output.print_message(&format!("Checklist {} deleted", id));
107            Ok(())
108        }
109        ChecklistCommands::AddItem { id, name, assignee } => {
110            let mut body = serde_json::json!({ "name": name });
111            if let Some(a) = assignee {
112                body["assignee"] = serde_json::json!(a);
113            }
114            let resp = client
115                .post(&format!("/v2/checklist/{}/checklist_item", id), &body)
116                .await?;
117            let checklist = resp.get("checklist").cloned().unwrap_or(resp);
118            output.print_single(&checklist, &["id", "name"], "id");
119            Ok(())
120        }
121        ChecklistCommands::UpdateItem {
122            id,
123            item_id,
124            name,
125            resolved,
126            assignee,
127            parent,
128        } => {
129            let mut body = serde_json::Map::new();
130            if let Some(n) = name {
131                body.insert("name".into(), serde_json::Value::String(n));
132            }
133            if resolved {
134                body.insert("resolved".into(), serde_json::Value::Bool(true));
135            }
136            if let Some(a) = assignee {
137                body.insert("assignee".into(), serde_json::json!(a));
138            }
139            if let Some(p) = parent {
140                body.insert("parent".into(), serde_json::Value::String(p));
141            }
142            let resp = client
143                .put(
144                    &format!("/v2/checklist/{}/checklist_item/{}", id, item_id),
145                    &serde_json::Value::Object(body),
146                )
147                .await?;
148            let checklist = resp.get("checklist").cloned().unwrap_or(resp);
149            output.print_single(&checklist, &["id", "name"], "id");
150            Ok(())
151        }
152        ChecklistCommands::DeleteItem { id, item_id } => {
153            client
154                .delete(&format!("/v2/checklist/{}/checklist_item/{}", id, item_id))
155                .await?;
156            output.print_message(&format!("Checklist item {} deleted", item_id));
157            Ok(())
158        }
159    }
160}