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