Skip to main content

clickup_cli/commands/
checklist.rs

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