use crate::Renderable;
use crate::components::*;
use crate::node::Node;
use crate::{DefaultModifiers, sp};
#[derive(Debug, Clone)]
pub struct Column {
pub node: Node,
pub title: Option<String>,
}
impl std::ops::Deref for Column {
type Target = Node;
fn deref(&self) -> &Self::Target {
&self.node
}
}
impl std::ops::DerefMut for Column {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.node
}
}
impl DefaultModifiers for Column {}
impl Column {
pub fn new(title: Option<&str>) -> Self {
Self {
node: Default::default(),
title: title.map(|title| title.to_string()),
}
}
pub fn span(&mut self, col_nbs: i32) -> &mut Self {
self.set_attr("span", col_nbs.to_string().as_str())
}
}
impl Renderable for Column {
fn render(mut self) -> Node {
self.tag("col");
self.node
}
}
#[derive(Debug, Clone)]
pub struct Row {
node: Node,
pub name: String,
pub action: Option<String>,
pub action_target: Option<String>,
pub download: Option<String>,
}
impl std::ops::Deref for Row {
type Target = Node;
fn deref(&self) -> &Self::Target {
&self.node
}
}
impl std::ops::DerefMut for Row {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.node
}
}
impl DefaultModifiers for Row {}
impl Appendable for Row {}
impl Row {
pub fn new(name: &str) -> Self {
Self {
node: Default::default(),
name: name.to_string(),
action: None,
action_target: None,
download: None,
}
}
pub fn action(&mut self, url: &str) -> &mut Self {
self.action = Some(url.to_string());
self
}
pub fn action_target(&mut self, target: &str) -> &mut Self {
self.action_target = Some(target.to_string());
self
}
pub fn download_action(&mut self, url: &str, file_name: &str) -> &mut Self {
self.action = Some(url.to_string());
self.download = Some(file_name.to_string());
self
}
}
impl Renderable for Row {
fn render(mut self) -> Node {
self.tag("tr");
if self.action.is_some() {
self.add_class("clickable");
}
self.node.children = self
.node
.children
.into_iter()
.map(|child| {
let mut td = View::new();
td.tag("td");
if let Some(url) = &self.action {
td.append_child({
let mut link = View::new();
link.add_class("link-row").tag("a").set_attr("href", url);
link.node.children.push(child);
if let Some(target) = &self.action_target {
link.set_attr("target", target);
}
if let Some(file_name) = &self.download {
link.set_attr("download", file_name);
}
link
});
} else {
td.node.children.push(child);
}
td.render()
})
.collect();
self.node
}
}
#[derive(Debug, Clone)]
pub struct Table {
name: String,
columns: Vec<Column>,
rows: Vec<Row>,
node: Node,
selectable: bool,
select_all: bool,
}
impl Table {
pub fn new(name: &str, columns: Vec<Column>) -> Self {
Self {
name: name.to_string(),
columns,
rows: vec![],
node: Default::default(),
selectable: false,
select_all: false,
}
}
pub fn selectable(&mut self, is_selectable: bool) -> &mut Self {
self.selectable = is_selectable;
self
}
pub fn display_select_all_checkbox(&mut self) -> &mut Self {
self.select_all = true;
self
}
pub fn alternate_row_color(&mut self) -> &mut Self {
self.add_class("alternate-row-color")
}
pub fn append_child(&mut self, row: Row) -> &mut Self {
self.rows.push(row);
self
}
}
impl std::ops::Deref for Table {
type Target = Node;
fn deref(&self) -> &Self::Target {
&self.node
}
}
impl std::ops::DerefMut for Table {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.node
}
}
impl DefaultModifiers for Table {}
impl Renderable for Table {
fn render(mut self) -> Node {
let table_has_header = self.columns.iter().any(|col| col.title.is_some());
self.tag("table").add_class("table");
if table_has_header {
self.node.children.push(
{
let mut thead = View::new();
thead.tag("thead").append_child({
let mut tr = View::new();
tr.tag("tr");
if self.selectable {
tr.prepend_child({
let mut checkbox_th = View::new();
checkbox_th.tag("th");
if self.select_all {
checkbox_th.append_child({
let mut checkbox =
Checkbox::new(&self.name, "", CheckboxStyle::Checkbox);
checkbox.attach_to_form("dummy").add_class("select-all");
checkbox
});
}
checkbox_th
});
}
self.columns.iter().for_each(|col| {
if let Some(title) = &col.title {
tr.append_child({
let mut th = Text::new(title, TextStyle::Label);
th.tag("th");
th
});
} else {
tr.append_child({
let mut th = View::new();
th.tag("th");
th
});
}
});
tr
});
thead
}
.render(),
);
}
self.node.children.insert(
0,
{
let mut colgroup = View::new();
colgroup.tag("colgroup");
if self.selectable {
colgroup.append_child({
let mut col = Column::new(None);
col.width(&sp(30));
col
});
}
self.columns.into_iter().for_each(|col| {
colgroup.append_child(col);
});
colgroup
}
.render(),
);
self.node.children.push(
{
let mut tbody = View::new();
tbody.tag("tbody");
for mut row in self.rows {
if self.selectable {
row.prepend_child({
Checkbox::new(&self.name, &row.name, CheckboxStyle::Checkbox)
});
}
tbody.append_child(row);
}
tbody
}
.render(),
);
self.node
}
}