rewrote TagList with a new behaviour
This commit is contained in:
parent
a82119f827
commit
c9a8c637c4
18
src/tags.rs
18
src/tags.rs
@ -4,7 +4,7 @@ use crate::repo;
|
|||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
struct ImageDetails {
|
struct ImageDetails {
|
||||||
architecture: String,
|
architecture: String,
|
||||||
// os: String,
|
// os: String,
|
||||||
@ -17,7 +17,7 @@ impl fmt::Display for ImageDetails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct Images {
|
pub struct Images {
|
||||||
images: Vec<ImageDetails>,
|
images: Vec<ImageDetails>,
|
||||||
#[serde(rename(deserialize = "name"))]
|
#[serde(rename(deserialize = "name"))]
|
||||||
@ -29,9 +29,7 @@ pub struct Images {
|
|||||||
pub struct Tags {
|
pub struct Tags {
|
||||||
count: usize,
|
count: usize,
|
||||||
#[serde(rename(deserialize = "next"))]
|
#[serde(rename(deserialize = "next"))]
|
||||||
next_page: Option<String>,
|
pub next_page: Option<String>,
|
||||||
#[serde(rename(deserialize = "previous"))]
|
|
||||||
prev_page: Option<String>,
|
|
||||||
pub results: Vec<Images>,
|
pub results: Vec<Images>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +41,6 @@ pub enum Error {
|
|||||||
Converting(String),
|
Converting(String),
|
||||||
/// invalid repos show a valid json with 0 tags
|
/// invalid repos show a valid json with 0 tags
|
||||||
NoTagsFound,
|
NoTagsFound,
|
||||||
NoPrevPage,
|
|
||||||
NoNextPage,
|
NoNextPage,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +50,6 @@ impl fmt::Display for Error {
|
|||||||
Error::Fetching(s) => write!(f, "Fetching error: {}", s),
|
Error::Fetching(s) => write!(f, "Fetching error: {}", s),
|
||||||
Error::Converting(s) => write!(f, "Converting error: {}", s),
|
Error::Converting(s) => write!(f, "Converting error: {}", s),
|
||||||
Error::NoNextPage => write!(f, "No next page available"),
|
Error::NoNextPage => write!(f, "No next page available"),
|
||||||
Error::NoPrevPage => write!(f, "No previous page available"),
|
|
||||||
Error::NoTagsFound => write!(f, "Given Repo has 0 tags. Is it valid?"),
|
Error::NoTagsFound => write!(f, "Given Repo has 0 tags. Is it valid?"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,14 +104,6 @@ impl Tags {
|
|||||||
None => Err(Error::NoNextPage),
|
None => Err(Error::NoNextPage),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns tags of previous page
|
|
||||||
pub fn prev_page(&self) -> Result<Self, Error> {
|
|
||||||
match &self.prev_page {
|
|
||||||
Some(url) => Self::with_url(url),
|
|
||||||
None => Err(Error::NoPrevPage),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Images {
|
impl fmt::Display for Images {
|
||||||
|
@ -44,7 +44,7 @@ impl Ui {
|
|||||||
pub fn run(opt: &Opt) {
|
pub fn run(opt: &Opt) {
|
||||||
let (repo_id, load_repo) = match &opt.repo {
|
let (repo_id, load_repo) = match &opt.repo {
|
||||||
None => (
|
None => (
|
||||||
"enter a repository or select one from docker-compose.yml",
|
"enter a repository here or select one from file widget",
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
Some(repo) => (String::as_str(repo), true),
|
Some(repo) => (String::as_str(repo), true),
|
||||||
@ -59,7 +59,7 @@ impl Ui {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if load_repo {
|
if load_repo {
|
||||||
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
ui.tags = tag_list::TagList::with_repo_name(ui.repo.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup tui
|
//setup tui
|
||||||
@ -113,20 +113,12 @@ impl Ui {
|
|||||||
},
|
},
|
||||||
Ok(Key::Ctrl('r')) => {
|
Ok(Key::Ctrl('r')) => {
|
||||||
ui.repo.confirm();
|
ui.repo.confirm();
|
||||||
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
ui.tags = tag_list::TagList::with_repo_name(ui.repo.get());
|
||||||
}
|
}
|
||||||
Ok(Key::Ctrl('n')) => match ui.tags.next_page() {
|
|
||||||
Err(e) => ui.info.set_info(&format!("{}", e)),
|
|
||||||
Ok(_) => (),
|
|
||||||
},
|
|
||||||
Ok(Key::Ctrl('p')) => match ui.tags.prev_page() {
|
|
||||||
Err(e) => ui.info.set_info(&format!("{}", e)),
|
|
||||||
Ok(_) => (),
|
|
||||||
},
|
|
||||||
Ok(Key::Char('\n')) => match ui.state {
|
Ok(Key::Char('\n')) => match ui.state {
|
||||||
State::EditRepo => {
|
State::EditRepo => {
|
||||||
ui.repo.confirm();
|
ui.repo.confirm();
|
||||||
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
ui.tags = tag_list::TagList::with_repo_name(ui.repo.get());
|
||||||
}
|
}
|
||||||
State::SelectTag => {
|
State::SelectTag => {
|
||||||
let mut repo = ui.repo.get();
|
let mut repo = ui.repo.get();
|
||||||
@ -172,7 +164,7 @@ impl Ui {
|
|||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
};
|
};
|
||||||
ui.repo.set(repo.to_string());
|
ui.repo.set(repo.to_string());
|
||||||
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
ui.tags = tag_list::TagList::with_repo_name(ui.repo.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,7 +185,7 @@ impl Ui {
|
|||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
};
|
};
|
||||||
ui.repo.set(repo.to_string());
|
ui.repo.set(repo.to_string());
|
||||||
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
ui.tags = tag_list::TagList::with_repo_name(ui.repo.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ impl NoYaml {
|
|||||||
|
|
||||||
// load tags if a repository was given thorugh paramter
|
// load tags if a repository was given thorugh paramter
|
||||||
if load_repo {
|
if load_repo {
|
||||||
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
ui.tags = tag_list::TagList::with_repo_name(ui.repo.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup tui
|
//setup tui
|
||||||
@ -100,22 +100,17 @@ impl NoYaml {
|
|||||||
}
|
}
|
||||||
Ok(Key::Ctrl('r')) => {
|
Ok(Key::Ctrl('r')) => {
|
||||||
ui.repo.confirm();
|
ui.repo.confirm();
|
||||||
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
ui.tags = tag_list::TagList::with_repo_name(ui.repo.get());
|
||||||
}
|
}
|
||||||
Ok(Key::Ctrl('n')) => match ui.tags.next_page() {
|
|
||||||
Err(e) => ui.info.set_info(&format!("{}", e)),
|
|
||||||
Ok(_) => (),
|
|
||||||
},
|
|
||||||
Ok(Key::Ctrl('p')) => match ui.tags.prev_page() {
|
|
||||||
Err(e) => ui.info.set_info(&format!("{}", e)),
|
|
||||||
Ok(_) => (),
|
|
||||||
},
|
|
||||||
Ok(Key::Char('\n')) => match ui.state {
|
Ok(Key::Char('\n')) => match ui.state {
|
||||||
State::EditRepo => {
|
State::EditRepo => {
|
||||||
ui.repo.confirm();
|
ui.repo.confirm();
|
||||||
ui.tags = tag_list::TagList::with_repo(ui.repo.get());
|
ui.tags = tag_list::TagList::with_repo_name(ui.repo.get());
|
||||||
|
}
|
||||||
|
State::SelectTag => {
|
||||||
|
ui.tags.get_selected();
|
||||||
|
()
|
||||||
}
|
}
|
||||||
_ => (),
|
|
||||||
},
|
},
|
||||||
Ok(Key::Char(key)) => match ui.state {
|
Ok(Key::Char(key)) => match ui.state {
|
||||||
State::EditRepo => {
|
State::EditRepo => {
|
||||||
@ -126,6 +121,21 @@ impl NoYaml {
|
|||||||
ui.tags.handle_input(Key::Char(key));
|
ui.tags.handle_input(Key::Char(key));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Ok(Key::Backspace) => match ui.state {
|
||||||
|
State::EditRepo => {
|
||||||
|
ui.info.set_info("Editing Repository");
|
||||||
|
ui.repo.handle_input(Key::Backspace);
|
||||||
|
}
|
||||||
|
State::SelectTag => (),
|
||||||
|
},
|
||||||
|
Ok(Key::Up) => match ui.state {
|
||||||
|
State::EditRepo => (),
|
||||||
|
State::SelectTag => ui.tags.handle_input(Key::Up),
|
||||||
|
},
|
||||||
|
Ok(Key::Down) => match ui.state {
|
||||||
|
State::EditRepo => (),
|
||||||
|
State::SelectTag => ui.tags.handle_input(Key::Down),
|
||||||
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ impl Info {
|
|||||||
Self {
|
Self {
|
||||||
info: String::from(info),
|
info: String::from(info),
|
||||||
keys: String::from(
|
keys: String::from(
|
||||||
"Tab Cycle widgets C-s Save C-r Reload C-q Quit C-n Next page C-p Previous page ↑ ↓ Select tags or image line",
|
"Tab Cycle widgets C-s Save C-r Reload C-q Quit ↑ ↓ Select tags or image line",
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,105 +6,77 @@ use tui::widgets::{Block, Borders, List, ListState};
|
|||||||
|
|
||||||
use crate::tags;
|
use crate::tags;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
NoneSelected,
|
NoneSelected,
|
||||||
NoTags,
|
NextPageSelected,
|
||||||
NoNextPage,
|
SelectedStatus,
|
||||||
NoPrevPage,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Error::NoTags => write!(f, "There are no tags"),
|
|
||||||
Error::NoneSelected => write!(f, "No tag selected"),
|
Error::NoneSelected => write!(f, "No tag selected"),
|
||||||
Error::NoNextPage => write!(f, "No next page available"),
|
Error::NextPageSelected => write!(f, "tried to get the next page"),
|
||||||
Error::NoPrevPage => write!(f, "No previous page available"),
|
Error::SelectedStatus => write!(f, "Status message was selected"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// used for creating a TagList
|
enum Line {
|
||||||
pub enum Type {
|
|
||||||
Status(String),
|
Status(String),
|
||||||
Repo(tags::Tags),
|
Image(tags::Images),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Line {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Line::Status(s) => write!(f, "{}", s),
|
||||||
|
Line::Image(i) => write!(f, "{}", i),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TagList {
|
pub struct TagList {
|
||||||
typ: Type,
|
lines: Vec<Line>,
|
||||||
state: ListState,
|
state: ListState,
|
||||||
|
tags: Option<tags::Tags>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TagList {
|
impl TagList {
|
||||||
fn new(typ: Type) -> Self {
|
|
||||||
Self {
|
|
||||||
typ,
|
|
||||||
state: ListState::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// create a TagList with a status message
|
|
||||||
pub fn with_status(status: &str) -> Self {
|
pub fn with_status(status: &str) -> Self {
|
||||||
Self::new(Type::Status(String::from(status)))
|
Self {
|
||||||
}
|
lines: vec![Line::Status(String::from(status))],
|
||||||
|
state: ListState::default(),
|
||||||
/// create a TagList
|
tags: None,
|
||||||
pub fn with_repo(name: String) -> Self {
|
|
||||||
match tags::Tags::new(name) {
|
|
||||||
Err(e) => Self::with_status(&format!("{}", e)),
|
|
||||||
Ok(tags) => Self::new(Type::Repo(tags)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// display next page if possible
|
pub fn with_repo_name(repo: String) -> Self {
|
||||||
pub fn next_page(&mut self) -> Result<(), Error> {
|
match tags::Tags::new(repo) {
|
||||||
match &self.typ {
|
Ok(tags) => Self::with_tags(tags),
|
||||||
Type::Status(_) => (),
|
Err(_) => Self::with_status("input repo was not found"),
|
||||||
Type::Repo(tags) => match tags.next_page() {
|
|
||||||
Err(_) => return Err(Error::NoNextPage),
|
|
||||||
Ok(tags) => self.typ = Type::Repo(tags),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// display previous page if possible
|
|
||||||
pub fn prev_page(&mut self) -> Result<(), Error> {
|
|
||||||
match &self.typ {
|
|
||||||
Type::Status(_) => (),
|
|
||||||
Type::Repo(tags) => match tags.prev_page() {
|
|
||||||
Err(_) => return Err(Error::NoPrevPage),
|
|
||||||
Ok(tags) => self.typ = Type::Repo(tags),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get a list of tag names with info
|
|
||||||
fn print_lines(&self) -> Vec<String> {
|
|
||||||
match &self.typ {
|
|
||||||
Type::Status(line) => vec![line.to_string()],
|
|
||||||
Type::Repo(tags) => tags.results.iter().map(|r| format!("{}", r)).collect(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get the list of tag names
|
pub fn with_tags(mut tags: tags::Tags) -> Self {
|
||||||
pub fn get_names(&self) -> Result<Vec<String>, Error> {
|
let mut lines: Vec<Line> = tags
|
||||||
match &self.typ {
|
.results
|
||||||
Type::Status(_) => Err(Error::NoTags),
|
.iter()
|
||||||
Type::Repo(tags) => Ok(tags.results.iter().map(|r| r.tag_name.clone()).collect()),
|
.map(|r| Line::Image(r.clone()))
|
||||||
}
|
.collect();
|
||||||
}
|
|
||||||
|
|
||||||
/// get the selected tag or return an error
|
match tags.next_page() {
|
||||||
pub fn get_selected(&self) -> Result<String, Error> {
|
Err(_) => (),
|
||||||
match &self.typ {
|
Ok(new_tags) => {
|
||||||
Type::Status(_) => Err(Error::NoTags),
|
lines.push(Line::Status(String::from("load more tags")));
|
||||||
Type::Repo(_) => match self.state.selected() {
|
tags = new_tags;
|
||||||
None => Err(Error::NoneSelected),
|
}
|
||||||
Some(i) => Ok(self.get_names().unwrap()[i].clone()),
|
};
|
||||||
},
|
|
||||||
|
Self {
|
||||||
|
lines,
|
||||||
|
state: ListState::default(),
|
||||||
|
tags: Some(tags),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,15 +87,11 @@ impl TagList {
|
|||||||
Style::default().fg(Color::Gray)
|
Style::default().fg(Color::Gray)
|
||||||
};
|
};
|
||||||
|
|
||||||
let lines = match &self.typ {
|
let items: Vec<tui::widgets::ListItem> = self
|
||||||
Type::Status(line) => vec![line.clone()],
|
.lines
|
||||||
Type::Repo(_) => self.print_lines(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let items: Vec<tui::widgets::ListItem> = lines
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|l| {
|
.map(|l| {
|
||||||
tui::widgets::ListItem::new(l.clone())
|
tui::widgets::ListItem::new(format!("{}", l))
|
||||||
.style(Style::default().fg(Color::White).bg(Color::Black))
|
.style(Style::default().fg(Color::White).bg(Color::Black))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -151,24 +119,63 @@ impl TagList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// select next tag
|
pub fn get_selected(&mut self) -> Result<String, Error> {
|
||||||
pub fn next(&mut self) {
|
|
||||||
match self.state.selected() {
|
match self.state.selected() {
|
||||||
None if self.print_lines().len() > 0 => self.state.select(Some(0)),
|
None => Err(Error::NoneSelected),
|
||||||
|
Some(i) if i == self.lines.len() - 1 => {
|
||||||
|
self.load_next_page();
|
||||||
|
Err(Error::NextPageSelected)
|
||||||
|
}
|
||||||
|
Some(i) => match &self.lines[i] {
|
||||||
|
Line::Status(_) => Err(Error::SelectedStatus),
|
||||||
|
Line::Image(i) => Ok(i.tag_name.clone()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_next_page(&mut self) {
|
||||||
|
match &self.tags {
|
||||||
|
Some(tags) => match tags.next_page() {
|
||||||
|
Err(_) => (),
|
||||||
|
Ok(new_tags) => {
|
||||||
|
//load new tags object
|
||||||
|
self.tags = Some(new_tags);
|
||||||
|
|
||||||
|
//remove "load next page"
|
||||||
|
let next_page = self.lines.pop();
|
||||||
|
|
||||||
|
//add tags
|
||||||
|
for image in &self.tags.as_ref().unwrap().results {
|
||||||
|
self.lines.push(Line::Image(image.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//readd next page
|
||||||
|
match self.tags.as_ref().unwrap().next_page {
|
||||||
|
None => (),
|
||||||
|
Some(_) => self.lines.push(next_page.unwrap()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
None => (),
|
None => (),
|
||||||
Some(i) if i == self.print_lines().len() - 1 => self.state.select(Some(0)),
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// select next tag
|
||||||
|
fn next(&mut self) {
|
||||||
|
match self.state.selected() {
|
||||||
|
None if self.lines.len() > 0 => self.state.select(Some(0)),
|
||||||
|
None => (),
|
||||||
|
Some(i) if i == self.lines.len() - 1 => self.state.select(Some(0)),
|
||||||
Some(i) => self.state.select(Some(i + 1)),
|
Some(i) => self.state.select(Some(i + 1)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// select previous tag
|
/// select previous tag
|
||||||
pub fn previous(&mut self) {
|
fn previous(&mut self) {
|
||||||
match self.state.selected() {
|
match self.state.selected() {
|
||||||
None if self.print_lines().len() > 0 => {
|
None if self.lines.len() > 0 => self.state.select(Some(self.lines.len())),
|
||||||
self.state.select(Some(self.print_lines().len()))
|
|
||||||
}
|
|
||||||
None => (),
|
None => (),
|
||||||
Some(i) if i == 0 => self.state.select(Some(self.print_lines().len() - 1)),
|
Some(i) if i == 0 => self.state.select(Some(self.lines.len() - 1)),
|
||||||
Some(i) => self.state.select(Some(i - 1)),
|
Some(i) => self.state.select(Some(i - 1)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user