codeberg_cli/actions/issue/
list.rs1use forgejo_api::structs::{Issue, IssueListIssuesQuery, IssueListIssuesQueryState};
2
3use crate::actions::GlobalArgs;
4use crate::render::json::JsonToStdout;
5use crate::render::option::{option_debug_display, option_display};
6use crate::render::spinner::spin_until_ready;
7use crate::types::api::state_type::ViewStateType;
8use crate::types::context::BergContext;
9use crate::types::git::OwnerRepo;
10use crate::types::output::OutputMode;
11
12use clap::Parser;
13
14#[derive(Parser, Debug)]
16pub struct ListIssueArgs {
17 #[arg(short, long, value_enum, default_value_t = ViewStateType::Open)]
19 pub state: ViewStateType,
20}
21
22impl ListIssueArgs {
23 pub async fn run(self, global_args: GlobalArgs) -> anyhow::Result<()> {
24 let ctx = BergContext::new(self, global_args).await?;
25 let OwnerRepo { repo, owner } = ctx.owner_repo()?;
26 let state = match ctx.args.state {
27 ViewStateType::Closed => IssueListIssuesQueryState::Closed,
28 ViewStateType::Open => IssueListIssuesQueryState::Open,
29 ViewStateType::All => IssueListIssuesQueryState::All,
30 };
31 let (_, mut issues_list) = spin_until_ready(
32 ctx.client
33 .issue_list_issues(
34 owner.as_str(),
35 repo.as_str(),
36 IssueListIssuesQuery {
37 state: Some(state),
38 ..Default::default()
39 },
40 )
41 .send(),
42 )
43 .await?;
44
45 issues_list.retain(|issue| issue.pull_request.is_none());
46
47 match ctx.global_args.output_mode {
48 OutputMode::Pretty => {
49 present_issues_list(&ctx, issues_list);
50 }
51 OutputMode::Json => issues_list.print_json()?,
52 }
53
54 Ok(())
55 }
56}
57
58fn present_issues_list(ctx: &BergContext<ListIssueArgs>, issues: Vec<Issue>) {
59 let issues_empty = issues.is_empty();
60
61 let mut table = ctx.make_table().add_table((!issues_empty).then(|| {
62 let mut inner_table = ctx.make_table();
63 inner_table
64 .set_header(vec!["Number", "Status", "Name", "Labels"])
65 .add_rows(issues.into_iter().map(|issue| {
66 let Issue {
67 title,
68 number,
69 labels,
70 state,
71 ..
72 } = issue;
73 let labels = labels.map(|labels| {
74 labels
75 .into_iter()
76 .map(|label| option_display(&label.name))
77 .collect::<Vec<_>>()
78 .join(",")
79 });
80 vec![
81 option_display(&number),
82 option_debug_display(&state),
83 option_display(&title),
84 option_display(&labels),
85 ]
86 }));
87 inner_table
88 }));
89
90 table.set_header(vec![format!(
91 "Issues{}",
92 if issues_empty {
93 " (empty)"
94 } else {
95 Default::default()
96 }
97 )]);
98
99 println!("{table}", table = table.show());
100}