@perspective-dev/viewer 5.4.0 → 5.5.1
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 +4 -4
- package/dist/cdn/perspective-viewer.js.map +2 -2
- package/dist/css/blueprint.css +1 -1
- package/dist/css/botanical.css +1 -1
- package/dist/css/dracula.css +1 -1
- package/dist/css/eggplant.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/ar.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/ledger.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/nord.css +1 -1
- package/dist/css/phosphor.css +1 -1
- package/dist/css/pro-dark.css +1 -1
- package/dist/css/pro.css +1 -1
- package/dist/css/solarized-dark.css +1 -1
- package/dist/css/solarized.css +1 -1
- package/dist/css/themes.css +1 -1
- package/dist/css/vaporwave.css +1 -1
- package/dist/css/velvet.css +1 -1
- package/dist/docs/perspective-docs.json +1 -1
- package/dist/esm/perspective-viewer.d.ts +2 -0
- package/dist/esm/perspective-viewer.inline.js +9 -9
- package/dist/esm/perspective-viewer.inline.js.map +3 -3
- package/dist/esm/perspective-viewer.js +4 -4
- package/dist/esm/perspective-viewer.js.map +2 -2
- package/dist/esm/plugin.d.ts +9 -0
- package/dist/esm/ts-rs/AddPanelOptions.d.ts +9 -0
- package/dist/esm/ts-rs/ExportMethod.d.ts +1 -1
- package/dist/esm/ts-rs/GetViewMode.d.ts +4 -0
- package/dist/esm/ts-rs/GetViewOptions.d.ts +8 -0
- package/dist/esm/ts-rs/RestoreOptions.d.ts +6 -0
- package/dist/esm/ts-rs/RestoreWorkspaceOptions.d.ts +9 -0
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +30 -22
- package/dist/wasm/perspective-viewer.d.ts +102 -47
- package/dist/wasm/perspective-viewer.js +233 -142
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +18 -18
- package/package.json +7 -7
- package/src/css/column-selector.css +11 -3
- package/src/css/column-style.css +162 -0
- package/src/css/config-selector.css +1 -1
- package/src/css/form/debug.css +9 -0
- package/src/css/status-bar.css +11 -0
- package/src/css/ui/containers/tabs.css +2 -1
- package/src/rust/agent/tools.rs +80 -7
- package/src/rust/components/column_selector/active_column.rs +9 -0
- package/src/rust/components/column_selector.rs +11 -0
- package/src/rust/components/column_settings_sidebar/style_tab/alignment_field.rs +90 -0
- package/src/rust/components/column_settings_sidebar/style_tab/font_field.rs +267 -0
- package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab.rs +68 -9
- package/src/rust/components/debug_panel.rs +107 -50
- package/src/rust/components/export_dropdown.rs +6 -0
- package/src/rust/components/main_panel/msg.rs +4 -0
- package/src/rust/components/main_panel.rs +14 -0
- package/src/rust/components/mod.rs +0 -1
- package/src/rust/components/plugin_tab.rs +57 -3
- package/src/rust/components/settings_panel.rs +6 -0
- package/src/rust/components/status_bar.rs +12 -3
- package/src/rust/components/status_indicator.rs +4 -0
- package/src/rust/components/viewer/filters.rs +2 -2
- package/src/rust/components/viewer/msg.rs +4 -0
- package/src/rust/components/viewer/panels.rs +6 -3
- package/src/rust/components/viewer/render.rs +1 -0
- package/src/rust/components/viewer/wiring.rs +14 -2
- package/src/rust/components/viewer.rs +2 -2
- package/src/rust/config/column_config_schema.rs +312 -8
- package/src/rust/config/datetime_column_style.rs +0 -11
- package/src/rust/config/export_method.rs +24 -0
- package/src/rust/config/mod.rs +0 -2
- package/src/rust/config/options.rs +50 -0
- package/src/rust/config/workspace_config.rs +69 -24
- package/src/rust/custom_elements/viewer.rs +214 -113
- package/src/rust/js/plugin.rs +3 -1
- package/src/rust/lib.rs +7 -3
- package/src/rust/queries/plugin_column_styles.rs +6 -5
- package/src/rust/renderer/plugin_config.rs +200 -41
- package/src/rust/renderer/plugin_store.rs +2 -1
- package/src/rust/renderer/props.rs +5 -0
- package/src/rust/renderer.rs +9 -0
- package/src/rust/session/metadata.rs +5 -10
- package/src/rust/session/props.rs +4 -0
- package/src/rust/session.rs +273 -195
- package/src/rust/tasks/copy_export.rs +67 -0
- package/src/rust/tasks/create_panel.rs +16 -13
- package/src/rust/tasks/pipeline.rs +26 -8
- package/src/rust/tasks/restore_panel.rs +129 -30
- package/src/rust/tasks/send_column_config.rs +3 -0
- package/src/rust/tasks/sync_update_panels.rs +148 -68
- package/src/rust/tasks/table_lifecycle.rs +7 -1
- package/src/rust/ui/containers/tab_list.rs +1 -1
- package/src/rust/ui/form/intl_label.rs +4 -23
- package/src/rust/ui/portal.rs +1 -0
- package/src/rust/utils/css_vars.rs +13 -0
- package/src/rust/{config/datetime_column_style/color_mode.rs → utils/in_flight.rs} +47 -35
- package/src/rust/utils/local_fonts.rs +395 -0
- package/src/rust/utils/mod.rs +4 -0
- package/src/rust/utils/pending_effects.rs +6 -30
- package/src/rust/workspace.rs +12 -0
- package/src/svg/status_pending.svg +3 -0
- package/src/themes/icons.css +1 -0
- package/src/themes/intl/ar.css +20 -7
- package/src/themes/intl/de.css +20 -7
- package/src/themes/intl/es.css +20 -7
- package/src/themes/intl/fr.css +20 -7
- package/src/themes/intl/ja.css +20 -7
- package/src/themes/intl/pt.css +20 -7
- package/src/themes/intl/zh.css +20 -7
- package/src/themes/intl.css +20 -7
- package/src/themes/monokai.css +1 -1
- package/src/themes/vaporwave.css +1 -1
- package/src/ts/perspective-viewer.ts +2 -0
- package/src/ts/plugin.ts +9 -0
- package/src/ts/ts-rs/AddPanelOptions.ts +10 -0
- package/src/ts/ts-rs/ExportMethod.ts +1 -1
- package/src/ts/ts-rs/{DatetimeColorMode.ts → GetViewMode.ts} +4 -1
- package/src/ts/ts-rs/GetViewOptions.ts +7 -0
- package/src/ts/ts-rs/RestoreOptions.ts +7 -1
- package/src/ts/ts-rs/RestoreWorkspaceOptions.ts +10 -0
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +31 -20
- package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
- package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
- package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
- package/src/rust/components/string_column_style.rs +0 -120
- package/src/rust/config/string_column_style.rs +0 -135
- package/src/ts/ts-rs/FormatMode.ts +0 -3
- package/src/ts/ts-rs/StringColorMode.ts +0 -3
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-adc6f3f79141112b → perspective-viewer-6813b568219c6763}/inline5.js +0 -0
|
@@ -100,6 +100,8 @@ fn get_menu_items(name: &str, is_chart: bool) -> Vec<ExportDropDownMenuItem> {
|
|
|
100
100
|
ExportMethod::Json.new_file(name, is_chart),
|
|
101
101
|
ExportMethod::Ndjson.new_file(name, is_chart),
|
|
102
102
|
ExportMethod::Arrow.new_file(name, is_chart),
|
|
103
|
+
ExportMethod::ArrowLz4.new_file(name, is_chart),
|
|
104
|
+
ExportMethod::ArrowZstd.new_file(name, is_chart),
|
|
103
105
|
ExportMethod::Html.new_file(name, is_chart),
|
|
104
106
|
ExportMethod::Plugin.new_file(name, is_chart),
|
|
105
107
|
]
|
|
@@ -109,6 +111,8 @@ fn get_menu_items(name: &str, is_chart: bool) -> Vec<ExportDropDownMenuItem> {
|
|
|
109
111
|
ExportMethod::Json.new_file(name, is_chart),
|
|
110
112
|
ExportMethod::Ndjson.new_file(name, is_chart),
|
|
111
113
|
ExportMethod::Arrow.new_file(name, is_chart),
|
|
114
|
+
ExportMethod::ArrowLz4.new_file(name, is_chart),
|
|
115
|
+
ExportMethod::ArrowZstd.new_file(name, is_chart),
|
|
112
116
|
ExportMethod::Html.new_file(name, is_chart),
|
|
113
117
|
]
|
|
114
118
|
},
|
|
@@ -118,6 +122,8 @@ fn get_menu_items(name: &str, is_chart: bool) -> Vec<ExportDropDownMenuItem> {
|
|
|
118
122
|
ExportMethod::JsonAll.new_file(name, is_chart),
|
|
119
123
|
ExportMethod::NdjsonAll.new_file(name, is_chart),
|
|
120
124
|
ExportMethod::ArrowAll.new_file(name, is_chart),
|
|
125
|
+
ExportMethod::ArrowLz4All.new_file(name, is_chart),
|
|
126
|
+
ExportMethod::ArrowZstdAll.new_file(name, is_chart),
|
|
121
127
|
]),
|
|
122
128
|
ExportDropDownMenuItem::OptGroup("Config".into(), vec![
|
|
123
129
|
ExportMethod::JsonConfig.new_file(name, is_chart),
|
|
@@ -25,6 +25,10 @@ pub enum MainPanelMsg {
|
|
|
25
25
|
/// deliver in every observed context.
|
|
26
26
|
StagedChanged,
|
|
27
27
|
|
|
28
|
+
/// A layout tree was staged for the retained panel set
|
|
29
|
+
/// (`layout_staged` PubSub): re-render so `reconcile` applies it.
|
|
30
|
+
LayoutStaged,
|
|
31
|
+
|
|
28
32
|
/// The `<regular-layout>` tree changed (fired by its
|
|
29
33
|
/// `regular-layout-update` event). Used to detect panels removed from
|
|
30
34
|
/// the layout (e.g. a frame's close button) so they can be disposed.
|
|
@@ -250,6 +250,9 @@ pub struct MainPanel {
|
|
|
250
250
|
/// `Workspace::staged_changed` → [`MainPanelMsg::StagedChanged`] on THIS
|
|
251
251
|
/// component's scope (see the message doc for why not the root's).
|
|
252
252
|
_staged_sub: crate::utils::Subscription,
|
|
253
|
+
|
|
254
|
+
/// `Workspace::layout_staged` → [`MainPanelMsg::LayoutStaged`].
|
|
255
|
+
_layout_staged_sub: crate::utils::Subscription,
|
|
253
256
|
}
|
|
254
257
|
|
|
255
258
|
impl Component for MainPanel {
|
|
@@ -351,6 +354,15 @@ impl Component for MainPanel {
|
|
|
351
354
|
.add_listener(move |()| cb.emit(()))
|
|
352
355
|
};
|
|
353
356
|
|
|
357
|
+
let layout_staged_sub = {
|
|
358
|
+
use crate::utils::AddListener;
|
|
359
|
+
let cb = ctx.link().callback(|_: ()| MainPanelMsg::LayoutStaged);
|
|
360
|
+
ctx.props()
|
|
361
|
+
.workspace
|
|
362
|
+
.layout_staged()
|
|
363
|
+
.add_listener(move |()| cb.emit(()))
|
|
364
|
+
};
|
|
365
|
+
|
|
354
366
|
Self {
|
|
355
367
|
main_panel_ref: NodeRef::default(),
|
|
356
368
|
layout_ref: NodeRef::default(),
|
|
@@ -368,6 +380,7 @@ impl Component for MainPanel {
|
|
|
368
380
|
theme_backgrounds: HashMap::new(),
|
|
369
381
|
stamped_frame_themes: None,
|
|
370
382
|
_staged_sub: staged_sub,
|
|
383
|
+
_layout_staged_sub: layout_staged_sub,
|
|
371
384
|
}
|
|
372
385
|
}
|
|
373
386
|
|
|
@@ -375,6 +388,7 @@ impl Component for MainPanel {
|
|
|
375
388
|
match msg {
|
|
376
389
|
MainPanelMsg::PointerEvent(event) => self.on_pointer_event(ctx, event),
|
|
377
390
|
MainPanelMsg::StagedChanged => true,
|
|
391
|
+
MainPanelMsg::LayoutStaged => true,
|
|
378
392
|
MainPanelMsg::LayoutUpdated => self.on_layout_updated(ctx),
|
|
379
393
|
MainPanelMsg::TabSelected(name) => self.on_tab_selected(ctx, name),
|
|
380
394
|
MainPanelMsg::ContextMenu(id, x, y) => self.on_context_menu(ctx, id, x, y),
|
|
@@ -19,10 +19,12 @@ use itertools::Itertools;
|
|
|
19
19
|
use perspective_client::config::ViewConfig;
|
|
20
20
|
use yew::prelude::*;
|
|
21
21
|
|
|
22
|
+
use crate::components::column_settings_sidebar::style_tab::alignment_field::AlignmentField;
|
|
23
|
+
use crate::components::column_settings_sidebar::style_tab::font_field::FontField;
|
|
22
24
|
use crate::components::column_settings_sidebar::style_tab::primitive_field::{
|
|
23
25
|
BoolField, ColorField, EnumField, NumberFieldPrimitive,
|
|
24
26
|
};
|
|
25
|
-
use crate::config::ControlSpec;
|
|
27
|
+
use crate::config::{Alignment, ControlSpec, FontToggle};
|
|
26
28
|
use crate::presentation::Presentation;
|
|
27
29
|
use crate::queries::get_plugin_config_schema;
|
|
28
30
|
use crate::renderer::Renderer;
|
|
@@ -72,9 +74,10 @@ pub fn PluginTab(props: &PluginTabProps) -> Html {
|
|
|
72
74
|
let schema = {
|
|
73
75
|
let renderer = props.renderer.clone();
|
|
74
76
|
let view_config = props.view_config.clone();
|
|
77
|
+
let plugin_config = props.plugin_config.clone();
|
|
75
78
|
use_memo(
|
|
76
79
|
(props.plugin_config.clone(), props.view_config.clone()),
|
|
77
|
-
move |_| match get_plugin_config_schema(&renderer, &view_config) {
|
|
80
|
+
move |_| match get_plugin_config_schema(&renderer, &view_config, Some(&plugin_config)) {
|
|
78
81
|
Ok(schema) => schema.fields,
|
|
79
82
|
Err(error) => {
|
|
80
83
|
tracing::error!("{}", error);
|
|
@@ -180,6 +183,58 @@ fn render_leaf(
|
|
|
180
183
|
/>
|
|
181
184
|
})
|
|
182
185
|
},
|
|
186
|
+
ControlSpec::Font {
|
|
187
|
+
key,
|
|
188
|
+
default,
|
|
189
|
+
size,
|
|
190
|
+
bold,
|
|
191
|
+
italic,
|
|
192
|
+
} => {
|
|
193
|
+
let current = raw_config
|
|
194
|
+
.get(&key)
|
|
195
|
+
.and_then(|v| v.as_str().map(|s| s.to_string()));
|
|
196
|
+
let toggle = |t: &FontToggle| raw_config.get(&t.key).and_then(|v| v.as_bool());
|
|
197
|
+
let size_current = size
|
|
198
|
+
.as_ref()
|
|
199
|
+
.and_then(|s| raw_config.get(&s.key))
|
|
200
|
+
.and_then(|v| v.as_f64());
|
|
201
|
+
let bold_current = bold.as_ref().and_then(toggle);
|
|
202
|
+
let italic_current = italic.as_ref().and_then(toggle);
|
|
203
|
+
Some(html! {
|
|
204
|
+
<FontField
|
|
205
|
+
field_key={key}
|
|
206
|
+
{default}
|
|
207
|
+
{current}
|
|
208
|
+
{size}
|
|
209
|
+
{size_current}
|
|
210
|
+
{bold}
|
|
211
|
+
{bold_current}
|
|
212
|
+
{italic}
|
|
213
|
+
{italic_current}
|
|
214
|
+
on_change={on_change.clone()}
|
|
215
|
+
/>
|
|
216
|
+
})
|
|
217
|
+
},
|
|
218
|
+
ControlSpec::Alignment {
|
|
219
|
+
key,
|
|
220
|
+
default,
|
|
221
|
+
corners,
|
|
222
|
+
} => {
|
|
223
|
+
let current = raw_config
|
|
224
|
+
.get(&key)
|
|
225
|
+
.and_then(|v| v.as_str())
|
|
226
|
+
.and_then(Alignment::parse);
|
|
227
|
+
|
|
228
|
+
Some(html! {
|
|
229
|
+
<AlignmentField
|
|
230
|
+
field_key={key}
|
|
231
|
+
{default}
|
|
232
|
+
{corners}
|
|
233
|
+
{current}
|
|
234
|
+
on_change={on_change.clone()}
|
|
235
|
+
/>
|
|
236
|
+
})
|
|
237
|
+
},
|
|
183
238
|
ControlSpec::Bool { key, default } => {
|
|
184
239
|
let current = raw_config.get(&key).and_then(|v| v.as_bool());
|
|
185
240
|
Some(html! {
|
|
@@ -220,7 +275,6 @@ fn render_leaf(
|
|
|
220
275
|
| ControlSpec::AggregateDepth
|
|
221
276
|
| ControlSpec::NumberSeriesStyle { .. }
|
|
222
277
|
| ControlSpec::DatetimeFormat { .. }
|
|
223
|
-
| ControlSpec::StringFormat
|
|
224
278
|
| ControlSpec::Symbols { .. }
|
|
225
279
|
| ControlSpec::NumberFormat { .. }
|
|
226
280
|
| ControlSpec::String { .. }
|
|
@@ -60,6 +60,10 @@ pub struct SettingsPanelProps {
|
|
|
60
60
|
/// prop-driven instead of reading `Renderer` directly.
|
|
61
61
|
pub plugin_config: PtrEqRc<serde_json::Map<String, serde_json::Value>>,
|
|
62
62
|
|
|
63
|
+
/// Snapshot of the active plugin's `columns_config` bucket, threaded
|
|
64
|
+
/// from `RendererProps` into `ColumnSelector`.
|
|
65
|
+
pub columns_config: PtrEqRc<ColumnConfigMap>,
|
|
66
|
+
|
|
63
67
|
/// Column currently being dragged (if any) — threaded to show drag
|
|
64
68
|
/// highlights without per-component `DragDrop` PubSub subscriptions.
|
|
65
69
|
pub drag_column: Option<String>,
|
|
@@ -114,6 +118,7 @@ impl PartialEq for SettingsPanelProps {
|
|
|
114
118
|
&& self.plugin_static_config == rhs.plugin_static_config
|
|
115
119
|
&& self.view_config == rhs.view_config
|
|
116
120
|
&& self.plugin_config == rhs.plugin_config
|
|
121
|
+
&& self.columns_config == rhs.columns_config
|
|
117
122
|
&& self.drag_column == rhs.drag_column
|
|
118
123
|
&& self.metadata == rhs.metadata
|
|
119
124
|
&& self.open_column_settings == rhs.open_column_settings
|
|
@@ -356,6 +361,7 @@ pub fn SettingsPanel(props: &SettingsPanelProps) -> Html {
|
|
|
356
361
|
named_column_count={props.named_column_count}
|
|
357
362
|
plugin_static_config={props.plugin_static_config.clone()}
|
|
358
363
|
view_config={props.view_config.clone()}
|
|
364
|
+
columns_config={props.columns_config.clone()}
|
|
359
365
|
drag_column={props.drag_column.clone()}
|
|
360
366
|
metadata={props.metadata.clone()}
|
|
361
367
|
selected_theme={props.selected_theme.clone()}
|
|
@@ -276,10 +276,19 @@ impl Component for StatusBar {
|
|
|
276
276
|
// TODO Memoizing these would reduce some vdom diffing later on
|
|
277
277
|
let onclose = ctx.link().callback(|_| StatusBarMsg::Eject);
|
|
278
278
|
let onpointerdown = ctx.link().callback(StatusBarMsg::PointerEvent);
|
|
279
|
-
let onexport = ctx.link().callback(|
|
|
280
|
-
|
|
279
|
+
let onexport = ctx.link().callback(|event: MouseEvent| {
|
|
280
|
+
event.prevent_default();
|
|
281
|
+
StatusBarMsg::Export
|
|
282
|
+
});
|
|
283
|
+
let oncopy = ctx.link().callback(|event: MouseEvent| {
|
|
284
|
+
event.prevent_default();
|
|
285
|
+
StatusBarMsg::Copy
|
|
286
|
+
});
|
|
281
287
|
let onreset = ctx.link().callback(StatusBarMsg::Reset);
|
|
282
|
-
let onnew = ctx.link().callback(|
|
|
288
|
+
let onnew = ctx.link().callback(|event: MouseEvent| {
|
|
289
|
+
event.prevent_default();
|
|
290
|
+
StatusBarMsg::NewPanel
|
|
291
|
+
});
|
|
283
292
|
let on_new_select = ctx.link().callback(StatusBarMsg::NewPanelPick);
|
|
284
293
|
let on_close_new = ctx.link().callback(|_| StatusBarMsg::CloseNewPanel);
|
|
285
294
|
|
|
@@ -51,6 +51,8 @@ pub fn StatusIndicator(props: &StatusIndicatorProps) -> Html {
|
|
|
51
51
|
&& matches!(props.session_props.has_table, Some(TableLoadState::Loading))
|
|
52
52
|
{
|
|
53
53
|
StatusIconState::Loading
|
|
54
|
+
} else if matches!(props.session_props.has_table, Some(TableLoadState::Pending)) {
|
|
55
|
+
StatusIconState::Pending
|
|
54
56
|
} else if props.update_count > 0 {
|
|
55
57
|
StatusIconState::Updating
|
|
56
58
|
} else if has_table_cells {
|
|
@@ -65,6 +67,7 @@ pub fn StatusIndicator(props: &StatusIndicatorProps) -> Html {
|
|
|
65
67
|
StatusIconState::Normal => "connected",
|
|
66
68
|
StatusIconState::Updating => "updating",
|
|
67
69
|
StatusIconState::Loading => "loading",
|
|
70
|
+
StatusIconState::Pending => "pending",
|
|
68
71
|
StatusIconState::Uninitialized => "uninitialized",
|
|
69
72
|
};
|
|
70
73
|
|
|
@@ -107,6 +110,7 @@ pub fn StatusIndicator(props: &StatusIndicatorProps) -> Html {
|
|
|
107
110
|
#[derive(Clone, Debug, PartialEq)]
|
|
108
111
|
enum StatusIconState {
|
|
109
112
|
Loading,
|
|
113
|
+
Pending,
|
|
110
114
|
Updating,
|
|
111
115
|
Errored(String, String, &'static str, bool),
|
|
112
116
|
Normal,
|
|
@@ -97,10 +97,10 @@ impl PerspectiveViewer {
|
|
|
97
97
|
derived
|
|
98
98
|
} else {
|
|
99
99
|
// Nothing derivable from the event's configs — fall back
|
|
100
|
-
// to the clicked-cell clause if the detail carried one
|
|
101
|
-
// else leave the current contribution untouched.
|
|
100
|
+
// to the clicked-cell clause if the detail carried one.
|
|
102
101
|
match selection.cell_fallback {
|
|
103
102
|
Some(x) => vec![x],
|
|
103
|
+
None if selection.clear_if_underivable => Vec::new(),
|
|
104
104
|
None => return false,
|
|
105
105
|
}
|
|
106
106
|
}
|
|
@@ -43,6 +43,10 @@ pub struct MasterSelection {
|
|
|
43
43
|
/// `filters` derives to nothing — e.g. a FLAT (un-grouped) datagrid
|
|
44
44
|
/// master, whose clicks carry no group-by path to filter on.
|
|
45
45
|
pub cell_fallback: Option<Filter>,
|
|
46
|
+
|
|
47
|
+
/// Whether an event deriving no clause and carrying no `cell_fallback`
|
|
48
|
+
/// clears the panel's contribution rather than leaving it untouched.
|
|
49
|
+
pub clear_if_underivable: bool,
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
@@ -190,7 +190,7 @@ impl PerspectiveViewer {
|
|
|
190
190
|
pub(super) fn on_panel_closed(&mut self, ctx: &Context<Self>, id: String) -> bool {
|
|
191
191
|
let id = PanelId::from(id);
|
|
192
192
|
if let Some(panel) = ctx.props().workspace.take_closing(&id) {
|
|
193
|
-
let eject = eject_panel(panel);
|
|
193
|
+
let eject = eject_panel(panel, Disposal::Reject);
|
|
194
194
|
match self.pending_closes.remove(&id) {
|
|
195
195
|
Some(completion) => completion.resolve_after(eject),
|
|
196
196
|
None => spawn_owned("close-panel", eject),
|
|
@@ -201,7 +201,7 @@ impl PerspectiveViewer {
|
|
|
201
201
|
|
|
202
202
|
match self.detach_panel(ctx, &id) {
|
|
203
203
|
Some(panel) => {
|
|
204
|
-
spawn_owned("close-panel", eject_panel(panel));
|
|
204
|
+
spawn_owned("close-panel", eject_panel(panel, Disposal::Reject));
|
|
205
205
|
true
|
|
206
206
|
},
|
|
207
207
|
None => false,
|
|
@@ -235,6 +235,7 @@ impl PerspectiveViewer {
|
|
|
235
235
|
None,
|
|
236
236
|
update,
|
|
237
237
|
client,
|
|
238
|
+
crate::session::MissingTable::Error,
|
|
238
239
|
)
|
|
239
240
|
.await?;
|
|
240
241
|
|
|
@@ -269,6 +270,7 @@ impl PerspectiveViewer {
|
|
|
269
270
|
None,
|
|
270
271
|
ViewerConfigInitial::new(table_name),
|
|
271
272
|
client,
|
|
273
|
+
crate::session::MissingTable::Error,
|
|
272
274
|
)
|
|
273
275
|
.await?;
|
|
274
276
|
|
|
@@ -313,6 +315,7 @@ impl PerspectiveViewer {
|
|
|
313
315
|
None,
|
|
314
316
|
ViewerConfigInitial::new(table),
|
|
315
317
|
Some(client),
|
|
318
|
+
crate::session::MissingTable::Error,
|
|
316
319
|
)
|
|
317
320
|
.await?;
|
|
318
321
|
|
|
@@ -334,7 +337,7 @@ impl PerspectiveViewer {
|
|
|
334
337
|
self._active_subscriptions = create_active_subscriptions(ctx, &session, &renderer);
|
|
335
338
|
self.session_props = session.to_props();
|
|
336
339
|
self.renderer_props = renderer.to_props(None);
|
|
337
|
-
self.update_count = session.
|
|
340
|
+
self.update_count = session.config_runs.count();
|
|
338
341
|
self.active_session = session;
|
|
339
342
|
self.active_renderer = renderer;
|
|
340
343
|
let presentation = ctx.props().presentation.clone();
|
|
@@ -95,6 +95,7 @@ impl PerspectiveViewer {
|
|
|
95
95
|
plugin_static_config={self.renderer_props.config.clone()}
|
|
96
96
|
{view_config}
|
|
97
97
|
plugin_config={self.renderer_props.plugin_config.clone()}
|
|
98
|
+
columns_config={self.renderer_props.columns_config.clone()}
|
|
98
99
|
{drag_column}
|
|
99
100
|
metadata={metadata.clone()}
|
|
100
101
|
open_column_settings={self.presentation_props.open_column_settings.clone()}
|
|
@@ -150,6 +150,7 @@ pub(super) fn global_filter_listener(
|
|
|
150
150
|
let selection = selected.then(|| MasterSelection {
|
|
151
151
|
cell_fallback: cell_fallback(&row, &column_names),
|
|
152
152
|
filters: insert_filters,
|
|
153
|
+
clear_if_underivable: true,
|
|
153
154
|
});
|
|
154
155
|
|
|
155
156
|
cb.emit((panel, selection));
|
|
@@ -210,6 +211,7 @@ pub(super) fn master_click_listener(
|
|
|
210
211
|
let selection = MasterSelection {
|
|
211
212
|
cell_fallback: cell_fallback(&row, &column_names),
|
|
212
213
|
filters: config.map(|x| x.filter).unwrap_or_default(),
|
|
214
|
+
clear_if_underivable: false,
|
|
213
215
|
};
|
|
214
216
|
|
|
215
217
|
cb.emit((panel, Some(selection)));
|
|
@@ -284,7 +286,8 @@ pub(super) fn create_active_subscriptions(
|
|
|
284
286
|
let sub4 = session.view_config_changed.add_notify_listener(&cb);
|
|
285
287
|
let sub5 = session.title_changed.add_notify_listener(&cb);
|
|
286
288
|
let sub6 = session
|
|
287
|
-
.
|
|
289
|
+
.config_runs
|
|
290
|
+
.changed()
|
|
288
291
|
.add_listener(ctx.link().callback(UpdateInFlight));
|
|
289
292
|
|
|
290
293
|
let sub7 = session.column_stats_changed.add_notify_listener(&cb);
|
|
@@ -304,12 +307,21 @@ pub(super) fn create_active_subscriptions(
|
|
|
304
307
|
}
|
|
305
308
|
});
|
|
306
309
|
|
|
310
|
+
let cb_columns_config = ctx.link().callback({
|
|
311
|
+
let renderer = renderer.clone();
|
|
312
|
+
move |_: ColumnConfigMap| UpdateRenderer(Box::new(renderer.to_props(None)))
|
|
313
|
+
});
|
|
314
|
+
|
|
307
315
|
let sub1 = renderer.plugin_changed.add_listener(cb_plugin);
|
|
308
316
|
let sub2 = renderer
|
|
309
317
|
.plugin_config_changed
|
|
310
318
|
.add_listener(cb_plugin_config);
|
|
311
319
|
|
|
312
|
-
|
|
320
|
+
let sub3 = renderer
|
|
321
|
+
.columns_config_changed
|
|
322
|
+
.add_listener(cb_columns_config);
|
|
323
|
+
|
|
324
|
+
vec![sub1, sub2, sub3]
|
|
313
325
|
};
|
|
314
326
|
|
|
315
327
|
let mut subscriptions = Vec::new();
|
|
@@ -124,8 +124,8 @@ pub struct PerspectiveViewer {
|
|
|
124
124
|
dragdrop_props: crate::presentation::DragDropProps,
|
|
125
125
|
|
|
126
126
|
/// The active panel's in-flight config-run count — a LEVEL-triggered
|
|
127
|
-
/// snapshot of `Session::
|
|
128
|
-
///
|
|
127
|
+
/// snapshot of `Session::config_runs` (RAII-settled; assigned by
|
|
128
|
+
/// `UpdateInFlight`, re-read on retarget). Threaded to
|
|
129
129
|
/// `StatusIndicator` as the "updating" spinner.
|
|
130
130
|
update_count: u32,
|
|
131
131
|
|