codeberg_cli/actions/pull_request/
view.rsuse super::display_pull_request;
use crate::actions::{text_manipulation::select_prompt_for, GeneralArgs};
use crate::render::comment::render_comment;
use crate::render::datetime::render_datetime_and_info;
use crate::render::option::option_display;
use crate::render::spinner::spin_until_ready;
use crate::render::ui::fuzzy_select_with_key;
use crate::types::api::state_type::ViewStateType;
use crate::types::context::BergContext;
use crate::types::git::OwnerRepo;
use anyhow::Context;
use clap::Parser;
use forgejo_api::structs::{
IssueGetCommentsQuery, PullRequest, RepoListPullRequestsQuery, RepoListPullRequestsQueryState,
};
use itertools::Itertools;
#[derive(Parser, Debug)]
#[command(about = "View details of a selected pull request")]
pub struct ViewPullRequestsArgs {
#[arg(
short,
long,
value_enum,
default_value_t = ViewStateType::All,
)]
pub state: ViewStateType,
#[arg(short, long)]
pub comments: bool,
}
impl ViewPullRequestsArgs {
pub async fn run(self, general_args: GeneralArgs) -> anyhow::Result<()> {
let _ = general_args;
let ctx = BergContext::new(self).await?;
let OwnerRepo { repo, owner } = ctx.owner_repo()?;
let state = match ctx.args.state {
ViewStateType::Closed => RepoListPullRequestsQueryState::Closed,
ViewStateType::Open => RepoListPullRequestsQueryState::Open,
ViewStateType::All => RepoListPullRequestsQueryState::All,
};
let pull_requests_list = spin_until_ready(ctx.client.repo_list_pull_requests(
owner.as_str(),
repo.as_str(),
RepoListPullRequestsQuery {
state: Some(state),
..Default::default()
},
))
.await?;
let pull_request = fuzzy_select_with_key(
&pull_requests_list,
select_prompt_for("pull request"),
display_pull_request,
)?;
if ctx.args.comments {
spin_until_ready(present_pull_request_comments(&ctx, pull_request)).await?;
} else {
present_pull_request_overview(&ctx, pull_request);
}
Ok(())
}
}
fn present_pull_request_overview(
ctx: &BergContext<ViewPullRequestsArgs>,
pull_request: &PullRequest,
) {
let rendered_datetime = pull_request
.created_at
.as_ref()
.map(render_datetime_and_info)
.unwrap_or_else(|| String::from("?"));
let mut table = ctx.make_table();
table
.set_header(vec![format!(
"Pull Request #{}",
option_display(&pull_request.id)
)])
.add_row(vec![
String::from("Title"),
option_display(&pull_request.title),
])
.add_row(vec![String::from("Created"), rendered_datetime])
.add_row(vec![
String::from("Labels"),
pull_request
.labels
.iter()
.flatten()
.map(|label| option_display(&label.name))
.join(", "),
])
.add_row(vec![
String::from("Description"),
option_display(&pull_request.body),
]);
println!("{table}");
}
async fn present_pull_request_comments(
ctx: &BergContext<ViewPullRequestsArgs>,
pull_request: &PullRequest,
) -> anyhow::Result<()> {
let OwnerRepo { repo, owner } = ctx.owner_repo()?;
let nr = pull_request.id.context("Selected pull request has no ID")?;
let comments = ctx
.client
.issue_get_comments(
owner.as_str(),
repo.as_str(),
nr as u64,
IssueGetCommentsQuery::default(),
)
.await?;
let header = format!(
"Pull Request #{} {}",
option_display(&pull_request.id),
if comments.is_empty() {
"(no comments)"
} else {
"comments"
}
);
let mut table = ctx.make_table();
table
.set_header(vec![header])
.add_rows(comments.into_iter().filter_map(|comment| {
let username = comment.user.as_ref()?.login.as_ref()?.as_str();
let creation_time = comment.created_at.as_ref()?;
let comment = comment.body.as_ref()?;
let comment = render_comment(&ctx.config, username, creation_time, comment);
Some(vec![comment])
}));
println!("{table}");
Ok(())
}