use std::rc::Rc;
use yew::prelude::*;
#[derive(Clone, PartialEq)]
pub enum NewPanelPick {
FromTable { client: String, table: String },
FromPanel(String),
}
pub type HostedTables = Rc<Vec<(String, Vec<String>)>>;
pub type PanelLabels = Rc<Vec<(String, Option<String>)>>;
pub type DerivedCounts = Rc<std::collections::BTreeMap<String, usize>>;
#[derive(Properties, PartialEq)]
pub struct NewPanelMenuProps {
pub tables: Option<HostedTables>,
pub panels: PanelLabels,
pub callback: Callback<NewPanelPick>,
#[prop_or_default]
pub derived: DerivedCounts,
#[prop_or_default]
pub on_delete: Option<Callback<String>>,
}
#[function_component]
pub fn NewPanelMenu(props: &NewPanelMenuProps) -> Html {
let pick = |value: NewPanelPick| props.callback.reform(move |_: MouseEvent| value.clone());
let tables = match &props.tables {
None => html! { <span class="no-results">{ "Loading..." }</span> },
Some(clients) if clients.iter().all(|(_, tables)| tables.is_empty()) => {
html! { <span class="no-results">{ "No tables" }</span> }
},
Some(clients) => {
let multi = clients.len() > 1;
clients
.iter()
.map(|(client, tables)| {
let rows = tables.iter().map(|table| {
let onmousedown = pick(NewPanelPick::FromTable {
client: client.clone(),
table: table.clone(),
});
let consumers = props.derived.get(table).copied();
let mut class = classes!("dropdown-menu-item");
if consumers.is_some() {
class.push("is-derived");
}
let on_delete = props
.on_delete
.clone()
.filter(|_| consumers == Some(0))
.map(|cb| {
let table = table.clone();
Callback::from(move |event: MouseEvent| {
event.stop_propagation();
cb.emit(table.clone());
})
});
html! {
<span {class} {onmousedown}>
{ table }
if let Some(count) = consumers.filter(|x| *x > 0) {
<span class="derived_consumers">{ count }</span>
}
if let Some(on_delete) = on_delete {
<span
class="derived_delete"
title="Delete this derived table"
onmousedown={on_delete}
onclick={Callback::from(|event: MouseEvent| {
event.stop_propagation();
})}
/>
}
</span>
}
});
html! {
<>
if multi { <span class="dropdown-group-sublabel">{ client }</span> }
{ for rows }
</>
}
})
.collect::<Html>()
},
};
let panels = if props.panels.is_empty() {
html! { <span class="no-results">{ "No panels" }</span> }
} else {
props
.panels
.iter()
.map(|(id, title)| {
let onmousedown = pick(NewPanelPick::FromPanel(id.clone()));
let label = title.clone().unwrap_or_else(|| id.clone());
html! { <span class="dropdown-menu-item" {onmousedown}>{ label }</span> }
})
.collect::<Html>()
};
html! {
<div class="new-panel-menu">
<span class="dropdown-group-label" data-label="new-from-table" />
<div class="dropdown-group-container">{ tables }</div>
<span class="dropdown-group-label" data-label="new-from-panel" />
<div class="dropdown-group-container">{ panels }</div>
</div>
}
}
pub fn derived_counts(
workspace: &crate::workspace::Workspace,
) -> crate::components::new_panel_menu::DerivedCounts {
std::rc::Rc::new(
workspace
.derived_names()
.into_iter()
.map(|name| {
let count = workspace.derived_consumers(&name);
(name, count)
})
.collect(),
)
}