@perspective-dev/viewer 4.5.2 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/perspective-viewer.js +20 -1
- 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/extensions.d.ts +22 -3
- package/dist/esm/perspective-viewer.d.ts +9 -0
- package/dist/esm/perspective-viewer.inline.js +20 -1
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +20 -1
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/plugin.d.ts +71 -5
- package/dist/esm/ts-rs/ClientOptions.d.ts +7 -0
- package/dist/esm/ts-rs/ExportMethod.d.ts +1 -0
- package/dist/esm/ts-rs/ExportOptions.d.ts +9 -0
- package/dist/esm/ts-rs/GetClientOptions.d.ts +8 -0
- package/dist/esm/ts-rs/GetTableOptions.d.ts +8 -0
- package/dist/esm/ts-rs/Layout.d.ts +11 -0
- package/dist/esm/ts-rs/Orientation.d.ts +4 -0
- package/dist/esm/ts-rs/PanelOptions.d.ts +7 -0
- package/dist/esm/ts-rs/PanelViewerConfig.d.ts +41 -0
- package/dist/esm/ts-rs/SplitLayout.d.ts +7 -0
- package/dist/esm/ts-rs/TabLayout.d.ts +10 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +8 -2
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +9 -0
- package/dist/esm/ts-rs/WindowAggregate.d.ts +1 -0
- package/dist/esm/ts-rs/WindowSort.d.ts +7 -0
- package/dist/esm/ts-rs/WindowSortDir.d.ts +6 -0
- package/dist/esm/ts-rs/WindowSpec.d.ts +46 -0
- package/dist/esm/ts-rs/Windows.d.ts +10 -0
- package/dist/esm/ts-rs/WorkspaceConfig.d.ts +40 -0
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +28 -0
- package/dist/wasm/perspective-viewer.d.ts +299 -78
- package/dist/wasm/perspective-viewer.js +544 -186
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +34 -26
- package/dist/wasm/snippets/perspective-viewer-8a8c7d5d696b43ae/inline0.js +6 -0
- package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline3.js → perspective-viewer-8a8c7d5d696b43ae/inline4.js} +5 -0
- package/package.json +3 -2
- package/src/css/_context_menu.css +14 -0
- package/src/css/column-selector.css +1 -0
- package/src/css/column-settings-panel.css +68 -3
- package/src/css/column-style.css +4 -3
- package/src/css/config-selector.css +22 -1
- package/src/css/containers/context-menu.css +107 -0
- package/src/css/containers/tabs.css +2 -2
- package/src/css/panel-tab.css +193 -0
- package/src/css/plugin-selector.css +7 -10
- package/src/css/status-bar.css +75 -81
- package/src/css/viewer.css +188 -70
- package/src/rust/components/column_dropdown.rs +40 -30
- package/src/rust/components/column_selector/active_column.rs +28 -45
- package/src/rust/components/column_selector/aggregate_selector.rs +4 -7
- package/src/rust/components/column_selector/column_selector_column_row.rs +73 -0
- package/src/rust/components/column_selector/config_selector.rs +40 -82
- package/src/rust/components/column_selector/expr_edit_button.rs +7 -1
- package/src/rust/components/column_selector/filter_column.rs +5 -15
- package/src/rust/components/column_selector/inactive_column.rs +11 -9
- package/src/rust/components/column_selector/sort_column.rs +3 -6
- package/src/rust/components/column_selector.rs +25 -14
- package/src/rust/components/column_settings_sidebar/style_tab.rs +2 -1
- package/src/rust/components/column_settings_sidebar/window_tab.rs +34 -0
- package/src/rust/components/column_settings_sidebar.rs +163 -16
- package/src/rust/components/containers/dragdrop_list.rs +73 -3
- package/src/rust/components/containers/sidebar.rs +99 -22
- package/src/rust/components/containers/split_panel.rs +181 -62
- package/src/rust/components/context_menu.rs +130 -0
- package/src/rust/components/editable_header.rs +2 -0
- package/src/rust/components/form/debug.rs +3 -0
- package/src/rust/components/global_filter_bar.rs +76 -0
- package/src/rust/components/main_panel/frame_theme.rs +186 -0
- package/src/rust/components/main_panel/msg.rs +62 -0
- package/src/rust/components/main_panel/presize.rs +220 -0
- package/src/rust/components/main_panel/reconcile.rs +224 -0
- package/src/rust/components/main_panel/render.rs +385 -0
- package/src/rust/components/main_panel/update.rs +184 -0
- package/src/rust/components/main_panel.rs +316 -71
- package/src/rust/components/mod.rs +5 -0
- package/src/rust/components/panel_menu.rs +493 -0
- package/src/rust/components/panel_tab.rs +510 -0
- package/src/rust/components/plugin_tab.rs +1 -1
- package/src/rust/components/portal.rs +7 -0
- package/src/rust/components/settings_panel.rs +13 -5
- package/src/rust/components/status_bar.rs +110 -178
- package/src/rust/components/status_indicator.rs +6 -9
- package/src/rust/components/style/mod.rs +5 -0
- package/src/rust/components/style/style_provider.rs +2 -0
- package/src/rust/components/viewer/filters.rs +133 -0
- package/src/rust/components/viewer/msg.rs +182 -0
- package/src/rust/components/viewer/panels.rs +326 -0
- package/src/rust/components/viewer/render.rs +255 -0
- package/src/rust/components/viewer/settings.rs +434 -0
- package/src/rust/components/viewer/snapshots.rs +134 -0
- package/src/rust/components/viewer/wiring.rs +505 -0
- package/src/rust/components/viewer.rs +245 -756
- package/src/rust/components/window_editor.rs +1013 -0
- package/src/rust/config/export_method.rs +1 -1
- package/src/rust/config/mod.rs +4 -0
- package/src/rust/config/options.rs +71 -0
- package/src/rust/config/viewer_config.rs +24 -2
- package/src/rust/config/workspace_config.rs +92 -0
- package/src/rust/custom_elements/copy_dropdown.rs +3 -1
- package/src/rust/custom_elements/debug_plugin.rs +20 -1
- package/src/rust/custom_elements/export_dropdown.rs +3 -1
- package/src/rust/custom_elements/viewer.rs +1015 -286
- package/src/rust/custom_events.rs +212 -61
- package/src/rust/js/mod.rs +2 -0
- package/src/rust/js/plugin.rs +297 -10
- package/src/rust/js/regular_layout.rs +258 -0
- package/src/rust/lib.rs +24 -2
- package/src/rust/presentation/column_locator.rs +16 -1
- package/src/rust/presentation.rs +66 -33
- package/src/rust/queries/columns_iter_set.rs +7 -1
- package/src/rust/queries/get_viewer_config.rs +29 -11
- package/src/rust/queries/plugin_column_styles.rs +2 -2
- package/src/rust/renderer/activate.rs +41 -14
- package/src/rust/renderer/dispatch.rs +463 -0
- package/src/rust/renderer/plugin_config.rs +495 -0
- package/src/rust/renderer/registry.rs +18 -6
- package/src/rust/renderer/render_timer.rs +29 -10
- package/src/rust/renderer.rs +384 -838
- package/src/rust/session/column_defaults_update.rs +26 -8
- package/src/rust/session/drag_drop_update.rs +18 -0
- package/src/rust/session/metadata.rs +66 -9
- package/src/rust/session/replace_expression_update.rs +1 -0
- package/src/rust/session/view_subscription.rs +30 -15
- package/src/rust/session.rs +755 -264
- package/src/rust/tasks/apply_global_filters.rs +89 -0
- package/src/rust/tasks/auto_pause.rs +171 -0
- package/src/rust/tasks/copy_export.rs +29 -19
- package/src/rust/tasks/create_panel.rs +243 -0
- package/src/rust/tasks/dismiss_render_warning.rs +3 -1
- package/src/rust/tasks/edit_expression.rs +4 -4
- package/src/rust/tasks/edit_window.rs +155 -0
- package/src/rust/tasks/eject.rs +64 -23
- package/src/rust/tasks/mod.rs +30 -4
- package/src/rust/tasks/pipeline.rs +411 -0
- package/src/rust/tasks/presize_panels.rs +324 -0
- package/src/rust/tasks/reset_all.rs +22 -12
- package/src/rust/tasks/resize_observer.rs +124 -87
- package/src/rust/tasks/restore_and_render.rs +80 -86
- package/src/rust/tasks/restore_panel.rs +145 -0
- package/src/rust/tasks/send_column_config.rs +5 -2
- package/src/rust/tasks/send_plugin_config.rs +5 -2
- package/src/rust/tasks/set_edit_mode.rs +59 -0
- package/src/rust/tasks/sync_update_panels.rs +152 -0
- package/src/rust/tasks/table_lifecycle.rs +158 -0
- package/src/rust/tasks/update_theme.rs +56 -12
- package/src/rust/utils/browser/dragdrop.rs +12 -0
- package/src/rust/utils/browser/tests/debounce.rs +49 -0
- package/src/rust/utils/completion.rs +56 -0
- package/src/rust/utils/custom_element.rs +5 -0
- package/src/rust/utils/debounce.rs +189 -17
- package/src/rust/utils/mod.rs +6 -0
- package/src/rust/utils/pending_effects.rs +62 -0
- package/src/rust/utils/spawn.rs +33 -0
- package/src/rust/utils/weak_scope.rs +0 -10
- package/src/rust/workspace.rs +846 -0
- package/src/svg/active-indicator.svg +3 -0
- package/src/svg/pin-icon.svg +5 -0
- package/src/themes/botanical.css +5 -2
- package/src/themes/defaults.css +54 -2
- package/src/themes/dracula.css +6 -3
- package/src/themes/gruvbox-dark.css +5 -2
- package/src/themes/gruvbox.css +5 -2
- package/src/themes/icons.css +5 -2
- package/src/themes/intl/de.css +7 -0
- package/src/themes/intl/es.css +7 -0
- package/src/themes/intl/fr.css +7 -0
- package/src/themes/intl/ja.css +7 -0
- package/src/themes/intl/pt.css +7 -0
- package/src/themes/intl/zh.css +7 -0
- package/src/themes/intl.css +10 -1
- package/src/themes/monokai.css +5 -2
- package/src/themes/phosphor.css +5 -2
- package/src/themes/pro-dark.css +5 -2
- package/src/themes/pro.css +2 -1
- package/src/themes/solarized-dark.css +5 -2
- package/src/themes/solarized.css +5 -2
- package/src/themes/vaporwave.css +5 -2
- package/src/ts/bootstrap.ts +8 -7
- package/src/ts/extensions.ts +30 -2
- package/src/ts/perspective-viewer.ts +10 -0
- package/src/ts/plugin.ts +72 -5
- package/src/ts/ts-rs/ClientOptions.ts +7 -0
- package/src/ts/ts-rs/ExportMethod.ts +3 -0
- package/src/ts/ts-rs/ExportOptions.ts +8 -0
- package/src/ts/ts-rs/GetClientOptions.ts +7 -0
- package/src/ts/ts-rs/GetTableOptions.ts +7 -0
- package/src/ts/ts-rs/Layout.ts +9 -0
- package/src/ts/ts-rs/Orientation.ts +6 -0
- package/src/ts/ts-rs/PanelOptions.ts +7 -0
- package/src/ts/ts-rs/PanelViewerConfig.ts +16 -0
- package/src/ts/ts-rs/SplitLayout.ts +5 -0
- package/src/ts/ts-rs/TabLayout.ts +11 -0
- package/src/ts/ts-rs/ViewerConfig.ts +7 -2
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +9 -0
- package/src/ts/ts-rs/WindowAggregate.ts +3 -0
- package/src/ts/ts-rs/WindowSort.ts +9 -0
- package/src/ts/ts-rs/WindowSortDir.ts +8 -0
- package/src/ts/ts-rs/WindowSpec.ts +46 -0
- package/src/ts/ts-rs/Windows.ts +10 -0
- package/src/ts/ts-rs/WorkspaceConfig.ts +36 -0
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +24 -0
- package/src/rust/tasks/intersection_observer.rs +0 -98
- package/src/rust/tasks/update_and_render.rs +0 -110
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline0.js → perspective-viewer-8a8c7d5d696b43ae/inline1.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline1.js → perspective-viewer-8a8c7d5d696b43ae/inline2.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline2.js → perspective-viewer-8a8c7d5d696b43ae/inline3.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline4.js → perspective-viewer-8a8c7d5d696b43ae/inline5.js} +0 -0
|
@@ -20,16 +20,19 @@ use crate::config::PluginStaticConfig;
|
|
|
20
20
|
|
|
21
21
|
#[extend::ext]
|
|
22
22
|
pub impl ViewConfigUpdate {
|
|
23
|
-
///
|
|
24
|
-
/// `
|
|
25
|
-
/// `
|
|
26
|
-
///
|
|
27
|
-
///
|
|
28
|
-
///
|
|
29
|
-
|
|
23
|
+
/// Coerce this update's `group_rollup_mode` to one the plugin accepts
|
|
24
|
+
/// (`PluginStaticConfig::group_rollup_modes`, feature-filtered). An
|
|
25
|
+
/// absent mode counts as `Rollup` for the acceptance check, so a plugin
|
|
26
|
+
/// that only renders `flat` (Treemap / Sunburst) gets it stamped even
|
|
27
|
+
/// when the update never mentions rollup at all.
|
|
28
|
+
///
|
|
29
|
+
/// Split out of [`Self::set_update_column_defaults`] so same-plugin
|
|
30
|
+
/// restores can enforce the mode WITHOUT the column-defaulting below —
|
|
31
|
+
/// that path must not touch `columns` (it would drop non-numeric color
|
|
32
|
+
/// slots from a partial restore).
|
|
33
|
+
fn set_update_rollup_defaults(
|
|
30
34
|
&mut self,
|
|
31
35
|
metadata: &SessionMetadata,
|
|
32
|
-
columns: &[Option<String>],
|
|
33
36
|
config_static: &PluginStaticConfig,
|
|
34
37
|
) {
|
|
35
38
|
let rollup_features = metadata
|
|
@@ -49,6 +52,21 @@ pub impl ViewConfigUpdate {
|
|
|
49
52
|
self.group_rollup_mode
|
|
50
53
|
);
|
|
51
54
|
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Appends additional columns to the `columns` field of this
|
|
58
|
+
/// `ViewConfigUpdate` by picking appropriate new columns from the
|
|
59
|
+
/// `SessionMetadata`, given the necessary column requirements of the
|
|
60
|
+
/// plugin provided by a `PluginStaticConfig`. For example, an "X/Y
|
|
61
|
+
/// Scatter" chart needs a minimum of 2 numeric columns to be
|
|
62
|
+
/// drawable.
|
|
63
|
+
fn set_update_column_defaults(
|
|
64
|
+
&mut self,
|
|
65
|
+
metadata: &SessionMetadata,
|
|
66
|
+
columns: &[Option<String>],
|
|
67
|
+
config_static: &PluginStaticConfig,
|
|
68
|
+
) {
|
|
69
|
+
self.set_update_rollup_defaults(metadata, config_static);
|
|
52
70
|
|
|
53
71
|
if let (None, Some(min_cols)) = (&self.columns, config_static.min_config_columns) {
|
|
54
72
|
let names_len = config_static.config_column_names.len();
|
|
@@ -96,9 +96,27 @@ pub impl ViewConfig {
|
|
|
96
96
|
config.filter.retain(|x| x.column() != column);
|
|
97
97
|
update.filter = Some(config.filter.clone());
|
|
98
98
|
},
|
|
99
|
+
DragEffect::Move(
|
|
100
|
+
DragTarget::WindowSource
|
|
101
|
+
| DragTarget::WindowOrderBy
|
|
102
|
+
| DragTarget::WindowPartitionBy,
|
|
103
|
+
) => {
|
|
104
|
+
// Staged origins (window-editor pills) have nothing to remove
|
|
105
|
+
// HERE - the editor's draft is not part of the view config
|
|
106
|
+
// this update mutates. The open `WindowEditor` observes the
|
|
107
|
+
// same `drop_received` event and clears the origin slot in
|
|
108
|
+
// its draft, completing the move.
|
|
109
|
+
},
|
|
99
110
|
}
|
|
100
111
|
|
|
101
112
|
match drop {
|
|
113
|
+
DragTarget::WindowSource
|
|
114
|
+
| DragTarget::WindowOrderBy
|
|
115
|
+
| DragTarget::WindowPartitionBy => {
|
|
116
|
+
// Unreachable: staged drops never build config updates
|
|
117
|
+
// (`DragTarget::is_staged` is excluded by every committing
|
|
118
|
+
// `drop_received` subscriber).
|
|
119
|
+
},
|
|
102
120
|
DragTarget::Active => {
|
|
103
121
|
if !is_swap_to_after_last {
|
|
104
122
|
if is_to_swap || is_from_required {
|
|
@@ -69,6 +69,7 @@ pub struct SessionMetadataState {
|
|
|
69
69
|
edit_port: f64,
|
|
70
70
|
view_schema: Option<HashMap<String, ColumnType>>,
|
|
71
71
|
expr_meta: Option<SessionViewExpressionMetadata>,
|
|
72
|
+
window_schema: HashMap<String, ColumnType>,
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
impl SessionMetadata {
|
|
@@ -95,6 +96,43 @@ impl SessionMetadata {
|
|
|
95
96
|
Ok(())
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
/// Records the pre-aggregation types of the config's window columns, so
|
|
100
|
+
/// `get_column_table_type` resolves them like any other derived column.
|
|
101
|
+
/// Types mirror the engine's `t_window_engine::resolve_dtype` rules from
|
|
102
|
+
/// the window's op and its source's table type - independent of any
|
|
103
|
+
/// aggregation the view may also apply.
|
|
104
|
+
pub(super) fn update_windows(
|
|
105
|
+
&mut self,
|
|
106
|
+
windows: &perspective_client::config::Windows,
|
|
107
|
+
) -> ApiResult<()> {
|
|
108
|
+
use perspective_client::config::WindowAggregate;
|
|
109
|
+
let window_schema = windows
|
|
110
|
+
.iter()
|
|
111
|
+
.filter_map(|(name, w)| {
|
|
112
|
+
let source = self.get_column_table_type(&w.column)?;
|
|
113
|
+
let dtype = match w.aggregate {
|
|
114
|
+
WindowAggregate::Sum
|
|
115
|
+
| WindowAggregate::Avg
|
|
116
|
+
| WindowAggregate::Stddev
|
|
117
|
+
| WindowAggregate::Var
|
|
118
|
+
| WindowAggregate::Rate
|
|
119
|
+
| WindowAggregate::Ema
|
|
120
|
+
| WindowAggregate::Diff => ColumnType::Float,
|
|
121
|
+
WindowAggregate::Count => ColumnType::Integer,
|
|
122
|
+
WindowAggregate::Min
|
|
123
|
+
| WindowAggregate::Max
|
|
124
|
+
| WindowAggregate::First
|
|
125
|
+
| WindowAggregate::Last
|
|
126
|
+
| WindowAggregate::Lag
|
|
127
|
+
| WindowAggregate::Lead => source,
|
|
128
|
+
};
|
|
129
|
+
Some((name.clone(), dtype))
|
|
130
|
+
})
|
|
131
|
+
.collect();
|
|
132
|
+
self.as_mut().unwrap().window_schema = window_schema;
|
|
133
|
+
Ok(())
|
|
134
|
+
}
|
|
135
|
+
|
|
98
136
|
/// Whether `view_schema` has been populated by a prior successful
|
|
99
137
|
/// `create_view`. Used by `Session::create_view` to force a full
|
|
100
138
|
/// build on first run even when `is_clean` happens to be true, so
|
|
@@ -212,6 +250,19 @@ impl SessionMetadata {
|
|
|
212
250
|
self.as_ref().map(|meta| &meta.column_names)
|
|
213
251
|
}
|
|
214
252
|
|
|
253
|
+
pub fn is_column_window(&self, name: &str) -> bool {
|
|
254
|
+
self.as_ref()
|
|
255
|
+
.map(|meta| meta.window_schema.contains_key(name))
|
|
256
|
+
.unwrap_or_default()
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
pub fn get_window_columns(&self) -> impl Iterator<Item = &'_ String> {
|
|
260
|
+
self.as_ref()
|
|
261
|
+
.map(|meta| meta.window_schema.keys())
|
|
262
|
+
.into_iter()
|
|
263
|
+
.flatten()
|
|
264
|
+
}
|
|
265
|
+
|
|
215
266
|
pub fn is_column_expression(&self, name: &str) -> bool {
|
|
216
267
|
let is_expr: Option<bool> = try {
|
|
217
268
|
self.as_ref()?
|
|
@@ -253,14 +304,18 @@ impl SessionMetadata {
|
|
|
253
304
|
pub fn get_column_table_type(&self, name: &str) -> Option<ColumnType> {
|
|
254
305
|
try {
|
|
255
306
|
let meta = self.as_ref()?;
|
|
256
|
-
meta.table_schema
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
307
|
+
meta.table_schema
|
|
308
|
+
.get(name)
|
|
309
|
+
.cloned()
|
|
310
|
+
.or_else(|| {
|
|
311
|
+
meta.expr_meta
|
|
312
|
+
.as_ref()?
|
|
313
|
+
.expressions
|
|
314
|
+
.expression_schema
|
|
315
|
+
.get(name)
|
|
316
|
+
.cloned()
|
|
317
|
+
})
|
|
318
|
+
.or_else(|| meta.window_schema.get(name).cloned())?
|
|
264
319
|
}
|
|
265
320
|
}
|
|
266
321
|
|
|
@@ -282,7 +337,9 @@ impl SessionMetadata {
|
|
|
282
337
|
/// expressions.
|
|
283
338
|
pub fn locator_name_or_default(&self, locator: &ColumnLocator) -> String {
|
|
284
339
|
match locator {
|
|
285
|
-
ColumnLocator::Table(s) | ColumnLocator::Expression(s)
|
|
340
|
+
ColumnLocator::Table(s) | ColumnLocator::Expression(s) | ColumnLocator::Window(s) => {
|
|
341
|
+
s.clone()
|
|
342
|
+
},
|
|
286
343
|
ColumnLocator::NewExpression => self.make_new_column_name(None),
|
|
287
344
|
}
|
|
288
345
|
}
|
|
@@ -36,6 +36,7 @@ pub struct ViewStats {
|
|
|
36
36
|
struct ViewSubscriptionData {
|
|
37
37
|
view: View,
|
|
38
38
|
config: Rc<ViewConfig>,
|
|
39
|
+
build_config: Rc<ViewConfig>,
|
|
39
40
|
callback_id: Rc<Cell<u32>>,
|
|
40
41
|
on_stats: Callback<ViewStats>,
|
|
41
42
|
on_update: Option<Callback<()>>,
|
|
@@ -59,8 +60,6 @@ impl ViewSubscriptionData {
|
|
|
59
60
|
Ok(JsValue::UNDEFINED)
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
/// TODO Use serde to serialize the full view config, instead of calculating
|
|
63
|
-
/// `is_aggregated` here.
|
|
64
63
|
async fn update_view_stats(self) -> ApiResult<JsValue> {
|
|
65
64
|
let dimensions = self.view.dimensions().await?;
|
|
66
65
|
let num_rows = dimensions.num_table_rows as u32;
|
|
@@ -80,13 +79,16 @@ impl ViewSubscriptionData {
|
|
|
80
79
|
}
|
|
81
80
|
|
|
82
81
|
async fn internal_delete(&self) -> ApiResult<()> {
|
|
82
|
+
if self.is_deleted.replace(true) {
|
|
83
|
+
return Ok(());
|
|
84
|
+
}
|
|
85
|
+
|
|
83
86
|
let view = &self.view;
|
|
84
87
|
if self.on_update.is_some() {
|
|
85
88
|
view.remove_update(self.callback_id.get()).await?;
|
|
86
89
|
}
|
|
87
90
|
|
|
88
91
|
view.delete().await?;
|
|
89
|
-
self.is_deleted.set(true);
|
|
90
92
|
Ok(())
|
|
91
93
|
}
|
|
92
94
|
}
|
|
@@ -104,13 +106,15 @@ impl ViewSubscription {
|
|
|
104
106
|
/// `View.on_update()`.
|
|
105
107
|
pub async fn new(
|
|
106
108
|
view: perspective_client::View,
|
|
107
|
-
config: ViewConfig
|
|
109
|
+
config: Rc<ViewConfig>,
|
|
110
|
+
build_config: Rc<ViewConfig>,
|
|
108
111
|
on_stats: Callback<ViewStats>,
|
|
109
112
|
on_update: Option<Callback<()>>,
|
|
110
113
|
) -> Result<Self, ApiError> {
|
|
111
114
|
let data = ViewSubscriptionData {
|
|
112
115
|
view,
|
|
113
|
-
config
|
|
116
|
+
config,
|
|
117
|
+
build_config,
|
|
114
118
|
on_stats,
|
|
115
119
|
callback_id: Rc::default(),
|
|
116
120
|
on_update,
|
|
@@ -142,10 +146,13 @@ impl ViewSubscription {
|
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
/// It is possible to re-use a `ViewSubscription` without a costly
|
|
145
|
-
/// resubscribe
|
|
146
|
-
/// `
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
/// resubscribe when the new config is engine-equivalent to the one the
|
|
150
|
+
/// bound `View` was built from (placeholder-only differences); the
|
|
151
|
+
/// snapshots still need updating so reads stay consistent with the run
|
|
152
|
+
/// that adopted them.
|
|
153
|
+
pub fn set_configs(&mut self, config: Rc<ViewConfig>, build_config: Rc<ViewConfig>) {
|
|
154
|
+
self.data.config = config;
|
|
155
|
+
self.data.build_config = build_config;
|
|
149
156
|
}
|
|
150
157
|
|
|
151
158
|
/// Getter for the underlying `View()`.
|
|
@@ -153,16 +160,24 @@ impl ViewSubscription {
|
|
|
153
160
|
&self.data.view
|
|
154
161
|
}
|
|
155
162
|
|
|
156
|
-
///
|
|
157
|
-
/// from (
|
|
158
|
-
///
|
|
159
|
-
///
|
|
160
|
-
///
|
|
161
|
-
///
|
|
163
|
+
/// User-facing snapshot of the [`ViewConfig`] the bound `View` was
|
|
164
|
+
/// constructed from (the persisted config at build time — global-filter
|
|
165
|
+
/// overlay excluded). This is the [`ViewConfig`] consistent with the
|
|
166
|
+
/// data the active plugin is currently rendering — not the live session
|
|
167
|
+
/// config, which may have been mutated synchronously ahead of the next
|
|
168
|
+
/// queued run.
|
|
162
169
|
pub fn get_view_config(&self) -> Rc<ViewConfig> {
|
|
163
170
|
self.data.config.clone()
|
|
164
171
|
}
|
|
165
172
|
|
|
173
|
+
/// The EFFECTIVE [`ViewConfig`] the bound `View` was built from
|
|
174
|
+
/// (persisted config + global-filter overlay at build time). This is
|
|
175
|
+
/// the value `Session::bind_view` compares a run's snapshot against to
|
|
176
|
+
/// decide SKIP / REUSE / REBUILD.
|
|
177
|
+
pub fn build_config(&self) -> Rc<ViewConfig> {
|
|
178
|
+
self.data.build_config.clone()
|
|
179
|
+
}
|
|
180
|
+
|
|
166
181
|
/// Delete this `View`. Neglecting to call this method before a
|
|
167
182
|
/// `ViewSubscription` is dropped will result in a log warning, but the
|
|
168
183
|
/// `View` will not leak.
|