Skip to content

Commit

Permalink
Make edit button sticky for active expression cols
Browse files Browse the repository at this point in the history
Hide edit button for cols with no styles or attrs
Hide the style tab unless needed (hack!)
Add a size trap for column settings panel width
Update column settings panel title to be less verbose
Update tests
  • Loading branch information
ada-x64 committed Nov 15, 2023
1 parent 4b1f190 commit ac97291
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 93 deletions.
10 changes: 8 additions & 2 deletions rust/perspective-viewer/src/rust/components/column_selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,15 @@ impl Component for ColumnSelector {
let ondragenter = ondragenter.reform(move |_| Some(idx));
let size_hint = if named_count > 0 { 50.0 } else { 28.0 };
named_count = named_count.saturating_sub(1);
let key = name.get_name().map(|x| x.to_owned()).unwrap_or_else(|| format!("__auto_{}__", idx));
let key = name
.get_name()
.map(|x| x.to_owned())
.unwrap_or_else(|| format!("__auto_{}__", idx));
let column_dropdown = self.column_dropdown.clone();
let is_editing = matches!(&ctx.props().selected_column, Some(ColumnLocator::Plain(x)) if x == &key);
let is_editing = matches!(
&ctx.props().selected_column,
Some(ColumnLocator::Plain(x)) | Some(ColumnLocator::Expr(Some(x))) if x == &key
);
html_nested! {
<ScrollPanelItem key={ key } { size_hint }>
<ActiveColumn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,15 @@ impl Component for ActiveColumn {
class.push("required");
};

// TODO: This doesn't scale well. Need a better attrs API.
// Thankfully this will be removed when we unify expression and table columns.
let show_edit_btn = match &*ctx.props().renderer.get_active_plugin().unwrap().name()
{
"Datagrid" => col_type != Type::Bool,
"X/Y Scatter" => col_type == Type::String && label.as_deref() == Some("Symbol"),
_ => false,
} || is_expression;

html! {
<div
class={ outer_classes }
Expand Down Expand Up @@ -368,12 +377,14 @@ impl Component for ActiveColumn {
<span class="column-selector--spacer"></span>
}

<ExprEditButton
name={ name.clone() }
on_open_expr_panel={ &ctx.props().on_open_expr_panel }
{ is_expression }
is_editing={ ctx.props().is_editing }
></ExprEditButton>
if show_edit_btn {
<ExprEditButton
name={ name.clone() }
on_open_expr_panel={ &ctx.props().on_open_expr_panel }
{ is_expression }
is_editing={ ctx.props().is_editing }
></ExprEditButton>
}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ pub struct ExprEditButtonProps {
pub is_editing: bool,
}

// TODO: Move this logic to ColumnSettingsSidebar
// Button should just pass the name to the on_open callback, and the sidebar
// should render it. generally, rendering logic should live on the closest
// component
/// A button that goes into a column-list for a custom expression
/// when pressed, it opens up the expression editor side-panel.
#[function_component]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

use std::fmt::Display;

use yew::{function_component, html, Callback, Html, Properties};
use yew::{function_component, html, use_callback, use_state, Callback, Html, Properties};

use crate::components::column_settings_sidebar::attributes_tab::AttributesTab;
use crate::components::column_settings_sidebar::style_tab::StyleTab;
Expand All @@ -21,6 +21,7 @@ use crate::components::containers::tablist::{Tab, TabList};
use crate::components::expression_editor::get_new_column_name;
use crate::components::style::LocalStyle;
use crate::components::viewer::ColumnLocator;
use crate::config::Type;
use crate::custom_events::CustomEvents;
use crate::model::*;
use crate::renderer::Renderer;
Expand Down Expand Up @@ -49,6 +50,7 @@ pub struct ColumnSettingsProps {
pub session: Session,
pub renderer: Renderer,
pub custom_events: CustomEvents,
pub width_override: Option<i32>,
}

derive_model!(CustomEvents, Session, Renderer for ColumnSettingsProps);
Expand All @@ -69,7 +71,7 @@ pub fn ColumnSettingsSidebar(p: &ColumnSettingsProps) -> Html {
let column_type = p.session.metadata().get_column_view_type(&column_name);
let is_active = column_type.is_some();

let (config, attrs) = p.get_plugin_config();
let (config, attrs) = (p.get_plugin_config(), p.get_plugin_attrs());
if config.is_none() || attrs.is_none() {
tracing::warn!(
"Could not get full plugin config!\nconfig (plugin.save()): {:?}\nplugin_attrs: {:?}",
Expand All @@ -79,14 +81,22 @@ pub fn ColumnSettingsSidebar(p: &ColumnSettingsProps) -> Html {
}
let maybe_ty = p.session.metadata().get_column_view_type(&column_name);

let title = format!("Editing ‘{column_name}’...");

let mut tabs = vec![];

// TODO: This is a hack and needs to be replaced.
let plugin = p.renderer.get_active_plugin().unwrap();
let show_styles = maybe_ty
.map(|ty| match &*plugin.name() {
"Datagrid" => ty != Type::Bool,
"X/Y Scatter" => ty == Type::String,
_ => false,
})
.unwrap_or_default();

if !matches!(p.selected_column, ColumnLocator::Expr(None))
&& show_styles
&& is_active
&& config.is_some()
&& attrs.is_some()
&& maybe_ty.is_some()
{
tabs.push(ColumnSettingsTab::Style);
Expand All @@ -95,58 +105,76 @@ pub fn ColumnSettingsSidebar(p: &ColumnSettingsProps) -> Html {
tabs.push(ColumnSettingsTab::Attributes);
}

clone!(
p.selected_column,
p.on_close,
p.session,
p.renderer,
p.custom_events,
column_name
);
let match_fn = Callback::from(move |tab| {
let match_fn = {
clone!(
selected_column,
on_close,
session,
renderer,
custom_events,
p.selected_column,
p.on_close,
p.session,
p.renderer,
p.custom_events,
column_name
);
match tab {
ColumnSettingsTab::Attributes => {
html! {
<AttributesTab
Callback::from(move |tab| {
clone!(
selected_column,
on_close,
session,
renderer,
custom_events,
column_name
);
match tab {
ColumnSettingsTab::Attributes => {
html! {
<AttributesTab
{ session }
{ renderer }
{ custom_events }

{ selected_column }
{ on_close }
/>
}
}
ColumnSettingsTab::Style => html! {
<StyleTab
{ session }
{ renderer }
{ custom_events }

{ selected_column }
{ on_close }
{ column_name }
ty={ maybe_ty.unwrap() }
/>
}
},
}
ColumnSettingsTab::Style => html! {
<StyleTab
{ session }
{ renderer }
{ custom_events }

{ column_name }
ty={ maybe_ty.unwrap() }
/>
},
}
});
})
};

let selected_tab = use_state(|| None);

let on_tab_change = {
clone!(selected_tab);
use_callback((), move |idx, _| {
selected_tab.set(Some(idx));
})
};

html_template! {
<LocalStyle href={css!("column-settings-panel")} />
<Sidebar
{title}
title={column_name}
on_close={p.on_close.clone()}
id_prefix="column_settings"
icon={"column_settings_icon"}
width_override={p.width_override}
selected_tab={*selected_tab}
>
<TabList<ColumnSettingsTab> {tabs} {match_fn} />
<TabList<ColumnSettingsTab>
{tabs}
{match_fn}
{on_tab_change}
selected_tab={*selected_tab}
/>
</Sidebar>

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ derive_model!(CustomEvents, Session, Renderer for ColumnStyleProps);
#[function_component]
pub fn ColumnStyle(p: &ColumnStyleProps) -> Html {
let props = p.clone();
let (config, attrs) = props.get_plugin_config();
let (config, attrs) = (props.get_plugin_config(), props.get_plugin_attrs());
let (config, attrs) = (config.unwrap(), attrs.unwrap());
let title = format!("{} Styling", props.ty.to_capitalized());
let opt_html = match props.ty {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::config::plugin::{PluginConfig, Symbol};
use crate::config::Type;
use crate::custom_elements::FilterDropDownElement;
use crate::custom_events::CustomEvents;
use crate::model::UpdatePluginConfig;
use crate::model::{GetPluginConfig, UpdatePluginConfig};
use crate::renderer::Renderer;
use crate::session::Session;
use crate::{css, derive_model, html_template};
Expand All @@ -49,7 +49,7 @@ pub struct SymbolAttrProps {
derive_model!(CustomEvents, Session, Renderer for SymbolAttrProps);
impl SymbolAttrProps {
pub fn get_config(&self) -> (PluginConfig, Vec<Symbol>) {
let (config, attrs) = self.get_plugin_config();
let (config, attrs) = (self.get_plugin_config(), self.get_plugin_attrs());
(
config.unwrap(),
attrs.and_then(|a| a.symbol.map(|s| s.symbols)).unwrap(),
Expand Down
35 changes: 33 additions & 2 deletions rust/perspective-viewer/src/rust/components/containers/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

use yew::{function_component, html, AttrValue, Callback, Children, Html, Properties};
use web_sys::Element;
use yew::{
function_component, html, use_effect_with, use_node_ref, use_state_eq, AttrValue, Callback,
Children, Html, Properties,
};

use crate::clone;

#[derive(PartialEq, Clone, Properties)]
pub struct SidebarProps {
Expand All @@ -21,14 +27,38 @@ pub struct SidebarProps {
pub title: String,
pub id_prefix: String,
pub icon: Option<String>,
pub width_override: Option<i32>,
pub selected_tab: Option<usize>,
}

/// Sidebars are designed to live in a [SplitPanel]
#[function_component]
pub fn Sidebar(p: &SidebarProps) -> Html {
let id = &p.id_prefix;
let noderef = use_node_ref();
let auto_width = use_state_eq(|| 0f64);

// this gets the last calculated width and ensures that
// the auto-width element is at least that big.
// this ensures the panel grows but does not shrink.
use_effect_with((p.children.clone(), p.selected_tab), {
clone!(noderef, auto_width, p.width_override);
move |_| {
if width_override.is_none() {
let updated_width = noderef
.cast::<Element>()
.map(|el| el.get_bounding_client_rect().width())
.unwrap_or_default();
auto_width.set((*auto_width).max(updated_width));
} else {
auto_width.set(0f64);
}
}
});
let width_style = format!("min-width: 200px; width: {}px", *auto_width);

html! {
<div class="sidebar_column" id={format!("{id}_sidebar")}>
<div class="sidebar_column" id={format!("{id}_sidebar")} ref={noderef}>
<SidebarCloseButton
id={ format!("{id}_close_button") }
on_close_sidebar={ &p.on_close }
Expand All @@ -45,6 +75,7 @@ pub fn Sidebar(p: &SidebarProps) -> Html {
<div class="sidebar_content" id={format!("{id}_content")}>
{p.children.iter().collect::<Html>()}
</div>
<div class="sidebar-auto-width" style={width_style}></div>
</div>
}
}
Expand Down
15 changes: 11 additions & 4 deletions rust/perspective-viewer/src/rust/components/containers/tablist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use yew::{classes, html, Callback, Component, Html, Properties};

use crate::components::style::LocalStyle;
use crate::{css, html_template};
use crate::{clone, css, html_template};

pub trait Tab: PartialEq + std::fmt::Display + Clone + Default + 'static {}
impl Tab for String {}
Expand All @@ -23,6 +23,8 @@ impl Tab for &'static str {}
pub struct TabListProps<T: Tab> {
pub tabs: Vec<T>,
pub match_fn: Callback<T, Html>,
pub on_tab_change: Callback<usize>,
pub selected_tab: Option<usize>,
}

pub enum TabListMsg {
Expand Down Expand Up @@ -54,8 +56,8 @@ impl<T: Tab> Component for TabList<T> {
}
}

fn changed(&mut self, _ctx: &yew::Context<Self>, _old_props: &Self::Properties) -> bool {
self.selected_idx = 0;
fn changed(&mut self, ctx: &yew::Context<Self>, _old_props: &Self::Properties) -> bool {
self.selected_idx = ctx.props().selected_tab.unwrap_or_default();
true
}

Expand All @@ -70,7 +72,12 @@ impl<T: Tab> Component for TabList<T> {
Some("tab"),
(idx == self.selected_idx).then_some("selected")
]);
let onclick = ctx.link().callback(move |_| TabListMsg::SetSelected(idx));

clone!(ctx.props().on_tab_change);
let onclick = ctx.link().callback(move |_| {
on_tab_change.emit(idx);
TabListMsg::SetSelected(idx)
});
html! {
<span {class} {onclick}>
<div class="tab-title">{tab.to_string()}</div>
Expand Down
1 change: 1 addition & 0 deletions rust/perspective-viewer/src/rust/components/viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ impl Component for PerspectiveViewer {
custom_events={ &ctx.props().custom_events }
{ selected_column }
on_close={ctx.link().callback(|_| PerspectiveViewerMsg::ToggleColumnSettings(None, None))}
width_override={self.column_settings_panel_width_override}
/>
<></>
</SplitPanel>
Expand Down
Loading

0 comments on commit ac97291

Please sign in to comment.