@perspective-dev/viewer 4.0.1 → 4.1.1
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 +1242 -753
- 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 +367 -169
- 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-11a3c51b6310ee99}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-9a89352df1552d2b → perspective-viewer-11a3c51b6310ee99}/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
package/src/rust/components/{column_settings_sidebar/sidebar.rs → column_settings_sidebar.rs}
RENAMED
|
@@ -9,77 +9,69 @@
|
|
|
9
9
|
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
mod attributes_tab;
|
|
13
|
+
|
|
14
|
+
mod save_settings;
|
|
15
|
+
mod style_tab;
|
|
12
16
|
|
|
13
|
-
use std::fmt::Display;
|
|
14
17
|
use std::rc::Rc;
|
|
15
18
|
|
|
16
19
|
use derivative::Derivative;
|
|
17
20
|
use itertools::Itertools;
|
|
18
21
|
use perspective_client::config::{ColumnType, Expression};
|
|
19
22
|
use perspective_client::utils::PerspectiveResultExt;
|
|
20
|
-
use yew::{Callback, Component, Html, Properties, html};
|
|
23
|
+
use yew::{Callback, Component, Html, Properties, html, props};
|
|
21
24
|
|
|
22
|
-
use
|
|
23
|
-
use
|
|
25
|
+
use self::attributes_tab::AttributesTabProps;
|
|
26
|
+
use self::style_tab::StyleTabProps;
|
|
24
27
|
use crate::components::column_settings_sidebar::attributes_tab::AttributesTab;
|
|
25
28
|
use crate::components::column_settings_sidebar::save_settings::SaveSettingsProps;
|
|
26
29
|
use crate::components::column_settings_sidebar::style_tab::StyleTab;
|
|
27
30
|
use crate::components::containers::sidebar::Sidebar;
|
|
28
|
-
use crate::components::containers::tab_list::
|
|
31
|
+
use crate::components::containers::tab_list::TabList;
|
|
29
32
|
use crate::components::editable_header::EditableHeaderProps;
|
|
30
33
|
use crate::components::expression_editor::ExpressionEditorProps;
|
|
31
34
|
use crate::components::style::LocalStyle;
|
|
32
35
|
use crate::components::type_icon::TypeIconType;
|
|
33
|
-
use crate::components::viewer::ColumnLocator;
|
|
34
36
|
use crate::custom_events::CustomEvents;
|
|
35
37
|
use crate::model::*;
|
|
36
|
-
use crate::presentation::Presentation;
|
|
38
|
+
use crate::presentation::{ColumnLocator, ColumnSettingsTab, Presentation};
|
|
37
39
|
use crate::renderer::Renderer;
|
|
38
40
|
use crate::session::Session;
|
|
39
|
-
use crate::utils
|
|
40
|
-
use crate
|
|
41
|
-
|
|
42
|
-
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
|
43
|
-
pub enum ColumnSettingsTab {
|
|
44
|
-
#[default]
|
|
45
|
-
Attributes,
|
|
46
|
-
Style,
|
|
47
|
-
}
|
|
48
|
-
impl Tab for ColumnSettingsTab {}
|
|
49
|
-
impl Display for ColumnSettingsTab {
|
|
50
|
-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
51
|
-
f.write_fmt(format_args!("{self:?}"))
|
|
52
|
-
}
|
|
53
|
-
}
|
|
41
|
+
use crate::utils::*;
|
|
42
|
+
use crate::*;
|
|
54
43
|
|
|
55
|
-
#[derive(Clone, Properties,
|
|
44
|
+
#[derive(Clone, Derivative, Properties, PerspectiveProperties!)]
|
|
56
45
|
#[derivative(Debug)]
|
|
57
|
-
pub struct
|
|
58
|
-
|
|
59
|
-
pub
|
|
46
|
+
pub struct ColumnSettingsPanelProps {
|
|
47
|
+
pub selected_column: ColumnLocator,
|
|
48
|
+
pub selected_tab: Option<ColumnSettingsTab>,
|
|
49
|
+
pub on_close: Callback<()>,
|
|
50
|
+
pub width_override: Option<i32>,
|
|
51
|
+
pub on_select_tab: Callback<ColumnSettingsTab>,
|
|
52
|
+
|
|
53
|
+
// State
|
|
60
54
|
#[derivative(Debug = "ignore")]
|
|
61
|
-
pub
|
|
55
|
+
pub custom_events: CustomEvents,
|
|
56
|
+
|
|
62
57
|
#[derivative(Debug = "ignore")]
|
|
63
58
|
pub presentation: Presentation,
|
|
59
|
+
|
|
64
60
|
#[derivative(Debug = "ignore")]
|
|
65
|
-
pub
|
|
61
|
+
pub renderer: Renderer,
|
|
66
62
|
|
|
67
|
-
|
|
68
|
-
pub
|
|
69
|
-
pub width_override: Option<i32>,
|
|
70
|
-
pub is_active: bool,
|
|
63
|
+
#[derivative(Debug = "ignore")]
|
|
64
|
+
pub session: Session,
|
|
71
65
|
}
|
|
72
66
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
impl PartialEq for ColumnSettingsProps {
|
|
67
|
+
impl PartialEq for ColumnSettingsPanelProps {
|
|
76
68
|
fn eq(&self, other: &Self) -> bool {
|
|
77
|
-
self.selected_column == other.selected_column && self.
|
|
69
|
+
self.selected_column == other.selected_column && self.selected_tab == other.selected_tab
|
|
78
70
|
}
|
|
79
71
|
}
|
|
80
72
|
|
|
81
73
|
#[derive(Debug)]
|
|
82
|
-
pub enum
|
|
74
|
+
pub enum ColumnSettingsPanelMsg {
|
|
83
75
|
SetExprValue(Rc<String>),
|
|
84
76
|
SetExprValid(bool),
|
|
85
77
|
SetHeaderValue(Option<String>),
|
|
@@ -91,105 +83,38 @@ pub enum ColumnSettingsMsg {
|
|
|
91
83
|
SessionUpdated(bool),
|
|
92
84
|
}
|
|
93
85
|
|
|
94
|
-
#[derive(
|
|
86
|
+
#[derive(Derivative)]
|
|
95
87
|
#[derivative(Debug)]
|
|
96
|
-
pub struct
|
|
97
|
-
|
|
98
|
-
expr_value: Rc<String>,
|
|
88
|
+
pub struct ColumnSettingsPanel {
|
|
89
|
+
column_name: String,
|
|
99
90
|
expr_valid: bool,
|
|
100
|
-
|
|
101
|
-
header_value: Option<String>,
|
|
91
|
+
expr_value: Rc<String>,
|
|
102
92
|
header_valid: bool,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
save_count: u8,
|
|
107
|
-
reset_enabled: bool,
|
|
108
|
-
reset_count: u8,
|
|
109
|
-
column_name: String,
|
|
93
|
+
header_value: Option<String>,
|
|
94
|
+
initial_expr_value: Rc<String>,
|
|
95
|
+
initial_header_value: Option<String>,
|
|
110
96
|
maybe_ty: Option<ColumnType>,
|
|
111
|
-
tabs: Vec<ColumnSettingsTab>,
|
|
112
|
-
|
|
113
97
|
on_input: Callback<Rc<String>>,
|
|
114
98
|
on_save: Callback<()>,
|
|
115
99
|
on_validate: Callback<bool>,
|
|
100
|
+
reset_count: u8,
|
|
101
|
+
reset_enabled: bool,
|
|
102
|
+
save_count: u8,
|
|
103
|
+
save_enabled: bool,
|
|
104
|
+
tabs: Vec<ColumnSettingsTab>,
|
|
116
105
|
|
|
117
106
|
#[derivative(Debug = "ignore")]
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
impl ColumnSettingsSidebar {
|
|
122
|
-
fn save_enabled_effect(&mut self) {
|
|
123
|
-
let changed = self.expr_value != self.initial_expr_value
|
|
124
|
-
|| self.header_value != self.initial_header_value;
|
|
125
|
-
let valid = self.expr_valid && self.header_valid;
|
|
126
|
-
self.save_enabled = changed && valid;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
fn initialize(&mut self, ctx: &yew::prelude::Context<Self>) {
|
|
130
|
-
let column_name = ctx
|
|
131
|
-
.props()
|
|
132
|
-
.selected_column
|
|
133
|
-
.name_or_default(&ctx.props().session);
|
|
134
|
-
let initial_expr_value = ctx
|
|
135
|
-
.props()
|
|
136
|
-
.session
|
|
137
|
-
.metadata()
|
|
138
|
-
.get_expression_by_alias(&column_name)
|
|
139
|
-
.unwrap_or_default();
|
|
140
|
-
let initial_expr_value = Rc::new(initial_expr_value);
|
|
141
|
-
let initial_header_value =
|
|
142
|
-
(*initial_expr_value != column_name).then_some(column_name.clone());
|
|
143
|
-
let maybe_ty = ctx.props().selected_column.view_type(ctx.props().session());
|
|
144
|
-
|
|
145
|
-
let tabs = {
|
|
146
|
-
let mut tabs = vec![];
|
|
147
|
-
let is_new_expr = ctx.props().selected_column.is_new_expr();
|
|
148
|
-
let show_styles = !is_new_expr
|
|
149
|
-
&& ctx
|
|
150
|
-
.props()
|
|
151
|
-
.can_render_column_styles(&column_name)
|
|
152
|
-
.unwrap_or_default();
|
|
153
|
-
|
|
154
|
-
if !is_new_expr && show_styles {
|
|
155
|
-
tabs.push(ColumnSettingsTab::Style);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if ctx.props().selected_column.is_expr() {
|
|
159
|
-
tabs.push(ColumnSettingsTab::Attributes);
|
|
160
|
-
}
|
|
161
|
-
tabs
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
let on_input = ctx.link().callback(ColumnSettingsMsg::SetExprValue);
|
|
165
|
-
let on_save = ctx.link().callback(ColumnSettingsMsg::OnSaveAttributes);
|
|
166
|
-
let on_validate = ctx.link().callback(ColumnSettingsMsg::SetExprValid);
|
|
167
|
-
*self = Self {
|
|
168
|
-
column_name,
|
|
169
|
-
expr_value: initial_expr_value.clone(),
|
|
170
|
-
initial_expr_value,
|
|
171
|
-
header_value: initial_header_value.clone(),
|
|
172
|
-
initial_header_value,
|
|
173
|
-
maybe_ty,
|
|
174
|
-
tabs,
|
|
175
|
-
header_valid: true,
|
|
176
|
-
on_input,
|
|
177
|
-
on_save,
|
|
178
|
-
on_validate,
|
|
179
|
-
session_sub: self.session_sub.take(),
|
|
180
|
-
..*self
|
|
181
|
-
}
|
|
182
|
-
}
|
|
107
|
+
_session_sub: Option<Subscription>,
|
|
183
108
|
}
|
|
184
109
|
|
|
185
|
-
impl Component for
|
|
186
|
-
type Message =
|
|
187
|
-
type Properties =
|
|
110
|
+
impl Component for ColumnSettingsPanel {
|
|
111
|
+
type Message = ColumnSettingsPanelMsg;
|
|
112
|
+
type Properties = ColumnSettingsPanelProps;
|
|
188
113
|
|
|
189
114
|
fn create(ctx: &yew::prelude::Context<Self>) -> Self {
|
|
190
115
|
let session_cb = ctx
|
|
191
116
|
.link()
|
|
192
|
-
.callback(|(is_update, _)|
|
|
117
|
+
.callback(|(is_update, _)| ColumnSettingsPanelMsg::SessionUpdated(is_update));
|
|
193
118
|
|
|
194
119
|
let session_sub = ctx
|
|
195
120
|
.props()
|
|
@@ -198,24 +123,32 @@ impl Component for ColumnSettingsSidebar {
|
|
|
198
123
|
.add_listener(session_cb);
|
|
199
124
|
|
|
200
125
|
let mut this = Self {
|
|
201
|
-
|
|
202
|
-
|
|
126
|
+
_session_sub: Some(session_sub),
|
|
127
|
+
initial_expr_value: Rc::default(),
|
|
128
|
+
expr_value: Rc::default(),
|
|
129
|
+
expr_valid: false,
|
|
130
|
+
initial_header_value: None,
|
|
131
|
+
header_value: None,
|
|
132
|
+
header_valid: false,
|
|
133
|
+
save_enabled: false,
|
|
134
|
+
save_count: 0,
|
|
135
|
+
reset_enabled: false,
|
|
136
|
+
reset_count: 0,
|
|
137
|
+
column_name: "".to_owned(),
|
|
138
|
+
maybe_ty: None,
|
|
139
|
+
tabs: vec![],
|
|
140
|
+
on_input: Callback::default(),
|
|
141
|
+
on_save: Callback::default(),
|
|
142
|
+
on_validate: Callback::default(),
|
|
203
143
|
};
|
|
144
|
+
|
|
204
145
|
this.initialize(ctx);
|
|
205
146
|
this
|
|
206
147
|
}
|
|
207
148
|
|
|
208
149
|
fn changed(&mut self, ctx: &yew::prelude::Context<Self>, old_props: &Self::Properties) -> bool {
|
|
209
150
|
if ctx.props() != old_props {
|
|
210
|
-
let selected_tab = self.selected_tab;
|
|
211
151
|
self.initialize(ctx);
|
|
212
|
-
self.selected_tab = selected_tab;
|
|
213
|
-
self.selected_tab_idx = self
|
|
214
|
-
.tabs
|
|
215
|
-
.iter()
|
|
216
|
-
.find_position(|tab| **tab == selected_tab)
|
|
217
|
-
.map(|(idx, _val)| idx)
|
|
218
|
-
.unwrap_or_default();
|
|
219
152
|
true
|
|
220
153
|
} else {
|
|
221
154
|
false
|
|
@@ -223,8 +156,8 @@ impl Component for ColumnSettingsSidebar {
|
|
|
223
156
|
}
|
|
224
157
|
|
|
225
158
|
fn update(&mut self, ctx: &yew::prelude::Context<Self>, msg: Self::Message) -> bool {
|
|
226
|
-
match msg {
|
|
227
|
-
|
|
159
|
+
let result = match msg {
|
|
160
|
+
ColumnSettingsPanelMsg::SetExprValue(val) => {
|
|
228
161
|
if self.expr_value != val {
|
|
229
162
|
self.expr_value = val;
|
|
230
163
|
self.reset_enabled = true;
|
|
@@ -233,12 +166,12 @@ impl Component for ColumnSettingsSidebar {
|
|
|
233
166
|
false
|
|
234
167
|
}
|
|
235
168
|
},
|
|
236
|
-
|
|
169
|
+
ColumnSettingsPanelMsg::SetExprValid(val) => {
|
|
237
170
|
self.expr_valid = val;
|
|
238
171
|
self.save_enabled_effect();
|
|
239
172
|
true
|
|
240
173
|
},
|
|
241
|
-
|
|
174
|
+
ColumnSettingsPanelMsg::SetHeaderValue(val) => {
|
|
242
175
|
if self.header_value != val {
|
|
243
176
|
self.header_value = val;
|
|
244
177
|
self.reset_enabled = true;
|
|
@@ -247,18 +180,17 @@ impl Component for ColumnSettingsSidebar {
|
|
|
247
180
|
false
|
|
248
181
|
}
|
|
249
182
|
},
|
|
250
|
-
|
|
183
|
+
ColumnSettingsPanelMsg::SetHeaderValid(val) => {
|
|
251
184
|
self.header_valid = val;
|
|
252
185
|
self.save_enabled_effect();
|
|
253
186
|
true
|
|
254
187
|
},
|
|
255
|
-
|
|
256
|
-
let rerender =
|
|
257
|
-
|
|
258
|
-
self.selected_tab_idx = idx;
|
|
188
|
+
ColumnSettingsPanelMsg::SetSelectedTab((_, val)) => {
|
|
189
|
+
let rerender = ctx.props().selected_tab != Some(val);
|
|
190
|
+
ctx.props().on_select_tab.emit(val);
|
|
259
191
|
rerender
|
|
260
192
|
},
|
|
261
|
-
|
|
193
|
+
ColumnSettingsPanelMsg::OnResetAttributes(()) => {
|
|
262
194
|
self.header_value.clone_from(&self.initial_header_value);
|
|
263
195
|
self.expr_value.clone_from(&self.initial_expr_value);
|
|
264
196
|
self.save_enabled = false;
|
|
@@ -266,11 +198,12 @@ impl Component for ColumnSettingsSidebar {
|
|
|
266
198
|
self.reset_count += 1;
|
|
267
199
|
true
|
|
268
200
|
},
|
|
269
|
-
|
|
201
|
+
ColumnSettingsPanelMsg::OnSaveAttributes(()) => {
|
|
270
202
|
let new_expr = Expression::new(
|
|
271
203
|
self.header_value.clone().map(|s| s.into()),
|
|
272
204
|
(*(self.expr_value)).clone().into(),
|
|
273
205
|
);
|
|
206
|
+
|
|
274
207
|
match &ctx.props().selected_column {
|
|
275
208
|
ColumnLocator::Table(_) => {
|
|
276
209
|
tracing::error!("Tried to save non-expression column!")
|
|
@@ -292,7 +225,7 @@ impl Component for ColumnSettingsSidebar {
|
|
|
292
225
|
self.save_count += 1;
|
|
293
226
|
true
|
|
294
227
|
},
|
|
295
|
-
|
|
228
|
+
ColumnSettingsPanelMsg::OnDelete(()) => {
|
|
296
229
|
if ctx.props().selected_column.is_saved_expr() {
|
|
297
230
|
ctx.props().delete_expr(&self.column_name).unwrap_or_log();
|
|
298
231
|
}
|
|
@@ -300,7 +233,7 @@ impl Component for ColumnSettingsSidebar {
|
|
|
300
233
|
ctx.props().on_close.emit(());
|
|
301
234
|
true
|
|
302
235
|
},
|
|
303
|
-
|
|
236
|
+
ColumnSettingsPanelMsg::SessionUpdated(is_update) => {
|
|
304
237
|
if !is_update {
|
|
305
238
|
self.initialize(ctx);
|
|
306
239
|
true
|
|
@@ -308,48 +241,62 @@ impl Component for ColumnSettingsSidebar {
|
|
|
308
241
|
false
|
|
309
242
|
}
|
|
310
243
|
},
|
|
311
|
-
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
result
|
|
312
247
|
}
|
|
313
248
|
|
|
314
249
|
fn view(&self, ctx: &yew::prelude::Context<Self>) -> Html {
|
|
315
|
-
let header_props = EditableHeaderProps {
|
|
250
|
+
let header_props = props!(EditableHeaderProps {
|
|
251
|
+
initial_value: self.initial_header_value.clone(),
|
|
252
|
+
placeholder: self.expr_value.clone(),
|
|
253
|
+
reset_count: self.reset_count,
|
|
254
|
+
editable: ctx.props().selected_column.is_expr()
|
|
255
|
+
&& matches!(
|
|
256
|
+
ctx.props().selected_tab,
|
|
257
|
+
Some(ColumnSettingsTab::Attributes)
|
|
258
|
+
),
|
|
316
259
|
icon_type: self
|
|
317
260
|
.maybe_ty
|
|
318
261
|
.map(|ty| ty.into())
|
|
319
262
|
.or(Some(TypeIconType::Expr)),
|
|
320
263
|
on_change: ctx.link().batch_callback(|(value, valid)| {
|
|
321
264
|
vec![
|
|
322
|
-
|
|
323
|
-
|
|
265
|
+
ColumnSettingsPanelMsg::SetHeaderValue(value),
|
|
266
|
+
ColumnSettingsPanelMsg::SetHeaderValid(valid),
|
|
324
267
|
]
|
|
325
268
|
}),
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
initial_value: self.initial_header_value.clone(),
|
|
329
|
-
placeholder: self.expr_value.clone(),
|
|
330
|
-
session: ctx.props().session.clone(),
|
|
331
|
-
reset_count: self.reset_count,
|
|
332
|
-
};
|
|
269
|
+
session: &ctx.props().session
|
|
270
|
+
});
|
|
333
271
|
|
|
334
|
-
let expr_editor = ExpressionEditorProps {
|
|
335
|
-
session: ctx.props().session.clone(),
|
|
272
|
+
let expr_editor = props!(ExpressionEditorProps {
|
|
336
273
|
on_input: self.on_input.clone(),
|
|
337
274
|
on_save: self.on_save.clone(),
|
|
338
275
|
on_validate: self.on_validate.clone(),
|
|
339
276
|
alias: ctx.props().selected_column.name().cloned(),
|
|
340
277
|
disabled: !ctx.props().selected_column.is_expr(),
|
|
341
278
|
reset_count: self.reset_count,
|
|
342
|
-
|
|
279
|
+
session: &ctx.props().session
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
let disable_delete = ctx
|
|
283
|
+
.props()
|
|
284
|
+
.session
|
|
285
|
+
.is_locator_active(&ctx.props().selected_column);
|
|
343
286
|
|
|
344
287
|
let save_section = SaveSettingsProps {
|
|
345
288
|
save_enabled: self.save_enabled,
|
|
346
289
|
reset_enabled: self.reset_enabled,
|
|
347
290
|
is_save: ctx.props().selected_column.name().is_some(),
|
|
348
|
-
on_reset: ctx
|
|
349
|
-
|
|
350
|
-
|
|
291
|
+
on_reset: ctx
|
|
292
|
+
.link()
|
|
293
|
+
.callback(ColumnSettingsPanelMsg::OnResetAttributes),
|
|
294
|
+
on_save: ctx
|
|
295
|
+
.link()
|
|
296
|
+
.callback(ColumnSettingsPanelMsg::OnSaveAttributes),
|
|
297
|
+
on_delete: ctx.link().callback(ColumnSettingsPanelMsg::OnDelete),
|
|
351
298
|
show_danger_zone: ctx.props().selected_column.is_saved_expr(),
|
|
352
|
-
disable_delete
|
|
299
|
+
disable_delete,
|
|
353
300
|
};
|
|
354
301
|
|
|
355
302
|
let attrs_tab = AttributesTabProps {
|
|
@@ -357,21 +304,28 @@ impl Component for ColumnSettingsSidebar {
|
|
|
357
304
|
save_section,
|
|
358
305
|
};
|
|
359
306
|
|
|
360
|
-
let style_tab = StyleTabProps {
|
|
361
|
-
custom_events: ctx.props().custom_events.clone(),
|
|
362
|
-
session: ctx.props().session.clone(),
|
|
363
|
-
renderer: ctx.props().renderer.clone(),
|
|
364
|
-
presentation: ctx.props().presentation.clone(),
|
|
307
|
+
let style_tab = props!(StyleTabProps {
|
|
365
308
|
ty: self.maybe_ty,
|
|
366
309
|
column_name: self.column_name.clone(),
|
|
367
310
|
group_by_depth: ctx.props().session.get_view_config().group_by.len() as u32,
|
|
368
|
-
|
|
311
|
+
custom_events: ctx.props().custom_events(),
|
|
312
|
+
presentation: ctx.props().presentation(),
|
|
313
|
+
renderer: ctx.props().renderer(),
|
|
314
|
+
session: ctx.props().session()
|
|
315
|
+
});
|
|
369
316
|
|
|
370
317
|
let tab_children = self.tabs.iter().map(|tab| match tab {
|
|
371
318
|
ColumnSettingsTab::Attributes => html! { <AttributesTab ..attrs_tab.clone() /> },
|
|
372
319
|
ColumnSettingsTab::Style => html! { <StyleTab ..style_tab.clone() /> },
|
|
373
320
|
});
|
|
374
321
|
|
|
322
|
+
let selected_tab_idx = self
|
|
323
|
+
.tabs
|
|
324
|
+
.iter()
|
|
325
|
+
.find_position(|tab| Some(**tab) == ctx.props().selected_tab)
|
|
326
|
+
.map(|(idx, _val)| idx)
|
|
327
|
+
.unwrap_or_default();
|
|
328
|
+
|
|
375
329
|
html! {
|
|
376
330
|
<>
|
|
377
331
|
<LocalStyle href={css!("column-settings-panel")} />
|
|
@@ -379,13 +333,13 @@ impl Component for ColumnSettingsSidebar {
|
|
|
379
333
|
on_close={ctx.props().on_close.clone()}
|
|
380
334
|
id_prefix="column_settings"
|
|
381
335
|
width_override={ctx.props().width_override}
|
|
382
|
-
selected_tab={
|
|
336
|
+
selected_tab={selected_tab_idx}
|
|
383
337
|
{header_props}
|
|
384
338
|
>
|
|
385
339
|
<TabList<ColumnSettingsTab>
|
|
386
340
|
tabs={self.tabs.clone()}
|
|
387
|
-
on_tab_change={ctx.link().callback(
|
|
388
|
-
selected_tab={
|
|
341
|
+
on_tab_change={ctx.link().callback(ColumnSettingsPanelMsg::SetSelectedTab)}
|
|
342
|
+
selected_tab={selected_tab_idx}
|
|
389
343
|
>
|
|
390
344
|
{ for tab_children }
|
|
391
345
|
</TabList<ColumnSettingsTab>>
|
|
@@ -394,3 +348,76 @@ impl Component for ColumnSettingsSidebar {
|
|
|
394
348
|
}
|
|
395
349
|
}
|
|
396
350
|
}
|
|
351
|
+
|
|
352
|
+
impl ColumnSettingsPanel {
|
|
353
|
+
fn save_enabled_effect(&mut self) {
|
|
354
|
+
let changed = self.expr_value != self.initial_expr_value
|
|
355
|
+
|| self.header_value != self.initial_header_value;
|
|
356
|
+
let valid = self.expr_valid && self.header_valid;
|
|
357
|
+
self.save_enabled = changed && valid;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
fn initialize(&mut self, ctx: &yew::prelude::Context<Self>) {
|
|
361
|
+
let column_name = ctx
|
|
362
|
+
.props()
|
|
363
|
+
.session
|
|
364
|
+
.locator_name_or_default(&ctx.props().selected_column);
|
|
365
|
+
|
|
366
|
+
let initial_expr_value = ctx
|
|
367
|
+
.props()
|
|
368
|
+
.session
|
|
369
|
+
.metadata()
|
|
370
|
+
.get_expression_by_alias(&column_name)
|
|
371
|
+
.unwrap_or_default();
|
|
372
|
+
|
|
373
|
+
let initial_expr_value = Rc::new(initial_expr_value);
|
|
374
|
+
let initial_header_value =
|
|
375
|
+
(*initial_expr_value != column_name).then_some(column_name.clone());
|
|
376
|
+
|
|
377
|
+
let maybe_ty = ctx
|
|
378
|
+
.props()
|
|
379
|
+
.session()
|
|
380
|
+
.locator_view_type(&ctx.props().selected_column);
|
|
381
|
+
|
|
382
|
+
let tabs = {
|
|
383
|
+
let mut tabs = vec![];
|
|
384
|
+
let is_new_expr = ctx.props().selected_column.is_new_expr();
|
|
385
|
+
let show_styles = !is_new_expr
|
|
386
|
+
&& ctx
|
|
387
|
+
.props()
|
|
388
|
+
.can_render_column_styles(&column_name)
|
|
389
|
+
.unwrap_or_default();
|
|
390
|
+
|
|
391
|
+
if !is_new_expr && show_styles {
|
|
392
|
+
tabs.push(ColumnSettingsTab::Style);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if ctx.props().selected_column.is_expr() {
|
|
396
|
+
tabs.push(ColumnSettingsTab::Attributes);
|
|
397
|
+
}
|
|
398
|
+
tabs
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
let on_input = ctx.link().callback(ColumnSettingsPanelMsg::SetExprValue);
|
|
402
|
+
let on_save = ctx
|
|
403
|
+
.link()
|
|
404
|
+
.callback(ColumnSettingsPanelMsg::OnSaveAttributes);
|
|
405
|
+
|
|
406
|
+
let on_validate = ctx.link().callback(ColumnSettingsPanelMsg::SetExprValid);
|
|
407
|
+
*self = Self {
|
|
408
|
+
column_name,
|
|
409
|
+
expr_value: initial_expr_value.clone(),
|
|
410
|
+
initial_expr_value,
|
|
411
|
+
header_value: initial_header_value.clone(),
|
|
412
|
+
initial_header_value,
|
|
413
|
+
maybe_ty,
|
|
414
|
+
tabs,
|
|
415
|
+
header_valid: true,
|
|
416
|
+
on_input,
|
|
417
|
+
on_save,
|
|
418
|
+
on_validate,
|
|
419
|
+
_session_sub: self._session_sub.take(),
|
|
420
|
+
..*self
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
@@ -21,21 +21,7 @@ use yew::prelude::*;
|
|
|
21
21
|
use crate::components::column_selector::{EmptyColumn, InPlaceColumn, InvalidColumn};
|
|
22
22
|
use crate::custom_elements::ColumnDropDownElement;
|
|
23
23
|
use crate::dragdrop::*;
|
|
24
|
-
|
|
25
|
-
/// Must be implemented by `Properties` of children of `DragDropList`, returning
|
|
26
|
-
/// the value a DragDropItem represents.
|
|
27
|
-
pub trait DragDropListItemProps: Properties {
|
|
28
|
-
type Item: Clone + PartialEq;
|
|
29
|
-
fn get_item(&self) -> Self::Item;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
pub trait DragContext<T> {
|
|
33
|
-
fn close(index: usize) -> T;
|
|
34
|
-
fn dragleave() -> T;
|
|
35
|
-
fn dragenter(index: usize) -> T;
|
|
36
|
-
fn create(col: InPlaceColumn) -> T;
|
|
37
|
-
fn is_self_move(effect: DragTarget) -> bool;
|
|
38
|
-
}
|
|
24
|
+
use crate::utils::DragTarget;
|
|
39
25
|
|
|
40
26
|
#[derive(Properties, Derivative)]
|
|
41
27
|
#[derivative(Clone(bound = ""))]
|
|
@@ -227,11 +213,10 @@ where
|
|
|
227
213
|
.position(|x| x.1.1.as_ref().unwrap().props.get_item() == *column);
|
|
228
214
|
|
|
229
215
|
valid_duplicate_drag = is_duplicate.is_some() && !ctx.props().allow_duplicates;
|
|
230
|
-
if let Some(duplicate) = is_duplicate
|
|
231
|
-
&& !
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
columns.remove(duplicate);
|
|
216
|
+
if let Some(duplicate) = is_duplicate {
|
|
217
|
+
if !is_append && (!ctx.props().allow_duplicates || is_self_move) {
|
|
218
|
+
columns.remove(duplicate);
|
|
219
|
+
}
|
|
235
220
|
}
|
|
236
221
|
|
|
237
222
|
// If inserting into the middle of the list, use
|
|
@@ -323,3 +308,18 @@ where
|
|
|
323
308
|
}
|
|
324
309
|
}
|
|
325
310
|
}
|
|
311
|
+
|
|
312
|
+
/// Must be implemented by `Properties` of children of `DragDropList`, returning
|
|
313
|
+
/// the value a DragDropItem represents.
|
|
314
|
+
pub trait DragDropListItemProps: Properties {
|
|
315
|
+
type Item: Clone + PartialEq;
|
|
316
|
+
fn get_item(&self) -> Self::Item;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
pub trait DragContext<T> {
|
|
320
|
+
fn close(index: usize) -> T;
|
|
321
|
+
fn dragleave() -> T;
|
|
322
|
+
fn dragenter(index: usize) -> T;
|
|
323
|
+
fn create(col: InPlaceColumn) -> T;
|
|
324
|
+
fn is_self_move(effect: DragTarget) -> bool;
|
|
325
|
+
}
|
|
@@ -20,10 +20,6 @@ use super::select::SelectItem;
|
|
|
20
20
|
use crate::components::style::LocalStyle;
|
|
21
21
|
use crate::*;
|
|
22
22
|
|
|
23
|
-
pub type DropDownMenuItem<T> = SelectItem<T>;
|
|
24
|
-
|
|
25
|
-
pub type DropDownMenuMsg = ();
|
|
26
|
-
|
|
27
23
|
#[derive(Properties, PartialEq)]
|
|
28
24
|
pub struct DropDownMenuProps<T>
|
|
29
25
|
where
|
|
@@ -44,7 +40,7 @@ impl<T> Component for DropDownMenu<T>
|
|
|
44
40
|
where
|
|
45
41
|
T: Into<Html> + Clone + PartialEq + 'static,
|
|
46
42
|
{
|
|
47
|
-
type Message =
|
|
43
|
+
type Message = ();
|
|
48
44
|
type Properties = DropDownMenuProps<T>;
|
|
49
45
|
|
|
50
46
|
fn create(_ctx: &Context<Self>) -> Self {
|
|
@@ -76,7 +72,7 @@ where
|
|
|
76
72
|
DropDownMenuItem::OptGroup(name, xs) => {
|
|
77
73
|
html! {
|
|
78
74
|
<>
|
|
79
|
-
<span class="dropdown-group-label">{ name }</span>
|
|
75
|
+
<span class="dropdown-group-label">{ name.as_ref() }</span>
|
|
80
76
|
<div class="dropdown-group-container">
|
|
81
77
|
{ xs.iter().map(|x| {
|
|
82
78
|
let click = ctx.props().callback.reform({
|
|
@@ -102,3 +98,5 @@ where
|
|
|
102
98
|
html! { <><LocalStyle href={css!("containers/dropdown-menu")} />{ body }</> }
|
|
103
99
|
}
|
|
104
100
|
}
|
|
101
|
+
|
|
102
|
+
pub type DropDownMenuItem<T> = SelectItem<T>;
|
|
@@ -15,14 +15,11 @@
|
|
|
15
15
|
|
|
16
16
|
pub mod dragdrop_list;
|
|
17
17
|
pub mod dropdown_menu;
|
|
18
|
-
pub mod kvpair;
|
|
19
18
|
pub mod scroll_panel;
|
|
20
19
|
pub mod scroll_panel_item;
|
|
21
20
|
pub mod select;
|
|
22
21
|
pub mod sidebar;
|
|
22
|
+
pub mod sidebar_close_button;
|
|
23
23
|
pub mod split_panel;
|
|
24
24
|
pub mod tab_list;
|
|
25
25
|
pub mod trap_door_panel;
|
|
26
|
-
|
|
27
|
-
#[cfg(test)]
|
|
28
|
-
mod tests;
|