@perspective-dev/viewer 4.4.1 → 4.5.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 +1 -2
- package/dist/cdn/perspective-viewer.js.map +4 -4
- package/dist/css/botanical.css +1 -1
- 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/phosphor.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/bootstrap.d.ts +2 -1
- package/dist/esm/column-format.d.ts +51 -0
- package/dist/esm/extensions.d.ts +2 -0
- package/dist/esm/perspective-viewer.d.ts +3 -1
- package/dist/esm/perspective-viewer.inline.js +1 -2
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +1 -2
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/perspective-viewer.worker.d.ts +2 -0
- package/dist/esm/plugin.d.ts +16 -72
- package/dist/esm/ts-rs/ColumnSelectMode.d.ts +1 -0
- package/dist/esm/ts-rs/PluginStaticConfig.d.ts +77 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +6 -3
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +7 -4
- package/dist/wasm/perspective-viewer.d.ts +77 -18
- package/dist/wasm/perspective-viewer.js +293 -144
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +20 -15
- package/package.json +24 -2
- package/src/css/column-selector.css +3 -2
- package/src/css/column-settings-panel.css +35 -6
- package/src/css/column-style.css +27 -2
- package/src/css/containers/scroll-panel.css +2 -1
- package/src/css/containers/tabs.css +8 -52
- package/src/css/dom/checkbox.css +0 -4
- package/src/css/form/code-editor.css +1 -0
- package/src/css/form/debug.css +3 -10
- package/src/css/plugin-selector.css +33 -0
- package/src/css/plugin-settings-panel.css +99 -0
- package/src/css/viewer.css +65 -3
- package/src/rust/components/column_dropdown.rs +3 -1
- package/src/rust/components/column_selector/active_column.rs +13 -19
- package/src/rust/components/column_selector/config_selector.rs +20 -20
- package/src/rust/components/column_selector/filter_column.rs +14 -14
- package/src/rust/components/column_selector/inactive_column.rs +9 -15
- package/src/rust/components/column_selector/pivot_column.rs +7 -7
- package/src/rust/components/column_selector/sort_column.rs +7 -7
- package/src/rust/components/column_selector.rs +55 -37
- package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +15 -7
- package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +394 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +15 -6
- package/src/rust/components/column_settings_sidebar/style_tab.rs +267 -136
- package/src/rust/components/column_settings_sidebar.rs +43 -49
- package/src/rust/components/containers/dragdrop_list.rs +5 -5
- package/src/rust/components/containers/mod.rs +0 -1
- package/src/rust/components/containers/scroll_panel.rs +21 -7
- package/src/rust/components/containers/sidebar.rs +8 -6
- package/src/rust/components/containers/split_panel.rs +3 -3
- package/src/rust/components/containers/tab_list.rs +3 -9
- package/src/rust/components/copy_dropdown.rs +2 -3
- package/src/rust/components/datetime_column_style.rs +19 -81
- package/src/rust/components/editable_header.rs +2 -3
- package/src/rust/components/export_dropdown.rs +2 -3
- package/src/rust/components/expression_editor.rs +29 -17
- package/src/rust/components/filter_dropdown.rs +2 -1
- package/src/rust/components/form/color_range_selector.rs +14 -7
- package/src/rust/components/form/debug.rs +47 -37
- package/src/rust/components/main_panel.rs +24 -65
- package/src/rust/components/mod.rs +2 -1
- package/src/rust/components/number_series_style.rs +161 -0
- package/src/rust/components/plugin_tab.rs +221 -0
- package/src/rust/components/settings_panel.rs +181 -59
- package/src/rust/components/status_bar.rs +140 -173
- package/src/rust/components/status_indicator.rs +15 -22
- package/src/rust/components/string_column_style.rs +20 -82
- package/src/rust/components/style_controls/number_string_format.rs +14 -30
- package/src/rust/components/viewer.rs +92 -131
- package/src/rust/config/column_config_schema.rs +195 -0
- package/src/rust/config/columns_config.rs +4 -97
- package/src/rust/config/datetime_column_style.rs +0 -5
- package/src/rust/config/mod.rs +8 -2
- package/src/rust/config/number_series_style.rs +79 -0
- package/src/rust/config/plugin_static_config.rs +144 -0
- package/src/rust/config/string_column_style.rs +0 -5
- package/src/rust/config/viewer_config.rs +5 -6
- package/src/rust/custom_elements/copy_dropdown.rs +30 -18
- package/src/rust/custom_elements/debug_plugin.rs +1 -3
- package/src/rust/custom_elements/export_dropdown.rs +26 -18
- package/src/rust/custom_elements/viewer.rs +62 -73
- package/src/rust/custom_events.rs +181 -224
- package/src/rust/js/plugin.rs +45 -117
- package/src/rust/lib.rs +34 -5
- package/src/rust/presentation/drag_helpers.rs +206 -0
- package/src/rust/presentation/props.rs +8 -0
- package/src/rust/presentation.rs +256 -41
- package/src/rust/{tasks → queries}/column_locator.rs +17 -73
- package/src/rust/queries/column_values.rs +59 -0
- package/src/rust/{tasks → queries}/columns_iter_set.rs +11 -18
- package/src/rust/queries/exports.rs +96 -0
- package/src/rust/queries/fetch_column_stats.rs +94 -0
- package/src/rust/queries/get_viewer_config.rs +54 -0
- package/src/rust/queries/mod.rs +44 -0
- package/src/rust/queries/plugin_column_styles.rs +101 -0
- package/src/rust/{engines.rs → queries/validate_expression.rs} +26 -15
- package/src/rust/renderer/activate.rs +1 -0
- package/src/rust/renderer/limits.rs +9 -4
- package/src/rust/renderer/plugin_store.rs +12 -0
- package/src/rust/renderer/props.rs +28 -3
- package/src/rust/renderer/registry.rs +40 -15
- package/src/rust/renderer.rs +640 -51
- package/src/rust/session/column_defaults_update.rs +20 -28
- package/src/rust/session/drag_drop_update.rs +10 -10
- package/src/rust/session/metadata.rs +31 -16
- package/src/rust/session/props.rs +15 -6
- package/src/rust/session/view_subscription.rs +10 -0
- package/src/rust/session.rs +109 -147
- package/src/rust/tasks/copy_export.rs +178 -158
- package/src/rust/tasks/{structural.rs → dismiss_render_warning.rs} +20 -40
- package/src/rust/tasks/edit_expression.rs +68 -88
- package/src/rust/tasks/eject.rs +25 -22
- package/src/rust/tasks/intersection_observer.rs +8 -21
- package/src/rust/tasks/mod.rs +19 -21
- package/src/rust/tasks/reset_all.rs +78 -0
- package/src/rust/tasks/resize_observer.rs +11 -33
- package/src/rust/tasks/restore_and_render.rs +117 -90
- package/src/rust/tasks/{get_viewer_config.rs → send_column_config.rs} +38 -35
- package/src/rust/tasks/send_plugin_config.rs +32 -33
- package/src/rust/tasks/update_and_render.rs +66 -47
- package/src/rust/{components/containers/trap_door_panel.rs → tasks/update_theme.rs} +34 -33
- package/src/rust/tasks/validate_expression.rs +61 -0
- package/src/rust/utils/browser/selection.rs +4 -4
- package/src/rust/utils/mod.rs +0 -63
- package/src/svg/mega-menu-icons-density.svg +23 -0
- package/src/svg/mega-menu-icons-map-density.svg +24 -0
- package/src/svg/mega-menu-icons-map-line.svg +19 -0
- package/src/themes/botanical.css +27 -53
- package/src/themes/defaults.css +24 -36
- package/src/themes/dracula.css +36 -54
- package/src/themes/gruvbox-dark.css +39 -59
- package/src/themes/gruvbox.css +16 -28
- package/src/themes/icons.css +3 -0
- package/src/themes/intl/de.css +42 -6
- package/src/themes/intl/es.css +42 -6
- package/src/themes/intl/fr.css +42 -6
- package/src/themes/intl/ja.css +42 -6
- package/src/themes/intl/pt.css +42 -6
- package/src/themes/intl/zh.css +42 -6
- package/src/themes/intl.css +37 -4
- package/src/themes/monokai.css +45 -61
- package/src/themes/phosphor.css +20 -29
- package/src/themes/pro-dark.css +25 -34
- package/src/themes/solarized-dark.css +21 -36
- package/src/themes/solarized.css +13 -23
- package/src/themes/vaporwave.css +40 -74
- package/src/ts/bootstrap.ts +14 -3
- package/src/ts/column-format.ts +162 -0
- package/src/ts/extensions.ts +4 -0
- package/src/ts/perspective-viewer.ts +9 -1
- package/src/{rust/components/column_settings_sidebar/style_tab/stub.rs → ts/perspective-viewer.worker.ts} +2 -22
- package/src/ts/plugin.ts +25 -101
- package/src/ts/ts-rs/{FormatUnit.ts → ColumnSelectMode.ts} +1 -1
- package/src/ts/ts-rs/PluginStaticConfig.ts +78 -0
- package/src/ts/ts-rs/ViewerConfig.ts +1 -2
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +2 -3
- package/dist/esm/ts-rs/ColumnConfigValues.d.ts +0 -31
- package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +0 -1
- package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +0 -15
- package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +0 -18
- package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
- package/dist/esm/ts-rs/DatetimeFormatType.d.ts +0 -6
- package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
- package/dist/esm/ts-rs/FormatUnit.d.ts +0 -1
- package/dist/esm/ts-rs/NumberBackgroundMode.d.ts +0 -1
- package/dist/esm/ts-rs/NumberForegroundMode.d.ts +0 -1
- package/dist/esm/ts-rs/PluginConfig.d.ts +0 -2
- package/dist/esm/ts-rs/RoundingMode.d.ts +0 -1
- package/dist/esm/ts-rs/RoundingPriority.d.ts +0 -1
- package/dist/esm/ts-rs/SignDisplay.d.ts +0 -1
- package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +0 -1
- package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +0 -6
- package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
- package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +0 -1
- package/dist/esm/ts-rs/UseGrouping.d.ts +0 -1
- package/src/rust/components/number_column_style.rs +0 -491
- package/src/rust/config/number_column_style.rs +0 -136
- package/src/rust/dragdrop.rs +0 -481
- package/src/rust/tasks/plugin_column_styles.rs +0 -98
- package/src/ts/ts-rs/ColumnConfigValues.ts +0 -14
- package/src/ts/ts-rs/CustomDatetimeFormat.ts +0 -3
- package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +0 -5
- package/src/ts/ts-rs/CustomNumberFormatConfig.ts +0 -8
- package/src/ts/ts-rs/DatetimeColorMode.ts +0 -3
- package/src/ts/ts-rs/DatetimeFormatType.ts +0 -8
- package/src/ts/ts-rs/FormatMode.ts +0 -3
- package/src/ts/ts-rs/NumberBackgroundMode.ts +0 -3
- package/src/ts/ts-rs/NumberForegroundMode.ts +0 -3
- package/src/ts/ts-rs/PluginConfig.ts +0 -4
- package/src/ts/ts-rs/RoundingMode.ts +0 -3
- package/src/ts/ts-rs/RoundingPriority.ts +0 -3
- package/src/ts/ts-rs/SignDisplay.ts +0 -3
- package/src/ts/ts-rs/SimpleDatetimeFormat.ts +0 -3
- package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +0 -4
- package/src/ts/ts-rs/StringColorMode.ts +0 -3
- package/src/ts/ts-rs/TrailingZeroDisplay.ts +0 -3
- package/src/ts/ts-rs/UseGrouping.ts +0 -3
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-d924246f0b4a3dce → perspective-viewer-39ab7da3ca157861}/inline4.js +0 -0
- /package/src/rust/{tasks → config}/export_method.rs +0 -0
- /package/src/rust/{tasks → queries}/export_app.rs +0 -0
- /package/src/rust/{tasks → queries}/is_invalid_drop.rs +0 -0
|
@@ -21,9 +21,9 @@ use crate::components::copy_dropdown::CopyDropDownMenu;
|
|
|
21
21
|
use crate::components::export_dropdown::ExportDropDownMenu;
|
|
22
22
|
use crate::components::portal::PortalModal;
|
|
23
23
|
use crate::components::status_bar_counter::StatusBarRowsCounter;
|
|
24
|
-
use crate::
|
|
24
|
+
use crate::config::*;
|
|
25
25
|
use crate::js::*;
|
|
26
|
-
use crate::presentation::Presentation;
|
|
26
|
+
use crate::presentation::{Presentation, PresentationProps};
|
|
27
27
|
use crate::renderer::*;
|
|
28
28
|
use crate::session::*;
|
|
29
29
|
use crate::tasks::*;
|
|
@@ -42,27 +42,21 @@ pub struct StatusBarProps {
|
|
|
42
42
|
#[prop_or_default]
|
|
43
43
|
pub on_settings: Option<Callback<()>>,
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
pub
|
|
49
|
-
pub
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
///
|
|
54
|
-
/// subscription.
|
|
55
|
-
pub title: Option<String>,
|
|
56
|
-
/// Theme state from presentation — threaded to avoid theme_config_updated /
|
|
57
|
-
/// visibility_changed subscriptions.
|
|
45
|
+
/// Snapshots threaded from root. Component reads `has_table`, `stats`,
|
|
46
|
+
/// `error`, `title` from session_props; `selected_theme`,
|
|
47
|
+
/// `available_themes`, `is_workspace` from presentation_props.
|
|
48
|
+
pub session_props: SessionProps,
|
|
49
|
+
pub presentation_props: PresentationProps,
|
|
50
|
+
|
|
51
|
+
/// Derived from root: `settings_open && has_table_loaded`. Used
|
|
52
|
+
/// here to drive the title-input enabled state and the theme picker
|
|
53
|
+
/// visibility.
|
|
58
54
|
pub is_settings_open: bool,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
pub is_workspace: bool,
|
|
55
|
+
|
|
56
|
+
/// In-flight render counter, threaded to `StatusIndicator`.
|
|
57
|
+
pub update_count: u32,
|
|
63
58
|
|
|
64
59
|
// State
|
|
65
|
-
pub custom_events: CustomEvents,
|
|
66
60
|
pub session: Session,
|
|
67
61
|
pub renderer: Renderer,
|
|
68
62
|
pub presentation: Presentation,
|
|
@@ -71,48 +65,10 @@ pub struct StatusBarProps {
|
|
|
71
65
|
impl PartialEq for StatusBarProps {
|
|
72
66
|
fn eq(&self, other: &Self) -> bool {
|
|
73
67
|
self.id == other.id
|
|
74
|
-
&& self.
|
|
75
|
-
&& self.
|
|
76
|
-
&& self.stats == other.stats
|
|
77
|
-
&& self.update_count == other.update_count
|
|
78
|
-
&& self.error == other.error
|
|
79
|
-
&& self.title == other.title
|
|
68
|
+
&& self.session_props == other.session_props
|
|
69
|
+
&& self.presentation_props == other.presentation_props
|
|
80
70
|
&& self.is_settings_open == other.is_settings_open
|
|
81
|
-
&& self.
|
|
82
|
-
&& self.available_themes == other.available_themes
|
|
83
|
-
&& self.is_workspace == other.is_workspace
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
impl HasCustomEvents for StatusBarProps {
|
|
88
|
-
fn custom_events(&self) -> &CustomEvents {
|
|
89
|
-
&self.custom_events
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
impl HasPresentation for StatusBarProps {
|
|
94
|
-
fn presentation(&self) -> &Presentation {
|
|
95
|
-
&self.presentation
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
impl HasRenderer for StatusBarProps {
|
|
100
|
-
fn renderer(&self) -> &Renderer {
|
|
101
|
-
&self.renderer
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
impl HasSession for StatusBarProps {
|
|
106
|
-
fn session(&self) -> &Session {
|
|
107
|
-
&self.session
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
impl StateProvider for StatusBarProps {
|
|
112
|
-
type State = StatusBarProps;
|
|
113
|
-
|
|
114
|
-
fn clone_state(&self) -> Self::State {
|
|
115
|
-
self.clone()
|
|
71
|
+
&& self.update_count == other.update_count
|
|
116
72
|
}
|
|
117
73
|
}
|
|
118
74
|
|
|
@@ -155,7 +111,7 @@ impl Component for StatusBar {
|
|
|
155
111
|
export_ref: NodeRef::default(),
|
|
156
112
|
input_ref: NodeRef::default(),
|
|
157
113
|
statusbar_ref: NodeRef::default(),
|
|
158
|
-
title: ctx.props().title.clone(),
|
|
114
|
+
title: ctx.props().session_props.title.clone(),
|
|
159
115
|
copy_target: None,
|
|
160
116
|
export_target: None,
|
|
161
117
|
}
|
|
@@ -165,119 +121,117 @@ impl Component for StatusBar {
|
|
|
165
121
|
// Keep the local title in sync with the prop whenever the session title
|
|
166
122
|
// changes externally (e.g. restore() call) or the settings panel opens /
|
|
167
123
|
// closes (which resets the input element).
|
|
168
|
-
if ctx.props().title != old_props.title
|
|
124
|
+
if ctx.props().session_props.title != old_props.session_props.title
|
|
169
125
|
|| ctx.props().is_settings_open != old_props.is_settings_open
|
|
170
126
|
{
|
|
171
|
-
self.title = ctx.props().title.clone();
|
|
127
|
+
self.title = ctx.props().session_props.title.clone();
|
|
172
128
|
}
|
|
173
129
|
true
|
|
174
130
|
}
|
|
175
131
|
|
|
176
132
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}))
|
|
133
|
+
let r: ApiResult<bool> = (|| {
|
|
134
|
+
Ok(match msg {
|
|
135
|
+
StatusBarMsg::Reset(event) => {
|
|
136
|
+
let all = event.shift_key();
|
|
137
|
+
ctx.props().on_reset.emit(all);
|
|
138
|
+
false
|
|
139
|
+
},
|
|
140
|
+
StatusBarMsg::ResetTheme => {
|
|
141
|
+
update_theme(
|
|
142
|
+
&ctx.props().session,
|
|
143
|
+
&ctx.props().renderer,
|
|
144
|
+
&ctx.props().presentation,
|
|
145
|
+
None,
|
|
146
|
+
);
|
|
147
|
+
true
|
|
148
|
+
},
|
|
149
|
+
StatusBarMsg::SetTheme(theme_name) => {
|
|
150
|
+
update_theme(
|
|
151
|
+
&ctx.props().session,
|
|
152
|
+
&ctx.props().renderer,
|
|
153
|
+
&ctx.props().presentation,
|
|
154
|
+
Some(theme_name),
|
|
155
|
+
);
|
|
156
|
+
false
|
|
157
|
+
},
|
|
158
|
+
StatusBarMsg::Export => {
|
|
159
|
+
self.export_target = self.export_ref.cast::<HtmlElement>();
|
|
160
|
+
true
|
|
161
|
+
},
|
|
162
|
+
StatusBarMsg::Copy => {
|
|
163
|
+
self.copy_target = self.copy_ref.cast::<HtmlElement>();
|
|
164
|
+
true
|
|
165
|
+
},
|
|
166
|
+
StatusBarMsg::CloseExport => {
|
|
167
|
+
self.export_target = None;
|
|
168
|
+
true
|
|
169
|
+
},
|
|
170
|
+
StatusBarMsg::CloseCopy => {
|
|
171
|
+
self.copy_target = None;
|
|
172
|
+
true
|
|
173
|
+
},
|
|
174
|
+
StatusBarMsg::Eject => {
|
|
175
|
+
ctx.props().presentation.on_eject.emit(());
|
|
176
|
+
false
|
|
177
|
+
},
|
|
178
|
+
StatusBarMsg::Noop => {
|
|
179
|
+
self.title = ctx.props().session_props.title.clone();
|
|
180
|
+
true
|
|
181
|
+
},
|
|
182
|
+
StatusBarMsg::TitleInputEvent => {
|
|
183
|
+
let elem = self.input_ref.cast::<HtmlInputElement>().into_apierror()?;
|
|
184
|
+
let title = elem.value();
|
|
185
|
+
let title = if title.trim().is_empty() {
|
|
186
|
+
None
|
|
187
|
+
} else {
|
|
188
|
+
Some(title)
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
self.title = title;
|
|
192
|
+
true
|
|
193
|
+
},
|
|
194
|
+
StatusBarMsg::TitleChangeEvent => {
|
|
195
|
+
let elem = self.input_ref.cast::<HtmlInputElement>().into_apierror()?;
|
|
196
|
+
let title = elem.value();
|
|
197
|
+
let title = if title.trim().is_empty() {
|
|
198
|
+
None
|
|
199
|
+
} else {
|
|
200
|
+
Some(title)
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
ctx.props().session.set_title(title);
|
|
204
|
+
false
|
|
205
|
+
},
|
|
206
|
+
StatusBarMsg::PointerEvent(event) => {
|
|
207
|
+
if event.target().map(JsValue::from)
|
|
208
|
+
== self.statusbar_ref.cast::<HtmlElement>().map(JsValue::from)
|
|
209
|
+
{
|
|
210
|
+
ctx.props().presentation.statusbar_pointer_event.emit(event);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
false
|
|
214
|
+
},
|
|
215
|
+
})
|
|
216
|
+
})();
|
|
217
|
+
r.unwrap_or_else(|e| {
|
|
218
|
+
web_sys::console::warn_1(&e.into());
|
|
219
|
+
Default::default()
|
|
220
|
+
})
|
|
266
221
|
}
|
|
267
222
|
|
|
268
223
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
269
224
|
let Self::Properties {
|
|
270
|
-
custom_events,
|
|
271
225
|
presentation,
|
|
272
226
|
renderer,
|
|
273
227
|
session,
|
|
274
228
|
..
|
|
275
229
|
} = ctx.props();
|
|
276
230
|
|
|
277
|
-
let has_table = ctx.props().has_table.clone();
|
|
278
|
-
let is_errored = ctx.props().is_errored;
|
|
231
|
+
let has_table = ctx.props().session_props.has_table.clone();
|
|
232
|
+
let is_errored = ctx.props().session_props.is_errored();
|
|
279
233
|
let is_settings_open = ctx.props().is_settings_open;
|
|
280
|
-
let title = &ctx.props().title;
|
|
234
|
+
let title = &ctx.props().session_props.title;
|
|
281
235
|
|
|
282
236
|
let mut is_updating_class_name = classes!();
|
|
283
237
|
if title.is_some() {
|
|
@@ -310,13 +264,13 @@ impl Component for StatusBar {
|
|
|
310
264
|
let is_menu = matches!(has_table, Some(TableLoadState::Loaded))
|
|
311
265
|
&& ctx.props().on_settings.as_ref().is_none();
|
|
312
266
|
let is_title = is_menu
|
|
313
|
-
|| ctx.props().is_workspace
|
|
267
|
+
|| ctx.props().presentation_props.is_workspace
|
|
314
268
|
|| title.is_some()
|
|
315
269
|
|| is_errored
|
|
316
270
|
|| presentation.is_active(&self.input_ref.cast::<Element>());
|
|
317
271
|
|
|
318
272
|
let is_settings = title.is_some()
|
|
319
|
-
|| ctx.props().is_workspace
|
|
273
|
+
|| ctx.props().presentation_props.is_workspace
|
|
320
274
|
|| !matches!(has_table, Some(TableLoadState::Loaded))
|
|
321
275
|
|| is_errored
|
|
322
276
|
|| is_settings_open
|
|
@@ -330,12 +284,21 @@ impl Component for StatusBar {
|
|
|
330
284
|
let link = link.clone();
|
|
331
285
|
spawn_local(async move {
|
|
332
286
|
let mime = x.method.mimetype(x.is_chart);
|
|
333
|
-
let task =
|
|
287
|
+
let task = export_method_to_blob(
|
|
288
|
+
&props.session,
|
|
289
|
+
&props.renderer,
|
|
290
|
+
&props.presentation,
|
|
291
|
+
x.method,
|
|
292
|
+
);
|
|
334
293
|
let result = copy_to_clipboard(task, mime).await;
|
|
335
|
-
|
|
294
|
+
let r = (|| -> ApiResult<()> {
|
|
336
295
|
result?;
|
|
337
296
|
link.send_message(StatusBarMsg::CloseCopy);
|
|
338
|
-
|
|
297
|
+
Ok(())
|
|
298
|
+
})();
|
|
299
|
+
if let Err(e) = r {
|
|
300
|
+
web_sys::console::warn_1(&e.into());
|
|
301
|
+
}
|
|
339
302
|
})
|
|
340
303
|
})
|
|
341
304
|
};
|
|
@@ -347,8 +310,15 @@ impl Component for StatusBar {
|
|
|
347
310
|
if !x.name.is_empty() {
|
|
348
311
|
clone!(props, link);
|
|
349
312
|
spawn_local(async move {
|
|
350
|
-
let val =
|
|
351
|
-
|
|
313
|
+
let val = export_method_to_blob(
|
|
314
|
+
&props.session,
|
|
315
|
+
&props.renderer,
|
|
316
|
+
&props.presentation,
|
|
317
|
+
x.method,
|
|
318
|
+
)
|
|
319
|
+
.await
|
|
320
|
+
.unwrap();
|
|
321
|
+
let is_chart = props.renderer.is_chart();
|
|
352
322
|
download(&x.as_filename(is_chart), &val).unwrap();
|
|
353
323
|
link.send_message(StatusBarMsg::CloseExport);
|
|
354
324
|
})
|
|
@@ -370,13 +340,10 @@ impl Component for StatusBar {
|
|
|
370
340
|
{onpointerdown}
|
|
371
341
|
>
|
|
372
342
|
<StatusIndicator
|
|
373
|
-
{custom_events}
|
|
374
343
|
{renderer}
|
|
375
344
|
{session}
|
|
376
345
|
update_count={ctx.props().update_count}
|
|
377
|
-
|
|
378
|
-
has_table={ctx.props().has_table.clone()}
|
|
379
|
-
stats={ctx.props().stats.clone()}
|
|
346
|
+
session_props={ctx.props().session_props.clone()}
|
|
380
347
|
/>
|
|
381
348
|
if is_title {
|
|
382
349
|
<label
|
|
@@ -396,14 +363,14 @@ impl Component for StatusBar {
|
|
|
396
363
|
</label>
|
|
397
364
|
}
|
|
398
365
|
if is_title {
|
|
399
|
-
<StatusBarRowsCounter stats={ctx.props().stats.clone()} />
|
|
366
|
+
<StatusBarRowsCounter stats={ctx.props().session_props.stats.clone()} />
|
|
400
367
|
}
|
|
401
368
|
<div id="spacer" />
|
|
402
369
|
if is_menu {
|
|
403
370
|
<div id="menu-bar" class="section">
|
|
404
371
|
<ThemeSelector
|
|
405
|
-
theme={ctx.props().selected_theme.clone()}
|
|
406
|
-
themes={ctx.props().available_themes.clone()}
|
|
372
|
+
theme={ctx.props().presentation_props.selected_theme.clone()}
|
|
373
|
+
themes={ctx.props().presentation_props.available_themes.clone()}
|
|
407
374
|
on_change={ctx.link().callback(StatusBarMsg::SetTheme)}
|
|
408
375
|
on_reset={ctx.link().callback(|_| StatusBarMsg::ResetTheme)}
|
|
409
376
|
/>
|
|
@@ -454,7 +421,7 @@ impl Component for StatusBar {
|
|
|
454
421
|
target={self.copy_target.clone()}
|
|
455
422
|
own_focus=true
|
|
456
423
|
on_close={on_close_copy}
|
|
457
|
-
theme={ctx.props().selected_theme.clone().unwrap_or_default()}
|
|
424
|
+
theme={ctx.props().presentation_props.selected_theme.clone().unwrap_or_default()}
|
|
458
425
|
>
|
|
459
426
|
<CopyDropDownMenu renderer={renderer.clone()} callback={on_copy_select} />
|
|
460
427
|
</PortalModal>
|
|
@@ -463,7 +430,7 @@ impl Component for StatusBar {
|
|
|
463
430
|
target={self.export_target.clone()}
|
|
464
431
|
own_focus=true
|
|
465
432
|
on_close={on_close_export}
|
|
466
|
-
theme={ctx.props().selected_theme.clone().unwrap_or_default()}
|
|
433
|
+
theme={ctx.props().presentation_props.selected_theme.clone().unwrap_or_default()}
|
|
467
434
|
>
|
|
468
435
|
<ExportDropDownMenu
|
|
469
436
|
renderer={renderer.clone()}
|
|
@@ -12,32 +12,27 @@
|
|
|
12
12
|
|
|
13
13
|
use perspective_client::config::ViewConfigUpdate;
|
|
14
14
|
use perspective_js::utils::ApiError;
|
|
15
|
-
use wasm_bindgen::JsValue;
|
|
16
15
|
use web_sys::*;
|
|
17
16
|
use yew::prelude::*;
|
|
18
17
|
|
|
19
|
-
use crate::custom_events::CustomEvents;
|
|
20
18
|
use crate::renderer::Renderer;
|
|
21
|
-
use crate::session::{Session,
|
|
19
|
+
use crate::session::{Session, SessionProps, TableLoadState};
|
|
22
20
|
use crate::utils::*;
|
|
23
21
|
|
|
24
22
|
/// Value-prop version: no PubSub subscriptions, no reducer.
|
|
25
23
|
/// The parent (`StatusBar`) re-renders this component whenever
|
|
26
|
-
/// `
|
|
27
|
-
/// `IncrementUpdateCount` / `DecrementUpdateCount` / `UpdateSession`
|
|
24
|
+
/// `session_props.error/has_table/stats` or `update_count` change (via
|
|
25
|
+
/// root's `IncrementUpdateCount` / `DecrementUpdateCount` / `UpdateSession`
|
|
26
|
+
/// messages).
|
|
28
27
|
#[derive(PartialEq, Properties)]
|
|
29
28
|
pub struct StatusIndicatorProps {
|
|
30
|
-
pub custom_events: CustomEvents,
|
|
31
29
|
pub renderer: Renderer,
|
|
32
30
|
pub session: Session,
|
|
33
31
|
/// Number of in-flight renders (>0 → "updating" spinner).
|
|
34
32
|
pub update_count: u32,
|
|
35
|
-
///
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
pub has_table: Option<TableLoadState>,
|
|
39
|
-
/// Row/column statistics — used to distinguish "loading" from "connected".
|
|
40
|
-
pub stats: Option<ViewStats>,
|
|
33
|
+
/// Snapshot of session value props — read for `error`, `has_table`,
|
|
34
|
+
/// `stats` to derive the icon state.
|
|
35
|
+
pub session_props: SessionProps,
|
|
41
36
|
}
|
|
42
37
|
|
|
43
38
|
/// An indicator component which displays the current status of the perspective
|
|
@@ -46,19 +41,22 @@ pub struct StatusIndicatorProps {
|
|
|
46
41
|
#[function_component]
|
|
47
42
|
pub fn StatusIndicator(props: &StatusIndicatorProps) -> Html {
|
|
48
43
|
let has_table_cells = props
|
|
44
|
+
.session_props
|
|
49
45
|
.stats
|
|
50
46
|
.as_ref()
|
|
51
47
|
.and_then(|s| s.num_table_cells)
|
|
52
48
|
.is_some();
|
|
53
49
|
|
|
54
|
-
let state = if let Some(err) = &props.error {
|
|
50
|
+
let state = if let Some(err) = &props.session_props.error {
|
|
55
51
|
StatusIconState::Errored(
|
|
56
52
|
err.message(),
|
|
57
53
|
err.stacktrace(),
|
|
58
54
|
err.kind(),
|
|
59
55
|
err.is_reconnect(),
|
|
60
56
|
)
|
|
61
|
-
} else if !has_table_cells
|
|
57
|
+
} else if !has_table_cells
|
|
58
|
+
&& matches!(props.session_props.has_table, Some(TableLoadState::Loading))
|
|
59
|
+
{
|
|
62
60
|
StatusIconState::Loading
|
|
63
61
|
} else if props.update_count > 0 {
|
|
64
62
|
StatusIconState::Updating
|
|
@@ -78,13 +76,8 @@ pub fn StatusIndicator(props: &StatusIndicatorProps) -> Html {
|
|
|
78
76
|
};
|
|
79
77
|
|
|
80
78
|
let onclick = use_async_callback(
|
|
81
|
-
(
|
|
82
|
-
|
|
83
|
-
props.renderer.clone(),
|
|
84
|
-
props.custom_events.clone(),
|
|
85
|
-
state.clone(),
|
|
86
|
-
),
|
|
87
|
-
async move |_: MouseEvent, (session, renderer, custom_events, state)| {
|
|
79
|
+
(props.session.clone(), props.renderer.clone(), state.clone()),
|
|
80
|
+
async move |_: MouseEvent, (session, renderer, state)| {
|
|
88
81
|
match &state {
|
|
89
82
|
StatusIconState::Errored(..) => {
|
|
90
83
|
session.reconnect().await?;
|
|
@@ -96,7 +89,7 @@ pub fn StatusIndicator(props: &StatusIndicatorProps) -> Html {
|
|
|
96
89
|
.await?;
|
|
97
90
|
},
|
|
98
91
|
StatusIconState::Normal => {
|
|
99
|
-
|
|
92
|
+
session.status_indicator_clicked.emit(());
|
|
100
93
|
},
|
|
101
94
|
_ => {},
|
|
102
95
|
};
|