clickup_cli/commands/
group.rs1use crate::client::ClickUpClient;
2use crate::commands::auth::resolve_token;
3use crate::commands::workspace::resolve_workspace;
4use crate::error::CliError;
5use crate::output::OutputConfig;
6use crate::Cli;
7use clap::Subcommand;
8
9#[derive(Subcommand)]
10pub enum GroupCommands {
11 List,
13 Create {
15 #[arg(long)]
17 name: String,
18 #[arg(long = "member")]
20 members: Vec<String>,
21 },
22 Update {
24 id: String,
26 #[arg(long)]
28 name: Option<String>,
29 #[arg(long = "add-member")]
31 add_members: Vec<String>,
32 #[arg(long = "rem-member")]
34 rem_members: Vec<String>,
35 },
36 Delete {
38 id: String,
40 },
41}
42
43const GROUP_FIELDS: &[&str] = &["id", "name", "members"];
44
45pub async fn execute(command: GroupCommands, cli: &Cli) -> Result<(), CliError> {
46 let token = resolve_token(cli)?;
47 let client = ClickUpClient::new(&token, cli.timeout)?;
48 let output = OutputConfig::from_cli(&cli.output, &cli.fields, cli.no_header, cli.quiet);
49
50 match command {
51 GroupCommands::List => {
52 let resp = client.get("/v2/group").await?;
53 let groups = resp
54 .get("groups")
55 .and_then(|g| g.as_array())
56 .cloned()
57 .unwrap_or_default();
58 output.print_items(&groups, GROUP_FIELDS, "id");
59 Ok(())
60 }
61 GroupCommands::Create { name, members } => {
62 let team_id = resolve_workspace(cli)?;
63 let body = serde_json::json!({
64 "name": name,
65 "member_ids": members,
66 });
67 let resp = client
68 .post(&format!("/v2/team/{}/group", team_id), &body)
69 .await?;
70 let group = resp.get("group").cloned().unwrap_or(resp);
71 output.print_single(&group, GROUP_FIELDS, "id");
72 Ok(())
73 }
74 GroupCommands::Update {
75 id,
76 name,
77 add_members,
78 rem_members,
79 } => {
80 let mut body = serde_json::Map::new();
81 if let Some(n) = name {
82 body.insert("name".into(), serde_json::Value::String(n));
83 }
84 if !add_members.is_empty() || !rem_members.is_empty() {
85 let add: Vec<serde_json::Value> = add_members
86 .into_iter()
87 .map(serde_json::Value::String)
88 .collect();
89 let rem: Vec<serde_json::Value> = rem_members
90 .into_iter()
91 .map(serde_json::Value::String)
92 .collect();
93 body.insert(
94 "members".into(),
95 serde_json::json!({ "add": add, "rem": rem }),
96 );
97 }
98 let resp = client
99 .put(
100 &format!("/v2/group/{}", id),
101 &serde_json::Value::Object(body),
102 )
103 .await?;
104 let group = resp.get("group").cloned().unwrap_or(resp);
105 output.print_single(&group, GROUP_FIELDS, "id");
106 Ok(())
107 }
108 GroupCommands::Delete { id } => {
109 client.delete(&format!("/v2/group/{}", id)).await?;
110 output.print_message(&format!("Group {} deleted", id));
111 Ok(())
112 }
113 }
114}