@perspective-dev/viewer 4.4.0 → 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 -0
- 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 +6 -0
- package/dist/esm/perspective-viewer.d.ts +4 -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 +21 -77
- 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 +39 -0
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +7 -4
- package/dist/wasm/perspective-viewer.d.ts +88 -24
- package/dist/wasm/perspective-viewer.js +320 -151
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +22 -17
- package/package.json +24 -2
- package/src/css/column-selector.css +3 -2
- package/src/css/column-settings-panel.css +36 -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/status-bar.css +1 -1
- 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 -132
- 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 +7 -8
- package/src/rust/custom_elements/copy_dropdown.rs +30 -18
- package/src/rust/custom_elements/debug_plugin.rs +5 -7
- package/src/rust/custom_elements/export_dropdown.rs +26 -18
- package/src/rust/custom_elements/viewer.rs +77 -77
- package/src/rust/custom_events.rs +181 -224
- package/src/rust/js/plugin.rs +45 -117
- package/src/rust/lib.rs +39 -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 +649 -55
- 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 -89
- 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/datagrid-select-row-tree.svg +13 -0
- 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 +42 -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 +4 -18
- 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 +175 -0
- 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/themes.css +1 -0
- 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 +12 -1
- package/src/ts/perspective-viewer.ts +10 -1
- package/src/{rust/components/column_settings_sidebar/style_tab/stub.rs → ts/perspective-viewer.worker.ts} +2 -22
- package/src/ts/plugin.ts +29 -105
- 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 +14 -0
- 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 -483
- package/src/rust/config/number_column_style.rs +0 -132
- 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-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → perspective-viewer-39ab7da3ca157861}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-68fef752754ffbc6 → 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
package/src/rust/session.rs
CHANGED
|
@@ -18,13 +18,13 @@ pub(crate) mod replace_expression_update;
|
|
|
18
18
|
mod view_subscription;
|
|
19
19
|
|
|
20
20
|
use std::cell::{Ref, RefCell};
|
|
21
|
-
use std::collections::HashSet;
|
|
21
|
+
use std::collections::{HashMap, HashSet};
|
|
22
22
|
use std::future::Future;
|
|
23
23
|
use std::ops::Deref;
|
|
24
24
|
use std::rc::Rc;
|
|
25
25
|
|
|
26
26
|
use perspective_client::config::*;
|
|
27
|
-
use perspective_client::{Client, ClientError, ReconnectCallback, View
|
|
27
|
+
use perspective_client::{Client, ClientError, ReconnectCallback, View};
|
|
28
28
|
use perspective_js::apierror;
|
|
29
29
|
use perspective_js::utils::*;
|
|
30
30
|
use wasm_bindgen::prelude::*;
|
|
@@ -36,9 +36,18 @@ pub use self::metadata::{MetadataRef, SessionMetadata, SessionMetadataRc};
|
|
|
36
36
|
pub use self::props::{SessionProps, TableLoadState};
|
|
37
37
|
pub use self::view_subscription::ViewStats;
|
|
38
38
|
use self::view_subscription::*;
|
|
39
|
-
use crate::
|
|
39
|
+
use crate::config::PluginStaticConfig;
|
|
40
40
|
use crate::utils::*;
|
|
41
41
|
|
|
42
|
+
/// Per-column numeric stats sourced from `View::get_min_max`. Keyed by
|
|
43
|
+
/// column name in [`SessionHandle::column_stats`]; populated lazily by
|
|
44
|
+
/// the `fetch_column_abs_max` task; cleared on every
|
|
45
|
+
/// `view_config_changed`.
|
|
46
|
+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
|
47
|
+
pub struct ColumnStats {
|
|
48
|
+
pub abs_max: Option<f64>,
|
|
49
|
+
}
|
|
50
|
+
|
|
42
51
|
/// Immutable state for `Session`.
|
|
43
52
|
#[derive(Default)]
|
|
44
53
|
pub struct SessionHandle {
|
|
@@ -50,6 +59,34 @@ pub struct SessionHandle {
|
|
|
50
59
|
pub view_config_changed: PubSub<()>,
|
|
51
60
|
pub title_changed: PubSub<Option<String>>,
|
|
52
61
|
|
|
62
|
+
/// Fires when the user clicks the status indicator while in
|
|
63
|
+
/// [`StatusIconState::Normal`]. `wire_custom_events` is the only
|
|
64
|
+
/// listener and fans this out as the `perspective-status-indicator-click`
|
|
65
|
+
/// `CustomEvent`.
|
|
66
|
+
pub status_indicator_clicked: PubSub<()>,
|
|
67
|
+
|
|
68
|
+
/// Per-column numeric stats cache. Populated by the
|
|
69
|
+
/// `fetch_column_abs_max` task and consumed by the schema-query
|
|
70
|
+
/// path so plugins emit gradient defaults without
|
|
71
|
+
/// per-render `View::get_min_max` round trips. Cleared
|
|
72
|
+
/// synchronously inside [`Session::update_view_config`].
|
|
73
|
+
column_stats: RefCell<HashMap<String, ColumnStats>>,
|
|
74
|
+
|
|
75
|
+
/// Memoized snapshots used by [`Session::to_props`] to keep
|
|
76
|
+
/// `PtrEqRc` identity stable across repeated `to_props()` calls
|
|
77
|
+
/// when the underlying value hasn't changed. Without this, every
|
|
78
|
+
/// `PubSub` fire (including `column_stats_changed`) produces a
|
|
79
|
+
/// fresh `Rc` for `config` / `metadata`, triggering downstream
|
|
80
|
+
/// `use_effect_with(view_config, ...)` effects to spuriously
|
|
81
|
+
/// refire — closing a loop with the stats fetch path.
|
|
82
|
+
cached_config: RefCell<Option<PtrEqRc<ViewConfig>>>,
|
|
83
|
+
cached_metadata: RefCell<Option<SessionMetadataRc>>,
|
|
84
|
+
|
|
85
|
+
/// Fires when [`SessionHandle::column_stats`] is updated (insert or
|
|
86
|
+
/// clear). Subscribers re-render and re-query the schema with the
|
|
87
|
+
/// new value.
|
|
88
|
+
pub column_stats_changed: PubSub<()>,
|
|
89
|
+
|
|
53
90
|
/// Injected callback from the root component, replacing the former
|
|
54
91
|
/// `stats_changed: PubSub` field. Fires when view stats are updated.
|
|
55
92
|
pub on_stats_changed: RefCell<Option<Callback<()>>>,
|
|
@@ -325,10 +362,10 @@ impl Session {
|
|
|
325
362
|
}
|
|
326
363
|
}
|
|
327
364
|
|
|
328
|
-
pub fn update_column_defaults(&self,
|
|
365
|
+
pub fn update_column_defaults(&self, config_static: &PluginStaticConfig) {
|
|
329
366
|
if self.borrow().config.columns.is_empty() {
|
|
330
367
|
let mut update = ViewConfigUpdate::default();
|
|
331
|
-
self.set_update_column_defaults(&mut update,
|
|
368
|
+
self.set_update_column_defaults(&mut update, config_static);
|
|
332
369
|
self.borrow_mut().config.apply_update(update);
|
|
333
370
|
}
|
|
334
371
|
}
|
|
@@ -418,92 +455,6 @@ impl Session {
|
|
|
418
455
|
Ok(())
|
|
419
456
|
}
|
|
420
457
|
|
|
421
|
-
/// Validate an expression string and marshall the results.
|
|
422
|
-
pub async fn validate_expr(
|
|
423
|
-
&self,
|
|
424
|
-
expr: &str,
|
|
425
|
-
) -> Result<Option<perspective_client::ExprValidationError>, ApiError> {
|
|
426
|
-
let table = self.borrow().table.as_ref().unwrap().clone();
|
|
427
|
-
let errors = table
|
|
428
|
-
.validate_expressions(
|
|
429
|
-
ExpressionsDeserde::Map(std::collections::HashMap::from_iter([(
|
|
430
|
-
"_".to_string(),
|
|
431
|
-
expr.to_string(),
|
|
432
|
-
)]))
|
|
433
|
-
.into(),
|
|
434
|
-
)
|
|
435
|
-
.await?
|
|
436
|
-
.errors;
|
|
437
|
-
|
|
438
|
-
Ok(errors.get("_").cloned())
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
pub async fn arrow_as_vec(
|
|
442
|
-
&self,
|
|
443
|
-
flat: bool,
|
|
444
|
-
window: Option<ViewWindow>,
|
|
445
|
-
) -> Result<Vec<u8>, ApiError> {
|
|
446
|
-
Ok(self
|
|
447
|
-
.flat_view(flat)
|
|
448
|
-
.await?
|
|
449
|
-
.to_arrow(window.unwrap_or_default())
|
|
450
|
-
.await?
|
|
451
|
-
.into())
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
pub async fn arrow_as_jsvalue(
|
|
455
|
-
&self,
|
|
456
|
-
flat: bool,
|
|
457
|
-
window: Option<ViewWindow>,
|
|
458
|
-
) -> Result<js_sys::ArrayBuffer, ApiError> {
|
|
459
|
-
let arrow = self
|
|
460
|
-
.flat_view(flat)
|
|
461
|
-
.await?
|
|
462
|
-
.to_arrow(window.unwrap_or_default())
|
|
463
|
-
.await?;
|
|
464
|
-
Ok(js_sys::Uint8Array::from(&arrow[..])
|
|
465
|
-
.buffer()
|
|
466
|
-
.unchecked_into())
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
pub async fn ndjson_as_jsvalue(
|
|
470
|
-
&self,
|
|
471
|
-
flat: bool,
|
|
472
|
-
window: Option<ViewWindow>,
|
|
473
|
-
) -> Result<js_sys::JsString, ApiError> {
|
|
474
|
-
let json: String = self
|
|
475
|
-
.flat_view(flat)
|
|
476
|
-
.await?
|
|
477
|
-
.to_ndjson(window.unwrap_or_default())
|
|
478
|
-
.await?;
|
|
479
|
-
|
|
480
|
-
Ok(json.into())
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
pub async fn json_as_jsvalue(
|
|
484
|
-
&self,
|
|
485
|
-
flat: bool,
|
|
486
|
-
window: Option<ViewWindow>,
|
|
487
|
-
) -> Result<js_sys::Object, ApiError> {
|
|
488
|
-
let json: String = self
|
|
489
|
-
.flat_view(flat)
|
|
490
|
-
.await?
|
|
491
|
-
.to_columns_string(window.unwrap_or_default())
|
|
492
|
-
.await?;
|
|
493
|
-
|
|
494
|
-
Ok(js_sys::JSON::parse(&json)?.unchecked_into())
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
pub async fn csv_as_jsvalue(
|
|
498
|
-
&self,
|
|
499
|
-
flat: bool,
|
|
500
|
-
window: Option<ViewWindow>,
|
|
501
|
-
) -> Result<js_sys::JsString, ApiError> {
|
|
502
|
-
let window = window.unwrap_or_default();
|
|
503
|
-
let csv = self.flat_view(flat).await?.to_csv(window).await;
|
|
504
|
-
Ok(csv.map(js_sys::JsString::from)?)
|
|
505
|
-
}
|
|
506
|
-
|
|
507
458
|
pub fn get_view(&self) -> Option<View> {
|
|
508
459
|
self.borrow()
|
|
509
460
|
.view_sub
|
|
@@ -519,58 +470,29 @@ impl Session {
|
|
|
519
470
|
Ref::map(self.borrow(), |x| &x.config)
|
|
520
471
|
}
|
|
521
472
|
|
|
522
|
-
///
|
|
473
|
+
/// Snapshot of the [`ViewConfig`] the currently-bound `View` was
|
|
474
|
+
/// constructed from. Returns `None` if no `View` has been created
|
|
475
|
+
/// yet (e.g., the post-`load`/pre-render window, or after a reset).
|
|
523
476
|
///
|
|
524
|
-
///
|
|
525
|
-
///
|
|
526
|
-
///
|
|
527
|
-
///
|
|
528
|
-
///
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
/// - `column` The name of the column (or expression).
|
|
532
|
-
pub async fn get_column_values(&self, column: String) -> Result<Vec<String>, ApiError> {
|
|
533
|
-
let expressions = Some(self.borrow().config.expressions.clone());
|
|
534
|
-
let config = ViewConfigUpdate {
|
|
535
|
-
group_by: Some(vec![column]),
|
|
536
|
-
columns: Some(vec![]),
|
|
537
|
-
expressions,
|
|
538
|
-
..ViewConfigUpdate::default()
|
|
539
|
-
};
|
|
540
|
-
|
|
541
|
-
let table = self.borrow().table.clone().unwrap();
|
|
542
|
-
let view = table.view(Some(config.clone())).await?;
|
|
543
|
-
let csv = view.to_csv(ViewWindow::default()).await?;
|
|
544
|
-
|
|
545
|
-
ApiFuture::spawn(async move {
|
|
546
|
-
view.delete().await?;
|
|
547
|
-
Ok(())
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
let res = csv
|
|
551
|
-
.lines()
|
|
552
|
-
.map(|val| {
|
|
553
|
-
if val.starts_with('\"') && val.ends_with('\"') {
|
|
554
|
-
(val[1..val.len() - 1]).to_owned()
|
|
555
|
-
} else {
|
|
556
|
-
val.to_owned()
|
|
557
|
-
}
|
|
558
|
-
})
|
|
559
|
-
.skip(2)
|
|
560
|
-
.collect::<Vec<String>>();
|
|
561
|
-
Ok(res)
|
|
477
|
+
/// Prefer this over [`Self::get_view_config`] when you need a
|
|
478
|
+
/// value consistent with what the active plugin is rendering.
|
|
479
|
+
/// `get_view_config` returns the live config, which is mutated
|
|
480
|
+
/// synchronously by [`Self::update_view_config`] ahead of the next
|
|
481
|
+
/// draw and so may temporarily disagree with the bound `View`.
|
|
482
|
+
pub fn get_rendered_view_config(&self) -> Option<Rc<ViewConfig>> {
|
|
483
|
+
self.borrow().view_sub.as_ref().map(|s| s.get_view_config())
|
|
562
484
|
}
|
|
563
485
|
|
|
564
486
|
pub fn set_update_column_defaults(
|
|
565
487
|
&self,
|
|
566
488
|
config_update: &mut ViewConfigUpdate,
|
|
567
|
-
|
|
489
|
+
config_static: &PluginStaticConfig,
|
|
568
490
|
) {
|
|
569
491
|
use self::column_defaults_update::*;
|
|
570
492
|
config_update.set_update_column_defaults(
|
|
571
493
|
&self.metadata(),
|
|
572
494
|
&self.get_view_config().columns,
|
|
573
|
-
|
|
495
|
+
config_static,
|
|
574
496
|
)
|
|
575
497
|
}
|
|
576
498
|
|
|
@@ -586,12 +508,42 @@ impl Session {
|
|
|
586
508
|
|
|
587
509
|
if self.borrow_mut().config.apply_update(config_update) && self.0.borrow().is_clean {
|
|
588
510
|
self.0.borrow_mut().is_clean = false;
|
|
511
|
+
// View config changed → cached stats are stale.
|
|
512
|
+
self.clear_column_stats();
|
|
589
513
|
self.view_config_changed.emit(());
|
|
590
514
|
}
|
|
591
515
|
|
|
592
516
|
Ok(())
|
|
593
517
|
}
|
|
594
518
|
|
|
519
|
+
/// Read the cached `ColumnStats` for a column. Returns `None` if no
|
|
520
|
+
/// fetch has populated this column yet (or the cache was just
|
|
521
|
+
/// cleared by a view-config change).
|
|
522
|
+
pub fn get_column_stats(&self, column_name: &str) -> Option<ColumnStats> {
|
|
523
|
+
self.column_stats.borrow().get(column_name).copied()
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/// Insert a freshly-fetched `abs_max` for a column and notify
|
|
527
|
+
/// subscribers via [`SessionHandle::column_stats_changed`].
|
|
528
|
+
pub fn set_column_abs_max(&self, column_name: String, abs_max: f64) {
|
|
529
|
+
self.column_stats
|
|
530
|
+
.borrow_mut()
|
|
531
|
+
.entry(column_name)
|
|
532
|
+
.or_default()
|
|
533
|
+
.abs_max = Some(abs_max);
|
|
534
|
+
self.column_stats_changed.emit(());
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/// Drop the entire stats cache. Called when the view config changes
|
|
538
|
+
/// (filter / group_by / etc.) so stats are re-fetched on next
|
|
539
|
+
/// schema query.
|
|
540
|
+
pub fn clear_column_stats(&self) {
|
|
541
|
+
if !self.column_stats.borrow().is_empty() {
|
|
542
|
+
self.column_stats.borrow_mut().clear();
|
|
543
|
+
self.column_stats_changed.emit(());
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
595
547
|
/// In order to create a new view in this session, the session must first be
|
|
596
548
|
/// validated to create a `ValidSession<'_>` guard.
|
|
597
549
|
pub async fn validate(&self) -> Result<ValidSession<'_>, ApiError> {
|
|
@@ -643,19 +595,6 @@ impl Session {
|
|
|
643
595
|
Ok(ValidSession(self, is_diff))
|
|
644
596
|
}
|
|
645
597
|
|
|
646
|
-
async fn flat_view(&self, flat: bool) -> ApiResult<View> {
|
|
647
|
-
if flat {
|
|
648
|
-
let table = self.borrow().table.clone().into_apierror()?;
|
|
649
|
-
Ok(table.view(None).await?)
|
|
650
|
-
} else {
|
|
651
|
-
self.borrow()
|
|
652
|
-
.view_sub
|
|
653
|
-
.as_ref()
|
|
654
|
-
.map(|x| x.get_view().clone())
|
|
655
|
-
.into_apierror()
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
|
|
659
598
|
fn update_stats(&self, stats: ViewStats) {
|
|
660
599
|
self.borrow_mut().stats = Some(stats);
|
|
661
600
|
if let Some(cb) = self.on_stats_changed.borrow().as_ref() {
|
|
@@ -772,9 +711,31 @@ impl Session {
|
|
|
772
711
|
/// for passing as a Yew prop. Called by the root component whenever a
|
|
773
712
|
/// session-related PubSub event fires.
|
|
774
713
|
pub fn to_props(&self) -> SessionProps {
|
|
714
|
+
let column_stats = PtrEqRc::new(self.column_stats.borrow().clone());
|
|
775
715
|
let data = self.borrow();
|
|
716
|
+
|
|
717
|
+
// Reuse memoized snapshots when the underlying value hasn't
|
|
718
|
+
// changed. PtrEq identity must be stable across `to_props()`
|
|
719
|
+
// calls triggered by *unrelated* pubsubs (e.g. our own
|
|
720
|
+
// `column_stats_changed`), or downstream effects keyed on
|
|
721
|
+
// these `PtrEqRc`s will spuriously refire.
|
|
722
|
+
let config = {
|
|
723
|
+
let mut cached = self.cached_config.borrow_mut();
|
|
724
|
+
if !matches!(&*cached, Some(c) if **c == data.config) {
|
|
725
|
+
*cached = Some(PtrEqRc::new(data.config.clone()));
|
|
726
|
+
}
|
|
727
|
+
cached.clone().unwrap()
|
|
728
|
+
};
|
|
729
|
+
let metadata = {
|
|
730
|
+
let mut cached = self.cached_metadata.borrow_mut();
|
|
731
|
+
if !matches!(&*cached, Some(m) if **m == data.metadata) {
|
|
732
|
+
*cached = Some(PtrEqRc::new(data.metadata.clone()));
|
|
733
|
+
}
|
|
734
|
+
cached.clone().unwrap()
|
|
735
|
+
};
|
|
736
|
+
|
|
776
737
|
SessionProps {
|
|
777
|
-
config
|
|
738
|
+
config,
|
|
778
739
|
stats: data.stats.clone(),
|
|
779
740
|
has_table: if data.table.is_some() {
|
|
780
741
|
Some(TableLoadState::Loaded)
|
|
@@ -785,7 +746,8 @@ impl Session {
|
|
|
785
746
|
},
|
|
786
747
|
error: data.error.clone(),
|
|
787
748
|
title: data.title.clone(),
|
|
788
|
-
metadata
|
|
749
|
+
metadata,
|
|
750
|
+
column_stats,
|
|
789
751
|
}
|
|
790
752
|
}
|
|
791
753
|
}
|