@perspective-dev/viewer 4.2.0 → 4.4.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/botanical.css +1 -0
- 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/intl/de.css +1 -1
- package/dist/css/intl/es.css +1 -1
- package/dist/css/intl/fr.css +1 -1
- package/dist/css/intl/ja.css +1 -1
- package/dist/css/intl/pt.css +1 -1
- package/dist/css/intl/zh.css +1 -1
- package/dist/css/intl.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 +32 -1
- package/dist/esm/perspective-viewer.d.ts +1 -0
- 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/ts-rs/GroupRollupMode.d.ts +1 -0
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +2 -0
- package/dist/wasm/perspective-viewer.d.ts +57 -53
- package/dist/wasm/perspective-viewer.js +197 -164
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +17 -18
- package/package.json +9 -6
- package/src/{less/aggregate-selector.less → css/aggregate-selector.css} +23 -20
- package/src/css/column-dropdown.css +109 -0
- package/src/{less/column-selector.less → css/column-selector.css} +161 -159
- package/src/{less/column-settings-panel.less → css/column-settings-panel.css} +69 -59
- package/src/{less/column-style.less → css/column-style.css} +52 -66
- package/src/{less/column-symbol-attributes.less → css/column-symbol-attributes.css} +15 -14
- package/src/css/config-selector.css +441 -0
- package/src/{less/containers/dropdown-menu.less → css/containers/dropdown-menu.css} +20 -19
- package/src/{less/containers/pairs-list.less → css/containers/pairs-list.css} +13 -12
- package/src/{themes/variables.less → css/containers/scroll-panel.css} +25 -22
- package/src/{less/containers/split-panel.less → css/containers/split-panel.css} +15 -14
- package/src/{less/containers/tabs.less → css/containers/tabs.css} +17 -19
- package/src/css/dom/checkbox.css +102 -0
- package/src/css/dom/scrollbar.css +35 -0
- package/src/{less/dom/select.less → css/dom/select.css} +17 -18
- package/src/{less/empty-column.less → css/empty-column.css} +19 -18
- package/src/{less/expression-editor.less → css/expression-editor.css} +19 -18
- package/src/{less/filter-dropdown.less → css/filter-dropdown.css} +12 -11
- package/src/{less/filter-item.less → css/filter-item.css} +16 -15
- package/src/{less/form/code-editor.less → css/form/code-editor.css} +26 -30
- package/src/{less/form/debug.less → css/form/debug.css} +19 -18
- package/src/{less/function-dropdown.less → css/function-dropdown.css} +12 -11
- package/src/css/plugin-selector.css +261 -0
- package/src/{less/render-warning.less → css/render-warning.css} +18 -17
- package/src/{less/status-bar.less → css/status-bar.css} +156 -144
- package/src/css/type-icon.css +116 -0
- package/src/{less/viewer.less → css/viewer.css} +112 -146
- package/src/rust/components/column_dropdown.rs +229 -119
- package/src/rust/components/column_selector/active_column.rs +81 -62
- package/src/rust/components/column_selector/add_expression_button.rs +1 -0
- package/src/rust/components/column_selector/aggregate_selector.rs +25 -15
- package/src/rust/components/column_selector/config_selector.rs +374 -185
- package/src/rust/components/column_selector/empty_column.rs +2 -2
- package/src/rust/components/column_selector/expr_edit_button.rs +8 -2
- package/src/rust/components/column_selector/filter_column.rs +37 -26
- package/src/rust/components/column_selector/inactive_column.rs +41 -29
- package/src/rust/components/column_selector/invalid_column.rs +7 -18
- package/src/rust/components/column_selector/pivot_column.rs +21 -10
- package/src/rust/components/column_selector/sort_column.rs +23 -13
- package/src/rust/components/column_selector.rs +189 -100
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +3 -2
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs_item.rs +3 -2
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +2 -3
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +7 -1
- package/src/rust/components/column_settings_sidebar/style_tab.rs +153 -112
- package/src/rust/components/column_settings_sidebar.rs +91 -53
- package/src/rust/components/containers/dragdrop_list.rs +29 -7
- package/src/rust/components/containers/scroll_panel.rs +8 -1
- package/src/rust/components/containers/select.rs +3 -3
- package/src/rust/components/containers/sidebar_close_button.rs +1 -1
- package/src/rust/components/containers/split_panel.rs +3 -2
- package/src/rust/components/containers/tab_list.rs +1 -1
- package/src/rust/components/copy_dropdown.rs +7 -28
- package/src/rust/components/datetime_column_style/custom.rs +2 -2
- package/src/rust/components/datetime_column_style/simple.rs +2 -2
- package/src/rust/components/datetime_column_style.rs +4 -2
- package/src/rust/components/editable_header.rs +7 -4
- package/src/rust/components/empty_row.rs +1 -1
- package/src/rust/components/export_dropdown.rs +4 -30
- package/src/rust/components/expression_editor.rs +19 -10
- package/src/rust/components/filter_dropdown.rs +246 -102
- package/src/rust/components/font_loader.rs +11 -28
- package/src/rust/components/form/code_editor.rs +17 -2
- package/src/rust/components/form/color_range_selector.rs +19 -6
- package/src/rust/components/form/debug.rs +30 -13
- package/src/rust/components/function_dropdown.rs +186 -113
- package/src/rust/components/main_panel.rs +71 -89
- package/src/rust/components/mod.rs +1 -1
- package/src/rust/components/modal.rs +7 -1
- package/src/rust/components/number_column_style.rs +22 -7
- package/src/rust/components/plugin_selector.rs +34 -92
- package/src/rust/components/portal.rs +274 -0
- package/src/rust/components/render_warning.rs +72 -123
- package/src/rust/components/settings_panel.rs +115 -11
- package/src/rust/components/status_bar.rs +222 -98
- package/src/rust/components/status_bar_counter.rs +8 -20
- package/src/rust/components/status_indicator.rs +64 -111
- package/src/rust/components/string_column_style.rs +2 -2
- package/src/rust/components/style/style_cache.rs +5 -1
- package/src/rust/components/viewer.rs +391 -39
- package/src/rust/custom_elements/copy_dropdown.rs +102 -21
- package/src/rust/custom_elements/export_dropdown.rs +102 -20
- package/src/rust/custom_elements/mod.rs +0 -7
- package/src/rust/custom_elements/modal.rs +7 -103
- package/src/rust/custom_elements/viewer.rs +99 -35
- package/src/rust/custom_events.rs +23 -2
- package/src/rust/dragdrop.rs +149 -10
- package/src/{less/containers/scroll-panel.less → rust/engines.rs} +15 -13
- package/src/rust/js/plugin.rs +20 -1
- package/src/rust/lib.rs +5 -4
- package/src/rust/presentation/props.rs +39 -0
- package/src/rust/presentation/sheets.rs +3 -3
- package/src/rust/presentation.rs +44 -8
- package/src/rust/renderer/limits.rs +32 -3
- package/src/{less/dom/scrollbar.less → rust/renderer/props.rs} +18 -19
- package/src/rust/renderer/registry.rs +8 -1
- package/src/rust/renderer.rs +83 -9
- package/src/rust/session/column_defaults_update.rs +18 -0
- package/src/rust/session/metadata.rs +23 -2
- package/src/rust/session/props.rs +178 -0
- package/src/rust/session/replace_expression_update.rs +1 -0
- package/src/rust/session.rs +124 -117
- package/src/rust/tasks/column_locator.rs +133 -0
- package/src/rust/{model → tasks}/columns_iter_set.rs +14 -23
- package/src/rust/{model → tasks}/edit_expression.rs +34 -10
- package/src/rust/{model → tasks}/eject.rs +2 -2
- package/src/rust/{model → tasks}/get_viewer_config.rs +0 -11
- package/src/rust/{model → tasks}/intersection_observer.rs +22 -4
- package/src/{less/containers/radio-list.less → rust/tasks/is_invalid_drop.rs} +21 -14
- package/src/rust/tasks/mod.rs +52 -0
- package/src/rust/{model → tasks}/plugin_column_styles.rs +69 -46
- package/src/rust/{model → tasks}/resize_observer.rs +39 -6
- package/src/rust/{model → tasks}/send_plugin_config.rs +1 -1
- package/src/rust/tasks/structural.rs +53 -0
- package/src/rust/utils/mod.rs +4 -0
- package/src/rust/utils/modal_position.rs +110 -0
- package/src/rust/utils/ptr_eq_rc.rs +74 -0
- package/src/rust/utils/pubsub.rs +11 -1
- package/src/svg/bg-pattern.png +0 -0
- package/src/svg/close-icon.svg +1 -1
- package/src/svg/expression.svg +1 -1
- package/src/svg/mega-menu-icons-candlestick.svg +1 -1
- package/src/svg/mega-menu-icons-datagrid.svg +1 -2
- package/src/svg/mega-menu-icons-heatmap.svg +1 -1
- package/src/svg/mega-menu-icons-map-scatter.svg +1 -1
- package/src/svg/mega-menu-icons-ohlc.svg +1 -1
- package/src/svg/mega-menu-icons-sunburst.svg +1 -1
- package/src/svg/mega-menu-icons-treemap.svg +1 -1
- package/src/svg/mega-menu-icons-x-bar.svg +1 -1
- package/src/svg/mega-menu-icons-x-y-line.svg +1 -1
- package/src/svg/mega-menu-icons-x-y-scatter.svg +1 -1
- package/src/svg/mega-menu-icons-y-area.svg +1 -1
- package/src/svg/mega-menu-icons-y-bar.svg +1 -1
- package/src/svg/mega-menu-icons-y-line.svg +1 -1
- package/src/svg/mega-menu-icons-y-scatter.svg +1 -1
- package/src/svg/radio-hover.svg +1 -1
- package/src/svg/radio-off.svg +1 -1
- package/src/svg/radio-on.svg +1 -1
- package/src/themes/botanical.css +157 -0
- package/src/themes/defaults.css +139 -0
- package/src/themes/dracula.css +233 -0
- package/src/themes/gruvbox-dark.css +255 -0
- package/src/themes/gruvbox.css +134 -0
- package/src/themes/icons.css +124 -0
- package/src/themes/intl/de.css +102 -0
- package/src/themes/intl/es.css +102 -0
- package/src/themes/intl/fr.css +102 -0
- package/src/themes/intl/ja.css +102 -0
- package/src/themes/intl/pt.css +102 -0
- package/src/themes/intl/zh.css +102 -0
- package/src/themes/intl.css +102 -0
- package/src/themes/monokai.css +233 -0
- package/src/themes/pro-dark.css +158 -0
- package/src/themes/{themes.less → pro.css} +17 -20
- package/src/themes/solarized-dark.css +135 -0
- package/src/themes/solarized.css +95 -0
- package/src/themes/themes.css +22 -0
- package/src/themes/vaporwave.css +256 -0
- package/src/ts/extensions.ts +73 -2
- package/src/ts/perspective-viewer.ts +1 -0
- package/src/ts/ts-rs/GroupRollupMode.ts +3 -0
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +2 -1
- package/tsconfig.json +1 -0
- package/dist/css/variables.css +0 -0
- package/src/less/column-dropdown.less +0 -95
- package/src/less/config-selector.less +0 -363
- package/src/less/dom/checkbox.less +0 -100
- package/src/less/plugin-selector.less +0 -183
- package/src/less/type-icon.less +0 -68
- package/src/rust/components/error_message.rs +0 -56
- package/src/rust/custom_elements/column_dropdown.rs +0 -123
- package/src/rust/custom_elements/filter_dropdown.rs +0 -179
- package/src/rust/custom_elements/function_dropdown.rs +0 -115
- package/src/rust/model/column_locator.rs +0 -82
- package/src/rust/model/is_invalid_drop.rs +0 -36
- package/src/rust/model/mod.rs +0 -100
- package/src/rust/model/reset_all.rs +0 -38
- package/src/rust/model/structural.rs +0 -244
- package/src/themes/dracula.less +0 -101
- package/src/themes/gruvbox-dark.less +0 -116
- package/src/themes/gruvbox.less +0 -152
- package/src/themes/icons.less +0 -130
- package/src/themes/intl/de.less +0 -102
- package/src/themes/intl/es.less +0 -102
- package/src/themes/intl/fr.less +0 -102
- package/src/themes/intl/ja.less +0 -102
- package/src/themes/intl/pt.less +0 -102
- package/src/themes/intl/zh.less +0 -102
- package/src/themes/intl.less +0 -102
- package/src/themes/monokai.less +0 -107
- package/src/themes/pro-dark.less +0 -147
- package/src/themes/pro.less +0 -186
- package/src/themes/solarized-dark.less +0 -78
- package/src/themes/solarized.less +0 -102
- package/src/themes/vaporwave.less +0 -145
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline4.js +0 -0
- /package/src/rust/{model → tasks}/copy_export.rs +0 -0
- /package/src/rust/{model → tasks}/export_app.rs +0 -0
- /package/src/rust/{model → tasks}/export_method.rs +0 -0
- /package/src/rust/{model → tasks}/restore_and_render.rs +0 -0
- /package/src/rust/{model → tasks}/update_and_render.rs +0 -0
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
use std::collections::HashSet;
|
|
14
14
|
use std::rc::Rc;
|
|
15
15
|
|
|
16
|
-
use perspective_client::config
|
|
17
|
-
use perspective_client::utils::PerspectiveResultExt;
|
|
16
|
+
use perspective_client::config::{ViewConfig, *};
|
|
18
17
|
use perspective_js::utils::ApiFuture;
|
|
19
18
|
use yew::prelude::*;
|
|
20
19
|
|
|
@@ -22,23 +21,38 @@ use super::InPlaceColumn;
|
|
|
22
21
|
use super::filter_column::*;
|
|
23
22
|
use super::pivot_column::*;
|
|
24
23
|
use super::sort_column::*;
|
|
24
|
+
use crate::components::column_dropdown::{ColumnDropDownElement, ColumnDropDownPortal};
|
|
25
25
|
use crate::components::containers::dragdrop_list::*;
|
|
26
|
+
use crate::components::containers::select::{Select, SelectItem};
|
|
27
|
+
use crate::components::filter_dropdown::{FilterDropDownElement, FilterDropDownPortal};
|
|
26
28
|
use crate::components::style::LocalStyle;
|
|
27
|
-
use crate::
|
|
29
|
+
use crate::css;
|
|
28
30
|
use crate::dragdrop::*;
|
|
29
|
-
use crate::model::*;
|
|
30
31
|
use crate::renderer::*;
|
|
32
|
+
use crate::session::drag_drop_update::*;
|
|
31
33
|
use crate::session::*;
|
|
32
34
|
use crate::utils::*;
|
|
33
|
-
use crate::{PerspectiveProperties, css};
|
|
34
35
|
|
|
35
|
-
#[derive(
|
|
36
|
+
#[derive(Clone, Properties)]
|
|
36
37
|
pub struct ConfigSelectorProps {
|
|
37
38
|
pub onselect: Callback<()>,
|
|
38
39
|
|
|
39
40
|
#[prop_or_default]
|
|
40
41
|
pub ondragenter: Callback<()>,
|
|
41
42
|
|
|
43
|
+
/// Current view config threaded as a value prop so that config changes
|
|
44
|
+
/// (group_by, sort, filter, etc.) trigger re-renders via normal prop
|
|
45
|
+
/// diffing rather than a PubSub `view_created` subscription.
|
|
46
|
+
pub view_config: PtrEqRc<ViewConfig>,
|
|
47
|
+
/// Column currently being dragged — threaded to show `dragdrop-highlight`
|
|
48
|
+
/// without subscribing to `dragstart_received`/`dragend_received`.
|
|
49
|
+
pub drag_column: Option<String>,
|
|
50
|
+
/// Session metadata snapshot — threaded from `SessionProps`.
|
|
51
|
+
pub metadata: SessionMetadataRc,
|
|
52
|
+
|
|
53
|
+
/// Selected theme name, threaded for PortalModal consumers.
|
|
54
|
+
pub selected_theme: Option<String>,
|
|
55
|
+
|
|
42
56
|
// State
|
|
43
57
|
pub session: Session,
|
|
44
58
|
pub renderer: Renderer,
|
|
@@ -46,30 +60,31 @@ pub struct ConfigSelectorProps {
|
|
|
46
60
|
}
|
|
47
61
|
|
|
48
62
|
impl PartialEq for ConfigSelectorProps {
|
|
49
|
-
fn eq(&self,
|
|
50
|
-
|
|
63
|
+
fn eq(&self, other: &Self) -> bool {
|
|
64
|
+
self.view_config == other.view_config
|
|
65
|
+
&& self.drag_column == other.drag_column
|
|
66
|
+
&& self.metadata == other.metadata
|
|
67
|
+
&& self.selected_theme == other.selected_theme
|
|
51
68
|
}
|
|
52
69
|
}
|
|
53
70
|
|
|
54
71
|
#[derive(Debug)]
|
|
55
72
|
pub enum ConfigSelectorMsg {
|
|
56
|
-
DragStart,
|
|
57
|
-
DragEnd,
|
|
58
73
|
DragOver(usize, DragTarget),
|
|
59
74
|
DragLeave(DragTarget),
|
|
60
75
|
Drop(String, DragTarget, DragEffect, usize),
|
|
61
76
|
Close(usize, DragTarget),
|
|
62
77
|
SetFilterValue(usize, String),
|
|
63
78
|
TransposePivots,
|
|
64
|
-
ViewCreated,
|
|
65
79
|
New(DragTarget, InPlaceColumn),
|
|
80
|
+
UpdateGroupRollupMode(GroupRollupMode),
|
|
66
81
|
}
|
|
67
82
|
|
|
68
83
|
#[derive(Clone)]
|
|
69
84
|
pub struct ConfigSelector {
|
|
70
85
|
filter_dropdown: FilterDropDownElement,
|
|
71
86
|
column_dropdown: ColumnDropDownElement,
|
|
72
|
-
_subscriptions: [Rc<Subscription>;
|
|
87
|
+
_subscriptions: [Rc<Subscription>; 1],
|
|
73
88
|
}
|
|
74
89
|
|
|
75
90
|
impl Component for ConfigSelector {
|
|
@@ -77,12 +92,6 @@ impl Component for ConfigSelector {
|
|
|
77
92
|
type Properties = ConfigSelectorProps;
|
|
78
93
|
|
|
79
94
|
fn create(ctx: &Context<Self>) -> Self {
|
|
80
|
-
let cb = ctx.link().callback(|_| ConfigSelectorMsg::DragStart);
|
|
81
|
-
let drag_sub = Rc::new(ctx.props().dragdrop.dragstart_received.add_listener(cb));
|
|
82
|
-
|
|
83
|
-
let cb = ctx.link().callback(|_| ConfigSelectorMsg::DragEnd);
|
|
84
|
-
let dragend_sub = Rc::new(ctx.props().dragdrop.dragend_received.add_listener(cb));
|
|
85
|
-
|
|
86
95
|
let cb = ctx
|
|
87
96
|
.link()
|
|
88
97
|
.callback(|x: (String, DragTarget, DragEffect, usize)| {
|
|
@@ -90,12 +99,9 @@ impl Component for ConfigSelector {
|
|
|
90
99
|
});
|
|
91
100
|
let drop_sub = Rc::new(ctx.props().dragdrop.drop_received.add_listener(cb));
|
|
92
101
|
|
|
93
|
-
let cb = ctx.link().callback(|_| ConfigSelectorMsg::ViewCreated);
|
|
94
|
-
let view_sub = Rc::new(ctx.props().session.view_created.add_listener(cb));
|
|
95
|
-
|
|
96
102
|
let filter_dropdown = FilterDropDownElement::new(ctx.props().session.clone());
|
|
97
103
|
let column_dropdown = ColumnDropDownElement::new(ctx.props().session.clone());
|
|
98
|
-
let _subscriptions = [drop_sub
|
|
104
|
+
let _subscriptions = [drop_sub];
|
|
99
105
|
Self {
|
|
100
106
|
filter_dropdown,
|
|
101
107
|
column_dropdown,
|
|
@@ -105,8 +111,6 @@ impl Component for ConfigSelector {
|
|
|
105
111
|
|
|
106
112
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
107
113
|
match msg {
|
|
108
|
-
ConfigSelectorMsg::DragStart | ConfigSelectorMsg::ViewCreated => true,
|
|
109
|
-
ConfigSelectorMsg::DragEnd => true,
|
|
110
114
|
ConfigSelectorMsg::DragOver(index, action) => {
|
|
111
115
|
let should_render = ctx.props().dragdrop.notify_drag_enter(action, index);
|
|
112
116
|
if should_render {
|
|
@@ -119,7 +123,7 @@ impl Component for ConfigSelector {
|
|
|
119
123
|
true
|
|
120
124
|
},
|
|
121
125
|
ConfigSelectorMsg::Close(index, DragTarget::Sort) => {
|
|
122
|
-
let mut sort = ctx.props().
|
|
126
|
+
let mut sort = ctx.props().view_config.sort.clone();
|
|
123
127
|
sort.remove(index);
|
|
124
128
|
let sort = Some(sort);
|
|
125
129
|
let config = ViewConfigUpdate {
|
|
@@ -127,59 +131,121 @@ impl Component for ConfigSelector {
|
|
|
127
131
|
..ViewConfigUpdate::default()
|
|
128
132
|
};
|
|
129
133
|
|
|
130
|
-
|
|
131
|
-
.
|
|
132
|
-
.
|
|
133
|
-
.
|
|
134
|
+
{
|
|
135
|
+
let session = ctx.props().session.clone();
|
|
136
|
+
let renderer = ctx.props().renderer.clone();
|
|
137
|
+
if session.update_view_config(config).is_ok() {
|
|
138
|
+
ApiFuture::spawn(async move {
|
|
139
|
+
renderer.apply_pending_plugin()?;
|
|
140
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
134
144
|
|
|
135
145
|
ctx.props().onselect.emit(());
|
|
136
146
|
false
|
|
137
147
|
},
|
|
138
|
-
ConfigSelectorMsg::
|
|
139
|
-
let mut group_by = ctx.props().session.get_view_config().group_by.clone();
|
|
140
|
-
group_by.remove(index);
|
|
148
|
+
ConfigSelectorMsg::UpdateGroupRollupMode(mode) => {
|
|
141
149
|
let config = ViewConfigUpdate {
|
|
142
|
-
|
|
150
|
+
group_rollup_mode: Some(mode),
|
|
143
151
|
..ViewConfigUpdate::default()
|
|
144
152
|
};
|
|
145
153
|
|
|
146
|
-
|
|
147
|
-
.
|
|
148
|
-
.
|
|
149
|
-
.
|
|
154
|
+
{
|
|
155
|
+
let session = ctx.props().session.clone();
|
|
156
|
+
let renderer = ctx.props().renderer.clone();
|
|
157
|
+
if session.update_view_config(config).is_ok() {
|
|
158
|
+
ApiFuture::spawn(async move {
|
|
159
|
+
renderer.apply_pending_plugin()?;
|
|
160
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
150
164
|
|
|
151
|
-
ctx.props().onselect.emit(());
|
|
152
165
|
false
|
|
153
166
|
},
|
|
167
|
+
ConfigSelectorMsg::Close(index, DragTarget::GroupBy) => {
|
|
168
|
+
if ctx.props().view_config.group_rollup_mode == GroupRollupMode::Total {
|
|
169
|
+
let requirements = ctx.props().renderer.metadata();
|
|
170
|
+
|
|
171
|
+
let rollup_features = ctx
|
|
172
|
+
.props()
|
|
173
|
+
.metadata
|
|
174
|
+
.get_features()
|
|
175
|
+
.map(|x| x.get_group_rollup_modes())
|
|
176
|
+
.unwrap();
|
|
177
|
+
|
|
178
|
+
let group_rollups = requirements.get_group_rollups(&rollup_features);
|
|
179
|
+
|
|
180
|
+
ctx.link()
|
|
181
|
+
.send_message(ConfigSelectorMsg::UpdateGroupRollupMode(
|
|
182
|
+
group_rollups.first().cloned().unwrap(),
|
|
183
|
+
));
|
|
184
|
+
false
|
|
185
|
+
} else {
|
|
186
|
+
let mut group_by = ctx.props().view_config.group_by.clone();
|
|
187
|
+
group_by.remove(index);
|
|
188
|
+
let config = ViewConfigUpdate {
|
|
189
|
+
group_by: Some(group_by),
|
|
190
|
+
..ViewConfigUpdate::default()
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
{
|
|
194
|
+
let session = ctx.props().session.clone();
|
|
195
|
+
let renderer = ctx.props().renderer.clone();
|
|
196
|
+
if session.update_view_config(config).is_ok() {
|
|
197
|
+
ApiFuture::spawn(async move {
|
|
198
|
+
renderer.apply_pending_plugin()?;
|
|
199
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
ctx.props().onselect.emit(());
|
|
205
|
+
false
|
|
206
|
+
}
|
|
207
|
+
},
|
|
154
208
|
ConfigSelectorMsg::Close(index, DragTarget::SplitBy) => {
|
|
155
|
-
let mut split_by = ctx.props().
|
|
209
|
+
let mut split_by = ctx.props().view_config.split_by.clone();
|
|
156
210
|
split_by.remove(index);
|
|
157
211
|
let config = ViewConfigUpdate {
|
|
158
212
|
split_by: Some(split_by),
|
|
159
213
|
..ViewConfigUpdate::default()
|
|
160
214
|
};
|
|
161
215
|
|
|
162
|
-
|
|
163
|
-
.
|
|
164
|
-
.
|
|
165
|
-
.
|
|
216
|
+
{
|
|
217
|
+
let session = ctx.props().session.clone();
|
|
218
|
+
let renderer = ctx.props().renderer.clone();
|
|
219
|
+
if session.update_view_config(config).is_ok() {
|
|
220
|
+
ApiFuture::spawn(async move {
|
|
221
|
+
renderer.apply_pending_plugin()?;
|
|
222
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
166
226
|
|
|
167
227
|
ctx.props().onselect.emit(());
|
|
168
228
|
false
|
|
169
229
|
},
|
|
170
230
|
ConfigSelectorMsg::Close(index, DragTarget::Filter) => {
|
|
171
231
|
self.filter_dropdown.hide().unwrap();
|
|
172
|
-
let mut filter = ctx.props().
|
|
232
|
+
let mut filter = ctx.props().view_config.filter.clone();
|
|
173
233
|
filter.remove(index);
|
|
174
234
|
let config = ViewConfigUpdate {
|
|
175
235
|
filter: Some(filter),
|
|
176
236
|
..ViewConfigUpdate::default()
|
|
177
237
|
};
|
|
178
238
|
|
|
179
|
-
|
|
180
|
-
.
|
|
181
|
-
.
|
|
182
|
-
.
|
|
239
|
+
{
|
|
240
|
+
let session = ctx.props().session.clone();
|
|
241
|
+
let renderer = ctx.props().renderer.clone();
|
|
242
|
+
if session.update_view_config(config).is_ok() {
|
|
243
|
+
ApiFuture::spawn(async move {
|
|
244
|
+
renderer.apply_pending_plugin()?;
|
|
245
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
183
249
|
|
|
184
250
|
ctx.props().onselect.emit(());
|
|
185
251
|
false
|
|
@@ -188,18 +254,31 @@ impl Component for ConfigSelector {
|
|
|
188
254
|
ConfigSelectorMsg::Drop(column, action, effect, index)
|
|
189
255
|
if action != DragTarget::Active =>
|
|
190
256
|
{
|
|
191
|
-
let
|
|
257
|
+
let col_type = ctx
|
|
258
|
+
.props()
|
|
259
|
+
.metadata
|
|
260
|
+
.get_column_table_type(column.as_str())
|
|
261
|
+
.unwrap();
|
|
262
|
+
let update = ctx.props().view_config.create_drag_drop_update(
|
|
192
263
|
column,
|
|
264
|
+
col_type,
|
|
193
265
|
index,
|
|
194
266
|
action,
|
|
195
267
|
effect,
|
|
196
268
|
&ctx.props().renderer.metadata(),
|
|
269
|
+
ctx.props().metadata.get_features().unwrap(),
|
|
197
270
|
);
|
|
198
271
|
|
|
199
|
-
|
|
200
|
-
.
|
|
201
|
-
.
|
|
202
|
-
.
|
|
272
|
+
{
|
|
273
|
+
let session = ctx.props().session.clone();
|
|
274
|
+
let renderer = ctx.props().renderer.clone();
|
|
275
|
+
if session.update_view_config(update).is_ok() {
|
|
276
|
+
ApiFuture::spawn(async move {
|
|
277
|
+
renderer.apply_pending_plugin()?;
|
|
278
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
203
282
|
|
|
204
283
|
ctx.props().onselect.emit(());
|
|
205
284
|
false
|
|
@@ -211,7 +290,7 @@ impl Component for ConfigSelector {
|
|
|
211
290
|
},
|
|
212
291
|
ConfigSelectorMsg::Drop(..) => false,
|
|
213
292
|
ConfigSelectorMsg::TransposePivots => {
|
|
214
|
-
let mut view_config = ctx.props().
|
|
293
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
215
294
|
std::mem::swap(&mut view_config.group_by, &mut view_config.split_by);
|
|
216
295
|
|
|
217
296
|
let update = ViewConfigUpdate {
|
|
@@ -220,15 +299,22 @@ impl Component for ConfigSelector {
|
|
|
220
299
|
..ViewConfigUpdate::default()
|
|
221
300
|
};
|
|
222
301
|
|
|
223
|
-
|
|
224
|
-
.
|
|
225
|
-
.
|
|
226
|
-
.
|
|
302
|
+
{
|
|
303
|
+
let session = ctx.props().session.clone();
|
|
304
|
+
let renderer = ctx.props().renderer.clone();
|
|
305
|
+
if session.update_view_config(update).is_ok() {
|
|
306
|
+
ApiFuture::spawn(async move {
|
|
307
|
+
renderer.apply_pending_plugin()?;
|
|
308
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
227
312
|
ctx.props().onselect.emit(());
|
|
228
313
|
false
|
|
229
314
|
},
|
|
315
|
+
|
|
230
316
|
ConfigSelectorMsg::SetFilterValue(index, input) => {
|
|
231
|
-
let mut filter = ctx.props().
|
|
317
|
+
let mut filter = ctx.props().view_config.filter.clone();
|
|
232
318
|
|
|
233
319
|
// TODO Can't special case these - need to make this part of the
|
|
234
320
|
// Features API.
|
|
@@ -258,47 +344,65 @@ impl Component for ConfigSelector {
|
|
|
258
344
|
}
|
|
259
345
|
};
|
|
260
346
|
|
|
261
|
-
|
|
262
|
-
.
|
|
263
|
-
.
|
|
264
|
-
.
|
|
347
|
+
{
|
|
348
|
+
let session = ctx.props().session.clone();
|
|
349
|
+
let renderer = ctx.props().renderer.clone();
|
|
350
|
+
if session.update_view_config(update).is_ok() {
|
|
351
|
+
ApiFuture::spawn(async move {
|
|
352
|
+
renderer.apply_pending_plugin()?;
|
|
353
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
265
357
|
|
|
266
358
|
false
|
|
267
359
|
},
|
|
268
360
|
ConfigSelectorMsg::New(DragTarget::GroupBy, InPlaceColumn::Column(col)) => {
|
|
269
|
-
let mut view_config = ctx.props().
|
|
361
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
270
362
|
view_config.group_by.push(col);
|
|
271
363
|
let update = ViewConfigUpdate {
|
|
272
364
|
group_by: Some(view_config.group_by),
|
|
273
365
|
..ViewConfigUpdate::default()
|
|
274
366
|
};
|
|
275
367
|
|
|
276
|
-
|
|
277
|
-
.
|
|
278
|
-
.
|
|
279
|
-
.
|
|
368
|
+
{
|
|
369
|
+
let session = ctx.props().session.clone();
|
|
370
|
+
let renderer = ctx.props().renderer.clone();
|
|
371
|
+
if session.update_view_config(update).is_ok() {
|
|
372
|
+
ApiFuture::spawn(async move {
|
|
373
|
+
renderer.apply_pending_plugin()?;
|
|
374
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
280
378
|
|
|
281
379
|
ctx.props().onselect.emit(());
|
|
282
380
|
false
|
|
283
381
|
},
|
|
284
382
|
ConfigSelectorMsg::New(DragTarget::SplitBy, InPlaceColumn::Column(col)) => {
|
|
285
|
-
let mut view_config = ctx.props().
|
|
383
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
286
384
|
view_config.split_by.push(col);
|
|
287
385
|
let update = ViewConfigUpdate {
|
|
288
386
|
split_by: Some(view_config.split_by),
|
|
289
387
|
..ViewConfigUpdate::default()
|
|
290
388
|
};
|
|
291
389
|
|
|
292
|
-
|
|
293
|
-
.
|
|
294
|
-
.
|
|
295
|
-
.
|
|
390
|
+
{
|
|
391
|
+
let session = ctx.props().session.clone();
|
|
392
|
+
let renderer = ctx.props().renderer.clone();
|
|
393
|
+
if session.update_view_config(update).is_ok() {
|
|
394
|
+
ApiFuture::spawn(async move {
|
|
395
|
+
renderer.apply_pending_plugin()?;
|
|
396
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
296
400
|
|
|
297
401
|
ctx.props().onselect.emit(());
|
|
298
402
|
false
|
|
299
403
|
},
|
|
300
404
|
ConfigSelectorMsg::New(DragTarget::Filter, InPlaceColumn::Column(column)) => {
|
|
301
|
-
let mut view_config = ctx.props().
|
|
405
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
302
406
|
let op = ctx.props().default_op(column.as_str()).unwrap_or_default();
|
|
303
407
|
view_config.filter.push(Filter::new(
|
|
304
408
|
&column,
|
|
@@ -311,32 +415,44 @@ impl Component for ConfigSelector {
|
|
|
311
415
|
..ViewConfigUpdate::default()
|
|
312
416
|
};
|
|
313
417
|
|
|
314
|
-
|
|
315
|
-
.
|
|
316
|
-
.
|
|
317
|
-
.
|
|
418
|
+
{
|
|
419
|
+
let session = ctx.props().session.clone();
|
|
420
|
+
let renderer = ctx.props().renderer.clone();
|
|
421
|
+
if session.update_view_config(update).is_ok() {
|
|
422
|
+
ApiFuture::spawn(async move {
|
|
423
|
+
renderer.apply_pending_plugin()?;
|
|
424
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
318
428
|
|
|
319
429
|
ctx.props().onselect.emit(());
|
|
320
430
|
false
|
|
321
431
|
},
|
|
322
432
|
ConfigSelectorMsg::New(DragTarget::Sort, InPlaceColumn::Column(col)) => {
|
|
323
|
-
let mut view_config = ctx.props().
|
|
433
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
324
434
|
view_config.sort.push(Sort(col, SortDir::Asc));
|
|
325
435
|
let update = ViewConfigUpdate {
|
|
326
436
|
sort: Some(view_config.sort),
|
|
327
437
|
..ViewConfigUpdate::default()
|
|
328
438
|
};
|
|
329
439
|
|
|
330
|
-
|
|
331
|
-
.
|
|
332
|
-
.
|
|
333
|
-
.
|
|
440
|
+
{
|
|
441
|
+
let session = ctx.props().session.clone();
|
|
442
|
+
let renderer = ctx.props().renderer.clone();
|
|
443
|
+
if session.update_view_config(update).is_ok() {
|
|
444
|
+
ApiFuture::spawn(async move {
|
|
445
|
+
renderer.apply_pending_plugin()?;
|
|
446
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
}
|
|
334
450
|
|
|
335
451
|
ctx.props().onselect.emit(());
|
|
336
452
|
false
|
|
337
453
|
},
|
|
338
454
|
ConfigSelectorMsg::New(DragTarget::GroupBy, InPlaceColumn::Expression(col)) => {
|
|
339
|
-
let mut view_config = ctx.props().
|
|
455
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
340
456
|
view_config.group_by.push(col.name.as_ref().to_owned());
|
|
341
457
|
view_config.expressions.insert(&col);
|
|
342
458
|
let update = ViewConfigUpdate {
|
|
@@ -345,16 +461,22 @@ impl Component for ConfigSelector {
|
|
|
345
461
|
..ViewConfigUpdate::default()
|
|
346
462
|
};
|
|
347
463
|
|
|
348
|
-
|
|
349
|
-
.
|
|
350
|
-
.
|
|
351
|
-
.
|
|
464
|
+
{
|
|
465
|
+
let session = ctx.props().session.clone();
|
|
466
|
+
let renderer = ctx.props().renderer.clone();
|
|
467
|
+
if session.update_view_config(update).is_ok() {
|
|
468
|
+
ApiFuture::spawn(async move {
|
|
469
|
+
renderer.apply_pending_plugin()?;
|
|
470
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
}
|
|
352
474
|
|
|
353
475
|
ctx.props().onselect.emit(());
|
|
354
476
|
false
|
|
355
477
|
},
|
|
356
478
|
ConfigSelectorMsg::New(DragTarget::SplitBy, InPlaceColumn::Expression(col)) => {
|
|
357
|
-
let mut view_config = ctx.props().
|
|
479
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
358
480
|
view_config.split_by.push(col.name.as_ref().to_owned());
|
|
359
481
|
view_config.expressions.insert(&col);
|
|
360
482
|
let update = ViewConfigUpdate {
|
|
@@ -363,16 +485,22 @@ impl Component for ConfigSelector {
|
|
|
363
485
|
..ViewConfigUpdate::default()
|
|
364
486
|
};
|
|
365
487
|
|
|
366
|
-
|
|
367
|
-
.
|
|
368
|
-
.
|
|
369
|
-
.
|
|
488
|
+
{
|
|
489
|
+
let session = ctx.props().session.clone();
|
|
490
|
+
let renderer = ctx.props().renderer.clone();
|
|
491
|
+
if session.update_view_config(update).is_ok() {
|
|
492
|
+
ApiFuture::spawn(async move {
|
|
493
|
+
renderer.apply_pending_plugin()?;
|
|
494
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
}
|
|
370
498
|
|
|
371
499
|
ctx.props().onselect.emit(());
|
|
372
500
|
false
|
|
373
501
|
},
|
|
374
502
|
ConfigSelectorMsg::New(DragTarget::Filter, InPlaceColumn::Expression(col)) => {
|
|
375
|
-
let mut view_config = ctx.props().
|
|
503
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
376
504
|
let column = col.name.as_ref();
|
|
377
505
|
view_config.filter.push(Filter::new(
|
|
378
506
|
column,
|
|
@@ -389,16 +517,22 @@ impl Component for ConfigSelector {
|
|
|
389
517
|
..ViewConfigUpdate::default()
|
|
390
518
|
};
|
|
391
519
|
|
|
392
|
-
|
|
393
|
-
.
|
|
394
|
-
.
|
|
395
|
-
.
|
|
520
|
+
{
|
|
521
|
+
let session = ctx.props().session.clone();
|
|
522
|
+
let renderer = ctx.props().renderer.clone();
|
|
523
|
+
if session.update_view_config(update).is_ok() {
|
|
524
|
+
ApiFuture::spawn(async move {
|
|
525
|
+
renderer.apply_pending_plugin()?;
|
|
526
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
}
|
|
396
530
|
|
|
397
531
|
ctx.props().onselect.emit(());
|
|
398
532
|
false
|
|
399
533
|
},
|
|
400
534
|
ConfigSelectorMsg::New(DragTarget::Sort, InPlaceColumn::Expression(col)) => {
|
|
401
|
-
let mut view_config = ctx.props().
|
|
535
|
+
let mut view_config = (*ctx.props().view_config).clone();
|
|
402
536
|
view_config
|
|
403
537
|
.sort
|
|
404
538
|
.push(Sort(col.name.as_ref().to_owned(), SortDir::Asc));
|
|
@@ -409,10 +543,16 @@ impl Component for ConfigSelector {
|
|
|
409
543
|
..ViewConfigUpdate::default()
|
|
410
544
|
};
|
|
411
545
|
|
|
412
|
-
|
|
413
|
-
.
|
|
414
|
-
.
|
|
415
|
-
.
|
|
546
|
+
{
|
|
547
|
+
let session = ctx.props().session.clone();
|
|
548
|
+
let renderer = ctx.props().renderer.clone();
|
|
549
|
+
if session.update_view_config(update).is_ok() {
|
|
550
|
+
ApiFuture::spawn(async move {
|
|
551
|
+
renderer.apply_pending_plugin()?;
|
|
552
|
+
renderer.draw(session.validate().await?.create_view()).await
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
416
556
|
|
|
417
557
|
ctx.props().onselect.emit(());
|
|
418
558
|
false
|
|
@@ -434,124 +574,163 @@ impl Component for ConfigSelector {
|
|
|
434
574
|
session,
|
|
435
575
|
..
|
|
436
576
|
} = ctx.props();
|
|
437
|
-
let config =
|
|
577
|
+
let config = &ctx.props().view_config;
|
|
438
578
|
let transpose = ctx.link().callback(|_| ConfigSelectorMsg::TransposePivots);
|
|
439
579
|
let column_dropdown = self.column_dropdown.clone();
|
|
440
|
-
let class =
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
""
|
|
444
|
-
}
|
|
580
|
+
let mut class = classes!();
|
|
581
|
+
|
|
582
|
+
if ctx.props().drag_column.is_some() {
|
|
583
|
+
class.push("dragdrop-highlight");
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if config.group_rollup_mode == GroupRollupMode::Total {
|
|
587
|
+
class.push("group-rollup-mode-total");
|
|
588
|
+
}
|
|
445
589
|
|
|
446
590
|
let dragend = Callback::from({
|
|
447
591
|
let dragdrop = dragdrop.clone();
|
|
448
592
|
move |_event| dragdrop.notify_drag_end()
|
|
449
593
|
});
|
|
450
594
|
|
|
451
|
-
let metadata =
|
|
595
|
+
let metadata = &ctx.props().metadata;
|
|
452
596
|
let features = metadata.get_features().unwrap();
|
|
597
|
+
let requirements = renderer.metadata();
|
|
598
|
+
let on_group_rollup_mode = ctx
|
|
599
|
+
.link()
|
|
600
|
+
.callback(ConfigSelectorMsg::UpdateGroupRollupMode);
|
|
601
|
+
|
|
602
|
+
let rollup_features = metadata
|
|
603
|
+
.get_features()
|
|
604
|
+
.map(|x| x.get_group_rollup_modes())
|
|
605
|
+
.unwrap();
|
|
606
|
+
|
|
607
|
+
let group_rollups = requirements.get_group_rollups(&rollup_features);
|
|
453
608
|
|
|
454
609
|
html! {
|
|
455
|
-
|
|
456
|
-
<
|
|
457
|
-
|
|
458
|
-
<
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
610
|
+
<>
|
|
611
|
+
<div slot="top_panel" id="top_panel" {class} ondragend={dragend}>
|
|
612
|
+
<LocalStyle href={css!("config-selector")} />
|
|
613
|
+
<div class="pivot_controls">
|
|
614
|
+
if group_rollups.len() > 1 {
|
|
615
|
+
<Select<GroupRollupMode>
|
|
616
|
+
id="group_rollup_mode_selector"
|
|
617
|
+
wrapper_class="group_rollup_wrapper"
|
|
618
|
+
is_autosize=true
|
|
619
|
+
values={Rc::new(
|
|
620
|
+
group_rollups
|
|
621
|
+
.iter()
|
|
622
|
+
.map(|x| SelectItem::Option(*x))
|
|
623
|
+
.collect(),
|
|
624
|
+
)}
|
|
625
|
+
selected={config.group_rollup_mode}
|
|
626
|
+
on_select={on_group_rollup_mode}
|
|
627
|
+
/>
|
|
628
|
+
}
|
|
629
|
+
if !config.group_by.is_empty() && config.split_by.is_empty() {
|
|
630
|
+
<span
|
|
631
|
+
id="transpose_button"
|
|
632
|
+
class="rrow centered"
|
|
633
|
+
title="Transpose Pivots"
|
|
634
|
+
onmousedown={transpose.clone()}
|
|
635
|
+
/>
|
|
636
|
+
}
|
|
637
|
+
</div>
|
|
638
|
+
if features.group_by {
|
|
639
|
+
<GroupBySelector
|
|
640
|
+
name="group_by"
|
|
641
|
+
disabled={config.group_rollup_mode == GroupRollupMode::Total}
|
|
642
|
+
parent={ctx.link().clone()}
|
|
643
|
+
column_dropdown={column_dropdown.clone()}
|
|
644
|
+
exclude={config.group_by.iter().cloned().collect::<HashSet<_>>()}
|
|
645
|
+
is_dragover={ctx.props().dragdrop.is_dragover(DragTarget::GroupBy)}
|
|
646
|
+
{dragdrop}
|
|
647
|
+
>
|
|
648
|
+
{ for config.group_by.iter().map(|group_by| {
|
|
475
649
|
html_nested! {
|
|
476
650
|
<PivotColumn
|
|
477
651
|
action={DragTarget::GroupBy}
|
|
478
652
|
column={group_by.clone()}
|
|
653
|
+
metadata={metadata.clone()}
|
|
479
654
|
{dragdrop}
|
|
480
|
-
{session}
|
|
655
|
+
opt_session={session}
|
|
481
656
|
>
|
|
482
657
|
</PivotColumn>
|
|
483
658
|
}
|
|
484
659
|
}) }
|
|
485
|
-
|
|
486
|
-
}
|
|
487
|
-
if features.split_by {
|
|
488
|
-
if !config.split_by.is_empty() {
|
|
489
|
-
<span
|
|
490
|
-
id="transpose_button"
|
|
491
|
-
class="rrow centered"
|
|
492
|
-
title="Transpose Pivots"
|
|
493
|
-
onmousedown={transpose}
|
|
494
|
-
/>
|
|
660
|
+
</GroupBySelector>
|
|
495
661
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
662
|
+
if features.split_by {
|
|
663
|
+
if !config.split_by.is_empty() {
|
|
664
|
+
<div class="pivot_controls">
|
|
665
|
+
<span
|
|
666
|
+
id="transpose_button"
|
|
667
|
+
class="rrow centered"
|
|
668
|
+
title="Transpose Pivots"
|
|
669
|
+
onmousedown={transpose}
|
|
670
|
+
/>
|
|
671
|
+
</div>
|
|
672
|
+
}
|
|
673
|
+
<SplitBySelector
|
|
674
|
+
name="split_by"
|
|
675
|
+
parent={ctx.link().clone()}
|
|
676
|
+
column_dropdown={column_dropdown.clone()}
|
|
677
|
+
exclude={config.split_by.iter().cloned().collect::<HashSet<_>>()}
|
|
678
|
+
is_dragover={dragdrop.is_dragover(DragTarget::SplitBy)}
|
|
679
|
+
{dragdrop}
|
|
680
|
+
>
|
|
681
|
+
{ for config.split_by.iter().map(|split_by| {
|
|
505
682
|
html_nested! {
|
|
506
683
|
<PivotColumn
|
|
507
684
|
action={ DragTarget::SplitBy }
|
|
508
685
|
column={ split_by.clone() }
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
{session}>
|
|
686
|
+
metadata={metadata.clone()}
|
|
687
|
+
{dragdrop}
|
|
688
|
+
opt_session={session}>
|
|
512
689
|
</PivotColumn>
|
|
513
690
|
}
|
|
514
691
|
}) }
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
692
|
+
</SplitBySelector>
|
|
693
|
+
}
|
|
694
|
+
if features.sort {
|
|
695
|
+
<SortSelector
|
|
696
|
+
name="sort"
|
|
697
|
+
allow_duplicates=true
|
|
698
|
+
parent={ctx.link().clone()}
|
|
699
|
+
column_dropdown={column_dropdown.clone()}
|
|
700
|
+
exclude={config.sort.iter().map(|x| x.0.clone()).collect::<HashSet<_>>()}
|
|
701
|
+
is_dragover={dragdrop.is_dragover(DragTarget::Sort).map(|(index, name)| {
|
|
525
702
|
(index, Sort(name, SortDir::Asc))
|
|
526
703
|
})}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
704
|
+
{dragdrop}
|
|
705
|
+
>
|
|
706
|
+
{ for config.sort.iter().enumerate().map(|(idx, sort)| {
|
|
530
707
|
html_nested! {
|
|
531
708
|
<SortColumn
|
|
532
709
|
idx={ idx }
|
|
533
710
|
sort={ sort.clone() }
|
|
711
|
+
view_config={config.clone()}
|
|
712
|
+
metadata={metadata.clone()}
|
|
534
713
|
{dragdrop}
|
|
535
714
|
{renderer}
|
|
536
715
|
{session}>
|
|
537
716
|
</SortColumn>
|
|
538
717
|
}
|
|
539
718
|
}) }
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
719
|
+
</SortSelector>
|
|
720
|
+
}
|
|
721
|
+
if !features.filter_ops.is_empty() {
|
|
722
|
+
<FilterSelector
|
|
723
|
+
name="filter"
|
|
724
|
+
allow_duplicates=true
|
|
725
|
+
parent={ctx.link().clone()}
|
|
726
|
+
{column_dropdown}
|
|
727
|
+
exclude={config.filter.iter().map(|x| x.column().to_string()).collect::<HashSet<_>>()}
|
|
728
|
+
is_dragover={dragdrop.is_dragover(DragTarget::Filter).map(|(index, name)| {
|
|
550
729
|
(index, Filter::new(&name, "", FilterTerm::Scalar(Scalar::Null)))
|
|
551
730
|
})}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
731
|
+
{dragdrop}
|
|
732
|
+
>
|
|
733
|
+
{ for config.filter.iter().enumerate().map(|(idx, filter)| {
|
|
555
734
|
let filter_keydown = ctx.link()
|
|
556
735
|
.callback(move |txt| ConfigSelectorMsg::SetFilterValue(idx, txt));
|
|
557
736
|
|
|
@@ -561,24 +740,34 @@ impl Component for ConfigSelector {
|
|
|
561
740
|
filter_dropdown={ &self.filter_dropdown }
|
|
562
741
|
filter={ filter.clone() }
|
|
563
742
|
on_keydown={ filter_keydown }
|
|
743
|
+
view_config={config.clone()}
|
|
744
|
+
metadata={metadata.clone()}
|
|
564
745
|
{dragdrop}
|
|
565
746
|
{renderer}
|
|
566
747
|
{session}>
|
|
567
748
|
</FilterColumn>
|
|
568
749
|
}
|
|
569
750
|
}) }
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
751
|
+
</FilterSelector>
|
|
752
|
+
}
|
|
753
|
+
</div>
|
|
754
|
+
<ColumnDropDownPortal
|
|
755
|
+
element={self.column_dropdown.clone()}
|
|
756
|
+
theme={ctx.props().selected_theme.clone().unwrap_or_default()}
|
|
757
|
+
/>
|
|
758
|
+
<FilterDropDownPortal
|
|
759
|
+
element={self.filter_dropdown.clone()}
|
|
760
|
+
theme={ctx.props().selected_theme.clone().unwrap_or_default()}
|
|
761
|
+
/>
|
|
762
|
+
</>
|
|
573
763
|
}
|
|
574
764
|
}
|
|
575
765
|
}
|
|
576
766
|
|
|
577
767
|
impl ConfigSelectorProps {
|
|
578
768
|
fn default_op(&self, column: &str) -> Option<String> {
|
|
579
|
-
let
|
|
580
|
-
let
|
|
581
|
-
let col_type = metadata.get_column_table_type(column)?;
|
|
769
|
+
let features = self.metadata.get_features()?;
|
|
770
|
+
let col_type = self.metadata.get_column_table_type(column)?;
|
|
582
771
|
let first = features.default_op(col_type)?;
|
|
583
772
|
Some(first.to_string())
|
|
584
773
|
}
|