Skip to main content

wekan_cli/commands/
cards.rs

1mod archive;
2mod create;
3mod delete;
4mod find_by_custom_field;
5mod get;
6mod list;
7mod restore;
8mod set_custom_field;
9mod update;
10
11#[cfg(test)]
12mod tests;
13
14use clap::{Args, Subcommand};
15
16use crate::{
17    client::WekanClientFactory, command_result::CommandSuccess, credentials::CredentialStore,
18    error::AppError, input::ConfirmationProvider,
19};
20
21#[derive(Debug, Args)]
22pub struct CardArgs {
23    #[command(subcommand)]
24    pub command: CardCommand,
25}
26
27#[derive(Debug, Subcommand)]
28pub enum CardCommand {
29    /// List the cards returned by Wekan for a board list.
30    List(list::ListArgs),
31
32    /// Show one card by board, list, and card ID.
33    Get(get::GetArgs),
34
35    /// Assign an existing custom-field entry on an active card.
36    SetCustomField(set_custom_field::SetCustomFieldArgs),
37    /// Find active cards using Wekan's string custom-field query.
38    FindByCustomField(find_by_custom_field::FindByCustomFieldArgs),
39    /// Create a card in a board list.
40    Create(Box<create::CreateArgs>),
41
42    /// Update one or more editable card fields.
43    Update(Box<update::UpdateArgs>),
44
45    /// Archive an active card and its child cards.
46    Archive(archive::ArchiveArgs),
47
48    /// Restore an archived card and its child cards.
49    Restore(restore::RestoreArgs),
50
51    /// Permanently delete a card and its child resources.
52    Delete(delete::DeleteArgs),
53}
54
55pub(crate) async fn dispatch(
56    command: CardCommand,
57    client_factory: &WekanClientFactory,
58    credential_store: &dyn CredentialStore,
59    confirmation: &dyn ConfirmationProvider,
60) -> Result<CommandSuccess, AppError> {
61    match command {
62        CardCommand::List(args) => list::execute(args, client_factory, credential_store).await,
63        CardCommand::Get(args) => get::execute(args, client_factory, credential_store).await,
64        CardCommand::SetCustomField(args) => {
65            set_custom_field::execute(args, client_factory, credential_store).await
66        }
67        CardCommand::FindByCustomField(args) => {
68            find_by_custom_field::execute(args, client_factory, credential_store).await
69        }
70        CardCommand::Create(args) => create::execute(*args, client_factory, credential_store).await,
71        CardCommand::Update(args) => update::execute(*args, client_factory, credential_store).await,
72        CardCommand::Archive(args) => {
73            archive::execute(args, client_factory, credential_store).await
74        }
75        CardCommand::Restore(args) => {
76            restore::execute(args, client_factory, credential_store).await
77        }
78        CardCommand::Delete(args) => {
79            delete::execute(args, client_factory, credential_store, confirmation).await
80        }
81    }
82}
83
84fn non_empty(value: &str) -> Result<String, String> {
85    trimmed_non_empty(value)
86}
87
88fn trimmed_non_empty(value: &str) -> Result<String, String> {
89    let value = value.trim();
90    if value.is_empty() {
91        Err("value must not be empty or whitespace".to_owned())
92    } else {
93        Ok(value.to_owned())
94    }
95}
96
97fn date_input(value: &str) -> Result<crate::client::cards::CardDateInput, String> {
98    use crate::client::cards::CardDateInput;
99    Ok(match value.trim().parse::<serde_json::Number>() {
100        Ok(number) => CardDateInput::EpochMilliseconds(number),
101        Err(_) => CardDateInput::Text(value.to_owned()),
102    })
103}