singularity_cli/commands/
task_group.rs1use 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}