Skip to main content

wekan_cli/commands/
swimlanes.rs

1mod create;
2mod delete;
3mod get;
4mod list;
5mod transfer;
6mod update;
7
8#[cfg(test)]
9mod tests;
10
11use clap::{Args, Subcommand};
12
13use crate::{
14    client::WekanClientFactory, command_result::CommandSuccess, credentials::CredentialStore,
15    error::AppError, input::ConfirmationProvider,
16};
17
18#[derive(Debug, Args)]
19pub struct SwimlaneArgs {
20    #[command(subcommand)]
21    pub command: SwimlaneCommand,
22}
23
24#[derive(Debug, Subcommand)]
25pub enum SwimlaneCommand {
26    /// Copy a swimlane using Wekan's native transfer behavior.
27    Copy(transfer::TransferArgs),
28    /// Move or reposition a swimlane using Wekan's native behavior.
29    Move(transfer::TransferArgs),
30    /// List the swimlanes returned by Wekan for a board.
31    List(list::ListArgs),
32
33    /// Show one swimlane by board and swimlane ID.
34    Get(get::GetArgs),
35
36    /// Create a swimlane on a board.
37    Create(create::CreateArgs),
38
39    /// Update a swimlane title.
40    Update(update::UpdateArgs),
41
42    /// Permanently delete a swimlane and cascade according to Wekan behavior.
43    Delete(delete::DeleteArgs),
44}
45
46pub(crate) async fn dispatch(
47    command: SwimlaneCommand,
48    client_factory: &WekanClientFactory,
49    credential_store: &dyn CredentialStore,
50    confirmation: &dyn ConfirmationProvider,
51) -> Result<CommandSuccess, AppError> {
52    match command {
53        SwimlaneCommand::Copy(args) => {
54            transfer::execute(args, false, client_factory, credential_store).await
55        }
56        SwimlaneCommand::Move(args) => {
57            transfer::execute(args, true, client_factory, credential_store).await
58        }
59        SwimlaneCommand::List(args) => list::execute(args, client_factory, credential_store).await,
60        SwimlaneCommand::Get(args) => get::execute(args, client_factory, credential_store).await,
61        SwimlaneCommand::Create(args) => {
62            create::execute(args, client_factory, credential_store).await
63        }
64        SwimlaneCommand::Update(args) => {
65            update::execute(args, client_factory, credential_store).await
66        }
67        SwimlaneCommand::Delete(args) => {
68            delete::execute(args, client_factory, credential_store, confirmation).await
69        }
70    }
71}
72
73fn non_empty(value: &str) -> Result<String, String> {
74    trimmed_non_empty(value)
75}
76
77fn trimmed_non_empty(value: &str) -> Result<String, String> {
78    let value = value.trim();
79    if value.is_empty() {
80        Err("value must not be empty or whitespace".to_owned())
81    } else {
82        Ok(value.to_owned())
83    }
84}
85
86fn finite_number(value: &str) -> Result<f64, String> {
87    let value = value
88        .parse::<f64>()
89        .map_err(|_| "value must be a number".to_owned())?;
90    if value.is_finite() {
91        Ok(value)
92    } else {
93        Err("value must be finite".to_owned())
94    }
95}