Skip to content

Commit

Permalink
Merge pull request #1 from Simon-Busch/add-pr-to-review
Browse files Browse the repository at this point in the history
ADD list with PR to review
  • Loading branch information
Simon-Busch authored Apr 24, 2023
2 parents c7966cd + a8354c2 commit 0ca7fc0
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 77 deletions.
2 changes: 1 addition & 1 deletion src/api/fetch_github_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use reqwest::header;

use crate::structs;
use structs::{ApiResponse, IssueComments};
use std::{error::Error};
use std::error::Error;


pub async fn get_github_response(username: &str, access_token: &str, status: &str) -> Result<ApiResponse, Box<dyn Error>> {
Expand Down
43 changes: 43 additions & 0 deletions src/api/fetch_github_pr_review.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use reqwest::header::{HeaderValue, ACCEPT};
use reqwest::header;

use crate::structs;
use structs::ApiResponse;
use std::error::Error;

pub async fn fetch_github_pr_review(username: &str, access_token: &str) -> Result<ApiResponse, Box<dyn Error>> {
let mut headers = header::HeaderMap::new();
headers.insert(
ACCEPT,
HeaderValue::from_static("application/vnd.github.v3+json"),
);
headers.insert(
"Authorization",
HeaderValue::from_str(&format!("Bearer {}", access_token)).unwrap(),
);
headers.insert("User-Agent", HeaderValue::from_static("my app"));
let client = reqwest::Client::builder()
.default_headers(headers)
.build()?;
let base_url = "https://api.github.com";
let url = format!(
"{}/search/issues?q=type:pr+review-requested:{}+state:open
",
base_url, username
);
let github_response = client
.get(url)
.send()
.await?
.text()
.await?;

let mut items: ApiResponse = serde_json::from_str(&github_response)?;
for item in items.items.iter_mut() {
let url_parts: Vec<&str> = item.url.split("/").collect();
item.repository = Some(url_parts[url_parts.len() - 3].to_string());
item.organization = Some(url_parts[url_parts.len() - 4].to_string());
item.is_pr = url_parts.contains(&"pull");
}
Ok(items)
}
14 changes: 11 additions & 3 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ use crate::structs;
use structs::{ApiResponseItem};
use std::{error::Error};
mod fetch_github_data;
mod fetch_github_pr_review;
mod update_issue_status;
use fetch_github_data::get_github_response;
use fetch_github_pr_review::fetch_github_pr_review;
use chrono::{DateTime, NaiveDateTime, Utc};

fn parse_date_string(date_string: &str) -> DateTime<Utc> {
let naive_date = NaiveDateTime::parse_from_str(date_string, "%Y-%m-%dT%H:%M:%SZ").unwrap();
DateTime::from_utc(naive_date, Utc)
}

pub async fn init_gh_data(username: &str, access_token: &str) -> Result<(Vec<ApiResponseItem>, Vec<ApiResponseItem>, i32, i32), Box<dyn Error>> {
pub async fn init_gh_data(username: &str, access_token: &str) -> Result<(Vec<ApiResponseItem>, Vec<ApiResponseItem>, Vec<ApiResponseItem>, i32, i32, i32), Box<dyn Error>> {
// Get list of open issues
let issues_list_response_open = get_github_response(username, access_token, "open").await?;
let mut issues_list_open = issues_list_response_open.items.to_owned();
Expand All @@ -22,12 +24,18 @@ pub async fn init_gh_data(username: &str, access_token: &str) -> Result<(Vec<Api
let mut issues_list_closed = issues_list_response_closed.items.to_owned();
issues_list_closed.sort_by_key(|i| parse_date_string(&i.updated_at));
issues_list_closed.reverse();
// Get list of Assigned for review PR
let assigned_pr = fetch_github_pr_review(username, access_token).await?;
let mut assigned_pr_list = assigned_pr.items.to_owned();
assigned_pr_list.sort_by_key(|i| parse_date_string(&i.updated_at));
assigned_pr_list.reverse();

// Convert the lengths of the issue lists to i32
// Convert the lengths of the objects lists to i32
let issues_list_open_len = issues_list_response_open.total_count;
let issues_list_closed_len = issues_list_response_closed.total_count;
let assigned_pr_list_len = assigned_pr.total_count;

Ok((issues_list_open, issues_list_closed, issues_list_open_len, issues_list_closed_len))
Ok((issues_list_open, issues_list_closed, assigned_pr_list, issues_list_open_len, issues_list_closed_len, assigned_pr_list_len))
}

pub use update_issue_status::update_issue_status;
166 changes: 95 additions & 71 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use dotenv::dotenv;
use tokio;
use std::{error::Error, sync::mpsc};
use tui::{
backend::{CrosstermBackend},
backend::CrosstermBackend,
layout::{Alignment, Constraint, Direction, Layout},
style::{Color, Modifier, Style},
text::{Span, Spans},
Expand All @@ -40,6 +40,7 @@ enum MenuItem {
Assignments,
Closed,
Refresh,
ToReview,
}

impl From<MenuItem> for usize {
Expand All @@ -49,6 +50,7 @@ impl From<MenuItem> for usize {
MenuItem::Assignments => 1,
MenuItem::Closed => 2,
MenuItem::Refresh => 3,
MenuItem::ToReview => 4,
}
}
}
Expand Down Expand Up @@ -94,9 +96,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
// Render the loading screen
render_waiting_screen(&mut terminal)?;

let (mut issues_list_open, mut issues_list_closed, mut issues_list_open_len, mut issues_list_closed_len) = init_gh_data(&username, &access_token).await?;
let (mut issues_list_open, mut issues_list_closed, mut assigned_pr_list, mut issues_list_open_len, mut issues_list_closed_len, mut assigned_pr_list_len) = init_gh_data(&username, &access_token).await?;

let menu_titles = vec!["Home","Assignments", "Closed", "Refresh" , "Quit"];
let menu_titles = vec!["Home","Assignments", "Closed", "Refresh", "To Review", "Quit"];
let mut active_menu_item = MenuItem::Home;

let mut issue_list_state_open = ListState::default();
Expand All @@ -105,11 +107,15 @@ async fn main() -> Result<(), Box<dyn Error>> {
let mut issue_list_state_closed = ListState::default();
issue_list_state_closed.select(Some(0));

let mut issue_list_state_to_review = ListState::default();
issue_list_state_to_review.select(Some(0));

let mut action_list_state = ListState::default();
action_list_state.select(Some(0));

let mut active_open = true;
let mut show_comment = false;
let mut to_review_open = false;

// Create a flag to keep track of whether the prompt window is open
let mut prompt_open = false;
Expand Down Expand Up @@ -167,7 +173,7 @@ async fn main() -> Result<(), Box<dyn Error>> {

rect.render_widget(tabs, chunks[0]);
match active_menu_item {
MenuItem::Home => rect.render_widget(render_home(&issues_list_open_len, &issues_list_closed_len, &username), chunks[1]),
MenuItem::Home => rect.render_widget(render_home(&issues_list_open_len, &issues_list_closed_len, &assigned_pr_list_len, &username), chunks[1]),
MenuItem::Assignments => {
let data_chunck = Layout::default()
.direction(Direction::Horizontal)
Expand All @@ -182,10 +188,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
rect.render_stateful_widget(left, data_chunck[0], &mut issue_list_state_open);
rect.render_widget(right, data_chunck[1]);
if prompt_open == true {
let items = vec![
ListItem::new(" 1 - Close issue"),
];
render_popup(rect, items);
let items = vec![
ListItem::new(" 1 - Close issue"),
];
render_popup(rect, items);
}
} else if active_open == true && show_comment == true {
let selected_issue_index = issue_list_state_open.selected();
Expand All @@ -195,31 +201,34 @@ async fn main() -> Result<(), Box<dyn Error>> {
}
},
MenuItem::Closed => {
let data_chunck = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[Constraint::Percentage(30), Constraint::Percentage(70)].as_ref(),
)
.split(chunks[1]);
if active_open == false {
let selected_issue_index = issue_list_state_closed.selected();
let (left, right) = render_issues(&issues_list_closed, selected_issue_index, show_comment);
rect.render_stateful_widget(left, data_chunck[0], &mut issue_list_state_closed);
rect.render_widget(right, data_chunck[1]);
}
let data_chunck = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[Constraint::Percentage(30), Constraint::Percentage(70)].as_ref(),
)
.split(chunks[1]);
if active_open == false {
let selected_issue_index = issue_list_state_closed.selected();
let (left, right) = render_issues(&issues_list_closed, selected_issue_index, show_comment);
rect.render_stateful_widget(left, data_chunck[0], &mut issue_list_state_closed);
rect.render_widget(right, data_chunck[1]);
}
},
MenuItem::Refresh => {
let data_chunck = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[Constraint::Percentage(30), Constraint::Percentage(70)].as_ref(),
)
.split(chunks[1]);
let selected_issue_index = issue_list_state_open.selected();
let (left, right) = render_issues(&issues_list_open, selected_issue_index, show_comment);
rect.render_stateful_widget(left, data_chunck[0], &mut issue_list_state_open);
rect.render_widget(right, data_chunck[1]);
},
MenuItem::ToReview => {
let data_chunck = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[Constraint::Percentage(30), Constraint::Percentage(70)].as_ref(),
)
.split(chunks[1]);
let selected_issue_index = issue_list_state_to_review.selected();
// println!("assigned_pr_list: {:?}", assigned_pr_list );
let (left, right) = render_issues(&assigned_pr_list, selected_issue_index, show_comment);
rect.render_stateful_widget(left, data_chunck[0], &mut issue_list_state_to_review);
rect.render_widget(right, data_chunck[1]);
}
}
rect.render_widget(copyright, chunks[2]);
})?;
Expand All @@ -234,47 +243,58 @@ async fn main() -> Result<(), Box<dyn Error>> {
KeyCode::Char('h') => active_menu_item = MenuItem::Home,
KeyCode::Char('a') => {
active_open = true;
active_menu_item = MenuItem::Assignments
to_review_open = false;
active_menu_item = MenuItem::Assignments;
},
KeyCode::Char('c') => {
active_open = false;
to_review_open = false;
active_menu_item = MenuItem::Closed
},
KeyCode::Down => {
let (state, items) = get_current_state_and_list(
active_open,
to_review_open,
&mut issue_list_state_open,
&mut issue_list_state_closed,
&mut issue_list_state_to_review,
&issues_list_open,
&issues_list_closed,
&assigned_pr_list
);
move_selection(state, items, 1);
}
KeyCode::Up => {
let (state, _) = get_current_state_and_list(
active_open,
&mut issue_list_state_open,
&mut issue_list_state_closed,
&issues_list_open,
&issues_list_closed,
);
move_selection(state, &issues_list_open, -1);
}
KeyCode::Enter => {
let (state, list) = get_current_state_and_list(
active_open,
&mut issue_list_state_open,
&mut issue_list_state_closed,
&issues_list_open,
&issues_list_closed,
);
if let Some(selected) = state.selected() {
let url = &list[selected].url;
if let Err(e) = open::that(url) {
eprintln!("Failed to open URL '{}': {}", url, e);
}
}
}
}
KeyCode::Up => {
let (state, _) = get_current_state_and_list(
active_open,
to_review_open,
&mut issue_list_state_open,
&mut issue_list_state_closed,
&mut issue_list_state_to_review,
&issues_list_open,
&issues_list_closed,
&assigned_pr_list
);
move_selection(state, &issues_list_open, -1);
}
KeyCode::Enter => {
let (state, list) = get_current_state_and_list(
active_open,
to_review_open,
&mut issue_list_state_open,
&mut issue_list_state_closed,
&mut issue_list_state_to_review,
&issues_list_open,
&issues_list_closed,
&assigned_pr_list
);
if let Some(selected) = state.selected() {
let url = &list[selected].url;
if let Err(e) = open::that(url) {
eprintln!("Failed to open URL '{}': {}", url, e);
}
}
}
KeyCode::Right => {
if active_open == true {
show_comment = true;
Expand All @@ -289,13 +309,13 @@ async fn main() -> Result<(), Box<dyn Error>> {
// close issue
let state;
let list: &Vec<ApiResponseItem>;
if active_open == true {
state = &mut issue_list_state_open;
list = &issues_list_open;
} else {
state = &mut issue_list_state_closed;
list = &issues_list_closed;
}
if active_open == true {
state = &mut issue_list_state_open;
list = &issues_list_open;
} else {
state = &mut issue_list_state_closed;
list = &issues_list_closed;
}
if let Some(selected) = state.selected() {
let number = list[selected].number;
let repo_owner = list[selected].organization.as_ref().unwrap().to_owned();
Expand All @@ -317,15 +337,19 @@ async fn main() -> Result<(), Box<dyn Error>> {
prompt_open = !prompt_open;
}
},

KeyCode::Char('r') => {
(issues_list_open, issues_list_closed, issues_list_open_len, issues_list_closed_len) = init_gh_data(&username, &access_token).await.unwrap();
}

(issues_list_open, issues_list_closed, assigned_pr_list, issues_list_open_len, issues_list_closed_len, assigned_pr_list_len) = init_gh_data(&username, &access_token).await.unwrap();
},
KeyCode::Char('t') => {
if to_review_open == false {
to_review_open = true;
active_menu_item = MenuItem::ToReview;
}
},
_ => {}
},
Event::Tick => {}
}
},
Event::Tick => {}
}
}
Ok(())
}
7 changes: 6 additions & 1 deletion src/render_items/render_home.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use tui::{
widgets::{Block, BorderType, Borders, Paragraph}
};

pub fn render_home<'a>(opened: &i32, closed: &i32, username: &String) -> Paragraph<'a> {
pub fn render_home<'a>(opened: &i32, closed: &i32, review: &i32, username: &String) -> Paragraph<'a> {
let home = Paragraph::new(vec![
Spans::from(vec![Span::raw("")]),
Spans::from(vec![Span::raw("")]),
Expand All @@ -28,6 +28,11 @@ pub fn render_home<'a>(opened: &i32, closed: &i32, username: &String) -> Paragra
closed,
))]),
Spans::from(vec![Span::raw("")]),
Spans::from(vec![Span::raw(format!(
"{} To review",
review,
))]),
Spans::from(vec![Span::raw("")]),
Spans::from(vec![Span::raw("")]),
Spans::from(vec![Span::raw("")]),
Spans::from(vec![Span::raw("")]),
Expand Down
Loading

0 comments on commit 0ca7fc0

Please sign in to comment.