use crate::commands::exports::{self, DeliveryArgs, LocaleArgs};
use crate::{
client::{
WekanClientFactory,
exports::{ExportFormat, ExportRequest, ExportTarget},
},
command_result::CommandSuccess,
credentials::CredentialStore,
error::AppError,
};
use clap::Args;
#[derive(Debug, Args)]
pub struct ExportArgs {
#[arg(value_parser = exports::identifier)]
pub board_id: String,
#[arg(long,value_parser = exports::BOARD_FORMATS)]
pub format: String,
#[arg(long = "field",value_parser = exports::BOARD_FIELDS)]
pub fields: Vec<String>,
#[arg(long,value_parser = exports::scope_id)]
pub swimlane: Option<String>,
#[arg(long,value_parser = exports::scope_id)]
pub list: Option<String>,
#[arg(long,value_parser = exports::scope_id)]
pub card: Option<String>,
#[arg(long,value_parser = exports::scope_id)]
pub checklist: Option<String>,
#[arg(long,action=clap::ArgAction::Set)]
pub attachments: Option<bool>,
#[arg(long)]
pub delimiter: Option<String>,
#[command(flatten)]
pub locale: LocaleArgs,
#[command(flatten)]
pub delivery: DeliveryArgs,
}
impl ExportArgs {
pub(crate) fn validate(&self) -> Result<(), AppError> {
self.delivery.validate()?;
let scoped = self.swimlane.is_some()
|| self.list.is_some()
|| self.card.is_some()
|| self.checklist.is_some();
if scoped
&& !matches!(
self.format.as_str(),
"json" | "xlsx" | "pdf" | "zip" | "ics"
)
{
return Err(AppError::invalid_input(
"scope selectors require json, xlsx, pdf, zip or ics format",
));
}
if self.attachments.is_some() && self.format != "json" {
return Err(AppError::invalid_input(
"--attachments requires json format",
));
}
if self.delimiter.is_some() && self.format != "csv" {
return Err(AppError::invalid_input("--delimiter requires csv format"));
}
if self.locale.is_set() && !matches!(self.format.as_str(), "xlsx" | "pdf") {
return Err(AppError::invalid_input(
"locale options require xlsx or pdf format",
));
}
if !self.fields.is_empty() && self.format == "ics" {
return Err(AppError::invalid_input("ics does not support --field"));
}
Ok(())
}
}
pub(crate) async fn execute(
args: ExportArgs,
factory: &WekanClientFactory,
store: &dyn CredentialStore,
) -> Result<CommandSuccess, AppError> {
args.validate()?;
let request = ExportRequest {
fields: args.fields,
swimlane_id: args.swimlane,
list_id: args.list,
card_id: args.card,
checklist_id: args.checklist,
attachments: args.attachments,
delimiter: args.delimiter,
language: args.locale.language,
date_format: args.locale.date_format,
timezone: args.locale.timezone,
..Default::default()
};
let format: ExportFormat = args.format.parse().expect("validated export format");
exports::execute(
ExportTarget::Board {
board_id: args.board_id,
},
format,
request,
args.delivery,
factory,
store,
)
.await
}