Skip to main content

wekan_cli/commands/
custom_fields.rs

1mod create;
2mod delete;
3mod get;
4mod list;
5mod update;
6use crate::{
7    client::WekanClientFactory, command_result::CommandSuccess, credentials::CredentialStore,
8    error::AppError, input::ConfirmationProvider,
9};
10use clap::{Args, Subcommand};
11#[derive(Debug, Args)]
12pub struct CustomFieldArgs {
13    #[command(subcommand)]
14    pub command: CustomFieldCommand,
15}
16#[derive(Debug, Subcommand)]
17pub enum CustomFieldCommand {
18    /// List board custom-field definitions.
19    List(list::ListArgs),
20    /// Get board custom-field definitions.
21    Get(get::GetArgs),
22    /// Create board custom-field definitions.
23    Create(create::CreateArgs),
24    /// Update board custom-field definitions.
25    Update(update::UpdateArgs),
26    /// Permanently delete board custom-field definitions.
27    Delete(delete::DeleteArgs),
28    /// Manage custom-field dropdown items.
29    Item(super::custom_field_items::CustomFieldItemArgs),
30}
31pub(crate) async fn dispatch(
32    command: CustomFieldCommand,
33    factory: &WekanClientFactory,
34    store: &dyn CredentialStore,
35    confirmation: &dyn ConfirmationProvider,
36) -> Result<CommandSuccess, AppError> {
37    match command {
38        CustomFieldCommand::List(args) => list::execute(args, factory, store).await,
39        CustomFieldCommand::Get(args) => get::execute(args, factory, store).await,
40        CustomFieldCommand::Create(args) => create::execute(args, factory, store).await,
41        CustomFieldCommand::Update(args) => update::execute(args, factory, store).await,
42        CustomFieldCommand::Delete(args) => {
43            delete::execute(args, factory, store, confirmation).await
44        }
45        CustomFieldCommand::Item(args) => {
46            super::custom_field_items::dispatch(args.command, factory, store, confirmation).await
47        }
48    }
49}
50pub(crate) fn non_empty(value: &str) -> Result<String, String> {
51    let value = crate::client::trim_javascript_whitespace(value);
52    if value.is_empty() {
53        Err("value must not be empty or whitespace".to_owned())
54    } else {
55        crate::client::custom_fields::validate_custom_field_identifier(value)
56            .map_err(str::to_owned)?;
57        Ok(value.to_owned())
58    }
59}
60fn field_type(value: &str) -> Result<crate::client::custom_fields::CustomFieldType, String> {
61    serde_json::from_value(serde_json::Value::String(value.to_owned())).map_err(|_| {
62        "expected text, number, date, dropdown, checkbox, currency or stringtemplate".to_owned()
63    })
64}
65fn settings(value: &str) -> Result<crate::client::custom_fields::CustomFieldSettings, String> {
66    let value: serde_json::Value =
67        serde_json::from_str(value).map_err(|_| "expected a settings JSON object".to_owned())?;
68    if !value.is_object() {
69        return Err("expected a settings JSON object".to_owned());
70    }
71    let settings: crate::client::custom_fields::CustomFieldSettings = serde_json::from_value(value)
72        .map_err(|_| {
73            "expected custom-field settings with only the known, correctly typed properties"
74                .to_owned()
75        })?;
76    settings
77        .validate_dropdown_item_ids()
78        .map_err(str::to_owned)?;
79    Ok(settings)
80}
81pub(crate) fn exact_json(value: &str) -> Result<serde_json::Value, String> {
82    serde_json::from_str(value).map_err(|_| "expected a JSON value".to_owned())
83}
84fn type_name(value: crate::client::custom_fields::CustomFieldType) -> String {
85    use crate::client::custom_fields::CustomFieldType::*;
86    match value {
87        Text => "text",
88        Number => "number",
89        Date => "date",
90        Dropdown => "dropdown",
91        Checkbox => "checkbox",
92        Currency => "currency",
93        Stringtemplate => "stringtemplate",
94    }
95    .to_owned()
96}
97fn detail(
98    value: crate::client::custom_fields::CustomFieldDocument,
99) -> crate::command_result::CustomFieldDetail {
100    use crate::command_result::{CustomFieldDetail, CustomFieldDropdownItem, CustomFieldSettings};
101    CustomFieldDetail {
102        custom_field_id: value.custom_field_id,
103        board_ids: value.board_ids,
104        name: value.name,
105        field_type: type_name(value.field_type),
106        settings: CustomFieldSettings {
107            currency_code: value.settings.currency_code.flatten(),
108            dropdown_items: value.settings.dropdown_items.flatten().map(|items| {
109                items
110                    .into_iter()
111                    .map(|item| CustomFieldDropdownItem {
112                        item_id: item.item_id,
113                        name: item.name,
114                    })
115                    .collect()
116            }),
117            stringtemplate_format: value.settings.stringtemplate_format.flatten(),
118            stringtemplate_separator: value.settings.stringtemplate_separator.flatten(),
119        },
120        show_on_card: value.show_on_card,
121        automatically_on_card: value.automatically_on_card,
122        always_on_card: value.always_on_card,
123        show_label_on_mini_card: value.show_label_on_mini_card,
124        show_sum_at_top_of_list: value.show_sum_at_top_of_list,
125        created_at: value.created_at,
126        modified_at: value.modified_at,
127    }
128}
129
130#[cfg(test)]
131mod tests;