@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
|
@@ -25,16 +25,17 @@ use crate::components::column_settings_sidebar::ColumnSettingsPanel;
|
|
|
25
25
|
use crate::components::main_panel::MainPanel;
|
|
26
26
|
use crate::components::settings_panel::SettingsPanel;
|
|
27
27
|
use crate::config::*;
|
|
28
|
+
use crate::css;
|
|
28
29
|
use crate::custom_events::CustomEvents;
|
|
29
|
-
use crate::dragdrop
|
|
30
|
-
use crate::
|
|
31
|
-
use crate::presentation::{ColumnLocator, ColumnSettingsTab, Presentation};
|
|
32
|
-
use crate::renderer
|
|
33
|
-
use crate::session
|
|
30
|
+
use crate::dragdrop::{DragDropProps, *};
|
|
31
|
+
use crate::js::JsPerspectiveViewerPlugin;
|
|
32
|
+
use crate::presentation::{ColumnLocator, ColumnSettingsTab, Presentation, PresentationProps};
|
|
33
|
+
use crate::renderer::{RendererProps, *};
|
|
34
|
+
use crate::session::{SessionProps, *};
|
|
35
|
+
use crate::tasks::*;
|
|
34
36
|
use crate::utils::*;
|
|
35
|
-
use crate::{PerspectiveProperties, css};
|
|
36
37
|
|
|
37
|
-
#[derive(Clone, Properties
|
|
38
|
+
#[derive(Clone, Properties)]
|
|
38
39
|
pub struct PerspectiveViewerProps {
|
|
39
40
|
/// The light DOM element this component will render to.
|
|
40
41
|
pub elem: web_sys::HtmlElement,
|
|
@@ -53,9 +54,41 @@ impl PartialEq for PerspectiveViewerProps {
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
impl PerspectiveViewerProps {
|
|
57
|
-
fn
|
|
58
|
-
self.
|
|
57
|
+
impl HasCustomEvents for PerspectiveViewerProps {
|
|
58
|
+
fn custom_events(&self) -> &CustomEvents {
|
|
59
|
+
&self.custom_events
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
impl HasDragDrop for PerspectiveViewerProps {
|
|
64
|
+
fn dragdrop(&self) -> &DragDrop {
|
|
65
|
+
&self.dragdrop
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
impl HasPresentation for PerspectiveViewerProps {
|
|
70
|
+
fn presentation(&self) -> &Presentation {
|
|
71
|
+
&self.presentation
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
impl HasRenderer for PerspectiveViewerProps {
|
|
76
|
+
fn renderer(&self) -> &Renderer {
|
|
77
|
+
&self.renderer
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
impl HasSession for PerspectiveViewerProps {
|
|
82
|
+
fn session(&self) -> &Session {
|
|
83
|
+
&self.session
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
impl StateProvider for PerspectiveViewerProps {
|
|
88
|
+
type State = PerspectiveViewerProps;
|
|
89
|
+
|
|
90
|
+
fn clone_state(&self) -> Self::State {
|
|
91
|
+
self.clone()
|
|
59
92
|
}
|
|
60
93
|
}
|
|
61
94
|
|
|
@@ -75,12 +108,34 @@ pub enum PerspectiveViewerMsg {
|
|
|
75
108
|
ToggleDebug,
|
|
76
109
|
ToggleSettingsComplete(SettingsUpdate, Sender<()>),
|
|
77
110
|
ToggleSettingsInit(Option<SettingsUpdate>, Option<Sender<ApiResult<JsValue>>>),
|
|
111
|
+
UpdateSession(Box<SessionProps>),
|
|
112
|
+
UpdateRenderer(Box<RendererProps>),
|
|
113
|
+
UpdatePresentation(Box<PresentationProps>),
|
|
114
|
+
|
|
115
|
+
/// Update only `is_settings_open` in the presentation snapshot without
|
|
116
|
+
/// touching `available_themes` (which requires async data).
|
|
117
|
+
UpdateSettingsOpen(bool),
|
|
118
|
+
UpdateIsWorkspace(bool),
|
|
119
|
+
|
|
120
|
+
/// Update only `open_column_settings` in the presentation snapshot.
|
|
121
|
+
UpdateColumnSettings(Box<crate::presentation::OpenColumnSettings>),
|
|
122
|
+
UpdateDragDrop(Box<DragDropProps>),
|
|
123
|
+
|
|
124
|
+
/// Update only stats-related fields of `session_props` without touching
|
|
125
|
+
/// `config`. This prevents `stats_changed` events (e.g. from `reset()`)
|
|
126
|
+
/// from propagating a freshly-cleared config to the column selector.
|
|
127
|
+
UpdateSessionStats(Option<ViewStats>, Option<TableLoadState>),
|
|
128
|
+
|
|
129
|
+
/// Increment/decrement the in-flight render counter threaded to
|
|
130
|
+
/// `StatusIndicator` so it can show the "updating" spinner.
|
|
131
|
+
IncrementUpdateCount,
|
|
132
|
+
DecrementUpdateCount,
|
|
78
133
|
}
|
|
79
134
|
|
|
80
135
|
use PerspectiveViewerMsg::*;
|
|
81
136
|
|
|
82
137
|
pub struct PerspectiveViewer {
|
|
83
|
-
_subscriptions:
|
|
138
|
+
_subscriptions: Vec<Subscription>,
|
|
84
139
|
column_settings_panel_width_override: Option<i32>,
|
|
85
140
|
debug_open: bool,
|
|
86
141
|
fonts: FontLoaderProps,
|
|
@@ -89,6 +144,18 @@ pub struct PerspectiveViewer {
|
|
|
89
144
|
on_resize: Rc<PubSub<()>>,
|
|
90
145
|
settings_open: bool,
|
|
91
146
|
settings_panel_width_override: Option<i32>,
|
|
147
|
+
|
|
148
|
+
/// Value-semantic state snapshots (Step 4 scaffold).
|
|
149
|
+
/// Populated by `UpdateSession` / `UpdateRenderer` / `UpdatePresentation` /
|
|
150
|
+
/// `UpdateDragDrop` messages dispatched from async engine tasks.
|
|
151
|
+
session_props: SessionProps,
|
|
152
|
+
renderer_props: RendererProps,
|
|
153
|
+
presentation_props: PresentationProps,
|
|
154
|
+
dragdrop_props: DragDropProps,
|
|
155
|
+
|
|
156
|
+
/// Counts in-flight renders (incremented on `view_config_changed`,
|
|
157
|
+
/// decremented on `view_created`). Threaded to `StatusIndicator`.
|
|
158
|
+
update_count: u32,
|
|
92
159
|
}
|
|
93
160
|
|
|
94
161
|
impl Component for PerspectiveViewer {
|
|
@@ -98,36 +165,38 @@ impl Component for PerspectiveViewer {
|
|
|
98
165
|
fn create(ctx: &Context<Self>) -> Self {
|
|
99
166
|
let elem = ctx.props().elem.clone();
|
|
100
167
|
let fonts = FontLoaderProps::new(&elem, ctx.link().callback(|()| PreloadFontsUpdate));
|
|
168
|
+
inject_engine_callbacks(ctx);
|
|
169
|
+
let subscriptions = create_subscriptions(ctx);
|
|
170
|
+
let session_props = ctx.props().session.to_props();
|
|
171
|
+
let renderer_props = ctx.props().renderer.to_props(None);
|
|
172
|
+
let presentation_props = ctx.props().presentation.to_props(PtrEqRc::new(vec![]));
|
|
101
173
|
|
|
102
|
-
|
|
103
|
-
let props = ctx.props().clone();
|
|
104
|
-
let callback = ctx.link().batch_callback(move |(update, _)| {
|
|
105
|
-
if update {
|
|
106
|
-
vec![]
|
|
107
|
-
} else {
|
|
108
|
-
let locator = props.get_current_column_locator();
|
|
109
|
-
vec![OpenColumnSettings {
|
|
110
|
-
locator,
|
|
111
|
-
sender: None,
|
|
112
|
-
toggle: false,
|
|
113
|
-
}]
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
ctx.props()
|
|
118
|
-
.renderer
|
|
119
|
-
.render_limits_changed
|
|
120
|
-
.add_listener(callback)
|
|
121
|
-
};
|
|
122
|
-
|
|
174
|
+
// Memoized callback for column settings drawer
|
|
123
175
|
let on_close_column_settings = ctx.link().callback(|_| OpenColumnSettings {
|
|
124
176
|
locator: None,
|
|
125
177
|
sender: None,
|
|
126
178
|
toggle: false,
|
|
127
179
|
});
|
|
128
180
|
|
|
181
|
+
// Kick off an initial async theme fetch so that `available_themes` is
|
|
182
|
+
// populated even if `theme_config_updated` fires before the PubSub
|
|
183
|
+
// subscription is registered.
|
|
184
|
+
{
|
|
185
|
+
let presentation = ctx.props().presentation.clone();
|
|
186
|
+
let cb = ctx.link().callback(move |themes: PtrEqRc<Vec<String>>| {
|
|
187
|
+
UpdatePresentation(Box::new(presentation.to_props(themes)))
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
let presentation = ctx.props().presentation.clone();
|
|
191
|
+
ApiFuture::spawn(async move {
|
|
192
|
+
let themes = presentation.get_available_themes().await?;
|
|
193
|
+
cb.emit(themes);
|
|
194
|
+
Ok(())
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
129
198
|
Self {
|
|
130
|
-
_subscriptions:
|
|
199
|
+
_subscriptions: subscriptions,
|
|
131
200
|
column_settings_panel_width_override: None,
|
|
132
201
|
debug_open: false,
|
|
133
202
|
fonts,
|
|
@@ -136,6 +205,11 @@ impl Component for PerspectiveViewer {
|
|
|
136
205
|
on_resize: Default::default(),
|
|
137
206
|
settings_open: false,
|
|
138
207
|
settings_panel_width_override: None,
|
|
208
|
+
session_props,
|
|
209
|
+
renderer_props,
|
|
210
|
+
presentation_props,
|
|
211
|
+
dragdrop_props: DragDropProps::default(),
|
|
212
|
+
update_count: 0,
|
|
139
213
|
}
|
|
140
214
|
}
|
|
141
215
|
|
|
@@ -250,7 +324,7 @@ impl Component for PerspectiveViewer {
|
|
|
250
324
|
} else {
|
|
251
325
|
locator.as_ref().and_then(|x| {
|
|
252
326
|
x.name().map(|x| {
|
|
253
|
-
if
|
|
327
|
+
if self.session_props.is_column_active(x) {
|
|
254
328
|
ColumnSettingsTab::Style
|
|
255
329
|
} else {
|
|
256
330
|
ColumnSettingsTab::Attributes
|
|
@@ -303,6 +377,56 @@ impl Component for PerspectiveViewer {
|
|
|
303
377
|
|
|
304
378
|
true
|
|
305
379
|
},
|
|
380
|
+
UpdateSession(props) => {
|
|
381
|
+
let changed = *props != self.session_props;
|
|
382
|
+
self.session_props = *props;
|
|
383
|
+
changed
|
|
384
|
+
},
|
|
385
|
+
UpdateSessionStats(stats, has_table) => {
|
|
386
|
+
let changed =
|
|
387
|
+
stats != self.session_props.stats || has_table != self.session_props.has_table;
|
|
388
|
+
self.session_props.stats = stats;
|
|
389
|
+
self.session_props.has_table = has_table;
|
|
390
|
+
changed
|
|
391
|
+
},
|
|
392
|
+
UpdateRenderer(props) => {
|
|
393
|
+
let changed = *props != self.renderer_props;
|
|
394
|
+
self.renderer_props = *props;
|
|
395
|
+
changed
|
|
396
|
+
},
|
|
397
|
+
UpdatePresentation(props) => {
|
|
398
|
+
let changed = *props != self.presentation_props;
|
|
399
|
+
self.presentation_props = *props;
|
|
400
|
+
changed
|
|
401
|
+
},
|
|
402
|
+
UpdateSettingsOpen(open) => {
|
|
403
|
+
let changed = open != self.presentation_props.is_settings_open;
|
|
404
|
+
self.presentation_props.is_settings_open = open;
|
|
405
|
+
changed
|
|
406
|
+
},
|
|
407
|
+
UpdateIsWorkspace(is_workspace) => {
|
|
408
|
+
let changed = is_workspace != self.presentation_props.is_workspace;
|
|
409
|
+
self.presentation_props.is_workspace = is_workspace;
|
|
410
|
+
changed
|
|
411
|
+
},
|
|
412
|
+
UpdateColumnSettings(ocs) => {
|
|
413
|
+
let changed = *ocs != self.presentation_props.open_column_settings;
|
|
414
|
+
self.presentation_props.open_column_settings = *ocs;
|
|
415
|
+
changed
|
|
416
|
+
},
|
|
417
|
+
UpdateDragDrop(props) => {
|
|
418
|
+
let changed = *props != self.dragdrop_props;
|
|
419
|
+
self.dragdrop_props = *props;
|
|
420
|
+
changed
|
|
421
|
+
},
|
|
422
|
+
IncrementUpdateCount => {
|
|
423
|
+
self.update_count = self.update_count.saturating_add(1);
|
|
424
|
+
true
|
|
425
|
+
},
|
|
426
|
+
DecrementUpdateCount => {
|
|
427
|
+
self.update_count = self.update_count.saturating_sub(1);
|
|
428
|
+
true
|
|
429
|
+
},
|
|
306
430
|
}
|
|
307
431
|
}
|
|
308
432
|
|
|
@@ -334,13 +458,15 @@ impl Component for PerspectiveViewer {
|
|
|
334
458
|
..
|
|
335
459
|
} = ctx.props();
|
|
336
460
|
|
|
337
|
-
let is_settings_open = self.settings_open
|
|
461
|
+
let is_settings_open = self.settings_open
|
|
462
|
+
&& matches!(self.session_props.has_table, Some(TableLoadState::Loaded));
|
|
463
|
+
|
|
338
464
|
let mut class = classes!();
|
|
339
465
|
if !is_settings_open {
|
|
340
466
|
class.push("settings-closed");
|
|
341
467
|
}
|
|
342
468
|
|
|
343
|
-
if
|
|
469
|
+
if self.session_props.title.is_some() {
|
|
344
470
|
class.push("titled");
|
|
345
471
|
}
|
|
346
472
|
|
|
@@ -360,8 +486,28 @@ impl Component for PerspectiveViewer {
|
|
|
360
486
|
|
|
361
487
|
let on_close_settings = ctx.link().callback(|()| ToggleSettingsInit(None, None));
|
|
362
488
|
let on_debug = ctx.link().callback(|_| ToggleDebug);
|
|
363
|
-
let selected_column =
|
|
364
|
-
|
|
489
|
+
let selected_column = get_current_column_locator(
|
|
490
|
+
&self.presentation_props.open_column_settings,
|
|
491
|
+
&ctx.props().renderer,
|
|
492
|
+
&self.session_props.config,
|
|
493
|
+
&self.session_props.metadata,
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
let selected_tab = self.presentation_props.open_column_settings.tab;
|
|
497
|
+
let plugin_name = self.renderer_props.plugin_name.clone();
|
|
498
|
+
let available_plugins = self.renderer_props.available_plugins.clone();
|
|
499
|
+
let has_table = self.session_props.has_table.clone();
|
|
500
|
+
let named_column_count = self
|
|
501
|
+
.renderer_props
|
|
502
|
+
.requirements
|
|
503
|
+
.names
|
|
504
|
+
.as_ref()
|
|
505
|
+
.map(|n| n.len())
|
|
506
|
+
.unwrap_or(0);
|
|
507
|
+
|
|
508
|
+
let view_config = self.session_props.config.clone();
|
|
509
|
+
let drag_column = self.dragdrop_props.column.clone();
|
|
510
|
+
let metadata = self.session_props.metadata.clone();
|
|
365
511
|
let settings_panel = html! {
|
|
366
512
|
if is_settings_open {
|
|
367
513
|
<SettingsPanel
|
|
@@ -370,6 +516,15 @@ impl Component for PerspectiveViewer {
|
|
|
370
516
|
on_select_column={on_open_expr_panel}
|
|
371
517
|
is_debug={self.debug_open}
|
|
372
518
|
{on_debug}
|
|
519
|
+
{plugin_name}
|
|
520
|
+
{available_plugins}
|
|
521
|
+
{has_table}
|
|
522
|
+
{named_column_count}
|
|
523
|
+
{view_config}
|
|
524
|
+
{drag_column}
|
|
525
|
+
metadata={metadata.clone()}
|
|
526
|
+
open_column_settings={self.presentation_props.open_column_settings.clone()}
|
|
527
|
+
selected_theme={self.presentation_props.selected_theme.clone()}
|
|
373
528
|
{dragdrop}
|
|
374
529
|
{presentation}
|
|
375
530
|
{renderer}
|
|
@@ -395,6 +550,10 @@ impl Component for PerspectiveViewer {
|
|
|
395
550
|
on_close={self.on_close_column_settings.clone()}
|
|
396
551
|
width_override={self.column_settings_panel_width_override}
|
|
397
552
|
{on_select_tab}
|
|
553
|
+
plugin_name={self.renderer_props.plugin_name.clone()}
|
|
554
|
+
{metadata}
|
|
555
|
+
view_config={self.session_props.config.clone()}
|
|
556
|
+
selected_theme={self.presentation_props.selected_theme.clone()}
|
|
398
557
|
{custom_events}
|
|
399
558
|
{presentation}
|
|
400
559
|
{renderer}
|
|
@@ -405,8 +564,38 @@ impl Component for PerspectiveViewer {
|
|
|
405
564
|
}
|
|
406
565
|
};
|
|
407
566
|
|
|
567
|
+
let on_reset = ctx.link().callback(|all| Reset(all, None));
|
|
568
|
+
let render_limits = self.renderer_props.render_limits;
|
|
569
|
+
let has_table = self.session_props.has_table.clone();
|
|
570
|
+
let is_errored = self.session_props.error.is_some();
|
|
571
|
+
let stats = self.session_props.stats.clone();
|
|
572
|
+
let update_count = self.update_count;
|
|
573
|
+
let error = self.session_props.error.clone();
|
|
574
|
+
let is_settings_open = self.settings_open
|
|
575
|
+
&& matches!(self.session_props.has_table, Some(TableLoadState::Loaded));
|
|
576
|
+
let title = self.session_props.title.clone();
|
|
577
|
+
let selected_theme = self.presentation_props.selected_theme.clone();
|
|
578
|
+
let available_themes = self.presentation_props.available_themes.clone();
|
|
408
579
|
let main_panel = html! {
|
|
409
|
-
<MainPanel
|
|
580
|
+
<MainPanel
|
|
581
|
+
{on_settings}
|
|
582
|
+
{on_reset}
|
|
583
|
+
{render_limits}
|
|
584
|
+
{has_table}
|
|
585
|
+
{is_errored}
|
|
586
|
+
{stats}
|
|
587
|
+
{update_count}
|
|
588
|
+
{error}
|
|
589
|
+
{is_settings_open}
|
|
590
|
+
{title}
|
|
591
|
+
{selected_theme}
|
|
592
|
+
{available_themes}
|
|
593
|
+
is_workspace={self.presentation_props.is_workspace}
|
|
594
|
+
{custom_events}
|
|
595
|
+
{presentation}
|
|
596
|
+
{renderer}
|
|
597
|
+
{session}
|
|
598
|
+
/>
|
|
410
599
|
};
|
|
411
600
|
|
|
412
601
|
let debug_panel = html! {
|
|
@@ -523,3 +712,166 @@ impl PerspectiveViewer {
|
|
|
523
712
|
};
|
|
524
713
|
}
|
|
525
714
|
}
|
|
715
|
+
|
|
716
|
+
/// Subscribe to PubSub events that still have non-root subscribers and
|
|
717
|
+
/// therefore cannot yet be replaced with direct callbacks.
|
|
718
|
+
fn create_subscriptions(ctx: &Context<PerspectiveViewer>) -> Vec<Subscription> {
|
|
719
|
+
let session_props_sub = {
|
|
720
|
+
let session = ctx.props().session.clone();
|
|
721
|
+
let cb = ctx
|
|
722
|
+
.link()
|
|
723
|
+
.callback(move |_: ()| UpdateSession(Box::new(session.to_props())));
|
|
724
|
+
|
|
725
|
+
let s = &ctx.props().session;
|
|
726
|
+
let sub1 = s.table_loaded.add_notify_listener(&cb);
|
|
727
|
+
let sub2 = s.table_unloaded.add_notify_listener(&cb);
|
|
728
|
+
let sub3 = s.view_created.add_notify_listener(&cb);
|
|
729
|
+
let sub4 = s.view_config_changed.add_notify_listener(&cb);
|
|
730
|
+
let sub5 = s.title_changed.add_notify_listener(&cb);
|
|
731
|
+
let sub6 = s
|
|
732
|
+
.view_config_changed
|
|
733
|
+
.add_listener(ctx.link().callback(|_| IncrementUpdateCount));
|
|
734
|
+
|
|
735
|
+
let sub7 = s
|
|
736
|
+
.view_created
|
|
737
|
+
.add_listener(ctx.link().callback(|_| DecrementUpdateCount));
|
|
738
|
+
|
|
739
|
+
vec![sub1, sub2, sub3, sub4, sub5, sub6, sub7]
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
let renderer_props_sub = {
|
|
743
|
+
let renderer = ctx.props().renderer.clone();
|
|
744
|
+
let cb_plugin = ctx.link().callback({
|
|
745
|
+
move |_: JsPerspectiveViewerPlugin| UpdateRenderer(Box::new(renderer.to_props(None)))
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
let sub1 = ctx.props().renderer.plugin_changed.add_listener(cb_plugin);
|
|
749
|
+
vec![sub1]
|
|
750
|
+
};
|
|
751
|
+
|
|
752
|
+
let presentation_props_sub = {
|
|
753
|
+
let presentation = ctx.props().presentation.clone();
|
|
754
|
+
let cb_settings = ctx.link().callback(UpdateSettingsOpen);
|
|
755
|
+
let cb_theme = {
|
|
756
|
+
let pres = presentation.clone();
|
|
757
|
+
ctx.link()
|
|
758
|
+
.callback(move |(themes, _): (PtrEqRc<Vec<String>>, _)| {
|
|
759
|
+
UpdatePresentation(Box::new(pres.to_props(themes)))
|
|
760
|
+
})
|
|
761
|
+
};
|
|
762
|
+
|
|
763
|
+
let cb_column_settings = {
|
|
764
|
+
let pres = presentation.clone();
|
|
765
|
+
ctx.link().callback(move |_: (bool, Option<String>)| {
|
|
766
|
+
UpdateColumnSettings(Box::new(pres.get_open_column_settings()))
|
|
767
|
+
})
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
let sub1 = presentation.settings_open_changed.add_listener(cb_settings);
|
|
771
|
+
let sub2 = presentation.theme_config_updated.add_listener(cb_theme);
|
|
772
|
+
let sub3 = presentation
|
|
773
|
+
.column_settings_open_changed
|
|
774
|
+
.add_listener(cb_column_settings);
|
|
775
|
+
|
|
776
|
+
vec![sub1, sub2, sub3]
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
let dragdrop_props_sub = {
|
|
780
|
+
let cb_clear = ctx.link().callback(|_: ()| UpdateDragDrop(Box::default()));
|
|
781
|
+
let sub1 = ctx
|
|
782
|
+
.props()
|
|
783
|
+
.dragdrop
|
|
784
|
+
.drop_received
|
|
785
|
+
.add_notify_listener(&cb_clear);
|
|
786
|
+
|
|
787
|
+
vec![sub1]
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
let mut subscriptions = Vec::new();
|
|
791
|
+
subscriptions.extend(session_props_sub);
|
|
792
|
+
subscriptions.extend(renderer_props_sub);
|
|
793
|
+
subscriptions.extend(presentation_props_sub);
|
|
794
|
+
subscriptions.extend(dragdrop_props_sub);
|
|
795
|
+
subscriptions
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/// Inject direct callbacks into the engine handles, replacing PubSub fields
|
|
799
|
+
/// that were exclusively consumed by the root component.
|
|
800
|
+
fn inject_engine_callbacks(ctx: &Context<PerspectiveViewer>) {
|
|
801
|
+
// Session: on_stats_changed
|
|
802
|
+
{
|
|
803
|
+
let session = ctx.props().session.clone();
|
|
804
|
+
let cb = ctx.link().callback(move |_: ()| {
|
|
805
|
+
UpdateSessionStats(session.get_table_stats(), session.has_table())
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
*ctx.props().session.on_stats_changed.borrow_mut() = Some(cb);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// Session: on_table_errored
|
|
812
|
+
{
|
|
813
|
+
let session = ctx.props().session.clone();
|
|
814
|
+
let cb = ctx
|
|
815
|
+
.link()
|
|
816
|
+
.callback(move |_: ()| UpdateSession(Box::new(session.to_props())));
|
|
817
|
+
|
|
818
|
+
*ctx.props().session.on_table_errored.borrow_mut() = Some(cb);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// Renderer: on_render_limits_changed (combines UpdateRenderer + column
|
|
822
|
+
// locator recheck that were previously two separate PubSub subscriptions).
|
|
823
|
+
{
|
|
824
|
+
clone!(
|
|
825
|
+
ctx.props().presentation,
|
|
826
|
+
ctx.props().renderer,
|
|
827
|
+
ctx.props().session
|
|
828
|
+
);
|
|
829
|
+
|
|
830
|
+
let cb = ctx.link().batch_callback(move |limits: RenderLimits| {
|
|
831
|
+
let mut msgs = vec![UpdateRenderer(Box::new(renderer.to_props(Some(limits))))];
|
|
832
|
+
if !limits.is_update {
|
|
833
|
+
let locator = get_current_column_locator(
|
|
834
|
+
&presentation.get_open_column_settings(),
|
|
835
|
+
&renderer,
|
|
836
|
+
&session.get_view_config(),
|
|
837
|
+
&session.metadata(),
|
|
838
|
+
);
|
|
839
|
+
|
|
840
|
+
msgs.push(OpenColumnSettings {
|
|
841
|
+
locator,
|
|
842
|
+
sender: None,
|
|
843
|
+
toggle: false,
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
msgs
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
*ctx.props().renderer.on_render_limits_changed.borrow_mut() = Some(cb);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Presentation: on_is_workspace_changed
|
|
854
|
+
{
|
|
855
|
+
let cb = ctx.link().callback(UpdateIsWorkspace);
|
|
856
|
+
*ctx.props()
|
|
857
|
+
.presentation
|
|
858
|
+
.on_is_workspace_changed
|
|
859
|
+
.borrow_mut() = Some(cb);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// DragDrop: on_dragstart
|
|
863
|
+
{
|
|
864
|
+
let dragdrop = ctx.props().dragdrop.clone();
|
|
865
|
+
let cb = ctx
|
|
866
|
+
.link()
|
|
867
|
+
.callback(move |_: DragEffect| UpdateDragDrop(Box::new(dragdrop.to_props())));
|
|
868
|
+
|
|
869
|
+
*ctx.props().dragdrop.on_dragstart.borrow_mut() = Some(cb);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// DragDrop: on_dragend
|
|
873
|
+
{
|
|
874
|
+
let cb = ctx.link().callback(|_: ()| UpdateDragDrop(Box::default()));
|
|
875
|
+
*ctx.props().dragdrop.on_dragend.borrow_mut() = Some(cb);
|
|
876
|
+
}
|
|
877
|
+
}
|