@perspective-dev/viewer 4.0.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/perspective-viewer.js +2 -2
- package/dist/cdn/perspective-viewer.js.map +4 -4
- package/dist/css/dracula.css +1 -1
- package/dist/css/gruvbox-dark.css +1 -1
- package/dist/css/gruvbox.css +1 -1
- package/dist/css/icons.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/pro-dark.css +1 -1
- package/dist/css/pro.css +1 -1
- package/dist/css/solarized-dark.css +1 -1
- package/dist/css/solarized.css +1 -1
- package/dist/css/themes.css +1 -1
- package/dist/css/vaporwave.css +1 -1
- package/dist/esm/extensions.d.ts +23 -2
- package/dist/esm/perspective-viewer.d.ts +2 -7
- package/dist/esm/perspective-viewer.inline.js +2 -2
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +2 -2
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/plugin.d.ts +1 -1
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +1 -0
- package/dist/wasm/perspective-viewer.d.ts +218 -46
- package/dist/wasm/perspective-viewer.js +1250 -761
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +38 -19
- package/package.json +1 -1
- package/src/less/containers/scroll-panel.less +0 -1
- package/src/less/plugin-selector.less +15 -5
- package/src/less/status-bar.less +75 -27
- package/src/less/viewer.less +140 -58
- package/src/rust/components/column_dropdown.rs +21 -21
- package/src/rust/components/column_selector/active_column.rs +131 -120
- package/src/rust/components/column_selector/add_expression_button.rs +5 -0
- package/src/rust/components/column_selector/aggregate_selector.rs +8 -4
- package/src/rust/components/column_selector/config_selector.rs +170 -161
- package/src/rust/components/column_selector/empty_column.rs +16 -11
- package/src/rust/components/column_selector/{expression_toolbar.rs → expr_edit_button.rs} +7 -0
- package/src/rust/components/column_selector/filter_column.rs +195 -194
- package/src/rust/components/column_selector/inactive_column.rs +82 -67
- package/src/rust/components/column_selector/pivot_column.rs +16 -11
- package/src/rust/components/column_selector/sort_column.rs +9 -7
- package/src/rust/components/column_selector.rs +42 -37
- package/src/rust/components/column_settings_sidebar/save_settings.rs +3 -1
- package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +58 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +6 -6
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +2 -94
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs_item.rs +111 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +3 -3
- package/src/rust/components/column_settings_sidebar/style_tab.rs +23 -83
- package/src/rust/components/{column_settings_sidebar/sidebar.rs → column_settings_sidebar.rs} +198 -171
- package/src/rust/components/containers/dragdrop_list.rs +20 -20
- package/src/rust/components/containers/dropdown_menu.rs +4 -6
- package/src/rust/components/containers/mod.rs +1 -4
- package/src/rust/components/containers/scroll_panel.rs +80 -80
- package/src/rust/components/containers/scroll_panel_item.rs +36 -36
- package/src/rust/components/containers/select.rs +46 -44
- package/src/rust/components/containers/sidebar.rs +3 -19
- package/src/rust/components/{column_settings_sidebar/style_tab/symbol/symbol_config.rs → containers/sidebar_close_button.rs} +15 -9
- package/src/rust/components/containers/split_panel.rs +212 -200
- package/src/rust/components/containers/tab_list.rs +11 -11
- package/src/rust/components/copy_dropdown.rs +22 -25
- package/src/rust/components/datetime_column_style/custom.rs +19 -19
- package/src/rust/components/datetime_column_style/simple.rs +13 -14
- package/src/rust/components/datetime_column_style.rs +75 -76
- package/src/rust/components/editable_header.rs +18 -14
- package/src/rust/components/empty_row.rs +5 -5
- package/src/rust/components/export_dropdown.rs +42 -42
- package/src/rust/components/expression_editor.rs +25 -19
- package/src/rust/components/filter_dropdown.rs +22 -22
- package/src/rust/components/font_loader.rs +11 -9
- package/src/rust/components/form/code_editor.rs +106 -105
- package/src/rust/components/form/color_range_selector.rs +14 -12
- package/src/rust/components/form/color_selector.rs +3 -1
- package/src/rust/components/form/debug.rs +95 -94
- package/src/rust/components/form/highlight.rs +5 -3
- package/src/rust/components/form/mod.rs +3 -2
- package/src/rust/components/form/optional_field.rs +2 -2
- package/src/rust/components/form/{select_field.rs → select_enum_field.rs} +1 -46
- package/src/rust/components/form/select_value_field.rs +64 -0
- package/src/rust/components/function_dropdown.rs +21 -21
- package/src/rust/components/main_panel.rs +219 -0
- package/src/rust/components/mod.rs +6 -6
- package/src/rust/components/modal.rs +42 -42
- package/src/rust/components/number_column_style.rs +34 -88
- package/src/rust/components/plugin_selector.rs +22 -25
- package/src/rust/components/render_warning.rs +9 -6
- package/src/rust/components/settings_panel.rs +82 -0
- package/src/rust/components/status_bar.rs +250 -146
- package/src/rust/components/status_bar_counter.rs +26 -119
- package/src/rust/components/status_indicator.rs +95 -79
- package/src/rust/components/string_column_style.rs +45 -45
- package/src/rust/components/style/style_provider.rs +1 -15
- package/src/rust/components/style_controls/number_string_format/digits_section.rs +1 -1
- package/src/rust/components/style_controls/number_string_format/misc_section.rs +1 -1
- package/src/rust/components/style_controls/number_string_format/style_section.rs +1 -1
- package/src/rust/components/style_controls/number_string_format.rs +45 -46
- package/src/rust/components/type_icon.rs +14 -11
- package/src/rust/components/viewer.rs +241 -384
- package/src/rust/config/columns_config.rs +2 -2
- package/src/rust/config/datetime_column_style.rs +1 -6
- package/src/rust/config/mod.rs +1 -0
- package/src/rust/config/number_column_style.rs +0 -6
- package/src/rust/config/number_string_format.rs +27 -4
- package/src/rust/config/viewer_config.rs +27 -167
- package/src/rust/custom_elements/copy_dropdown.rs +14 -6
- package/src/rust/custom_elements/export_dropdown.rs +15 -7
- package/src/rust/custom_elements/filter_dropdown.rs +4 -4
- package/src/rust/custom_elements/mod.rs +3 -0
- package/src/rust/custom_elements/viewer.rs +353 -161
- package/src/rust/custom_events.rs +55 -32
- package/src/rust/dragdrop.rs +4 -24
- package/src/rust/exprtk/cursor.rs +10 -1
- package/src/rust/exprtk/mod.rs +2 -0
- package/src/rust/exprtk/tokenize.rs +20 -3
- package/src/rust/js/clipboard.rs +2 -2
- package/src/rust/js/mimetype.rs +2 -7
- package/src/rust/js/mod.rs +0 -1
- package/src/rust/js/plugin.rs +7 -0
- package/src/rust/lib.rs +18 -5
- package/src/rust/model/column_locator.rs +82 -0
- package/src/rust/model/columns_iter_set.rs +1 -0
- package/src/rust/model/copy_export.rs +50 -14
- package/src/rust/model/edit_expression.rs +2 -5
- package/src/rust/model/eject.rs +41 -0
- package/src/rust/model/get_viewer_config.rs +4 -28
- package/src/rust/model/intersection_observer.rs +20 -8
- package/src/rust/model/mod.rs +11 -4
- package/src/rust/model/plugin_column_styles.rs +0 -31
- package/src/rust/model/reset_all.rs +38 -0
- package/src/rust/model/resize_observer.rs +34 -7
- package/src/rust/model/restore_and_render.rs +12 -7
- package/src/rust/{utils/scope.rs → model/send_plugin_config.rs} +32 -35
- package/src/rust/model/structural.rs +194 -23
- package/src/rust/model/update_and_render.rs +14 -4
- package/src/rust/{model/create_col.rs → presentation/column_locator.rs} +73 -42
- package/src/rust/{utils/wasm_abi.rs → presentation/sheets.rs} +54 -40
- package/src/rust/presentation.rs +60 -119
- package/src/rust/renderer/activate.rs +20 -5
- package/src/rust/renderer/limits.rs +0 -149
- package/src/rust/renderer/render_timer.rs +1 -1
- package/src/rust/renderer.rs +34 -18
- package/src/rust/root.rs +50 -0
- package/src/rust/session/column_defaults_update.rs +4 -4
- package/src/rust/session/drag_drop_update.rs +1 -1
- package/src/rust/session/metadata.rs +3 -17
- package/src/rust/session/replace_expression_update.rs +1 -2
- package/src/rust/session.rs +162 -82
- package/src/rust/utils/browser/blob.rs +16 -2
- package/src/rust/utils/browser/download.rs +1 -0
- package/src/rust/{components/column_settings_sidebar/mod.rs → utils/browser/dragdrop.rs} +14 -5
- package/src/rust/utils/browser/mod.rs +8 -4
- package/src/rust/utils/browser/selection.rs +5 -0
- package/src/rust/utils/custom_element.rs +28 -13
- package/src/rust/utils/datetime.rs +5 -0
- package/src/rust/utils/debounce.rs +7 -1
- package/src/rust/utils/hooks/use_async_callback.rs +7 -17
- package/src/rust/utils/mod.rs +28 -40
- package/src/rust/utils/number_format.rs +6 -5
- package/src/rust/utils/pubsub.rs +15 -10
- package/src/rust/utils/weak_scope.rs +11 -1
- package/src/svg/bookmark-icon.svg +4 -0
- package/src/svg/drag-handle copy.svg +10 -0
- package/src/svg/drawer-tab-hover.svg +5 -7
- package/src/svg/drawer-tab-invert-hover.svg +4 -8
- package/src/svg/drawer-tab-invert.svg +4 -7
- package/src/svg/drawer-tab.svg +4 -6
- package/src/svg/status_ok.svg +24 -24
- package/src/ts/extensions.ts +51 -3
- package/src/ts/perspective-viewer.ts +2 -14
- package/src/ts/plugin.ts +1 -1
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab/column_style.rs +0 -177
- package/src/rust/components/containers/tests/mod.rs +0 -11
- package/src/rust/components/containers/tests/split_panel.rs +0 -91
- package/src/rust/js/testing.rs +0 -149
- package/src/rust/utils/tee.rs +0 -88
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-0d326a25c1022412}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-0d326a25c1022412}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-0d326a25c1022412}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-0d326a25c1022412}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-0d326a25c1022412}/inline4.js +0 -0
- /package/src/rust/components/{style_controls.rs → style_controls/mod.rs} +0 -0
- /package/src/rust/{components/containers → config}/kvpair.rs +0 -0
|
@@ -19,6 +19,18 @@ use crate::utils::WeakScope;
|
|
|
19
19
|
|
|
20
20
|
static CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/css/column-dropdown.css"));
|
|
21
21
|
|
|
22
|
+
#[derive(Properties, PartialEq)]
|
|
23
|
+
pub struct ColumnDropDownProps {
|
|
24
|
+
#[prop_or_default]
|
|
25
|
+
pub weak_link: WeakScope<ColumnDropDown>,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
impl ModalLink<ColumnDropDown> for ColumnDropDownProps {
|
|
29
|
+
fn weak_link(&self) -> &'_ WeakScope<ColumnDropDown> {
|
|
30
|
+
&self.weak_link
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
pub enum ColumnDropDownMsg {
|
|
23
35
|
SetValues(Vec<InPlaceColumn>, f64),
|
|
24
36
|
SetCallback(Callback<InPlaceColumn>),
|
|
@@ -34,18 +46,6 @@ pub struct ColumnDropDown {
|
|
|
34
46
|
on_select: Option<Callback<InPlaceColumn>>,
|
|
35
47
|
}
|
|
36
48
|
|
|
37
|
-
#[derive(Properties, PartialEq)]
|
|
38
|
-
pub struct ColumnDropDownProps {
|
|
39
|
-
#[prop_or_default]
|
|
40
|
-
pub weak_link: WeakScope<ColumnDropDown>,
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
impl ModalLink<ColumnDropDown> for ColumnDropDownProps {
|
|
44
|
-
fn weak_link(&self) -> &'_ WeakScope<ColumnDropDown> {
|
|
45
|
-
&self.weak_link
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
49
|
impl Component for ColumnDropDown {
|
|
50
50
|
type Message = ColumnDropDownMsg;
|
|
51
51
|
type Properties = ColumnDropDownProps;
|
|
@@ -91,19 +91,19 @@ impl Component for ColumnDropDown {
|
|
|
91
91
|
},
|
|
92
92
|
ColumnDropDownMsg::ItemDown => {
|
|
93
93
|
self.selected += 1;
|
|
94
|
-
if let Some(ref values) = self.values
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
if let Some(ref values) = self.values {
|
|
95
|
+
if self.selected >= values.len() {
|
|
96
|
+
self.selected = 0;
|
|
97
|
+
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
true
|
|
101
101
|
},
|
|
102
102
|
ColumnDropDownMsg::ItemUp => {
|
|
103
|
-
if let Some(ref values) = self.values
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
if let Some(ref values) = self.values {
|
|
104
|
+
if self.selected < 1 {
|
|
105
|
+
self.selected = values.len();
|
|
106
|
+
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
self.selected -= 1;
|
|
@@ -157,6 +157,6 @@ impl Component for ColumnDropDown {
|
|
|
157
157
|
self.width, self.width
|
|
158
158
|
);
|
|
159
159
|
|
|
160
|
-
html! { <><style>{
|
|
160
|
+
html! { <><style>{ CSS }</style><style>{ position }</style>{ body }</> }
|
|
161
161
|
}
|
|
162
162
|
}
|
|
@@ -14,47 +14,60 @@ use std::collections::HashSet;
|
|
|
14
14
|
|
|
15
15
|
use perspective_client::config::*;
|
|
16
16
|
use perspective_client::utils::PerspectiveResultExt;
|
|
17
|
+
use perspective_js::utils::ApiFuture;
|
|
17
18
|
use web_sys::*;
|
|
18
19
|
use yew::prelude::*;
|
|
19
20
|
|
|
20
21
|
use super::InPlaceColumn;
|
|
21
22
|
use super::aggregate_selector::*;
|
|
22
|
-
use super::
|
|
23
|
+
use super::expr_edit_button::*;
|
|
24
|
+
use crate::PerspectiveProperties;
|
|
23
25
|
use crate::components::column_selector::{EmptyColumn, InvalidColumn};
|
|
24
26
|
use crate::components::type_icon::TypeIcon;
|
|
25
|
-
use crate::components::viewer::ColumnLocator;
|
|
26
27
|
use crate::custom_elements::ColumnDropDownElement;
|
|
27
28
|
use crate::dragdrop::*;
|
|
28
29
|
use crate::js::plugin::*;
|
|
29
30
|
use crate::model::*;
|
|
30
|
-
use crate::presentation::
|
|
31
|
+
use crate::presentation::ColumnLocator;
|
|
31
32
|
use crate::renderer::*;
|
|
32
33
|
use crate::session::*;
|
|
33
|
-
use crate::*;
|
|
34
|
+
use crate::utils::*;
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
Empty,
|
|
37
|
-
Invalid,
|
|
38
|
-
Named(String),
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
#[derive(Properties, Clone)]
|
|
36
|
+
#[derive(Clone, Properties, PerspectiveProperties!)]
|
|
42
37
|
pub struct ActiveColumnProps {
|
|
38
|
+
/// The column's index in the list.
|
|
43
39
|
pub idx: usize,
|
|
40
|
+
|
|
41
|
+
/// The column definition (including name and type).
|
|
44
42
|
pub name: ActiveColumnState,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
pub renderer: Renderer,
|
|
48
|
-
pub presentation: Presentation,
|
|
43
|
+
|
|
44
|
+
/// The column select dropdown menu element.
|
|
49
45
|
pub column_dropdown: ColumnDropDownElement,
|
|
46
|
+
|
|
47
|
+
/// `dragenter` event.
|
|
50
48
|
pub ondragenter: Callback<()>,
|
|
49
|
+
|
|
50
|
+
/// `dragend` event.
|
|
51
51
|
pub ondragend: Callback<()>,
|
|
52
|
+
|
|
53
|
+
/// Fires when this component's select button is clicked.
|
|
52
54
|
pub onselect: Callback<()>,
|
|
55
|
+
|
|
56
|
+
/// Fires when this component's expression/config button is clicked.
|
|
53
57
|
pub on_open_expr_panel: Callback<ColumnLocator>,
|
|
54
58
|
|
|
59
|
+
/// Is this column in a grouped context (does the aggregate selector
|
|
60
|
+
/// need to be visible)?
|
|
55
61
|
#[prop_or_default]
|
|
56
62
|
pub is_aggregated: bool,
|
|
63
|
+
|
|
64
|
+
/// Is this column's expression/config side panel open?
|
|
57
65
|
pub is_editing: bool,
|
|
66
|
+
|
|
67
|
+
/// State
|
|
68
|
+
pub session: Session,
|
|
69
|
+
pub dragdrop: DragDrop,
|
|
70
|
+
pub renderer: Renderer,
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
impl PartialEq for ActiveColumnProps {
|
|
@@ -63,93 +76,6 @@ impl PartialEq for ActiveColumnProps {
|
|
|
63
76
|
}
|
|
64
77
|
}
|
|
65
78
|
|
|
66
|
-
impl ActiveColumnProps {
|
|
67
|
-
fn get_name(&self) -> Option<String> {
|
|
68
|
-
match &self.name.state {
|
|
69
|
-
ActiveColumnStateData::DragOver => Some(self.dragdrop.get_drag_column().unwrap()),
|
|
70
|
-
ActiveColumnStateData::Column(name) => Some(name.to_owned()),
|
|
71
|
-
ActiveColumnStateData::Required => None,
|
|
72
|
-
ActiveColumnStateData::Invalid => None,
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
fn get_table_type(&self) -> Option<ColumnType> {
|
|
77
|
-
self.get_name()
|
|
78
|
-
.as_ref()
|
|
79
|
-
.and_then(|x| self.session.metadata().get_column_table_type(x))
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
fn _get_view_type(&self) -> Option<ColumnType> {
|
|
83
|
-
self.get_name()
|
|
84
|
-
.as_ref()
|
|
85
|
-
.and_then(|x| self.session.metadata().get_column_view_type(x))
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
derive_model!(Renderer, Session for ActiveColumnProps);
|
|
90
|
-
|
|
91
|
-
impl ActiveColumnProps {
|
|
92
|
-
/// Remove an active column from `columns`, or alternatively make this
|
|
93
|
-
/// column the only column in `columns` if the shift key is set (via the
|
|
94
|
-
/// `shift` flag).
|
|
95
|
-
///
|
|
96
|
-
/// # Arguments
|
|
97
|
-
/// - `name` The name of the column to de-activate, which is a unique ID
|
|
98
|
-
/// with respect to `columns`.
|
|
99
|
-
/// - `shift` whether to toggle or select this column.
|
|
100
|
-
pub fn deactivate_column(&self, name: String, shift: bool) {
|
|
101
|
-
let mut columns = self.session.get_view_config().columns.clone();
|
|
102
|
-
let max_cols = self
|
|
103
|
-
.renderer
|
|
104
|
-
.metadata()
|
|
105
|
-
.names
|
|
106
|
-
.as_ref()
|
|
107
|
-
.map_or(0, |x| x.len());
|
|
108
|
-
|
|
109
|
-
match self.renderer.metadata().mode {
|
|
110
|
-
ColumnSelectMode::Toggle => {
|
|
111
|
-
let index = columns
|
|
112
|
-
.iter()
|
|
113
|
-
.position(|x| x.as_ref() == Some(&name))
|
|
114
|
-
.unwrap();
|
|
115
|
-
|
|
116
|
-
if max_cols > 0 && index < max_cols - 1 {
|
|
117
|
-
columns[index] = None;
|
|
118
|
-
} else if !shift && columns.len() > 1 {
|
|
119
|
-
columns.retain(|x| x.as_ref() != Some(&name));
|
|
120
|
-
} else if shift {
|
|
121
|
-
columns.clear();
|
|
122
|
-
columns.push(Some(name));
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
ColumnSelectMode::Select => {
|
|
126
|
-
columns.retain(|x| x.as_ref() != Some(&name));
|
|
127
|
-
},
|
|
128
|
-
}
|
|
129
|
-
self.apply_columns(columns);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
fn get_is_required(&self) -> bool {
|
|
133
|
-
let min_cols = self.renderer.metadata().min.unwrap_or(0);
|
|
134
|
-
self.idx < min_cols
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
fn get_aggregate(&self, name: &str) -> Option<Aggregate> {
|
|
138
|
-
self.session.get_view_config().aggregates.get(name).cloned()
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
fn apply_columns(&self, columns: Vec<Option<String>>) {
|
|
142
|
-
let config = ViewConfigUpdate {
|
|
143
|
-
columns: Some(columns),
|
|
144
|
-
..ViewConfigUpdate::default()
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
self.update_and_render(config)
|
|
148
|
-
.map(ApiFuture::spawn)
|
|
149
|
-
.unwrap_or_log();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
79
|
pub enum ActiveColumnMsg {
|
|
154
80
|
DeactivateColumn(String, bool),
|
|
155
81
|
MouseEnter(bool),
|
|
@@ -159,14 +85,12 @@ pub enum ActiveColumnMsg {
|
|
|
159
85
|
|
|
160
86
|
use ActiveColumnMsg::*;
|
|
161
87
|
|
|
162
|
-
/// An `ActiveColumn` indicates a column which is part of the `columns` field
|
|
163
|
-
/// a `ViewConfig
|
|
88
|
+
/// An [`ActiveColumn`] indicates a column which is part of the `columns` field
|
|
89
|
+
/// of a [`ViewConfig`]. It shows additional column details in context (like
|
|
164
90
|
/// selected aggregate), and supports drag/drop and missing entries.
|
|
165
91
|
/// TODO Break this into "Active", "Hover" and "Empty"?
|
|
166
|
-
#[derive(Default)]
|
|
167
92
|
pub struct ActiveColumn {
|
|
168
93
|
add_expression_ref: NodeRef,
|
|
169
|
-
is_required: bool,
|
|
170
94
|
mouseover: bool,
|
|
171
95
|
}
|
|
172
96
|
|
|
@@ -174,19 +98,13 @@ impl Component for ActiveColumn {
|
|
|
174
98
|
type Message = ActiveColumnMsg;
|
|
175
99
|
type Properties = ActiveColumnProps;
|
|
176
100
|
|
|
177
|
-
fn create(
|
|
178
|
-
let is_required = ctx.props().get_is_required();
|
|
101
|
+
fn create(_ctx: &Context<Self>) -> Self {
|
|
179
102
|
Self {
|
|
180
|
-
|
|
181
|
-
|
|
103
|
+
add_expression_ref: NodeRef::default(),
|
|
104
|
+
mouseover: false,
|
|
182
105
|
}
|
|
183
106
|
}
|
|
184
107
|
|
|
185
|
-
fn changed(&mut self, ctx: &Context<Self>, _old: &Self::Properties) -> bool {
|
|
186
|
-
self.is_required = ctx.props().get_is_required();
|
|
187
|
-
true
|
|
188
|
-
}
|
|
189
|
-
|
|
190
108
|
fn update(&mut self, ctx: &Context<Self>, msg: ActiveColumnMsg) -> bool {
|
|
191
109
|
match msg {
|
|
192
110
|
DeactivateColumn(column, shift_key) => {
|
|
@@ -248,6 +166,12 @@ impl Component for ActiveColumn {
|
|
|
248
166
|
}
|
|
249
167
|
|
|
250
168
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
169
|
+
enum ColumnState {
|
|
170
|
+
Empty,
|
|
171
|
+
Invalid,
|
|
172
|
+
Named(String),
|
|
173
|
+
}
|
|
174
|
+
|
|
251
175
|
let mut classes = classes!["column-selector-draggable"];
|
|
252
176
|
if ctx.props().is_aggregated {
|
|
253
177
|
classes.push("show-aggregate");
|
|
@@ -310,7 +234,7 @@ impl Component for ActiveColumn {
|
|
|
310
234
|
})
|
|
311
235
|
.collect();
|
|
312
236
|
|
|
313
|
-
let col_type = ctx.props().get_table_type();
|
|
237
|
+
let col_type = ctx.props().get_table_type(&ctx.props().name);
|
|
314
238
|
match (name, col_type) {
|
|
315
239
|
((label, ColumnState::Empty), _) => {
|
|
316
240
|
classes.push("empty-named");
|
|
@@ -353,7 +277,8 @@ impl Component for ActiveColumn {
|
|
|
353
277
|
}
|
|
354
278
|
},
|
|
355
279
|
((label, ColumnState::Named(name)), Some(col_type)) => {
|
|
356
|
-
let
|
|
280
|
+
let is_required = ctx.props().get_is_required(ctx.props().idx);
|
|
281
|
+
let remove_column = if is_required {
|
|
357
282
|
None
|
|
358
283
|
} else {
|
|
359
284
|
Some(ctx.link().callback({
|
|
@@ -389,7 +314,7 @@ impl Component for ActiveColumn {
|
|
|
389
314
|
|
|
390
315
|
let is_expression = ctx.props().session.metadata().is_column_expression(&name);
|
|
391
316
|
let mut class = ctx.props().renderer.metadata().mode.css();
|
|
392
|
-
if
|
|
317
|
+
if is_required {
|
|
393
318
|
class.push("required");
|
|
394
319
|
};
|
|
395
320
|
|
|
@@ -398,7 +323,6 @@ impl Component for ActiveColumn {
|
|
|
398
323
|
.can_render_column_styles(&name)
|
|
399
324
|
.unwrap_or_default();
|
|
400
325
|
let show_edit_btn = is_expression || can_render_styles;
|
|
401
|
-
|
|
402
326
|
html! {
|
|
403
327
|
<div
|
|
404
328
|
class={outer_classes}
|
|
@@ -427,7 +351,11 @@ impl Component for ActiveColumn {
|
|
|
427
351
|
session={&ctx.props().session}
|
|
428
352
|
/>
|
|
429
353
|
}
|
|
430
|
-
<span
|
|
354
|
+
<span
|
|
355
|
+
class="column_name"
|
|
356
|
+
>
|
|
357
|
+
{ name.clone() }
|
|
358
|
+
</span>
|
|
431
359
|
if !ctx.props().is_aggregated {
|
|
432
360
|
<span class="column-selector--spacer" />
|
|
433
361
|
}
|
|
@@ -460,3 +388,86 @@ impl Component for ActiveColumn {
|
|
|
460
388
|
}
|
|
461
389
|
}
|
|
462
390
|
}
|
|
391
|
+
|
|
392
|
+
impl ActiveColumnProps {
|
|
393
|
+
fn get_name(&self, defn: &ActiveColumnState) -> Option<String> {
|
|
394
|
+
match &defn.state {
|
|
395
|
+
ActiveColumnStateData::DragOver => Some(self.dragdrop.get_drag_column().unwrap()),
|
|
396
|
+
ActiveColumnStateData::Column(name) => Some(name.to_owned()),
|
|
397
|
+
ActiveColumnStateData::Required => None,
|
|
398
|
+
ActiveColumnStateData::Invalid => None,
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
fn get_table_type(&self, defn: &ActiveColumnState) -> Option<ColumnType> {
|
|
403
|
+
self.get_name(defn)
|
|
404
|
+
.as_ref()
|
|
405
|
+
.and_then(|x| self.session.metadata().get_column_table_type(x))
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
fn _get_view_type(&self, defn: &ActiveColumnState) -> Option<ColumnType> {
|
|
409
|
+
self.get_name(defn)
|
|
410
|
+
.as_ref()
|
|
411
|
+
.and_then(|x| self.session.metadata().get_column_view_type(x))
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/// Remove an active column from `columns`, or alternatively make this
|
|
415
|
+
/// column the only column in `columns` if the shift key is set (via the
|
|
416
|
+
/// `shift` flag).
|
|
417
|
+
///
|
|
418
|
+
/// # Arguments
|
|
419
|
+
/// - `name` The name of the column to de-activate, which is a unique ID
|
|
420
|
+
/// with respect to `columns`.
|
|
421
|
+
/// - `shift` whether to toggle or select this column.
|
|
422
|
+
fn deactivate_column(&self, name: String, shift: bool) {
|
|
423
|
+
let mut columns = self.session.get_view_config().columns.clone();
|
|
424
|
+
let max_cols = self
|
|
425
|
+
.renderer
|
|
426
|
+
.metadata()
|
|
427
|
+
.names
|
|
428
|
+
.as_ref()
|
|
429
|
+
.map_or(0, |x| x.len());
|
|
430
|
+
|
|
431
|
+
match self.renderer.metadata().mode {
|
|
432
|
+
ColumnSelectMode::Toggle => {
|
|
433
|
+
let index = columns
|
|
434
|
+
.iter()
|
|
435
|
+
.position(|x| x.as_ref() == Some(&name))
|
|
436
|
+
.unwrap();
|
|
437
|
+
|
|
438
|
+
if max_cols > 0 && index < max_cols - 1 {
|
|
439
|
+
columns[index] = None;
|
|
440
|
+
} else if !shift && columns.len() > 1 {
|
|
441
|
+
columns.retain(|x| x.as_ref() != Some(&name));
|
|
442
|
+
} else if shift {
|
|
443
|
+
columns.clear();
|
|
444
|
+
columns.push(Some(name));
|
|
445
|
+
}
|
|
446
|
+
},
|
|
447
|
+
ColumnSelectMode::Select => {
|
|
448
|
+
columns.retain(|x| x.as_ref() != Some(&name));
|
|
449
|
+
},
|
|
450
|
+
}
|
|
451
|
+
self.apply_columns(columns);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
fn get_is_required(&self, idx: usize) -> bool {
|
|
455
|
+
let min_cols = self.renderer.metadata().min.unwrap_or(0);
|
|
456
|
+
idx < min_cols
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
fn get_aggregate(&self, name: &str) -> Option<Aggregate> {
|
|
460
|
+
self.session.get_view_config().aggregates.get(name).cloned()
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
fn apply_columns(&self, columns: Vec<Option<String>>) {
|
|
464
|
+
let config = ViewConfigUpdate {
|
|
465
|
+
columns: Some(columns),
|
|
466
|
+
..ViewConfigUpdate::default()
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
self.update_and_render(config)
|
|
470
|
+
.map(ApiFuture::spawn)
|
|
471
|
+
.unwrap_or_log();
|
|
472
|
+
}
|
|
473
|
+
}
|
|
@@ -13,9 +13,13 @@
|
|
|
13
13
|
use yew::prelude::*;
|
|
14
14
|
|
|
15
15
|
use super::ColumnLocator;
|
|
16
|
+
|
|
16
17
|
#[derive(Clone, PartialEq, Properties)]
|
|
17
18
|
pub struct AddExpressionButtonProps {
|
|
19
|
+
// Fires when this button is clicked.
|
|
18
20
|
pub on_open_expr_panel: Callback<ColumnLocator>,
|
|
21
|
+
|
|
22
|
+
/// The column this butotn will open configuration for.
|
|
19
23
|
pub selected_column: Option<ColumnLocator>,
|
|
20
24
|
}
|
|
21
25
|
|
|
@@ -44,6 +48,7 @@ pub fn AddExpressionButton(p: &AddExpressionButtonProps) -> Html {
|
|
|
44
48
|
let onmousedown = p
|
|
45
49
|
.on_open_expr_panel
|
|
46
50
|
.reform(|_| ColumnLocator::NewExpression);
|
|
51
|
+
|
|
47
52
|
let class = if *is_mouseover || matches!(p.selected_column, Some(ColumnLocator::NewExpression))
|
|
48
53
|
{
|
|
49
54
|
classes!("dragdrop-hover")
|
|
@@ -15,6 +15,7 @@ use std::rc::Rc;
|
|
|
15
15
|
|
|
16
16
|
use perspective_client::config::*;
|
|
17
17
|
use perspective_client::utils::PerspectiveResultExt;
|
|
18
|
+
use perspective_js::utils::ApiFuture;
|
|
18
19
|
use yew::prelude::*;
|
|
19
20
|
|
|
20
21
|
use crate::components::containers::select::*;
|
|
@@ -22,18 +23,21 @@ use crate::components::style::LocalStyle;
|
|
|
22
23
|
use crate::model::*;
|
|
23
24
|
use crate::renderer::*;
|
|
24
25
|
use crate::session::*;
|
|
25
|
-
use crate
|
|
26
|
+
use crate::{PerspectiveProperties, css};
|
|
26
27
|
|
|
27
|
-
#[derive(Properties)]
|
|
28
|
+
#[derive(Properties, PerspectiveProperties!)]
|
|
28
29
|
pub struct AggregateSelectorProps {
|
|
30
|
+
/// The name of this aggregate.
|
|
29
31
|
pub column: String,
|
|
32
|
+
|
|
33
|
+
/// Which aggregate is currently selected.
|
|
30
34
|
pub aggregate: Option<Aggregate>,
|
|
35
|
+
|
|
36
|
+
// State
|
|
31
37
|
pub renderer: Renderer,
|
|
32
38
|
pub session: Session,
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
derive_model!(Renderer, Session for AggregateSelectorProps);
|
|
36
|
-
|
|
37
41
|
impl PartialEq for AggregateSelectorProps {
|
|
38
42
|
fn eq(&self, rhs: &Self) -> bool {
|
|
39
43
|
self.column == rhs.column && self.aggregate == rhs.aggregate
|