Skip to main content

singularity_cli/commands/
task_group.rs

1use anyhow::Result;
2use clap::Subcommand;
3
4use crate::client::ApiClient;
5use crate::models::task_group::{
6    TaskGroup, TaskGroupCreate, TaskGroupListResponse, TaskGroupUpdate,
7};
8
9#[derive(Subcommand)]
10pub enum TaskGroupCmd {
11    #[command(about = "List task groups, optionally filtered by parent project")]
12    List {
13        #[arg(long, help = "Filter by parent project ID (P-<uuid>)")]
14        parent: Option<String>,
15        #[arg(long, help = "Maximum number of groups to return (max 1000)")]
16        max_count: Option<u32>,
17        #[arg(long, help = "Number of groups to skip for pagination")]
18        offset: Option<u32>,
19        #[arg(long, help = "Include soft-deleted groups")]
20        include_removed: bool,
21    },
22    #[command(about = "Get a single task group by ID")]
23    Get {
24        #[arg(help = "Task group ID (Q-<uuid> format)")]
25        id: String,
26    },
27    #[command(about = "Create a new task group inside a project")]
28    Create {
29        #[arg(long, help = "Group title (required)")]
30        title: String,
31        #[arg(long, help = "Parent project ID (P-<uuid>, required)")]
32        parent: String,
33        #[arg(long, help = "Sort order within parent project")]
34        order: Option<f64>,
35    },
36    #[command(about = "Update an existing task group (only specified fields are changed)")]
37    Update {
38        #[arg(help = "Task group ID to update (Q-<uuid> format)")]
39        id: String,
40        #[arg(long, help = "New group title")]
41        title: Option<String>,
42        #[arg(long, help = "Move to a different project (P-<uuid>)")]
43        parent: Option<String>,
44        #[arg(long, help = "New sort order within parent")]
45        order: Option<f64>,
46    },
47    #[command(about = "Delete a task group by ID (soft-delete)")]
48    Delete {
49        #[arg(help = "Task group ID to delete (Q-<uuid> format)")]
50        id: String,
51    },
52}
53
54pub fn run(client: &ApiClient, cmd: TaskGroupCmd, json: bool) -> Result<()> {
55    match cmd {
56        TaskGroupCmd::List {
57            parent,
58            max_count,
59            offset,
60            include_removed,
61        } => {
62            let mut query: Vec<(&str, String)> = Vec::new();
63            if let Some(ref v) = parent {
64                query.push(("parent", v.to_string()));
65            }
66            if let Some(v) = max_count {
67                query.push(("maxCount", v.to_string()));
68            }
69            if let Some(v) = offset {
70                query.push(("offset", v.to_string()));
71            }
72            if include_removed {
73                query.push(("includeRemoved", "true".to_string()));
74            }
75
76            if json {
77                let resp: serde_json::Value = client.get("/v2/task-group", &query)?;
78                println!("{}", serde_json::to_string_pretty(&resp)?);
79            } else {
80                let resp: TaskGroupListResponse = client.get("/v2/task-group", &query)?;
81                if resp.task_groups.is_empty() {
82                    println!("No task groups found.");
83                } else {
84                    for g in &resp.task_groups {
85                        println!("{}\n", g.display_list_item());
86                    }
87                }
88            }
89        }
90        TaskGroupCmd::Get { id } => {
91            if json {
92                let resp: serde_json::Value = client.get(&format!("/v2/task-group/{}", id), &[])?;
93                println!("{}", serde_json::to_string_pretty(&resp)?);
94            } else {
95                let group: TaskGroup = client.get(&format!("/v2/task-group/{}", id), &[])?;
96                println!("{}", group.display_detail());
97            }
98        }
99        TaskGroupCmd::Create {
100            title,
101            parent,
102            order,
103        } => {
104            let data = TaskGroupCreate {
105                title,
106                parent,
107                parent_order: order,
108                fake: None,
109            };
110            if json {
111                let resp: serde_json::Value = client.post("/v2/task-group", &data)?;
112                println!("{}", serde_json::to_string_pretty(&resp)?);
113            } else {
114                let group: TaskGroup = client.post("/v2/task-group", &data)?;
115                println!("Created task group {}", group.id);
116            }
117        }
118        TaskGroupCmd::Update {
119            id,
120            title,
121            parent,
122            order,
123        } => {
124            let data = TaskGroupUpdate {
125                title,
126                parent,
127                parent_order: order,
128                fake: None,
129            };
130            if json {
131                let resp: serde_json::Value =
132                    client.patch(&format!("/v2/task-group/{}", id), &data)?;
133                println!("{}", serde_json::to_string_pretty(&resp)?);
134            } else {
135                let group: TaskGroup = client.patch(&format!("/v2/task-group/{}", id), &data)?;
136                println!("Updated task group {}", group.id);
137            }
138        }
139        TaskGroupCmd::Delete { id } => {
140            client.delete(&format!("/v2/task-group/{}", id))?;
141            println!("Deleted task group {}", id);
142        }
143    }
144    Ok(())
145}