@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
|
@@ -0,0 +1,133 @@
|
|
|
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 perspective_client::config::{ColumnType, ViewConfig};
|
|
14
|
+
|
|
15
|
+
use super::HasSession;
|
|
16
|
+
use super::plugin_column_styles::can_render_column_styles;
|
|
17
|
+
use crate::presentation::{ColumnLocator, OpenColumnSettings};
|
|
18
|
+
use crate::renderer::Renderer;
|
|
19
|
+
use crate::session::SessionMetadata;
|
|
20
|
+
use crate::tasks::{HasPresentation, HasRenderer, PluginColumnStyles};
|
|
21
|
+
|
|
22
|
+
/// Returns the column name for a locator, generating a default for new
|
|
23
|
+
/// expressions.
|
|
24
|
+
pub fn locator_name_or_default(metadata: &SessionMetadata, locator: &ColumnLocator) -> String {
|
|
25
|
+
match locator {
|
|
26
|
+
ColumnLocator::Table(s) | ColumnLocator::Expression(s) => s.clone(),
|
|
27
|
+
ColumnLocator::NewExpression => metadata.make_new_column_name(None),
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Returns the view type for a locator's column, if available.
|
|
32
|
+
pub fn locator_view_type(
|
|
33
|
+
metadata: &SessionMetadata,
|
|
34
|
+
locator: &ColumnLocator,
|
|
35
|
+
) -> Option<ColumnType> {
|
|
36
|
+
let name = locator.name().cloned().unwrap_or_default();
|
|
37
|
+
metadata.get_column_view_type(name.as_str())
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// Returns a [`ColumnLocator`] for a given column name, or [`None`] if no
|
|
41
|
+
/// such column exists.
|
|
42
|
+
pub fn get_column_locator(
|
|
43
|
+
metadata: &SessionMetadata,
|
|
44
|
+
name: Option<String>,
|
|
45
|
+
) -> Option<ColumnLocator> {
|
|
46
|
+
name.and_then(|name| {
|
|
47
|
+
if metadata.is_column_expression(&name) {
|
|
48
|
+
Some(ColumnLocator::Expression(name))
|
|
49
|
+
} else {
|
|
50
|
+
metadata.get_table_columns().and_then(|x| {
|
|
51
|
+
x.iter()
|
|
52
|
+
.find_map(|n| (n == &name).then_some(ColumnLocator::Table(name.clone())))
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Gets a [`ColumnLocator`] for the current UI's column settings state,
|
|
59
|
+
/// or [`None`] if it is not currently active.
|
|
60
|
+
pub fn get_current_column_locator(
|
|
61
|
+
open_column_settings: &OpenColumnSettings,
|
|
62
|
+
renderer: &Renderer,
|
|
63
|
+
view_config: &ViewConfig,
|
|
64
|
+
metadata: &SessionMetadata,
|
|
65
|
+
) -> Option<ColumnLocator> {
|
|
66
|
+
open_column_settings
|
|
67
|
+
.locator
|
|
68
|
+
.clone()
|
|
69
|
+
.filter(|locator| match locator {
|
|
70
|
+
ColumnLocator::Table(name) => {
|
|
71
|
+
locator
|
|
72
|
+
.name()
|
|
73
|
+
.map(|name| {
|
|
74
|
+
view_config.columns.iter().any(|maybe_col| {
|
|
75
|
+
maybe_col
|
|
76
|
+
.as_ref()
|
|
77
|
+
.map(|col| col == name)
|
|
78
|
+
.unwrap_or_default()
|
|
79
|
+
}) || view_config.group_by.iter().any(|col| col == name)
|
|
80
|
+
|| view_config.split_by.iter().any(|col| col == name)
|
|
81
|
+
|| view_config.filter.iter().any(|col| col.column() == name)
|
|
82
|
+
|| view_config.sort.iter().any(|col| &col.0 == name)
|
|
83
|
+
})
|
|
84
|
+
.unwrap_or_default()
|
|
85
|
+
&& can_render_column_styles(renderer, view_config, metadata, name)
|
|
86
|
+
.unwrap_or_default()
|
|
87
|
+
},
|
|
88
|
+
_ => true,
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// Trait facade — delegates to standalone functions above.
|
|
93
|
+
pub trait ColumnLocatorExt: HasSession {
|
|
94
|
+
fn locator_name_or_default(&self, locator: &ColumnLocator) -> String {
|
|
95
|
+
locator_name_or_default(&self.session().metadata(), locator)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
fn is_locator_active(&self, locator: &ColumnLocator) -> bool {
|
|
99
|
+
locator
|
|
100
|
+
.name()
|
|
101
|
+
.map(|name| self.session().to_props().is_column_active(name))
|
|
102
|
+
.unwrap_or_default()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fn locator_view_type(&self, locator: &ColumnLocator) -> Option<ColumnType> {
|
|
106
|
+
locator_view_type(&self.session().metadata(), locator)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fn get_column_locator(&self, name: Option<String>) -> Option<ColumnLocator> {
|
|
110
|
+
get_column_locator(&self.session().metadata(), name)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
impl<T: HasSession> ColumnLocatorExt for T {}
|
|
115
|
+
|
|
116
|
+
/// Trait facade for `get_current_column_locator`.
|
|
117
|
+
pub trait ColumnLocatorCurrentExt:
|
|
118
|
+
HasPresentation + HasRenderer + HasSession + PluginColumnStyles
|
|
119
|
+
{
|
|
120
|
+
fn get_current_column_locator(&self) -> Option<ColumnLocator> {
|
|
121
|
+
get_current_column_locator(
|
|
122
|
+
&self.presentation().get_open_column_settings(),
|
|
123
|
+
self.renderer(),
|
|
124
|
+
&self.session().get_view_config(),
|
|
125
|
+
&self.session().metadata(),
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
impl<T: HasPresentation + HasRenderer + HasSession + PluginColumnStyles> ColumnLocatorCurrentExt
|
|
131
|
+
for T
|
|
132
|
+
{
|
|
133
|
+
}
|
|
@@ -15,10 +15,10 @@ use std::collections::HashSet;
|
|
|
15
15
|
use itertools::Itertools;
|
|
16
16
|
use perspective_client::config::*;
|
|
17
17
|
|
|
18
|
-
use super::
|
|
18
|
+
use super::is_invalid_columns_column;
|
|
19
19
|
use crate::dragdrop::*;
|
|
20
20
|
use crate::renderer::*;
|
|
21
|
-
use crate::session
|
|
21
|
+
use crate::session::SessionMetadata;
|
|
22
22
|
use crate::utils::DragTarget;
|
|
23
23
|
use crate::*;
|
|
24
24
|
|
|
@@ -65,28 +65,16 @@ type Label = Option<String>;
|
|
|
65
65
|
/// iterator returning functions `active()`, `inactive()` and `expression()`.
|
|
66
66
|
pub struct ColumnsIteratorSet<'a> {
|
|
67
67
|
config: &'a ViewConfig,
|
|
68
|
-
session: &'a Session,
|
|
69
68
|
renderer: &'a Renderer,
|
|
70
|
-
metadata:
|
|
69
|
+
metadata: &'a SessionMetadata,
|
|
71
70
|
is_dragover_column: Option<(usize, String)>,
|
|
72
71
|
named_columns: Vec<String>,
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
impl HasRenderer for ColumnsIteratorSet<'_> {
|
|
76
|
-
fn renderer(&self) -> &'_ Renderer {
|
|
77
|
-
self.renderer
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
impl HasSession for ColumnsIteratorSet<'_> {
|
|
81
|
-
fn session(&self) -> &'_ Session {
|
|
82
|
-
self.session
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
74
|
impl<'a> ColumnsIteratorSet<'a> {
|
|
87
75
|
pub fn new(
|
|
88
76
|
config: &'a ViewConfig,
|
|
89
|
-
|
|
77
|
+
metadata: &'a SessionMetadata,
|
|
90
78
|
renderer: &'a Renderer,
|
|
91
79
|
dragdrop: &DragDrop,
|
|
92
80
|
) -> ColumnsIteratorSet<'a> {
|
|
@@ -94,9 +82,8 @@ impl<'a> ColumnsIteratorSet<'a> {
|
|
|
94
82
|
let named_columns = renderer.metadata().names.clone().unwrap_or_default();
|
|
95
83
|
ColumnsIteratorSet {
|
|
96
84
|
config,
|
|
97
|
-
session,
|
|
98
85
|
renderer,
|
|
99
|
-
metadata
|
|
86
|
+
metadata,
|
|
100
87
|
is_dragover_column,
|
|
101
88
|
named_columns,
|
|
102
89
|
}
|
|
@@ -117,10 +104,9 @@ impl<'a> ColumnsIteratorSet<'a> {
|
|
|
117
104
|
|| self.config.columns.len() < self.named_columns.len()
|
|
118
105
|
|| self.config.columns.iter().filter(|x| x.is_some()).count()
|
|
119
106
|
== self
|
|
120
|
-
.
|
|
121
|
-
.metadata()
|
|
107
|
+
.metadata
|
|
122
108
|
.get_table_columns()
|
|
123
|
-
.map(|x
|
|
109
|
+
.map(|x: &Vec<String>| x.len())
|
|
124
110
|
.unwrap_or_default()
|
|
125
111
|
+ self.config.expressions.len();
|
|
126
112
|
|
|
@@ -143,7 +129,12 @@ impl<'a> ColumnsIteratorSet<'a> {
|
|
|
143
129
|
.map(|x| self.renderer.metadata().is_swap(x))
|
|
144
130
|
.unwrap_or_default();
|
|
145
131
|
|
|
146
|
-
let is_swap_invalid =
|
|
132
|
+
let is_swap_invalid = is_invalid_columns_column(
|
|
133
|
+
self.config,
|
|
134
|
+
self.renderer.metadata().min,
|
|
135
|
+
from_column,
|
|
136
|
+
*to_index,
|
|
137
|
+
);
|
|
147
138
|
let is_dragover_after_last = *to_index == self.config.columns.len();
|
|
148
139
|
if is_swap_invalid {
|
|
149
140
|
let all_columns = self.config.columns.iter().map(|x| x.into());
|
|
@@ -299,7 +290,7 @@ impl<'a> ColumnsIteratorSet<'a> {
|
|
|
299
290
|
};
|
|
300
291
|
|
|
301
292
|
if !is_active || is_swap_over.unwrap_or_default() {
|
|
302
|
-
let col_type = self.
|
|
293
|
+
let col_type = self.metadata.get_column_table_type(name)?;
|
|
303
294
|
let is_visible = dragover_col.is_none_or(|(_, x)| x != name);
|
|
304
295
|
Some(OrderedColumn {
|
|
305
296
|
is_visible,
|
|
@@ -19,13 +19,31 @@ use crate::renderer::Renderer;
|
|
|
19
19
|
use crate::session::Session;
|
|
20
20
|
use crate::*;
|
|
21
21
|
|
|
22
|
-
#[derive(
|
|
22
|
+
#[derive(Clone, PartialEq)]
|
|
23
23
|
pub struct ExpressionUpdater {
|
|
24
24
|
presentation: Presentation,
|
|
25
25
|
renderer: Renderer,
|
|
26
26
|
session: Session,
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
impl HasPresentation for ExpressionUpdater {
|
|
30
|
+
fn presentation(&self) -> &Presentation {
|
|
31
|
+
&self.presentation
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
impl HasRenderer for ExpressionUpdater {
|
|
36
|
+
fn renderer(&self) -> &Renderer {
|
|
37
|
+
&self.renderer
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
impl HasSession for ExpressionUpdater {
|
|
42
|
+
fn session(&self) -> &Session {
|
|
43
|
+
&self.session
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
29
47
|
pub trait EditExpression: HasPresentation + HasRenderer + HasSession + UpdateAndRender {
|
|
30
48
|
fn get_expression_updater(&self) -> ExpressionUpdater {
|
|
31
49
|
ExpressionUpdater {
|
|
@@ -41,37 +59,43 @@ pub trait EditExpression: HasPresentation + HasRenderer + HasSession + UpdateAnd
|
|
|
41
59
|
ApiFuture::spawn(async move {
|
|
42
60
|
let update = this
|
|
43
61
|
.session
|
|
44
|
-
.
|
|
45
|
-
.
|
|
62
|
+
.to_props()
|
|
63
|
+
.create_replace_expression_update(&old_name, &new_expr);
|
|
46
64
|
|
|
65
|
+
this.update_and_render(update)?.await?;
|
|
47
66
|
this.presentation
|
|
48
67
|
.set_open_column_settings(Some(OpenColumnSettings {
|
|
49
68
|
locator: Some(ColumnLocator::Expression(new_expr.name.to_string())),
|
|
50
69
|
tab: Some(ColumnSettingsTab::Attributes),
|
|
51
70
|
}));
|
|
52
71
|
|
|
53
|
-
this.update_and_render(update)?.await?;
|
|
54
72
|
Ok(())
|
|
55
73
|
});
|
|
56
74
|
}
|
|
57
75
|
|
|
58
76
|
/// Saves a new expression. Spawns a future.
|
|
59
77
|
fn save_expr(&self, expr: Expression) -> ApiResult<()> {
|
|
78
|
+
let presentation = self.presentation().clone();
|
|
79
|
+
let expr_name: String = expr.name.clone().into();
|
|
60
80
|
let task = {
|
|
61
81
|
let mut serde_exprs = self.session().get_view_config().expressions.clone();
|
|
62
82
|
serde_exprs.insert(&expr);
|
|
63
|
-
self.presentation()
|
|
64
|
-
.set_open_column_settings(Some(OpenColumnSettings {
|
|
65
|
-
locator: Some(ColumnLocator::Expression(expr.name.clone().into())),
|
|
66
|
-
tab: Some(ColumnSettingsTab::Attributes),
|
|
67
|
-
}));
|
|
68
83
|
self.update_and_render(ViewConfigUpdate {
|
|
69
84
|
expressions: Some(serde_exprs),
|
|
70
85
|
..Default::default()
|
|
71
86
|
})
|
|
72
87
|
}?;
|
|
73
88
|
|
|
74
|
-
ApiFuture::spawn(
|
|
89
|
+
ApiFuture::spawn(async move {
|
|
90
|
+
task.await?;
|
|
91
|
+
presentation.set_open_column_settings(Some(OpenColumnSettings {
|
|
92
|
+
locator: Some(ColumnLocator::Expression(expr_name)),
|
|
93
|
+
tab: Some(ColumnSettingsTab::Attributes),
|
|
94
|
+
}));
|
|
95
|
+
|
|
96
|
+
Ok(())
|
|
97
|
+
});
|
|
98
|
+
|
|
75
99
|
Ok(())
|
|
76
100
|
}
|
|
77
101
|
|
|
@@ -16,7 +16,7 @@ use yew::Component;
|
|
|
16
16
|
use super::{HasRenderer, HasSession};
|
|
17
17
|
use crate::ApiFuture;
|
|
18
18
|
use crate::root::Root;
|
|
19
|
-
use crate::session::ResetOptions;
|
|
19
|
+
use crate::session::{ResetOptions, TableIntermediateState};
|
|
20
20
|
|
|
21
21
|
pub trait DeleteAll: HasSession + HasRenderer {
|
|
22
22
|
fn delete_all<T: Component>(&self, root: &Root<T>) -> ApiFuture<()> {
|
|
@@ -29,7 +29,7 @@ pub trait DeleteAll: HasSession + HasRenderer {
|
|
|
29
29
|
.reset(ResetOptions {
|
|
30
30
|
config: true,
|
|
31
31
|
expressions: true,
|
|
32
|
-
table:
|
|
32
|
+
table: Some(TableIntermediateState::Ejected),
|
|
33
33
|
..ResetOptions::default()
|
|
34
34
|
})
|
|
35
35
|
.await?;
|
|
@@ -10,9 +10,6 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
use perspective_client::config::ViewConfig;
|
|
14
|
-
|
|
15
|
-
use super::columns_iter_set::*;
|
|
16
13
|
use super::structural::*;
|
|
17
14
|
use crate::config::*;
|
|
18
15
|
use crate::*;
|
|
@@ -51,11 +48,3 @@ pub trait GetViewerConfigModel: HasSession + HasRenderer + HasPresentation {
|
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
impl<T: HasRenderer + HasSession + HasPresentation> GetViewerConfigModel for T {}
|
|
54
|
-
|
|
55
|
-
pub trait ColumnIteratorModel: HasSession + HasRenderer + HasDragDrop {
|
|
56
|
-
fn column_selector_iter_set<'a>(&'a self, config: &'a ViewConfig) -> ColumnsIteratorSet<'a> {
|
|
57
|
-
ColumnsIteratorSet::new(config, self.session(), self.renderer(), self.dragdrop())
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
impl<T: HasSession + HasRenderer + HasDragDrop> ColumnIteratorModel for T {}
|
|
@@ -16,10 +16,10 @@ use web_sys::*;
|
|
|
16
16
|
|
|
17
17
|
use crate::config::ViewerConfigUpdate;
|
|
18
18
|
use crate::js::*;
|
|
19
|
-
use crate::model::*;
|
|
20
19
|
use crate::presentation::Presentation;
|
|
21
20
|
use crate::renderer::*;
|
|
22
21
|
use crate::session::Session;
|
|
22
|
+
use crate::tasks::*;
|
|
23
23
|
use crate::utils::*;
|
|
24
24
|
use crate::*;
|
|
25
25
|
|
|
@@ -38,8 +38,9 @@ impl IntersectionObserverHandle {
|
|
|
38
38
|
) -> Self {
|
|
39
39
|
clone!(session, renderer, presentation);
|
|
40
40
|
let _callback = Closure::new(move |xs: js_sys::Array| {
|
|
41
|
+
// https://stackoverflow.com/questions/53862160/intersectionobserver-multiple-entries
|
|
41
42
|
let intersect = xs
|
|
42
|
-
.
|
|
43
|
+
.pop()
|
|
43
44
|
.unchecked_into::<IntersectionObserverEntry>()
|
|
44
45
|
.is_intersecting();
|
|
45
46
|
|
|
@@ -49,6 +50,7 @@ impl IntersectionObserverHandle {
|
|
|
49
50
|
session,
|
|
50
51
|
renderer,
|
|
51
52
|
};
|
|
53
|
+
|
|
52
54
|
ApiFuture::spawn(state.set_pause(intersect));
|
|
53
55
|
});
|
|
54
56
|
|
|
@@ -69,18 +71,34 @@ impl Drop for IntersectionObserverHandle {
|
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
#[derive(PerspectiveProperties!)]
|
|
73
74
|
struct IntersectionObserverState {
|
|
74
75
|
session: Session,
|
|
75
76
|
renderer: Renderer,
|
|
76
77
|
presentation: Presentation,
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
impl HasPresentation for IntersectionObserverState {
|
|
81
|
+
fn presentation(&self) -> &Presentation {
|
|
82
|
+
&self.presentation
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
impl HasRenderer for IntersectionObserverState {
|
|
87
|
+
fn renderer(&self) -> &Renderer {
|
|
88
|
+
&self.renderer
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
impl HasSession for IntersectionObserverState {
|
|
93
|
+
fn session(&self) -> &Session {
|
|
94
|
+
&self.session
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
79
98
|
impl IntersectionObserverState {
|
|
80
99
|
async fn set_pause(self, intersect: bool) -> ApiResult<()> {
|
|
81
100
|
if intersect {
|
|
82
101
|
if self.session.set_pause(false) {
|
|
83
|
-
self.presentation.visibility_changed.emit(intersect);
|
|
84
102
|
self.restore_and_render(ViewerConfigUpdate::default(), async move { Ok(()) })
|
|
85
103
|
.await?;
|
|
86
104
|
}
|
|
@@ -10,20 +10,27 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
.radio-list-item {
|
|
15
|
-
display: flex;
|
|
16
|
-
flex-wrap: wrap;
|
|
17
|
-
align-items: center;
|
|
13
|
+
use perspective_client::config::ViewConfig;
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
/// Checks whether dropping `from_column` at `to_index` in the active columns
|
|
16
|
+
/// list would be invalid (i.e. removing a required column to an empty slot).
|
|
17
|
+
pub fn is_invalid_columns_column(
|
|
18
|
+
config: &ViewConfig,
|
|
19
|
+
min: Option<usize>,
|
|
20
|
+
from_column: &String,
|
|
21
|
+
to_index: usize,
|
|
22
|
+
) -> bool {
|
|
23
|
+
let from_index = config
|
|
24
|
+
.columns
|
|
25
|
+
.iter()
|
|
26
|
+
.position(|x| x.as_ref() == Some(from_column));
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
let is_to_empty = !config
|
|
29
|
+
.columns
|
|
30
|
+
.get(to_index)
|
|
31
|
+
.map(|x| x.is_some())
|
|
32
|
+
.unwrap_or_default();
|
|
33
|
+
min.and_then(|x| from_index.map(|from_index| from_index < x))
|
|
34
|
+
.unwrap_or_default()
|
|
35
|
+
&& is_to_empty
|
|
29
36
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
//! Async tasks and model traits for coordinating state between `Session`,
|
|
14
|
+
//! `Renderer`, `Presentation`, and `DragDrop` singletons.
|
|
15
|
+
//!
|
|
16
|
+
//! Complex operations that span more than one state object are expressed as
|
|
17
|
+
//! traits whose bounds name exactly the state objects they require (e.g.
|
|
18
|
+
//! `UpdateAndRender: HasSession + HasRenderer`). Blanket impls apply the
|
|
19
|
+
//! trait to any struct that holds those fields and provides `Has*` accessors.
|
|
20
|
+
|
|
21
|
+
mod column_locator;
|
|
22
|
+
mod columns_iter_set;
|
|
23
|
+
mod copy_export;
|
|
24
|
+
mod edit_expression;
|
|
25
|
+
mod eject;
|
|
26
|
+
mod export_app;
|
|
27
|
+
mod export_method;
|
|
28
|
+
mod get_viewer_config;
|
|
29
|
+
mod intersection_observer;
|
|
30
|
+
mod is_invalid_drop;
|
|
31
|
+
mod plugin_column_styles;
|
|
32
|
+
mod resize_observer;
|
|
33
|
+
mod restore_and_render;
|
|
34
|
+
mod send_plugin_config;
|
|
35
|
+
mod structural;
|
|
36
|
+
mod update_and_render;
|
|
37
|
+
|
|
38
|
+
pub use self::column_locator::*;
|
|
39
|
+
pub use self::columns_iter_set::*;
|
|
40
|
+
pub use self::copy_export::*;
|
|
41
|
+
pub use self::edit_expression::*;
|
|
42
|
+
pub use self::eject::*;
|
|
43
|
+
pub use self::export_method::*;
|
|
44
|
+
pub use self::get_viewer_config::*;
|
|
45
|
+
pub use self::intersection_observer::*;
|
|
46
|
+
pub use self::is_invalid_drop::is_invalid_columns_column;
|
|
47
|
+
pub use self::plugin_column_styles::*;
|
|
48
|
+
pub use self::resize_observer::*;
|
|
49
|
+
pub use self::restore_and_render::*;
|
|
50
|
+
pub use self::send_plugin_config::*;
|
|
51
|
+
pub use self::structural::*;
|
|
52
|
+
pub use self::update_and_render::*;
|
|
@@ -11,64 +11,87 @@
|
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
13
|
use itertools::Itertools;
|
|
14
|
+
use perspective_client::config::ViewConfig;
|
|
14
15
|
use perspective_js::utils::ApiResult;
|
|
15
16
|
|
|
16
17
|
use super::{HasRenderer, HasSession};
|
|
17
18
|
use crate::config::ColumnStyleOpts;
|
|
19
|
+
use crate::renderer::Renderer;
|
|
20
|
+
use crate::session::SessionMetadata;
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
/// Queries the plugin to see if a given column can render column styles.
|
|
23
|
+
pub fn can_render_column_styles(
|
|
24
|
+
renderer: &Renderer,
|
|
25
|
+
view_config: &ViewConfig,
|
|
26
|
+
metadata: &SessionMetadata,
|
|
27
|
+
column_name: &str,
|
|
28
|
+
) -> ApiResult<bool> {
|
|
29
|
+
let plugin = renderer.get_active_plugin()?;
|
|
30
|
+
let names: Vec<String> = plugin
|
|
31
|
+
.config_column_names()
|
|
32
|
+
.and_then(|jsarr| serde_wasm_bindgen::from_value(jsarr.into()).ok())
|
|
33
|
+
.unwrap_or_default();
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.and_then(|(idx, _)| names.get(idx))
|
|
36
|
-
.map(|s| s.as_str());
|
|
35
|
+
let group = view_config
|
|
36
|
+
.columns
|
|
37
|
+
.iter()
|
|
38
|
+
.find_position(|maybe_s| maybe_s.as_deref() == Some(column_name))
|
|
39
|
+
.and_then(|(idx, _)| names.get(idx))
|
|
40
|
+
.map(|s| s.as_str());
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
.get_column_view_type(column_name)
|
|
42
|
-
.ok_or("Invalid column")?;
|
|
42
|
+
let view_type = metadata
|
|
43
|
+
.get_column_view_type(column_name)
|
|
44
|
+
.ok_or("Invalid column")?;
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
plugin.can_render_column_styles(&view_type.to_string(), group)
|
|
47
|
+
}
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
/// Queries the plugin for the available style control options for a column.
|
|
50
|
+
pub fn get_column_style_control_options(
|
|
51
|
+
renderer: &Renderer,
|
|
52
|
+
view_config: &ViewConfig,
|
|
53
|
+
metadata: &SessionMetadata,
|
|
54
|
+
column_name: &str,
|
|
55
|
+
) -> ApiResult<ColumnStyleOpts> {
|
|
56
|
+
let plugin = renderer.get_active_plugin()?;
|
|
57
|
+
let names: Vec<String> = plugin
|
|
58
|
+
.config_column_names()
|
|
59
|
+
.and_then(|jsarr| serde_wasm_bindgen::from_value(jsarr.into()).ok())
|
|
60
|
+
.unwrap_or_default();
|
|
61
|
+
|
|
62
|
+
let group = view_config
|
|
63
|
+
.columns
|
|
64
|
+
.iter()
|
|
65
|
+
.find_position(|maybe_s| maybe_s.as_deref() == Some(column_name))
|
|
66
|
+
.and_then(|(idx, _)| names.get(idx))
|
|
67
|
+
.map(|s| s.as_str());
|
|
54
68
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
.columns
|
|
59
|
-
.iter()
|
|
60
|
-
.find_position(|maybe_s| maybe_s.as_deref() == Some(column_name))
|
|
61
|
-
.and_then(|(idx, _)| names.get(idx))
|
|
62
|
-
.map(|s| s.as_str());
|
|
69
|
+
let view_type = metadata
|
|
70
|
+
.get_column_view_type(column_name)
|
|
71
|
+
.ok_or("Invalid column")?;
|
|
63
72
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
let controls = plugin.column_style_controls(&view_type.to_string(), group)?;
|
|
74
|
+
serde_wasm_bindgen::from_value(controls).map_err(|e| e.into())
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/// Trait facade — delegates to the standalone functions above.
|
|
78
|
+
pub trait PluginColumnStyles: HasSession + HasRenderer {
|
|
79
|
+
fn can_render_column_styles(&self, column_name: &str) -> ApiResult<bool> {
|
|
80
|
+
can_render_column_styles(
|
|
81
|
+
self.renderer(),
|
|
82
|
+
&self.session().get_view_config(),
|
|
83
|
+
&self.session().metadata(),
|
|
84
|
+
column_name,
|
|
85
|
+
)
|
|
86
|
+
}
|
|
69
87
|
|
|
70
|
-
|
|
71
|
-
|
|
88
|
+
fn get_column_style_control_options(&self, column_name: &str) -> ApiResult<ColumnStyleOpts> {
|
|
89
|
+
get_column_style_control_options(
|
|
90
|
+
self.renderer(),
|
|
91
|
+
&self.session().get_view_config(),
|
|
92
|
+
&self.session().metadata(),
|
|
93
|
+
column_name,
|
|
94
|
+
)
|
|
72
95
|
}
|
|
73
96
|
}
|
|
74
97
|
|