@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
|
@@ -107,6 +107,13 @@ pub async fn txt_as_jsvalue(
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/// Generate a result `Blob` for all types of [`ExportMethod`].
|
|
110
|
+
/// The `window` (or a default one) with Arrow IPC body compression `codec`.
|
|
111
|
+
fn compressed(window: Option<ViewWindow>, codec: &str) -> Option<ViewWindow> {
|
|
112
|
+
let mut window = window.unwrap_or_default();
|
|
113
|
+
window.compression = Some(codec.to_owned());
|
|
114
|
+
Some(window)
|
|
115
|
+
}
|
|
116
|
+
|
|
110
117
|
pub async fn export_method_to_blob(
|
|
111
118
|
session: &Session,
|
|
112
119
|
renderer: &Renderer,
|
|
@@ -152,6 +159,36 @@ pub async fn export_method_to_blob(
|
|
|
152
159
|
ExportMethod::ArrowAll => crate::queries::arrow_as_jsvalue(session, true, None)
|
|
153
160
|
.await?
|
|
154
161
|
.as_blob(),
|
|
162
|
+
ExportMethod::ArrowLz4 => {
|
|
163
|
+
crate::queries::arrow_as_jsvalue(session, false, compressed(None, "lz4"))
|
|
164
|
+
.await?
|
|
165
|
+
.as_blob()
|
|
166
|
+
},
|
|
167
|
+
ExportMethod::ArrowLz4Selected => {
|
|
168
|
+
crate::queries::arrow_as_jsvalue(session, false, compressed(viewport, "lz4"))
|
|
169
|
+
.await?
|
|
170
|
+
.as_blob()
|
|
171
|
+
},
|
|
172
|
+
ExportMethod::ArrowLz4All => {
|
|
173
|
+
crate::queries::arrow_as_jsvalue(session, true, compressed(None, "lz4"))
|
|
174
|
+
.await?
|
|
175
|
+
.as_blob()
|
|
176
|
+
},
|
|
177
|
+
ExportMethod::ArrowZstd => {
|
|
178
|
+
crate::queries::arrow_as_jsvalue(session, false, compressed(None, "zstd"))
|
|
179
|
+
.await?
|
|
180
|
+
.as_blob()
|
|
181
|
+
},
|
|
182
|
+
ExportMethod::ArrowZstdSelected => {
|
|
183
|
+
crate::queries::arrow_as_jsvalue(session, false, compressed(viewport, "zstd"))
|
|
184
|
+
.await?
|
|
185
|
+
.as_blob()
|
|
186
|
+
},
|
|
187
|
+
ExportMethod::ArrowZstdAll => {
|
|
188
|
+
crate::queries::arrow_as_jsvalue(session, true, compressed(None, "zstd"))
|
|
189
|
+
.await?
|
|
190
|
+
.as_blob()
|
|
191
|
+
},
|
|
155
192
|
ExportMethod::Html => html_as_jsvalue(session, renderer, presentation)
|
|
156
193
|
.await?
|
|
157
194
|
.as_blob(),
|
|
@@ -212,6 +249,36 @@ pub async fn export_method_to_jsvalue(
|
|
|
212
249
|
ExportMethod::ArrowAll => crate::queries::arrow_as_jsvalue(session, true, None)
|
|
213
250
|
.await?
|
|
214
251
|
.into(),
|
|
252
|
+
ExportMethod::ArrowLz4 => {
|
|
253
|
+
crate::queries::arrow_as_jsvalue(session, false, compressed(None, "lz4"))
|
|
254
|
+
.await?
|
|
255
|
+
.into()
|
|
256
|
+
},
|
|
257
|
+
ExportMethod::ArrowLz4Selected => {
|
|
258
|
+
crate::queries::arrow_as_jsvalue(session, false, compressed(viewport, "lz4"))
|
|
259
|
+
.await?
|
|
260
|
+
.into()
|
|
261
|
+
},
|
|
262
|
+
ExportMethod::ArrowLz4All => {
|
|
263
|
+
crate::queries::arrow_as_jsvalue(session, true, compressed(None, "lz4"))
|
|
264
|
+
.await?
|
|
265
|
+
.into()
|
|
266
|
+
},
|
|
267
|
+
ExportMethod::ArrowZstd => {
|
|
268
|
+
crate::queries::arrow_as_jsvalue(session, false, compressed(None, "zstd"))
|
|
269
|
+
.await?
|
|
270
|
+
.into()
|
|
271
|
+
},
|
|
272
|
+
ExportMethod::ArrowZstdSelected => {
|
|
273
|
+
crate::queries::arrow_as_jsvalue(session, false, compressed(viewport, "zstd"))
|
|
274
|
+
.await?
|
|
275
|
+
.into()
|
|
276
|
+
},
|
|
277
|
+
ExportMethod::ArrowZstdAll => {
|
|
278
|
+
crate::queries::arrow_as_jsvalue(session, true, compressed(None, "zstd"))
|
|
279
|
+
.await?
|
|
280
|
+
.into()
|
|
281
|
+
},
|
|
215
282
|
ExportMethod::Html => html_as_jsvalue(session, renderer, presentation).await?,
|
|
216
283
|
ExportMethod::Plugin if renderer.is_chart() => {
|
|
217
284
|
png_as_jsvalue(session, renderer).await?.into()
|
|
@@ -17,7 +17,7 @@ use crate::config::*;
|
|
|
17
17
|
use crate::custom_events::wire_panel_events;
|
|
18
18
|
use crate::presentation::*;
|
|
19
19
|
use crate::renderer::*;
|
|
20
|
-
use crate::session::{ResetOptions, Session};
|
|
20
|
+
use crate::session::{Disposal, MissingTable, ResetOptions, Session};
|
|
21
21
|
use crate::tasks::*;
|
|
22
22
|
use crate::utils::*;
|
|
23
23
|
use crate::workspace::{Panel, PanelId, PanelPhase, Workspace};
|
|
@@ -76,6 +76,7 @@ fn wire_panel_render_sub(session: &Session, renderer: &Renderer) -> Subscription
|
|
|
76
76
|
/// one. `theme` is stripped (element-level, not per-panel) and `client` —
|
|
77
77
|
/// or the element's default client when `None` — is bound so the config's
|
|
78
78
|
/// `table` resolves against it.
|
|
79
|
+
#[allow(clippy::too_many_arguments)]
|
|
79
80
|
pub(crate) async fn create_panel(
|
|
80
81
|
elem: &HtmlElement,
|
|
81
82
|
presentation: &Presentation,
|
|
@@ -84,6 +85,7 @@ pub(crate) async fn create_panel(
|
|
|
84
85
|
id: Option<PanelId>,
|
|
85
86
|
config: ViewerConfigInitial,
|
|
86
87
|
client: Option<perspective_client::Client>,
|
|
88
|
+
missing: MissingTable,
|
|
87
89
|
) -> ApiResult<PanelId> {
|
|
88
90
|
let (id, session, renderer, update) = create_panel_model(
|
|
89
91
|
elem,
|
|
@@ -120,6 +122,7 @@ pub(crate) async fn create_panel(
|
|
|
120
122
|
RestoreMode::Fresh,
|
|
121
123
|
update,
|
|
122
124
|
crate::tasks::RestoreErrors::Publish,
|
|
125
|
+
missing,
|
|
123
126
|
)
|
|
124
127
|
.await;
|
|
125
128
|
|
|
@@ -219,19 +222,19 @@ pub(crate) fn place_reserved(
|
|
|
219
222
|
/// renderer (slot-scoped plugin + light-DOM cleanup) and eject its table.
|
|
220
223
|
/// Shared by the root's `ClosePanel` handler and `restoreWorkspace`'s
|
|
221
224
|
/// batch replacement of the pre-existing panel set.
|
|
222
|
-
pub(crate) fn eject_panel(panel: Panel) -> ApiFuture<()> {
|
|
223
|
-
|
|
224
|
-
let dispose_task = panel.renderer.dispose();
|
|
225
|
-
let reset_task = panel.session.reset(ResetOptions {
|
|
226
|
-
config: true,
|
|
227
|
-
expressions: true,
|
|
228
|
-
table: Some(session::TableIntermediateState::Ejected),
|
|
229
|
-
..ResetOptions::default()
|
|
230
|
-
});
|
|
231
|
-
|
|
225
|
+
pub(crate) fn eject_panel(panel: Panel, disposal: Disposal) -> ApiFuture<()> {
|
|
226
|
+
panel.session.mark_disposed(disposal);
|
|
232
227
|
ApiFuture::new(async move {
|
|
233
|
-
|
|
234
|
-
|
|
228
|
+
panel.renderer.dispose().await?;
|
|
229
|
+
let was_errored = panel.session.is_errored();
|
|
230
|
+
let reset = panel.session.reset(ResetOptions {
|
|
231
|
+
config: true,
|
|
232
|
+
expressions: true,
|
|
233
|
+
table: Some(session::TableIntermediateState::Ejected),
|
|
234
|
+
..ResetOptions::default()
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
match reset.await.ignore_view_delete() {
|
|
235
238
|
Err(_) if was_errored => Ok(()),
|
|
236
239
|
Err(e) => Err(e),
|
|
237
240
|
Ok(_) => Ok(()),
|
|
@@ -22,7 +22,7 @@ use yew::prelude::*;
|
|
|
22
22
|
use crate::config::{ColumnConfigUpdate, PluginConfigUpdate};
|
|
23
23
|
use crate::presentation::Presentation;
|
|
24
24
|
use crate::renderer::{RenderContext, Renderer};
|
|
25
|
-
use crate::session::{BindDisposition, Session};
|
|
25
|
+
use crate::session::{BindDisposition, Disposal, Session};
|
|
26
26
|
use crate::utils::RenderGuard;
|
|
27
27
|
|
|
28
28
|
/// Snapshot → validate → bind → cache + pin the [`RenderContext`]. The core
|
|
@@ -227,6 +227,13 @@ pub(crate) async fn locked_run(
|
|
|
227
227
|
renderer
|
|
228
228
|
.clone()
|
|
229
229
|
.render_task(|guard| async move {
|
|
230
|
+
if let Some(disposal) = session.disposal() {
|
|
231
|
+
return match (disposal, spec.origin) {
|
|
232
|
+
(Disposal::Reject, RunOrigin::Public) => Err(ApiError::new("Panel disposed")),
|
|
233
|
+
_ => Ok(()),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
230
237
|
renderer.mount_active_plugin()?;
|
|
231
238
|
if let Some(task) = spec.task {
|
|
232
239
|
task.await?;
|
|
@@ -251,6 +258,18 @@ pub(crate) async fn locked_run(
|
|
|
251
258
|
let view_config_snapshot = session.get_view_config().clone();
|
|
252
259
|
let plugin_config_changed =
|
|
253
260
|
renderer.update_plugin_config(&view_config_snapshot, spec.plugin_config)?;
|
|
261
|
+
let plugin_config_snapshot = renderer.get_plugin_config();
|
|
262
|
+
let plugin_update =
|
|
263
|
+
JsValue::from_serde_ext(&plugin_config_snapshot).unwrap_or(JsValue::NULL);
|
|
264
|
+
|
|
265
|
+
let plugin_restored = plugin_config_changed || plugin_swapped;
|
|
266
|
+
if plugin_restored {
|
|
267
|
+
let columns_config = renderer
|
|
268
|
+
.all_columns_configs_materialized(&view_config_snapshot, &session)
|
|
269
|
+
.await;
|
|
270
|
+
plugin.restore(&plugin_update, Some(&columns_config))?;
|
|
271
|
+
}
|
|
272
|
+
|
|
254
273
|
let columns_config_changed = renderer.update_columns_configs(
|
|
255
274
|
&view_config_snapshot,
|
|
256
275
|
&session,
|
|
@@ -258,17 +277,16 @@ pub(crate) async fn locked_run(
|
|
|
258
277
|
)?;
|
|
259
278
|
|
|
260
279
|
let changed = plugin_config_changed || columns_config_changed;
|
|
261
|
-
if
|
|
262
|
-
let plugin_config_snapshot = renderer.get_plugin_config();
|
|
263
|
-
let plugin_update =
|
|
264
|
-
JsValue::from_serde_ext(&plugin_config_snapshot).unwrap_or(JsValue::NULL);
|
|
280
|
+
if columns_config_changed {
|
|
265
281
|
let columns_config = renderer
|
|
266
282
|
.all_columns_configs_materialized(&view_config_snapshot, &session)
|
|
267
283
|
.await;
|
|
268
284
|
plugin.restore(&plugin_update, Some(&columns_config))?;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
285
|
+
renderer.columns_config_changed.emit(columns_config);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if plugin_config_changed {
|
|
289
|
+
renderer.plugin_config_changed.emit(plugin_config_snapshot);
|
|
272
290
|
}
|
|
273
291
|
|
|
274
292
|
if spec
|
|
@@ -16,7 +16,9 @@ use perspective_client::utils::PerspectiveResultExt;
|
|
|
16
16
|
use crate::config::*;
|
|
17
17
|
use crate::presentation::Presentation;
|
|
18
18
|
use crate::renderer::Renderer;
|
|
19
|
-
use crate::session::{
|
|
19
|
+
use crate::session::{
|
|
20
|
+
LoadGuard, MissingTable, ResetOptions, Session, TableIntermediateState, probe_table,
|
|
21
|
+
};
|
|
20
22
|
use crate::tasks::*;
|
|
21
23
|
use crate::workspace::Workspace;
|
|
22
24
|
use crate::*;
|
|
@@ -38,27 +40,107 @@ pub(crate) enum RestoreErrors {
|
|
|
38
40
|
Suppress,
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
/// The client to bind and the opened `Table`, or `None` when pending.
|
|
44
|
+
type Probed = (
|
|
45
|
+
perspective_client::Client,
|
|
46
|
+
Option<perspective_client::Table>,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
/// Resolve and probe the client hosting `name` without touching the
|
|
50
|
+
/// session's own binding.
|
|
51
|
+
async fn probe(
|
|
52
|
+
session: &Session,
|
|
53
|
+
workspace: &Workspace,
|
|
54
|
+
name: &str,
|
|
55
|
+
missing: MissingTable,
|
|
56
|
+
) -> ApiResult<Probed> {
|
|
57
|
+
let current = session.get_client();
|
|
58
|
+
let resolved = workspace
|
|
59
|
+
.resolve_client_for_table(name, current.as_ref())
|
|
60
|
+
.await;
|
|
61
|
+
|
|
62
|
+
let client = resolved.or(current).into_apierror()?;
|
|
63
|
+
let table = probe_table(&client, name, missing).await?;
|
|
64
|
+
Ok((client, table))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// Bind an unbound or same-named session to `name`.
|
|
41
68
|
pub(crate) async fn bind_table_task(
|
|
42
69
|
session: &Session,
|
|
43
70
|
workspace: &Workspace,
|
|
44
71
|
name: String,
|
|
72
|
+
missing: MissingTable,
|
|
45
73
|
) -> ApiResult<()> {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
.
|
|
49
|
-
.await
|
|
74
|
+
if session
|
|
75
|
+
.get_table()
|
|
76
|
+
.is_some_and(|t| t.get_name() == name.as_str())
|
|
50
77
|
{
|
|
51
|
-
|
|
78
|
+
return Ok(());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let (client, table) = probe(session, workspace, &name, missing).await?;
|
|
82
|
+
session.set_client(client);
|
|
83
|
+
match table {
|
|
84
|
+
Some(table) => session.bind_table(table).await?,
|
|
85
|
+
None => session.pend_table(name).await?,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
session.commit_table_defaults();
|
|
89
|
+
Ok(())
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// Rebind a session to `name`, probing the incoming table before the
|
|
93
|
+
/// outgoing binding is dropped and replaying `load`'s journal over the
|
|
94
|
+
/// incoming table's defaults.
|
|
95
|
+
async fn rebind_table_task(
|
|
96
|
+
session: &Session,
|
|
97
|
+
renderer: &Renderer,
|
|
98
|
+
workspace: &Workspace,
|
|
99
|
+
name: String,
|
|
100
|
+
missing: MissingTable,
|
|
101
|
+
load: &LoadGuard,
|
|
102
|
+
) -> ApiResult<()> {
|
|
103
|
+
let probed = probe(session, workspace, &name, missing).await;
|
|
104
|
+
let journal = load.claim();
|
|
105
|
+
let (client, table) = probed?;
|
|
106
|
+
let Some(journal) = journal else {
|
|
107
|
+
return Ok(());
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
session
|
|
111
|
+
.reset(ResetOptions {
|
|
112
|
+
config: true,
|
|
113
|
+
expressions: true,
|
|
114
|
+
stats: true,
|
|
115
|
+
table: Some(TableIntermediateState::Reloaded),
|
|
116
|
+
})
|
|
117
|
+
.await?;
|
|
118
|
+
|
|
119
|
+
session.set_client(client);
|
|
120
|
+
match table {
|
|
121
|
+
Some(table) => session.bind_table(table).await?,
|
|
122
|
+
None => session.pend_table(name).await?,
|
|
52
123
|
}
|
|
53
124
|
|
|
54
|
-
session.set_table(name).await?;
|
|
55
125
|
session.commit_table_defaults();
|
|
126
|
+
for delta in journal {
|
|
127
|
+
session.commit_view_config(delta)?;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
session.commit_table_defaults();
|
|
131
|
+
if session.get_table().is_none()
|
|
132
|
+
&& let Some(plugin) = renderer.active_plugin()
|
|
133
|
+
{
|
|
134
|
+
plugin.clear().await?;
|
|
135
|
+
}
|
|
136
|
+
|
|
56
137
|
Ok(())
|
|
57
138
|
}
|
|
58
139
|
|
|
59
140
|
/// Apply a [`ViewerConfigUpdate`] to a single panel and re-draw — the one
|
|
60
141
|
/// pipeline shared by `restorePanel` (an existing panel), `restoreWorkspace`,
|
|
61
142
|
/// and `addPanel` (both fresh panels).
|
|
143
|
+
#[allow(clippy::too_many_arguments)]
|
|
62
144
|
pub(crate) async fn restore_panel(
|
|
63
145
|
session: &Session,
|
|
64
146
|
renderer: &Renderer,
|
|
@@ -67,6 +149,7 @@ pub(crate) async fn restore_panel(
|
|
|
67
149
|
mode: RestoreMode,
|
|
68
150
|
mut update: ViewerConfigUpdate,
|
|
69
151
|
errors: RestoreErrors,
|
|
152
|
+
missing: MissingTable,
|
|
70
153
|
) -> ApiResult<()> {
|
|
71
154
|
let active = matches!(mode, RestoreMode::Existing { active: true });
|
|
72
155
|
let fresh = matches!(mode, RestoreMode::Fresh);
|
|
@@ -100,21 +183,24 @@ pub(crate) async fn restore_panel(
|
|
|
100
183
|
let rollback =
|
|
101
184
|
matches!(errors, RestoreErrors::Suppress).then(|| session.get_view_config().clone());
|
|
102
185
|
|
|
103
|
-
let
|
|
104
|
-
|
|
105
|
-
|
|
186
|
+
let binding_before = (
|
|
187
|
+
session.get_table().map(|t| t.get_name().to_owned()),
|
|
188
|
+
session.pending_table(),
|
|
189
|
+
);
|
|
106
190
|
|
|
107
|
-
let
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
191
|
+
let load = match &update.table {
|
|
192
|
+
OptionalUpdate::Update(name)
|
|
193
|
+
if session.is_errored()
|
|
194
|
+
|| (!fresh
|
|
195
|
+
&& session
|
|
196
|
+
.get_table()
|
|
197
|
+
.map(|t| t.get_name() != name.as_str())
|
|
198
|
+
.unwrap_or(true)) =>
|
|
199
|
+
{
|
|
200
|
+
Some(session.begin_pending_load())
|
|
201
|
+
},
|
|
202
|
+
_ => None,
|
|
203
|
+
};
|
|
118
204
|
|
|
119
205
|
let result = restore_and_render(
|
|
120
206
|
session,
|
|
@@ -123,27 +209,40 @@ pub(crate) async fn restore_panel(
|
|
|
123
209
|
RunOrigin::Public,
|
|
124
210
|
update.clone(),
|
|
125
211
|
{
|
|
126
|
-
clone!(session, update.table, workspace);
|
|
212
|
+
clone!(session, renderer, update.table, workspace, load);
|
|
127
213
|
async move {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
214
|
+
let OptionalUpdate::Update(name) = table else {
|
|
215
|
+
return Ok(());
|
|
216
|
+
};
|
|
132
217
|
|
|
133
|
-
|
|
218
|
+
match &load {
|
|
219
|
+
Some(load) => {
|
|
220
|
+
rebind_table_task(&session, &renderer, &workspace, name, missing, load)
|
|
221
|
+
.await
|
|
222
|
+
},
|
|
223
|
+
None => bind_table_task(&session, &workspace, name, missing).await,
|
|
134
224
|
}
|
|
135
|
-
|
|
136
|
-
Ok(())
|
|
137
225
|
}
|
|
138
226
|
},
|
|
139
227
|
)
|
|
140
228
|
.await;
|
|
141
229
|
|
|
230
|
+
if let Some(load) = &load {
|
|
231
|
+
load.close();
|
|
232
|
+
}
|
|
233
|
+
|
|
142
234
|
if let Err(e) = &result {
|
|
143
235
|
match errors {
|
|
144
236
|
RestoreErrors::Publish => session.set_error(false, e.clone()).await?,
|
|
145
237
|
RestoreErrors::Suppress => {
|
|
146
|
-
|
|
238
|
+
let binding_after = (
|
|
239
|
+
session.get_table().map(|t| t.get_name().to_owned()),
|
|
240
|
+
session.pending_table(),
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
if let Some(config) = rollback
|
|
244
|
+
&& binding_after == binding_before
|
|
245
|
+
{
|
|
147
246
|
session.commit_view_config(config.into()).unwrap_or_log();
|
|
148
247
|
}
|
|
149
248
|
},
|
|
@@ -51,6 +51,9 @@ pub fn send_column_config(
|
|
|
51
51
|
renderer
|
|
52
52
|
.update_lazy(async move { Ok(session.get_view_with_dimensions()) })
|
|
53
53
|
.await?;
|
|
54
|
+
renderer
|
|
55
|
+
.columns_config_changed
|
|
56
|
+
.emit(columns_configs.clone());
|
|
54
57
|
renderer.column_style_changed.emit(columns_configs);
|
|
55
58
|
Ok(())
|
|
56
59
|
})
|