@perspective-dev/viewer 4.2.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/perspective-viewer.js +2 -2
- package/dist/cdn/perspective-viewer.js.map +4 -4
- package/dist/css/botanical.css +1 -0
- package/dist/css/dracula.css +1 -1
- package/dist/css/gruvbox-dark.css +1 -1
- package/dist/css/gruvbox.css +1 -1
- package/dist/css/icons.css +1 -1
- package/dist/css/intl/de.css +1 -1
- package/dist/css/intl/es.css +1 -1
- package/dist/css/intl/fr.css +1 -1
- package/dist/css/intl/ja.css +1 -1
- package/dist/css/intl/pt.css +1 -1
- package/dist/css/intl/zh.css +1 -1
- package/dist/css/intl.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/pro-dark.css +1 -1
- package/dist/css/pro.css +1 -1
- package/dist/css/solarized-dark.css +1 -1
- package/dist/css/solarized.css +1 -1
- package/dist/css/themes.css +1 -1
- package/dist/css/vaporwave.css +1 -1
- package/dist/esm/extensions.d.ts +32 -1
- package/dist/esm/perspective-viewer.d.ts +1 -0
- package/dist/esm/perspective-viewer.inline.js +2 -2
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +2 -2
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/ts-rs/GroupRollupMode.d.ts +1 -0
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +2 -0
- package/dist/wasm/perspective-viewer.d.ts +57 -53
- package/dist/wasm/perspective-viewer.js +197 -164
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +17 -18
- package/package.json +9 -6
- package/src/{less/aggregate-selector.less → css/aggregate-selector.css} +23 -20
- package/src/css/column-dropdown.css +109 -0
- package/src/{less/column-selector.less → css/column-selector.css} +161 -159
- package/src/{less/column-settings-panel.less → css/column-settings-panel.css} +69 -59
- package/src/{less/column-style.less → css/column-style.css} +52 -66
- package/src/{less/column-symbol-attributes.less → css/column-symbol-attributes.css} +15 -14
- package/src/css/config-selector.css +441 -0
- package/src/{less/containers/dropdown-menu.less → css/containers/dropdown-menu.css} +20 -19
- package/src/{less/containers/pairs-list.less → css/containers/pairs-list.css} +13 -12
- package/src/{themes/variables.less → css/containers/scroll-panel.css} +25 -22
- package/src/{less/containers/split-panel.less → css/containers/split-panel.css} +15 -14
- package/src/{less/containers/tabs.less → css/containers/tabs.css} +17 -19
- package/src/css/dom/checkbox.css +102 -0
- package/src/css/dom/scrollbar.css +35 -0
- package/src/{less/dom/select.less → css/dom/select.css} +17 -18
- package/src/{less/empty-column.less → css/empty-column.css} +19 -18
- package/src/{less/expression-editor.less → css/expression-editor.css} +19 -18
- package/src/{less/filter-dropdown.less → css/filter-dropdown.css} +12 -11
- package/src/{less/filter-item.less → css/filter-item.css} +16 -15
- package/src/{less/form/code-editor.less → css/form/code-editor.css} +26 -30
- package/src/{less/form/debug.less → css/form/debug.css} +19 -18
- package/src/{less/function-dropdown.less → css/function-dropdown.css} +12 -11
- package/src/css/plugin-selector.css +261 -0
- package/src/{less/render-warning.less → css/render-warning.css} +18 -17
- package/src/{less/status-bar.less → css/status-bar.css} +156 -144
- package/src/css/type-icon.css +116 -0
- package/src/{less/viewer.less → css/viewer.css} +112 -146
- package/src/rust/components/column_dropdown.rs +229 -119
- package/src/rust/components/column_selector/active_column.rs +81 -62
- package/src/rust/components/column_selector/add_expression_button.rs +1 -0
- package/src/rust/components/column_selector/aggregate_selector.rs +25 -15
- package/src/rust/components/column_selector/config_selector.rs +374 -185
- package/src/rust/components/column_selector/empty_column.rs +2 -2
- package/src/rust/components/column_selector/expr_edit_button.rs +8 -2
- package/src/rust/components/column_selector/filter_column.rs +37 -26
- package/src/rust/components/column_selector/inactive_column.rs +41 -29
- package/src/rust/components/column_selector/invalid_column.rs +7 -18
- package/src/rust/components/column_selector/pivot_column.rs +21 -10
- package/src/rust/components/column_selector/sort_column.rs +23 -13
- package/src/rust/components/column_selector.rs +189 -100
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +3 -2
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs_item.rs +3 -2
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +2 -3
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +7 -1
- package/src/rust/components/column_settings_sidebar/style_tab.rs +153 -112
- package/src/rust/components/column_settings_sidebar.rs +91 -53
- package/src/rust/components/containers/dragdrop_list.rs +29 -7
- package/src/rust/components/containers/scroll_panel.rs +8 -1
- package/src/rust/components/containers/select.rs +3 -3
- package/src/rust/components/containers/sidebar_close_button.rs +1 -1
- package/src/rust/components/containers/split_panel.rs +3 -2
- package/src/rust/components/containers/tab_list.rs +1 -1
- package/src/rust/components/copy_dropdown.rs +7 -28
- package/src/rust/components/datetime_column_style/custom.rs +2 -2
- package/src/rust/components/datetime_column_style/simple.rs +2 -2
- package/src/rust/components/datetime_column_style.rs +4 -2
- package/src/rust/components/editable_header.rs +7 -4
- package/src/rust/components/empty_row.rs +1 -1
- package/src/rust/components/export_dropdown.rs +4 -30
- package/src/rust/components/expression_editor.rs +19 -10
- package/src/rust/components/filter_dropdown.rs +246 -102
- package/src/rust/components/font_loader.rs +11 -28
- package/src/rust/components/form/code_editor.rs +17 -2
- package/src/rust/components/form/color_range_selector.rs +19 -6
- package/src/rust/components/form/debug.rs +30 -13
- package/src/rust/components/function_dropdown.rs +186 -113
- package/src/rust/components/main_panel.rs +71 -89
- package/src/rust/components/mod.rs +1 -1
- package/src/rust/components/modal.rs +7 -1
- package/src/rust/components/number_column_style.rs +22 -7
- package/src/rust/components/plugin_selector.rs +34 -92
- package/src/rust/components/portal.rs +274 -0
- package/src/rust/components/render_warning.rs +72 -123
- package/src/rust/components/settings_panel.rs +115 -11
- package/src/rust/components/status_bar.rs +222 -98
- package/src/rust/components/status_bar_counter.rs +8 -20
- package/src/rust/components/status_indicator.rs +64 -111
- package/src/rust/components/string_column_style.rs +2 -2
- package/src/rust/components/style/style_cache.rs +5 -1
- package/src/rust/components/viewer.rs +391 -39
- package/src/rust/custom_elements/copy_dropdown.rs +102 -21
- package/src/rust/custom_elements/export_dropdown.rs +102 -20
- package/src/rust/custom_elements/mod.rs +0 -7
- package/src/rust/custom_elements/modal.rs +7 -103
- package/src/rust/custom_elements/viewer.rs +99 -35
- package/src/rust/custom_events.rs +23 -2
- package/src/rust/dragdrop.rs +149 -10
- package/src/{less/containers/scroll-panel.less → rust/engines.rs} +15 -13
- package/src/rust/js/plugin.rs +20 -1
- package/src/rust/lib.rs +5 -4
- package/src/rust/presentation/props.rs +39 -0
- package/src/rust/presentation/sheets.rs +3 -3
- package/src/rust/presentation.rs +44 -8
- package/src/rust/renderer/limits.rs +32 -3
- package/src/{less/dom/scrollbar.less → rust/renderer/props.rs} +18 -19
- package/src/rust/renderer/registry.rs +8 -1
- package/src/rust/renderer.rs +83 -9
- package/src/rust/session/column_defaults_update.rs +18 -0
- package/src/rust/session/metadata.rs +23 -2
- package/src/rust/session/props.rs +178 -0
- package/src/rust/session/replace_expression_update.rs +1 -0
- package/src/rust/session.rs +124 -117
- package/src/rust/tasks/column_locator.rs +133 -0
- package/src/rust/{model → tasks}/columns_iter_set.rs +14 -23
- package/src/rust/{model → tasks}/edit_expression.rs +34 -10
- package/src/rust/{model → tasks}/eject.rs +2 -2
- package/src/rust/{model → tasks}/get_viewer_config.rs +0 -11
- package/src/rust/{model → tasks}/intersection_observer.rs +22 -4
- package/src/{less/containers/radio-list.less → rust/tasks/is_invalid_drop.rs} +21 -14
- package/src/rust/tasks/mod.rs +52 -0
- package/src/rust/{model → tasks}/plugin_column_styles.rs +69 -46
- package/src/rust/{model → tasks}/resize_observer.rs +39 -6
- package/src/rust/{model → tasks}/send_plugin_config.rs +1 -1
- package/src/rust/tasks/structural.rs +53 -0
- package/src/rust/utils/mod.rs +4 -0
- package/src/rust/utils/modal_position.rs +110 -0
- package/src/rust/utils/ptr_eq_rc.rs +74 -0
- package/src/rust/utils/pubsub.rs +11 -1
- package/src/svg/bg-pattern.png +0 -0
- package/src/svg/close-icon.svg +1 -1
- package/src/svg/expression.svg +1 -1
- package/src/svg/mega-menu-icons-candlestick.svg +1 -1
- package/src/svg/mega-menu-icons-datagrid.svg +1 -2
- package/src/svg/mega-menu-icons-heatmap.svg +1 -1
- package/src/svg/mega-menu-icons-map-scatter.svg +1 -1
- package/src/svg/mega-menu-icons-ohlc.svg +1 -1
- package/src/svg/mega-menu-icons-sunburst.svg +1 -1
- package/src/svg/mega-menu-icons-treemap.svg +1 -1
- package/src/svg/mega-menu-icons-x-bar.svg +1 -1
- package/src/svg/mega-menu-icons-x-y-line.svg +1 -1
- package/src/svg/mega-menu-icons-x-y-scatter.svg +1 -1
- package/src/svg/mega-menu-icons-y-area.svg +1 -1
- package/src/svg/mega-menu-icons-y-bar.svg +1 -1
- package/src/svg/mega-menu-icons-y-line.svg +1 -1
- package/src/svg/mega-menu-icons-y-scatter.svg +1 -1
- package/src/svg/radio-hover.svg +1 -1
- package/src/svg/radio-off.svg +1 -1
- package/src/svg/radio-on.svg +1 -1
- package/src/themes/botanical.css +157 -0
- package/src/themes/defaults.css +139 -0
- package/src/themes/dracula.css +233 -0
- package/src/themes/gruvbox-dark.css +255 -0
- package/src/themes/gruvbox.css +134 -0
- package/src/themes/icons.css +124 -0
- package/src/themes/intl/de.css +102 -0
- package/src/themes/intl/es.css +102 -0
- package/src/themes/intl/fr.css +102 -0
- package/src/themes/intl/ja.css +102 -0
- package/src/themes/intl/pt.css +102 -0
- package/src/themes/intl/zh.css +102 -0
- package/src/themes/intl.css +102 -0
- package/src/themes/monokai.css +233 -0
- package/src/themes/pro-dark.css +158 -0
- package/src/themes/{themes.less → pro.css} +17 -20
- package/src/themes/solarized-dark.css +135 -0
- package/src/themes/solarized.css +95 -0
- package/src/themes/themes.css +22 -0
- package/src/themes/vaporwave.css +256 -0
- package/src/ts/extensions.ts +73 -2
- package/src/ts/perspective-viewer.ts +1 -0
- package/src/ts/ts-rs/GroupRollupMode.ts +3 -0
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +2 -1
- package/tsconfig.json +1 -0
- package/dist/css/variables.css +0 -0
- package/src/less/column-dropdown.less +0 -95
- package/src/less/config-selector.less +0 -363
- package/src/less/dom/checkbox.less +0 -100
- package/src/less/plugin-selector.less +0 -183
- package/src/less/type-icon.less +0 -68
- package/src/rust/components/error_message.rs +0 -56
- package/src/rust/custom_elements/column_dropdown.rs +0 -123
- package/src/rust/custom_elements/filter_dropdown.rs +0 -179
- package/src/rust/custom_elements/function_dropdown.rs +0 -115
- package/src/rust/model/column_locator.rs +0 -82
- package/src/rust/model/is_invalid_drop.rs +0 -36
- package/src/rust/model/mod.rs +0 -100
- package/src/rust/model/reset_all.rs +0 -38
- package/src/rust/model/structural.rs +0 -244
- package/src/themes/dracula.less +0 -101
- package/src/themes/gruvbox-dark.less +0 -116
- package/src/themes/gruvbox.less +0 -152
- package/src/themes/icons.less +0 -130
- package/src/themes/intl/de.less +0 -102
- package/src/themes/intl/es.less +0 -102
- package/src/themes/intl/fr.less +0 -102
- package/src/themes/intl/ja.less +0 -102
- package/src/themes/intl/pt.less +0 -102
- package/src/themes/intl/zh.less +0 -102
- package/src/themes/intl.less +0 -102
- package/src/themes/monokai.less +0 -107
- package/src/themes/pro-dark.less +0 -147
- package/src/themes/pro.less +0 -186
- package/src/themes/solarized-dark.less +0 -78
- package/src/themes/solarized.less +0 -102
- package/src/themes/vaporwave.less +0 -145
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-1586156e058be573 → perspective-viewer-68fef752754ffbc6}/inline4.js +0 -0
- /package/src/rust/{model → tasks}/copy_export.rs +0 -0
- /package/src/rust/{model → tasks}/export_app.rs +0 -0
- /package/src/rust/{model → tasks}/export_method.rs +0 -0
- /package/src/rust/{model → tasks}/restore_and_render.rs +0 -0
- /package/src/rust/{model → tasks}/update_and_render.rs +0 -0
package/src/rust/lib.rs
CHANGED
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
// Required by yew's `html` macro.
|
|
17
17
|
#![recursion_limit = "1024"]
|
|
18
18
|
#![feature(const_type_name)]
|
|
19
|
-
#![feature(macro_metavar_expr)]
|
|
20
19
|
#![feature(iter_intersperse)]
|
|
21
20
|
#![feature(stmt_expr_attributes)]
|
|
22
21
|
#![feature(try_blocks)]
|
|
@@ -39,11 +38,12 @@ pub mod exprtk;
|
|
|
39
38
|
mod js;
|
|
40
39
|
mod root;
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
pub mod model;
|
|
41
|
+
pub mod engines;
|
|
44
42
|
mod presentation;
|
|
45
43
|
mod renderer;
|
|
46
44
|
mod session;
|
|
45
|
+
#[doc(hidden)]
|
|
46
|
+
pub mod tasks;
|
|
47
47
|
pub mod utils;
|
|
48
48
|
|
|
49
49
|
#[macro_use]
|
|
@@ -67,6 +67,7 @@ import type {
|
|
|
67
67
|
ColumnWindow,
|
|
68
68
|
ViewWindow,
|
|
69
69
|
OnUpdateOptions,
|
|
70
|
+
JoinOptions,
|
|
70
71
|
UpdateOptions,
|
|
71
72
|
DeleteOptions,
|
|
72
73
|
ViewConfigUpdate,
|
|
@@ -106,8 +107,8 @@ pub fn js_init() {
|
|
|
106
107
|
pub fn bootstrap_web_components(psp: &JsValue) {
|
|
107
108
|
define_web_component::<PerspectiveViewerElement>(psp);
|
|
108
109
|
define_web_component::<PerspectiveDebugPluginElement>(psp);
|
|
109
|
-
define_web_component::<ExportDropDownMenuElement>(psp);
|
|
110
110
|
define_web_component::<CopyDropDownMenuElement>(psp);
|
|
111
|
+
define_web_component::<ExportDropDownMenuElement>(psp);
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
/// Defining the web components needs an extern struct to reference the
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
use crate::presentation::OpenColumnSettings;
|
|
14
|
+
use crate::utils::PtrEqRc;
|
|
15
|
+
|
|
16
|
+
/// Value-semantic snapshot of the presentation/UI state used by the root
|
|
17
|
+
/// component to drive `is_settings_open`, `selected_theme`, and
|
|
18
|
+
/// `available_themes` into child components via plain props.
|
|
19
|
+
///
|
|
20
|
+
/// The `HtmlElement` handle, async theme-detection machinery, column-settings
|
|
21
|
+
/// state, and per-column config live in `PresentationEngine` and are not
|
|
22
|
+
/// passed as props.
|
|
23
|
+
#[derive(Clone, Debug, PartialEq, Default)]
|
|
24
|
+
pub struct PresentationProps {
|
|
25
|
+
/// Whether the settings panel is currently open.
|
|
26
|
+
pub is_settings_open: bool,
|
|
27
|
+
|
|
28
|
+
/// Detected theme names, in discovery order.
|
|
29
|
+
pub available_themes: PtrEqRc<Vec<String>>,
|
|
30
|
+
|
|
31
|
+
/// The currently selected theme name, if any theme is active.
|
|
32
|
+
pub selected_theme: Option<String>,
|
|
33
|
+
|
|
34
|
+
/// Snapshot of the currently opened column-settings sidebar state.
|
|
35
|
+
pub open_column_settings: OpenColumnSettings,
|
|
36
|
+
|
|
37
|
+
/// Whether this viewer is hosted inside a `<perspective-workspace>`.
|
|
38
|
+
pub is_workspace: bool,
|
|
39
|
+
}
|
|
@@ -21,7 +21,7 @@ macro_rules! iter_index {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/// Search the document's `styleSheets` for rules which apply to `elem` and
|
|
24
|
-
/// provide the `--theme-name` CSS custom property.
|
|
24
|
+
/// provide the `--psp-theme-name` CSS custom property.
|
|
25
25
|
pub fn get_theme_names(elem: &HtmlElement) -> Result<Vec<String>, JsValue> {
|
|
26
26
|
let sheets = global::document().style_sheets();
|
|
27
27
|
let mut themes: Vec<String> = vec![];
|
|
@@ -43,8 +43,8 @@ fn fill_rule_theme_names(
|
|
|
43
43
|
let style = rule.style();
|
|
44
44
|
let x = (0..style.length()).map(|x| style.item(x));
|
|
45
45
|
for property in x {
|
|
46
|
-
if property == "--theme-name" {
|
|
47
|
-
let name = style.get_property_value("--theme-name")?;
|
|
46
|
+
if property == "--psp-theme-name" {
|
|
47
|
+
let name = style.get_property_value("--psp-theme-name")?;
|
|
48
48
|
let trimmed = name.trim();
|
|
49
49
|
let theme = &trimmed[1..trimmed.len() - 1];
|
|
50
50
|
if themes.iter().find(|x| x == &theme).is_none() {
|
package/src/rust/presentation.rs
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
13
|
mod column_locator;
|
|
14
|
+
mod props;
|
|
14
15
|
mod sheets;
|
|
15
16
|
|
|
16
17
|
use std::cell::RefCell;
|
|
@@ -20,11 +21,12 @@ use std::rc::Rc;
|
|
|
20
21
|
|
|
21
22
|
use async_lock::Mutex;
|
|
22
23
|
use perspective_js::utils::{ApiFuture, ApiResult};
|
|
23
|
-
use wasm_bindgen::prelude::*;
|
|
24
24
|
use web_sys::*;
|
|
25
25
|
use yew::html::ImplicitClone;
|
|
26
|
+
use yew::prelude::*;
|
|
26
27
|
|
|
27
28
|
pub use self::column_locator::{ColumnLocator, ColumnSettingsTab, ColumnTab, OpenColumnSettings};
|
|
29
|
+
pub use self::props::PresentationProps;
|
|
28
30
|
use crate::config::{ColumnConfigUpdate, ColumnConfigValueUpdate, ColumnConfigValues};
|
|
29
31
|
use crate::utils::*;
|
|
30
32
|
|
|
@@ -48,11 +50,13 @@ pub struct PresentationHandle {
|
|
|
48
50
|
columns_config: RefCell<ColumnConfigMap>,
|
|
49
51
|
is_workspace: RefCell<Option<bool>>,
|
|
50
52
|
pub settings_open_changed: PubSub<bool>,
|
|
53
|
+
|
|
54
|
+
/// Injected callback from the root component, replacing the former
|
|
55
|
+
/// `is_workspace_changed: PubSub` field.
|
|
56
|
+
pub on_is_workspace_changed: RefCell<Option<Callback<bool>>>,
|
|
51
57
|
pub settings_before_open_changed: PubSub<bool>,
|
|
52
58
|
pub column_settings_open_changed: PubSub<(bool, Option<String>)>,
|
|
53
|
-
pub
|
|
54
|
-
pub theme_config_updated: PubSub<(Rc<Vec<String>>, Option<usize>)>,
|
|
55
|
-
pub visibility_changed: PubSub<bool>,
|
|
59
|
+
pub theme_config_updated: PubSub<(PtrEqRc<Vec<String>>, Option<usize>)>,
|
|
56
60
|
pub on_eject: PubSub<()>,
|
|
57
61
|
}
|
|
58
62
|
|
|
@@ -86,13 +90,12 @@ impl Presentation {
|
|
|
86
90
|
settings_open_changed: Default::default(),
|
|
87
91
|
settings_before_open_changed: Default::default(),
|
|
88
92
|
column_settings_open_changed: Default::default(),
|
|
89
|
-
|
|
93
|
+
on_is_workspace_changed: Default::default(),
|
|
90
94
|
columns_config: Default::default(),
|
|
91
95
|
is_settings_open: Default::default(),
|
|
92
96
|
open_column_settings: Default::default(),
|
|
93
97
|
theme_config_updated: PubSub::default(),
|
|
94
98
|
on_eject: PubSub::default(),
|
|
95
|
-
visibility_changed: PubSub::default(),
|
|
96
99
|
}));
|
|
97
100
|
|
|
98
101
|
ApiFuture::spawn(theme.clone().init());
|
|
@@ -110,6 +113,13 @@ impl Presentation {
|
|
|
110
113
|
elem.is_some() && &self.viewer_elem.shadow_root().unwrap().active_element() == elem
|
|
111
114
|
}
|
|
112
115
|
|
|
116
|
+
pub fn reset_attached(&self) {
|
|
117
|
+
*self.0.is_workspace.borrow_mut() = None;
|
|
118
|
+
if let Some(cb) = self.on_is_workspace_changed.borrow().as_ref() {
|
|
119
|
+
cb.emit(self.get_is_workspace());
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
113
123
|
pub fn get_is_workspace(&self) -> bool {
|
|
114
124
|
if self.is_workspace.borrow().is_none() {
|
|
115
125
|
if !self.viewer_elem.is_connected() {
|
|
@@ -174,7 +184,7 @@ impl Presentation {
|
|
|
174
184
|
/// Get the available theme names from the browser environment by parsing
|
|
175
185
|
/// readable stylesheets. This method is memoized - the state can be
|
|
176
186
|
/// flushed by calling `reset()`.
|
|
177
|
-
pub async fn get_available_themes(&self) -> ApiResult<
|
|
187
|
+
pub async fn get_available_themes(&self) -> ApiResult<PtrEqRc<Vec<String>>> {
|
|
178
188
|
let mut data = self.0.theme_data.lock().await;
|
|
179
189
|
if data.themes.is_none() {
|
|
180
190
|
await_dom_loaded().await?;
|
|
@@ -203,7 +213,9 @@ impl Presentation {
|
|
|
203
213
|
changed
|
|
204
214
|
}
|
|
205
215
|
|
|
206
|
-
pub async fn get_selected_theme_config(
|
|
216
|
+
pub async fn get_selected_theme_config(
|
|
217
|
+
&self,
|
|
218
|
+
) -> ApiResult<(PtrEqRc<Vec<String>>, Option<usize>)> {
|
|
207
219
|
let themes = self.get_available_themes().await?;
|
|
208
220
|
let name = self.0.viewer_elem.get_attribute("theme");
|
|
209
221
|
let index = name
|
|
@@ -308,4 +320,28 @@ impl Presentation {
|
|
|
308
320
|
config.insert(column_name, update);
|
|
309
321
|
}
|
|
310
322
|
}
|
|
323
|
+
|
|
324
|
+
/// Snapshot the current presentation state as a [`PresentationProps`]
|
|
325
|
+
/// value suitable for passing as a Yew prop. Called by the root component
|
|
326
|
+
/// whenever a presentation-related PubSub event fires.
|
|
327
|
+
///
|
|
328
|
+
/// `available_themes` must be provided by the caller because theme
|
|
329
|
+
/// detection is async and therefore not available synchronously here.
|
|
330
|
+
pub fn to_props(&self, available_themes: PtrEqRc<Vec<String>>) -> PresentationProps {
|
|
331
|
+
let theme_attr = self.0.viewer_elem.get_attribute("theme");
|
|
332
|
+
let selected_theme = theme_attr.as_deref().and_then(|name| {
|
|
333
|
+
available_themes
|
|
334
|
+
.iter()
|
|
335
|
+
.find(|x| x.as_str() == name)
|
|
336
|
+
.cloned()
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
PresentationProps {
|
|
340
|
+
is_settings_open: self.is_settings_open(),
|
|
341
|
+
available_themes,
|
|
342
|
+
selected_theme,
|
|
343
|
+
open_column_settings: self.get_open_column_settings(),
|
|
344
|
+
is_workspace: self.get_is_workspace(),
|
|
345
|
+
}
|
|
346
|
+
}
|
|
311
347
|
}
|
|
@@ -14,15 +14,38 @@ use perspective_js::utils::ApiError;
|
|
|
14
14
|
|
|
15
15
|
use crate::js::plugin::*;
|
|
16
16
|
|
|
17
|
+
/// The row/column limits computed for the current view and plugin
|
|
18
|
+
/// configuration.
|
|
19
|
+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
|
20
|
+
pub struct RenderLimits {
|
|
21
|
+
/// Whether this render was an incremental update (`true`) or a full
|
|
22
|
+
/// draw (`false`).
|
|
23
|
+
pub is_update: bool,
|
|
24
|
+
/// Total number of columns in the view.
|
|
25
|
+
pub num_cols: usize,
|
|
26
|
+
/// Total number of rows in the view.
|
|
27
|
+
pub num_rows: usize,
|
|
28
|
+
/// Maximum number of columns the plugin will render, if capped.
|
|
29
|
+
pub max_cols: Option<usize>,
|
|
30
|
+
/// Maximum number of rows the plugin will render, if capped.
|
|
31
|
+
pub max_rows: Option<usize>,
|
|
32
|
+
}
|
|
33
|
+
|
|
17
34
|
pub async fn get_row_and_col_limits(
|
|
18
35
|
view: &perspective_client::View,
|
|
19
36
|
plugin_metadata: &ViewConfigRequirements,
|
|
20
|
-
) -> Result<
|
|
37
|
+
) -> Result<RenderLimits, ApiError> {
|
|
21
38
|
let dimensions = view.dimensions().await?;
|
|
22
39
|
let num_cols = dimensions.num_view_columns as usize;
|
|
23
40
|
let num_rows = dimensions.num_view_rows as usize;
|
|
24
41
|
match (plugin_metadata.max_columns, plugin_metadata.render_warning) {
|
|
25
|
-
(Some(_), false) => Ok(
|
|
42
|
+
(Some(_), false) => Ok(RenderLimits {
|
|
43
|
+
is_update: false,
|
|
44
|
+
num_cols,
|
|
45
|
+
num_rows,
|
|
46
|
+
max_cols: None,
|
|
47
|
+
max_rows: None,
|
|
48
|
+
}),
|
|
26
49
|
(max_columns, _) => {
|
|
27
50
|
let schema = view.schema().await?;
|
|
28
51
|
let keys = schema.keys();
|
|
@@ -45,7 +68,13 @@ pub async fn get_row_and_col_limits(
|
|
|
45
68
|
.ceil() as usize
|
|
46
69
|
});
|
|
47
70
|
|
|
48
|
-
Ok(
|
|
71
|
+
Ok(RenderLimits {
|
|
72
|
+
is_update: false,
|
|
73
|
+
num_cols,
|
|
74
|
+
num_rows,
|
|
75
|
+
max_cols,
|
|
76
|
+
max_rows,
|
|
77
|
+
})
|
|
49
78
|
},
|
|
50
79
|
}
|
|
51
80
|
}
|
|
@@ -10,26 +10,25 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
13
|
+
use crate::js::plugin::ViewConfigRequirements;
|
|
14
|
+
use crate::renderer::limits::RenderLimits;
|
|
15
|
+
use crate::utils::PtrEqRc;
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
/// Value-semantic snapshot of the renderer state read by components.
|
|
18
|
+
///
|
|
19
|
+
/// The actual plugin JS objects, draw lock, and render timer live in
|
|
20
|
+
/// `RendererEngine` and are not passed as props.
|
|
21
|
+
#[derive(Clone, Debug, PartialEq, Default)]
|
|
22
|
+
pub struct RendererProps {
|
|
23
|
+
/// Name of the currently active plugin (e.g. `"Datagrid"`).
|
|
24
|
+
pub plugin_name: Option<String>,
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
box-shadow: inset 0px 0px 0 4px var(--inactive--color);
|
|
27
|
-
}
|
|
26
|
+
/// Column count / config requirements reported by the active plugin.
|
|
27
|
+
pub requirements: ViewConfigRequirements,
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
29
|
+
/// Most recently emitted render limits, if any.
|
|
30
|
+
pub render_limits: Option<RenderLimits>,
|
|
31
|
+
|
|
32
|
+
/// Names of all registered plugins, in registration order.
|
|
33
|
+
pub available_plugins: PtrEqRc<Vec<String>>,
|
|
35
34
|
}
|
|
@@ -102,7 +102,14 @@ pub impl LocalKey<Rc<RefCell<Vec<PluginRecord>>>> {
|
|
|
102
102
|
.unwrap_or_else(|| "Custom".to_owned()),
|
|
103
103
|
priority: plugin_inst.priority().unwrap_or_default(),
|
|
104
104
|
};
|
|
105
|
+
|
|
105
106
|
let mut plugins = plugin.borrow_mut();
|
|
107
|
+
if let Some(first) = plugins.first()
|
|
108
|
+
&& first.tag_name.as_str() == "perspective-viewer-plugin"
|
|
109
|
+
{
|
|
110
|
+
plugins.clear();
|
|
111
|
+
}
|
|
112
|
+
|
|
106
113
|
plugins.push(record);
|
|
107
114
|
plugins.sort_by(|a, b| Ord::cmp(&b.priority, &a.priority));
|
|
108
115
|
});
|
|
@@ -121,7 +128,7 @@ fn register_default() {
|
|
|
121
128
|
name: "Debug".to_owned(),
|
|
122
129
|
category: "Custom".to_owned(),
|
|
123
130
|
tag_name: "perspective-viewer-plugin".to_owned(),
|
|
124
|
-
priority:
|
|
131
|
+
priority: -1,
|
|
125
132
|
})
|
|
126
133
|
}
|
|
127
134
|
})
|
package/src/rust/renderer.rs
CHANGED
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
//! references throughout the application.
|
|
19
19
|
|
|
20
20
|
mod activate;
|
|
21
|
-
mod limits;
|
|
21
|
+
pub mod limits;
|
|
22
22
|
mod plugin_store;
|
|
23
|
+
mod props;
|
|
23
24
|
mod registry;
|
|
24
25
|
mod render_timer;
|
|
25
26
|
|
|
@@ -38,10 +39,13 @@ use perspective_js::utils::ApiResult;
|
|
|
38
39
|
use wasm_bindgen::prelude::*;
|
|
39
40
|
use web_sys::*;
|
|
40
41
|
use yew::html::ImplicitClone;
|
|
42
|
+
use yew::prelude::*;
|
|
41
43
|
|
|
42
44
|
use self::activate::*;
|
|
45
|
+
pub use self::limits::RenderLimits;
|
|
43
46
|
use self::limits::*;
|
|
44
47
|
use self::plugin_store::*;
|
|
48
|
+
pub use self::props::RendererProps;
|
|
45
49
|
pub use self::registry::*;
|
|
46
50
|
use self::render_timer::*;
|
|
47
51
|
use crate::config::*;
|
|
@@ -54,9 +58,13 @@ pub struct RendererData {
|
|
|
54
58
|
plugin_data: RefCell<RendererMutData>,
|
|
55
59
|
draw_lock: DebounceMutex,
|
|
56
60
|
pub plugin_changed: PubSub<JsPerspectiveViewerPlugin>,
|
|
57
|
-
pub render_limits_changed: PubSub<(bool, RenderLimits)>,
|
|
58
61
|
pub style_changed: PubSub<()>,
|
|
59
62
|
pub reset_changed: PubSub<()>,
|
|
63
|
+
|
|
64
|
+
/// Injected callback from the root component, replacing the former
|
|
65
|
+
/// `render_limits_changed: PubSub` field. Fires after every draw/update
|
|
66
|
+
/// with the computed render limits.
|
|
67
|
+
pub on_render_limits_changed: RefCell<Option<Callback<RenderLimits>>>,
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
/// Mutable state
|
|
@@ -70,8 +78,6 @@ pub struct RendererMutData {
|
|
|
70
78
|
pending_plugin: Option<usize>,
|
|
71
79
|
}
|
|
72
80
|
|
|
73
|
-
type RenderLimits = (usize, usize, Option<usize>, Option<usize>);
|
|
74
|
-
|
|
75
81
|
/// The state object responsible for the active [`JsPerspectiveViewerPlugin`].
|
|
76
82
|
#[derive(Clone)]
|
|
77
83
|
pub struct Renderer(Rc<RendererData>);
|
|
@@ -120,9 +126,9 @@ impl Renderer {
|
|
|
120
126
|
}),
|
|
121
127
|
draw_lock: Default::default(),
|
|
122
128
|
plugin_changed: Default::default(),
|
|
123
|
-
render_limits_changed: Default::default(),
|
|
124
129
|
style_changed: Default::default(),
|
|
125
130
|
reset_changed: Default::default(),
|
|
131
|
+
on_render_limits_changed: Default::default(),
|
|
126
132
|
}))
|
|
127
133
|
}
|
|
128
134
|
|
|
@@ -322,6 +328,31 @@ impl Renderer {
|
|
|
322
328
|
.await
|
|
323
329
|
}
|
|
324
330
|
|
|
331
|
+
pub async fn resize_with_dimensions(&self, width: f64, height: f64) -> ApiResult<()> {
|
|
332
|
+
let draw_mutex = self.draw_lock();
|
|
333
|
+
let timer = self.render_timer();
|
|
334
|
+
draw_mutex
|
|
335
|
+
.debounce(async {
|
|
336
|
+
set_timeout(timer.get_throttle()).await?;
|
|
337
|
+
let plugin = self.get_active_plugin()?;
|
|
338
|
+
let main_panel: &web_sys::HtmlElement = plugin.unchecked_ref();
|
|
339
|
+
let rect = main_panel.get_bounding_client_rect();
|
|
340
|
+
if (height - rect.height()).abs() > 0.5 || (width - rect.width()).abs() > 0.5 {
|
|
341
|
+
let new_width = format!("{}px", width);
|
|
342
|
+
let new_height = format!("{}px", height);
|
|
343
|
+
main_panel.style().set_property("width", &new_width)?;
|
|
344
|
+
main_panel.style().set_property("height", &new_height)?;
|
|
345
|
+
let result = plugin.resize().await;
|
|
346
|
+
main_panel.style().set_property("width", "")?;
|
|
347
|
+
main_panel.style().set_property("height", "")?;
|
|
348
|
+
result?;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
Ok(())
|
|
352
|
+
})
|
|
353
|
+
.await
|
|
354
|
+
}
|
|
355
|
+
|
|
325
356
|
/// This will take a future which _should_ create a new view and then will
|
|
326
357
|
/// draw it. As the `session` closure is asynchronous, it can be cancelled
|
|
327
358
|
/// by returning `None`.
|
|
@@ -367,14 +398,17 @@ impl Renderer {
|
|
|
367
398
|
async fn draw_view(&self, view: &perspective_client::View, is_update: bool) -> ApiResult<()> {
|
|
368
399
|
let plugin = self.get_active_plugin()?;
|
|
369
400
|
let meta = self.metadata().clone();
|
|
370
|
-
let limits = get_row_and_col_limits(view, &meta).await?;
|
|
371
|
-
|
|
401
|
+
let mut limits = get_row_and_col_limits(view, &meta).await?;
|
|
402
|
+
limits.is_update = is_update;
|
|
403
|
+
if let Some(cb) = self.0.on_render_limits_changed.borrow().as_ref() {
|
|
404
|
+
cb.emit(limits);
|
|
405
|
+
}
|
|
372
406
|
let viewer_elem = &self.0.borrow().viewer_elem.clone();
|
|
373
407
|
if is_update {
|
|
374
|
-
let task = plugin.update(view.clone().into(), limits.
|
|
408
|
+
let task = plugin.update(view.clone().into(), limits.max_cols, limits.max_rows, false);
|
|
375
409
|
activate_plugin(viewer_elem, &plugin, task).await?;
|
|
376
410
|
} else {
|
|
377
|
-
let task = plugin.draw(view.clone().into(), limits.
|
|
411
|
+
let task = plugin.draw(view.clone().into(), limits.max_cols, limits.max_rows, false);
|
|
378
412
|
activate_plugin(viewer_elem, &plugin, task).await?;
|
|
379
413
|
}
|
|
380
414
|
|
|
@@ -477,3 +511,43 @@ fn make_short_name(name: &str) -> String {
|
|
|
477
511
|
.filter(|x| x.is_alphabetic())
|
|
478
512
|
.collect()
|
|
479
513
|
}
|
|
514
|
+
|
|
515
|
+
impl Renderer {
|
|
516
|
+
/// Snapshot the current renderer state as a [`RendererProps`] value
|
|
517
|
+
/// suitable for passing as a Yew prop. Called by the root component
|
|
518
|
+
/// whenever a renderer-related PubSub event fires.
|
|
519
|
+
pub fn to_props(&self, render_limits: Option<RenderLimits>) -> RendererProps {
|
|
520
|
+
// Guard: don't touch the PluginStore if no plugin has been explicitly
|
|
521
|
+
// selected yet. Calling `get_active_plugin()` or `get_all_plugins()`
|
|
522
|
+
// triggers `PluginStore::init_lazy()`, which snapshots the
|
|
523
|
+
// PLUGIN_REGISTRY. If this happens during component `create()` —
|
|
524
|
+
// before JavaScript has called `registerPlugin()` — the cache will
|
|
525
|
+
// only contain the default Debug plugin and custom plugins registered
|
|
526
|
+
// later will never be found.
|
|
527
|
+
let has_plugin = self.0.borrow().plugins_idx.is_some();
|
|
528
|
+
if has_plugin {
|
|
529
|
+
let plugin_name = self.get_active_plugin().ok().map(|p| p.name());
|
|
530
|
+
let requirements = self.metadata().clone();
|
|
531
|
+
let available_plugins = self
|
|
532
|
+
.get_all_plugins()
|
|
533
|
+
.into_iter()
|
|
534
|
+
.map(|p| p.name())
|
|
535
|
+
.collect::<Vec<_>>()
|
|
536
|
+
.into();
|
|
537
|
+
|
|
538
|
+
RendererProps {
|
|
539
|
+
plugin_name,
|
|
540
|
+
requirements,
|
|
541
|
+
render_limits,
|
|
542
|
+
available_plugins,
|
|
543
|
+
}
|
|
544
|
+
} else {
|
|
545
|
+
RendererProps {
|
|
546
|
+
plugin_name: None,
|
|
547
|
+
requirements: ViewConfigRequirements::default(),
|
|
548
|
+
render_limits,
|
|
549
|
+
available_plugins: PtrEqRc::new(vec![]),
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
@@ -31,6 +31,24 @@ pub impl ViewConfigUpdate {
|
|
|
31
31
|
columns: &[Option<String>],
|
|
32
32
|
requirements: &ViewConfigRequirements,
|
|
33
33
|
) {
|
|
34
|
+
let rollup_features = metadata
|
|
35
|
+
.get_features()
|
|
36
|
+
.map(|x| x.get_group_rollup_modes())
|
|
37
|
+
.unwrap_or_default();
|
|
38
|
+
|
|
39
|
+
let group_rollups = requirements.get_group_rollups(&rollup_features);
|
|
40
|
+
if !group_rollups.contains(
|
|
41
|
+
self.group_rollup_mode
|
|
42
|
+
.as_ref()
|
|
43
|
+
.unwrap_or(&GroupRollupMode::Rollup),
|
|
44
|
+
) {
|
|
45
|
+
self.group_rollup_mode = group_rollups.first().cloned();
|
|
46
|
+
tracing::debug!(
|
|
47
|
+
"Setting plugin-advised rollup mode {:?}",
|
|
48
|
+
self.group_rollup_mode
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
34
52
|
if let (
|
|
35
53
|
None,
|
|
36
54
|
ViewConfigRequirements {
|
|
@@ -17,8 +17,10 @@ use std::ops::{Deref, DerefMut};
|
|
|
17
17
|
use perspective_client::config::*;
|
|
18
18
|
use perspective_js::apierror;
|
|
19
19
|
|
|
20
|
+
use crate::utils::PtrEqRc;
|
|
20
21
|
use crate::*;
|
|
21
22
|
|
|
23
|
+
#[derive(Clone, PartialEq)]
|
|
22
24
|
struct SessionViewExpressionMetadata {
|
|
23
25
|
edited: HashMap<String, String>,
|
|
24
26
|
expressions: perspective_client::ExprValidationResult,
|
|
@@ -28,9 +30,17 @@ struct SessionViewExpressionMetadata {
|
|
|
28
30
|
/// do so without `async`. It must be recreated by any `async` method which
|
|
29
31
|
/// changes the `View` and may temporarily be out-of-sync with the
|
|
30
32
|
/// `View`/`ViewConfig`.
|
|
31
|
-
#[derive(Default)]
|
|
33
|
+
#[derive(Clone, Default, PartialEq)]
|
|
32
34
|
pub struct SessionMetadata(Option<SessionMetadataState>);
|
|
33
35
|
|
|
36
|
+
pub type SessionMetadataRc = PtrEqRc<SessionMetadata>;
|
|
37
|
+
|
|
38
|
+
impl std::fmt::Debug for SessionMetadata {
|
|
39
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
40
|
+
f.write_str("SessionMetadata { .. }")
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
impl Deref for SessionMetadata {
|
|
35
45
|
type Target = Option<SessionMetadataState>;
|
|
36
46
|
|
|
@@ -50,7 +60,7 @@ pub type MetadataMutRef<'a> = std::cell::RefMut<'a, SessionMetadata>;
|
|
|
50
60
|
|
|
51
61
|
/// TODO the multiple `Option` types could probably be merged since they are
|
|
52
62
|
/// populated within an async lock
|
|
53
|
-
#[derive(Default)]
|
|
63
|
+
#[derive(Clone, Default, PartialEq)]
|
|
54
64
|
pub struct SessionMetadataState {
|
|
55
65
|
features: perspective_client::Features,
|
|
56
66
|
column_names: Vec<String>,
|
|
@@ -118,6 +128,17 @@ impl SessionMetadata {
|
|
|
118
128
|
|
|
119
129
|
/// Returns the unique column names in this session that are expression
|
|
120
130
|
/// columns.
|
|
131
|
+
pub fn get_expression_schema(&self) -> Option<&HashMap<String, ColumnType>> {
|
|
132
|
+
Some(
|
|
133
|
+
&self
|
|
134
|
+
.as_ref()?
|
|
135
|
+
.expr_meta
|
|
136
|
+
.as_ref()?
|
|
137
|
+
.expressions
|
|
138
|
+
.expression_schema,
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
121
142
|
pub fn get_expression_columns(&self) -> impl Iterator<Item = &'_ String> {
|
|
122
143
|
maybe!(Some(
|
|
123
144
|
self.as_ref()?
|