use crate::term::hyperlink; use crossterm::style::Stylize; use serde::{Deserialize, Serialize}; use std::io::Write; #[derive(Debug, Deserialize, Serialize)] pub struct JiraIssue { pub key: String, #[serde(rename = "self")] pub href: String, pub fields: JiraIssueResponseFields, } #[derive(Debug, Deserialize, Serialize)] pub struct JiraIssueResponseFields { pub summary: String, pub description: Option, pub status: Status, pub created: chrono::DateTime, pub priority: Priority, pub assignee: Person, pub reporter: Person, pub creator: Person, #[serde(rename = "duedate")] pub due_date: Option, pub comment: Option, pub votes: Votes, } #[derive(Debug, Deserialize, Serialize)] pub struct Status { pub name: String, } #[derive(Debug, Deserialize, Serialize)] pub struct Priority { pub name: String, pub id: String, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Person { #[serde(rename = "self")] pub href: String, #[serde(rename = "displayName")] pub display_name: String, #[serde(rename = "accountId")] pub account_id: String, #[serde(rename = "emailAddress")] pub email_address: Option, } #[derive(Debug, Default, Clone, Deserialize, Serialize)] pub struct Comments { pub total: u32, #[serde(rename = "maxResults")] pub max_results: u32, #[serde(rename = "startAt")] pub start_at: u32, pub comments: Vec, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Comment { #[serde(rename = "self")] pub href: String, pub id: String, pub author: Person, pub body: String, #[serde(rename = "updateAuthor")] pub update_author: Person, pub created: chrono::DateTime, } #[derive(Debug, Deserialize, Serialize)] pub struct Votes { #[serde(rename = "self")] pub href: String, #[serde(rename = "votes")] pub count: i32, #[serde(rename = "hasVoted")] pub has_voted: bool, } pub fn display_issues_pretty(issues: &[JiraIssue]) -> Result<(), Box> { println!("Found {} issues:", issues.len()); println!("{:-<80}", ""); for issue in issues { let mut tw = tabwriter::TabWriter::new(vec![]); writeln!(tw, "{}:\t{}", "Key".blue(), issue.key)?; writeln!(tw, "{}:\t{}", "Summary".blue(), issue.fields.summary)?; writeln!(tw, "{}:\t{}", "Status".blue(), issue.fields.status.name)?; writeln!( tw, "{}:\t{}", "Created".blue(), issue.fields.created.with_timezone(&chrono::Local) )?; writeln!( tw, "{}:\t{}", "Due Date".blue(), match issue.fields.due_date { None => "None".to_string(), Some(x) => x.to_string(), } )?; writeln!( tw, "{}", &hyperlink(&issue.href, &"Open Issue".green().to_string()) )?; tw.flush().unwrap(); let written = String::from_utf8(tw.into_inner().unwrap()).unwrap(); print!("{}", written); println!("{:-<80}", ""); } Ok(()) } pub fn display_issues_compact(issues: &[JiraIssue]) -> Result<(), Box> { println!("Found {} issues:", issues.len()); println!("{:-<80}", ""); let mut tw = tabwriter::TabWriter::new(vec![]); for issue in issues { writeln!( tw, "{}:\t{}", issue.key.clone().blue(), issue.fields.summary.clone().green() )?; } tw.flush().unwrap(); let written = String::from_utf8(tw.into_inner().unwrap()).unwrap(); print!("{}", written); Ok(()) } pub fn display_issues_json(issues: &[JiraIssue]) -> Result<(), Box> { let j = serde_json::to_string_pretty(issues)?; println!("{}", j); Ok(()) }