mod crud;
#[cfg(test)]
mod tests;
use std::path::PathBuf;
use anyhow::Result;
use clap::Subcommand;
use serde::Serialize;
use crate::commands::interactive;
use crate::output::OutputFormat;
use raps_acc::RfiClient;
use raps_dm::DataManagementClient;
#[derive(Debug, Subcommand)]
pub enum RfiCommands {
List {
project_id: Option<String>,
#[arg(long)]
status: Option<String>,
#[arg(long)]
since: Option<String>,
#[arg(long, hide = true)]
hub_id: Option<String>,
},
Get {
project_id: Option<String>,
rfi_id: Option<String>,
#[arg(long, hide = true)]
hub_id: Option<String>,
},
Create {
project_id: Option<String>,
#[arg(long)]
title: Option<String>,
#[arg(long)]
question: Option<String>,
#[arg(long, default_value = "normal")]
priority: String,
#[arg(long)]
due_date: Option<String>,
#[arg(long)]
assigned_to: Option<String>,
#[arg(long)]
location: Option<String>,
#[arg(long)]
discipline: Option<String>,
#[arg(long, value_name = "FILE")]
from_csv: Option<PathBuf>,
#[arg(long, hide = true)]
hub_id: Option<String>,
},
Update {
project_id: Option<String>,
rfi_id: Option<String>,
#[arg(long)]
title: Option<String>,
#[arg(long)]
question: Option<String>,
#[arg(long)]
answer: Option<String>,
#[arg(long)]
status: Option<String>,
#[arg(long)]
priority: Option<String>,
#[arg(long)]
due_date: Option<String>,
#[arg(long)]
assigned_to: Option<String>,
#[arg(long)]
location: Option<String>,
#[arg(long, hide = true)]
hub_id: Option<String>,
},
Delete {
project_id: Option<String>,
rfi_id: Option<String>,
#[arg(long, hide = true)]
hub_id: Option<String>,
},
}
impl RfiCommands {
pub async fn execute(
self,
client: &RfiClient,
dm_client: &DataManagementClient,
output_format: OutputFormat,
) -> Result<()> {
match self {
RfiCommands::List {
project_id,
status,
since,
hub_id,
} => {
let (p_id, _) = resolve_rfi_args(
dm_client,
client,
hub_id,
project_id,
Some("ignore".to_string()),
)
.await?;
crud::list_rfis(client, &p_id, status.as_deref(), since, output_format).await
}
RfiCommands::Get {
project_id,
rfi_id,
hub_id,
} => {
let (p_id, r_id) =
resolve_rfi_args(dm_client, client, hub_id, project_id, rfi_id).await?;
crud::get_rfi(client, &p_id, &r_id, output_format).await
}
RfiCommands::Create {
project_id,
title,
question,
priority,
due_date,
assigned_to,
location,
discipline,
from_csv,
hub_id,
} => {
let (p_id, _) = resolve_rfi_args(
dm_client,
client,
hub_id,
project_id,
Some("ignore".to_string()),
)
.await?;
crud::create_rfi(
client,
&p_id,
title,
question,
&priority,
due_date,
assigned_to,
location,
discipline,
from_csv,
output_format,
)
.await
}
RfiCommands::Update {
project_id,
rfi_id,
title,
question,
answer,
status,
priority,
due_date,
assigned_to,
location,
hub_id,
} => {
let (p_id, r_id) =
resolve_rfi_args(dm_client, client, hub_id, project_id, rfi_id).await?;
crud::update_rfi(
client,
&p_id,
&r_id,
title,
question,
answer,
status,
priority,
due_date,
assigned_to,
location,
output_format,
)
.await
}
RfiCommands::Delete {
project_id,
rfi_id,
hub_id,
} => {
let (p_id, r_id) =
resolve_rfi_args(dm_client, client, hub_id, project_id, rfi_id).await?;
crud::delete_rfi(client, &p_id, &r_id, output_format).await
}
}
}
}
async fn resolve_rfi_args(
dm_client: &DataManagementClient,
rfi_client: &RfiClient,
opt_hub_id: Option<String>,
opt_project_id: Option<String>,
opt_rfi_id: Option<String>,
) -> Result<(String, String)> {
let hub_id = match (&opt_hub_id, &opt_project_id, &opt_rfi_id) {
(Some(h), _, _) => h.clone(),
(None, Some(_), Some(_)) => String::new(), (None, _, _) => interactive::prompt_for_hub(dm_client).await?,
};
let project_id = match opt_project_id {
Some(p) => p,
None => interactive::prompt_for_project(dm_client, &hub_id).await?,
};
let rfi_id = match opt_rfi_id {
Some(r) if r == "ignore" => String::new(),
Some(r) => r,
None => interactive::prompt_for_rfi(rfi_client, &project_id).await?,
};
Ok((project_id, rfi_id))
}
#[derive(Serialize)]
pub(super) struct RfiOutput {
pub(super) id: String,
pub(super) number: Option<String>,
pub(super) title: String,
pub(super) status: String,
pub(super) priority: Option<String>,
pub(super) question: Option<String>,
pub(super) answer: Option<String>,
pub(super) due_date: Option<String>,
pub(super) assigned_to_name: Option<String>,
pub(super) created_at: Option<String>,
}
pub(super) fn truncate_str(s: &str, max_len: usize) -> String {
if s.len() <= max_len {
s.to_string()
} else {
format!("{}...", &s[..max_len - 3])
}
}