codeberg_cli/actions/issue/
list.rs1use forgejo_api::structs::{Issue, IssueListIssuesQuery};
2
3use crate::actions::GeneralArgs;
4use crate::render::option::{option_debug_display, option_display};
5use crate::render::spinner::spin_until_ready;
6use crate::types::context::BergContext;
7use crate::types::git::OwnerRepo;
8
9use clap::Parser;
10
11#[derive(Parser, Debug)]
13pub struct ListIssueArgs {
14 #[arg(short, long, value_name = "N")]
16 pub count: Option<u32>,
17}
18
19impl ListIssueArgs {
20 pub async fn run(self, general_args: GeneralArgs) -> anyhow::Result<()> {
21 let _ = general_args;
22 let ctx = BergContext::new(self, general_args).await?;
23 let OwnerRepo { repo, owner } = ctx.owner_repo()?;
24 let mut issues_list = spin_until_ready(ctx.client.issue_list_issues(
25 owner.as_str(),
26 repo.as_str(),
27 IssueListIssuesQuery {
28 page: ctx.args.count.as_ref().map(|_| 1),
29 limit: ctx.args.count,
30 ..Default::default()
31 },
32 ))
33 .await?;
34
35 issues_list.retain(|issue| issue.pull_request.is_none());
36
37 present_issues_list(&ctx, issues_list);
38
39 Ok(())
40 }
41}
42
43fn present_issues_list(ctx: &BergContext<ListIssueArgs>, issues: Vec<Issue>) {
44 let issues_empty = issues.is_empty();
45
46 let mut table = ctx.make_table().add_table((!issues_empty).then(|| {
47 let mut inner_table = ctx.make_table();
48 inner_table
49 .set_header(vec!["Number", "Status", "Name", "Labels"])
50 .add_rows(issues.into_iter().map(|issue| {
51 let Issue {
52 title,
53 number,
54 labels,
55 state,
56 ..
57 } = issue;
58 let labels = labels.map(|labels| {
59 labels
60 .into_iter()
61 .map(|label| option_display(&label.name))
62 .collect::<Vec<_>>()
63 .join(",")
64 });
65 vec![
66 option_display(&number),
67 option_debug_display(&state),
68 option_display(&title),
69 option_display(&labels),
70 ]
71 }));
72 inner_table
73 }));
74
75 table.set_header(vec![format!(
76 "Issues{}",
77 issues_empty.then_some(" (empty)").unwrap_or_default()
78 )]);
79
80 println!("{table}", table = table.show());
81}