use itertools::Itertools;
use perspective_client::config::ViewConfig;
use yew::prelude::*;
use crate::components::column_settings_sidebar::style_tab::primitive_field::{
BoolField, ColorField, ColorRangeField, EnumField, NumberFieldPrimitive,
};
use crate::components::style::LocalStyle;
use crate::config::ControlSpec;
use crate::css;
use crate::queries::get_plugin_config_schema;
use crate::renderer::Renderer;
use crate::session::Session;
use crate::tasks::send_plugin_config;
use crate::utils::PtrEqRc;
#[derive(Clone, PartialEq, Properties)]
pub struct PluginTabProps {
pub view_config: PtrEqRc<ViewConfig>,
pub plugin_config: PtrEqRc<serde_json::Map<String, serde_json::Value>>,
pub renderer: Renderer,
pub session: Session,
}
#[function_component]
pub fn PluginTab(props: &PluginTabProps) -> Html {
let schema = {
let renderer = props.renderer.clone();
let view_config = props.view_config.clone();
use_memo(
(props.plugin_config.clone(), props.view_config.clone()),
move |_| match get_plugin_config_schema(&renderer, &view_config) {
Ok(schema) => schema.fields,
Err(error) => {
tracing::error!("{}", error);
vec![]
},
},
)
};
let on_change = {
let session = props.session.clone();
let renderer = props.renderer.clone();
yew::Callback::from(move |update: crate::config::ColumnConfigFieldUpdate| {
send_plugin_config(&session, &renderer, update);
})
};
let raw_config = &*props.plugin_config;
let components = schema
.iter()
.cloned()
.filter_map(|spec| {
let component = match spec {
ControlSpec::Enum {
key,
variants,
default,
} => {
let current = raw_config
.get(&key)
.and_then(|v| v.as_str().map(|s| s.to_string()));
html! {
<EnumField
field_key={key}
{variants}
{default}
{current}
on_change={on_change.clone()}
/>
}
},
ControlSpec::Bool { key, default } => {
let current = raw_config.get(&key).and_then(|v| v.as_bool());
html! {
<BoolField
field_key={key}
{default}
{current}
on_change={on_change.clone()}
/>
}
},
ControlSpec::Color { key, default } => {
let current = raw_config
.get(&key)
.and_then(|v| v.as_str().map(|s| s.to_string()));
html! {
<ColorField
field_key={key}
{default}
{current}
on_change={on_change.clone()}
/>
}
},
ControlSpec::ColorRange {
key_pos,
key_neg,
default_pos,
default_neg,
is_gradient,
} => {
let current_pos = raw_config
.get(&key_pos)
.and_then(|v| v.as_str().map(|s| s.to_string()));
let current_neg = raw_config
.get(&key_neg)
.and_then(|v| v.as_str().map(|s| s.to_string()));
html! {
<ColorRangeField
field_key_pos={key_pos}
field_key_neg={key_neg}
{default_pos}
{default_neg}
{current_pos}
{current_neg}
{is_gradient}
on_change={on_change.clone()}
/>
}
},
ControlSpec::Number {
key,
default,
min,
max,
step,
include,
} => {
let current = raw_config.get(&key).and_then(|v| v.as_f64());
html! {
<NumberFieldPrimitive
field_key={key}
{default}
{current}
{min}
{max}
{step}
{include}
on_change={on_change.clone()}
/>
}
},
ControlSpec::AggregateDepth
| ControlSpec::NumberSeriesStyle { .. }
| ControlSpec::DatetimeFormat
| ControlSpec::StringFormat
| ControlSpec::Symbols { .. }
| ControlSpec::NumberFormat
| ControlSpec::String { .. } => {
return None;
},
};
Some(html! { <fieldset class="style-control">{ component }</fieldset> })
})
.collect_vec();
html! {
<div id="plugin-tab" class="sidebar_column scrollable">
<LocalStyle href={css!("column-style")} />
<LocalStyle href={css!("plugin-settings-panel")} />
<LocalStyle href={css!("containers/tabs")} />
<div id="plugin-config-container" class="tab-section">{ components }</div>
</div>
}
}