tui: Implement new table design for patches
This commit is contained in:
parent
b1c92f4a0d
commit
7c7379c733
|
|
@ -81,7 +81,7 @@ impl ViewPage for Home {
|
|||
|
||||
fn view(&mut self, app: &mut Application<Cid, Message, NoUserEvent>, frame: &mut Frame) {
|
||||
let area = frame.size();
|
||||
let navigation_h = 2u16;
|
||||
let navigation_h = 1u16;
|
||||
let layout = layout::default_page(area, navigation_h);
|
||||
|
||||
app.view(&Cid::Home(HomeCid::Navigation), frame, layout[0]);
|
||||
|
|
|
|||
|
|
@ -69,15 +69,15 @@ impl List for (PatchId, Patch) {
|
|||
let author = format_author(patch, profile);
|
||||
let author = TextSpan::from(author).fg(theme.colors.browser_patch_list_author);
|
||||
|
||||
let tags = format_tags(patch);
|
||||
let tags = TextSpan::from(tags).fg(theme.colors.browser_patch_list_tags);
|
||||
let timestamp = format_timestamp(patch);
|
||||
let timestamp = TextSpan::from(timestamp).fg(theme.colors.browser_patch_list_timestamp);
|
||||
|
||||
let comments = format_comments(patch);
|
||||
let comments = TextSpan::from(comments).fg(theme.colors.browser_patch_list_comments);
|
||||
|
||||
let timestamp = format_timestamp(patch);
|
||||
let timestamp = TextSpan::from(timestamp).fg(theme.colors.browser_patch_list_timestamp);
|
||||
let tags = format_tags(patch);
|
||||
let tags = TextSpan::from(tags).fg(theme.colors.browser_patch_list_tags);
|
||||
|
||||
vec![status, title, author, tags, comments, timestamp]
|
||||
vec![status, title, author, timestamp, comments, tags]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
use radicle::Profile;
|
||||
use tuirealm::command::{Cmd, CmdResult, Direction};
|
||||
use tuirealm::command::{Cmd, CmdResult};
|
||||
use tuirealm::props::{
|
||||
AttrValue, Attribute, Color, PropPayload, PropValue, Props, Style, TextModifiers, TextSpan,
|
||||
AttrValue, Attribute, BorderSides, BorderType, Color, PropPayload, PropValue, Props, Style,
|
||||
TextSpan,
|
||||
};
|
||||
use tuirealm::tui::layout::{Constraint, Rect};
|
||||
use tuirealm::tui::widgets::{Cell, Row, TableState};
|
||||
use tuirealm::tui::layout::{Constraint, Direction, Layout, Rect};
|
||||
use tuirealm::tui::widgets::{Block, Cell, Row, TableState};
|
||||
use tuirealm::{Frame, MockComponent, State, StateValue};
|
||||
|
||||
use crate::ui::components::common::label::Label;
|
||||
|
|
@ -12,6 +13,8 @@ use crate::ui::layout;
|
|||
use crate::ui::theme::Theme;
|
||||
use crate::ui::widget::{Widget, WidgetComponent};
|
||||
|
||||
use super::container::Header;
|
||||
|
||||
pub trait List {
|
||||
fn row(&self, theme: &Theme, profile: &Profile) -> Vec<TextSpan>;
|
||||
}
|
||||
|
|
@ -105,18 +108,17 @@ impl WidgetComponent for PropertyList {
|
|||
}
|
||||
|
||||
pub struct Table {
|
||||
header: Widget<Header>,
|
||||
state: TableState,
|
||||
}
|
||||
|
||||
impl Default for Table {
|
||||
fn default() -> Self {
|
||||
impl Table {
|
||||
pub fn new(header: Widget<Header>) -> Self {
|
||||
let mut state = TableState::default();
|
||||
state.select(Some(0));
|
||||
Self { state }
|
||||
Self { header, state }
|
||||
}
|
||||
}
|
||||
|
||||
impl Table {
|
||||
fn select_previous(&mut self) {
|
||||
let index = match self.state.selected() {
|
||||
Some(selected) if selected == 0 => 0,
|
||||
|
|
@ -135,18 +137,6 @@ impl Table {
|
|||
self.state.select(Some(index));
|
||||
}
|
||||
|
||||
fn header<'a>(spans: Vec<PropValue>) -> Row<'a> {
|
||||
Row::new(
|
||||
spans
|
||||
.iter()
|
||||
.map(|span| {
|
||||
Cell::from(span.clone().unwrap_text_span().content)
|
||||
.style(Style::default().add_modifier(TextModifiers::BOLD))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
|
||||
fn rows<'a>(spans: Vec<Vec<TextSpan>>) -> Vec<Row<'a>> {
|
||||
spans
|
||||
.iter()
|
||||
|
|
@ -173,19 +163,9 @@ impl WidgetComponent for Table {
|
|||
let content = properties
|
||||
.get_or(Attribute::Content, AttrValue::Table(vec![]))
|
||||
.unwrap_table();
|
||||
let background = properties
|
||||
.get_or(Attribute::Background, AttrValue::Color(Color::Reset))
|
||||
.unwrap_color();
|
||||
let highlight = properties
|
||||
.get_or(Attribute::HighlightedColor, AttrValue::Color(Color::Reset))
|
||||
.unwrap_color();
|
||||
let header = properties
|
||||
.get_or(
|
||||
Attribute::Custom("header"),
|
||||
AttrValue::Payload(PropPayload::Vec(vec![])),
|
||||
)
|
||||
.unwrap_payload()
|
||||
.unwrap_vec();
|
||||
let widths = properties
|
||||
.get_or(
|
||||
Attribute::Custom("widths"),
|
||||
|
|
@ -194,18 +174,27 @@ impl WidgetComponent for Table {
|
|||
.unwrap_payload()
|
||||
.unwrap_vec();
|
||||
|
||||
let header = Self::header(header);
|
||||
let layout = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(vec![Constraint::Length(3), Constraint::Min(1)])
|
||||
.split(area);
|
||||
|
||||
let rows = Self::rows(content);
|
||||
let widths = Self::widths(widths);
|
||||
|
||||
let table = tuirealm::tui::widgets::Table::new(rows)
|
||||
let rows = tuirealm::tui::widgets::Table::new(rows)
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(BorderSides::BOTTOM | BorderSides::LEFT | BorderSides::RIGHT)
|
||||
.border_style(Style::default().fg(Color::Rgb(48, 48, 48)))
|
||||
.border_type(BorderType::Rounded),
|
||||
)
|
||||
.highlight_style(Style::default().bg(highlight))
|
||||
.style(Style::default().bg(background))
|
||||
.column_spacing(3u16)
|
||||
.header(header)
|
||||
.widths(&widths);
|
||||
|
||||
frame.render_stateful_widget(table, area, &mut self.state);
|
||||
self.header.view(frame, layout[0]);
|
||||
frame.render_stateful_widget(rows, layout[1], &mut self.state);
|
||||
}
|
||||
|
||||
fn state(&self) -> State {
|
||||
|
|
@ -213,6 +202,8 @@ impl WidgetComponent for Table {
|
|||
}
|
||||
|
||||
fn perform(&mut self, properties: &Props, cmd: Cmd) -> CmdResult {
|
||||
use tuirealm::command::Direction;
|
||||
|
||||
let content = properties
|
||||
.get_or(Attribute::Content, AttrValue::Table(vec![]))
|
||||
.unwrap_table();
|
||||
|
|
|
|||
|
|
@ -38,6 +38,22 @@ pub fn container_header(theme: &Theme, label: &str) -> Widget<Header> {
|
|||
.custom("widths", widths)
|
||||
}
|
||||
|
||||
pub fn table_header(theme: &Theme, labels: &[&str], widths: &[u16]) -> Widget<Header> {
|
||||
let content = labels
|
||||
.iter()
|
||||
.map(|label| {
|
||||
PropValue::TextSpan(TextSpan::from(label.to_string()).fg(theme.colors.default_fg))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let widths = AttrValue::Payload(PropPayload::Vec(
|
||||
widths.iter().map(|w| PropValue::U16(*w)).collect(),
|
||||
));
|
||||
|
||||
Widget::new(Header::default())
|
||||
.content(AttrValue::Payload(PropPayload::Vec(content)))
|
||||
.custom("widths", widths)
|
||||
}
|
||||
|
||||
pub fn labeled_container(
|
||||
theme: &Theme,
|
||||
title: &str,
|
||||
|
|
@ -105,12 +121,25 @@ pub fn tabs(theme: &Theme, tabs: Vec<Widget<Label>>) -> Widget<Tabs> {
|
|||
.highlight(theme.colors.tabs_highlighted_fg)
|
||||
}
|
||||
|
||||
pub fn table(theme: &Theme, items: &[impl List], profile: &Profile) -> Widget<Table> {
|
||||
let table = Table::default();
|
||||
pub fn table(
|
||||
theme: &Theme,
|
||||
labels: &[&str],
|
||||
widths: &[u16],
|
||||
items: &[impl List],
|
||||
profile: &Profile,
|
||||
) -> Widget<Table> {
|
||||
let items = items.iter().map(|item| item.row(theme, profile)).collect();
|
||||
|
||||
let header = table_header(theme, labels, widths);
|
||||
let table = Table::new(header);
|
||||
|
||||
let widths = AttrValue::Payload(PropPayload::Vec(
|
||||
widths.iter().map(|w| PropValue::U16(*w)).collect(),
|
||||
));
|
||||
|
||||
Widget::new(table)
|
||||
.content(AttrValue::Table(items))
|
||||
.custom("widths", widths)
|
||||
.background(theme.colors.labeled_container_bg)
|
||||
.highlight(theme.colors.item_list_highlighted_bg)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use radicle::cob::patch::{Patch, PatchId};
|
||||
use radicle::identity::{Id, Project};
|
||||
use radicle::Profile;
|
||||
use tuirealm::props::{PropPayload, PropValue, TextSpan};
|
||||
use tuirealm::AttrValue;
|
||||
|
||||
use crate::ui::components::common::container::Tabs;
|
||||
use crate::ui::components::common::Browser;
|
||||
|
|
@ -63,26 +61,10 @@ pub fn patches(
|
|||
],
|
||||
);
|
||||
|
||||
let widths = AttrValue::Payload(PropPayload::Vec(vec![
|
||||
PropValue::U16(2),
|
||||
PropValue::U16(43),
|
||||
PropValue::U16(15),
|
||||
PropValue::U16(15),
|
||||
PropValue::U16(5),
|
||||
PropValue::U16(20),
|
||||
]));
|
||||
let header = AttrValue::Payload(PropPayload::Vec(vec![
|
||||
PropValue::TextSpan(TextSpan::from("")),
|
||||
PropValue::TextSpan(TextSpan::from("title")),
|
||||
PropValue::TextSpan(TextSpan::from("author")),
|
||||
PropValue::TextSpan(TextSpan::from("tags")),
|
||||
PropValue::TextSpan(TextSpan::from("comments")),
|
||||
PropValue::TextSpan(TextSpan::from("date")),
|
||||
]));
|
||||
let labels = vec!["", "title", "author", "time", "comments", "tags"];
|
||||
let widths = vec![3u16, 42, 15, 10, 5, 25];
|
||||
|
||||
let table = common::table(theme, items, profile)
|
||||
.custom("widths", widths)
|
||||
.custom("header", header);
|
||||
let table = common::table(theme, &labels, &widths, items, profile);
|
||||
let browser: Browser<(PatchId, Patch)> = Browser::new(table, shortcuts);
|
||||
|
||||
Widget::new(browser)
|
||||
|
|
|
|||
Loading…
Reference in New Issue