clickup_cli/commands/
field.rs1use clap::Subcommand;
2use crate::client::ClickUpClient;
3use crate::commands::auth::resolve_token;
4use crate::commands::workspace::resolve_workspace;
5use crate::error::CliError;
6use crate::output::OutputConfig;
7use crate::Cli;
8
9#[derive(Subcommand)]
10pub enum FieldCommands {
11 List {
13 #[arg(long)]
15 list: Option<String>,
16 #[arg(long)]
18 folder: Option<String>,
19 #[arg(long)]
21 space: Option<String>,
22 #[arg(long = "workspace-level")]
24 workspace_level: bool,
25 },
26 Set {
28 task_id: String,
30 field_id: String,
32 #[arg(long)]
34 value: String,
35 },
36 Unset {
38 task_id: String,
40 field_id: String,
42 },
43}
44
45const FIELD_FIELDS: &[&str] = &["id", "name", "type", "required"];
46
47pub async fn execute(command: FieldCommands, cli: &Cli) -> Result<(), CliError> {
48 let token = resolve_token(cli)?;
49 let client = ClickUpClient::new(&token, cli.timeout)?;
50 let output = OutputConfig::from_cli(&cli.output, &cli.fields, cli.no_header, cli.quiet);
51
52 match command {
53 FieldCommands::List {
54 list,
55 folder,
56 space,
57 workspace_level,
58 } => {
59 let path = if let Some(list_id) = list {
60 format!("/v2/list/{}/field", list_id)
61 } else if let Some(folder_id) = folder {
62 format!("/v2/folder/{}/field", folder_id)
63 } else if let Some(space_id) = space {
64 format!("/v2/space/{}/field", space_id)
65 } else if workspace_level {
66 let ws_id = resolve_workspace(cli)?;
67 format!("/v2/team/{}/field", ws_id)
68 } else {
69 return Err(CliError::ClientError {
70 message: "Specify --list, --folder, --space, or --workspace-level".into(),
71 status: 0,
72 });
73 };
74
75 let resp = client.get(&path).await?;
76 let fields = resp
77 .get("fields")
78 .and_then(|f| f.as_array())
79 .cloned()
80 .unwrap_or_default();
81 output.print_items(&fields, FIELD_FIELDS, "id");
82 Ok(())
83 }
84 FieldCommands::Set {
85 task_id,
86 field_id,
87 value,
88 } => {
89 let parsed_value: serde_json::Value = serde_json::from_str(&value)
91 .unwrap_or_else(|_| serde_json::Value::String(value));
92 let body = serde_json::json!({ "value": parsed_value });
93 let resp = client
94 .post(&format!("/v2/task/{}/field/{}", task_id, field_id), &body)
95 .await?;
96 output.print_single(&resp, FIELD_FIELDS, "id");
97 Ok(())
98 }
99 FieldCommands::Unset { task_id, field_id } => {
100 client
101 .delete(&format!("/v2/task/{}/field/{}", task_id, field_id))
102 .await?;
103 output.print_message(&format!(
104 "Field {} cleared on task {}",
105 field_id, task_id
106 ));
107 Ok(())
108 }
109 }
110}