codeberg_cli/actions/milestone/
create.rsuse crate::render::ui::multi_fuzzy_select_with_key;
use crate::types::context::BergContext;
use crate::{actions::GeneralArgs, types::git::OwnerRepo};
use forgejo_api::structs::CreateMilestoneOption;
use strum::{Display, VariantArray};
use crate::actions::text_manipulation::{edit_prompt_for, input_prompt_for};
use clap::Parser;
#[derive(Parser, Debug)]
pub struct CreateMilestoneArgs {
#[arg(short, long)]
pub title: Option<String>,
#[arg(short, long)]
pub description: Option<String>,
}
#[derive(Display, PartialEq, Eq, VariantArray)]
enum CreatableFields {
Title,
Description,
}
impl CreateMilestoneArgs {
pub async fn run(self, general_args: GeneralArgs) -> anyhow::Result<()> {
let _ = general_args;
let ctx = BergContext::new(self).await?;
let OwnerRepo { owner, repo } = ctx.owner_repo()?;
let options = create_options(&ctx).await?;
let milestone = ctx
.client
.issue_create_milestone(owner.as_str(), repo.as_str(), options)
.await?;
tracing::debug!("{milestone:?}");
Ok(())
}
}
async fn create_options(
ctx: &BergContext<CreateMilestoneArgs>,
) -> anyhow::Result<CreateMilestoneOption> {
let mut options = CreateMilestoneOption {
description: None,
due_on: None,
state: None,
title: None,
};
let optional_data = {
use CreatableFields::*;
[
(Title, ctx.args.title.is_none()),
(Description, ctx.args.description.is_none()),
]
.into_iter()
.filter_map(|(name, missing)| missing.then_some(name))
.collect::<Vec<_>>()
};
let chosen_optionals = multi_fuzzy_select_with_key(
&optional_data,
"Choose optional properties",
|_| false,
|o| o.to_string(),
)?;
{
use CreatableFields::*;
options.title = milestone_title(ctx, chosen_optionals.contains(&&Title))?;
options.description = milestone_description(ctx, chosen_optionals.contains(&&Description))?;
}
Ok(options)
}
fn milestone_title(
ctx: &BergContext<CreateMilestoneArgs>,
interactive: bool,
) -> anyhow::Result<Option<String>> {
let title = match ctx.args.title.as_ref() {
Some(title) => title.clone(),
None => {
if !interactive {
return Ok(None);
}
inquire::Text::new(input_prompt_for("Label Name").as_str()).prompt()?
}
};
Ok(Some(title))
}
fn milestone_description(
ctx: &BergContext<CreateMilestoneArgs>,
interactive: bool,
) -> anyhow::Result<Option<String>> {
let description = match ctx.args.description.as_ref() {
Some(desc) => desc.clone(),
None => {
if !interactive {
return Ok(None);
}
inquire::Editor::new(edit_prompt_for("a description").as_str())
.with_predefined_text("Enter a milestone description")
.prompt()?
}
};
Ok(Some(description))
}