@perspective-dev/viewer 5.5.0 → 5.6.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/README.md +82 -3
- package/dist/cdn/perspective-viewer.js +9 -9
- package/dist/cdn/perspective-viewer.js.map +3 -3
- 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/column-format.js +2 -0
- package/dist/esm/column-format.js.map +7 -0
- package/dist/esm/extensions.d.ts +3 -13
- package/dist/esm/perspective-viewer.d.ts +1 -1
- package/dist/esm/perspective-viewer.js +9 -9
- package/dist/esm/perspective-viewer.js.map +3 -3
- package/dist/esm/plugin.d.ts +4 -1
- package/dist/esm/select-detail.d.ts +15 -0
- package/dist/esm/select-detail.js +2 -0
- package/dist/esm/select-detail.js.map +7 -0
- package/dist/esm/ts-rs/DerivedTableConfig.d.ts +35 -0
- package/dist/esm/ts-rs/ExportMethod.d.ts +1 -1
- package/dist/esm/ts-rs/PanelViewerConfig.d.ts +7 -6
- package/dist/esm/ts-rs/RestoreOptions.d.ts +3 -7
- package/dist/esm/ts-rs/TableRef.d.ts +9 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +7 -6
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +7 -5
- package/dist/esm/ts-rs/WorkspaceConfig.d.ts +9 -1
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +9 -0
- package/dist/wasm/perspective-viewer.d.ts +126 -35
- package/dist/wasm/perspective-viewer.js +320 -185
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +21 -17
- package/package.json +33 -20
- package/src/css/column-selector.css +205 -50
- package/src/css/ui/containers/context-menu.css +12 -1
- package/src/css/ui/containers/dropdown-menu-items.css +29 -0
- package/src/css/ui/containers/scroll-panel.css +4 -1
- package/src/rust/agent/client/protocol.rs +0 -89
- package/src/rust/agent/markdown/mod.rs +0 -238
- package/src/rust/agent/preamble.md +1 -0
- package/src/rust/agent/tools.rs +2 -16
- package/src/rust/components/column_selector/active_column.rs +15 -5
- package/src/rust/components/column_selector/add_expression_button.rs +9 -26
- package/src/rust/components/column_selector/config_selector.rs +34 -6
- package/src/rust/components/column_selector/derived_control.rs +229 -0
- package/src/rust/components/column_selector/expr_edit_button.rs +3 -2
- package/src/rust/components/column_selector/filter_column.rs +0 -2
- package/src/rust/components/column_selector/inactive_column.rs +4 -5
- package/src/rust/components/column_selector/pivot_column.rs +21 -1
- package/src/rust/components/column_selector/sort_column.rs +4 -3
- package/src/rust/components/column_selector.rs +21 -1
- package/src/rust/components/column_settings_sidebar/save_settings.rs +5 -3
- package/src/rust/components/column_settings_sidebar/style_tab.rs +1 -0
- package/src/rust/components/column_settings_sidebar.rs +25 -19
- package/src/rust/components/debug_panel.rs +38 -29
- package/src/rust/components/dragdrop_list.rs +8 -9
- package/src/rust/components/export_dropdown.rs +6 -0
- package/src/rust/components/main_panel/msg.rs +6 -4
- package/src/rust/components/main_panel/reconcile.rs +6 -1
- package/src/rust/components/main_panel/render.rs +70 -51
- package/src/rust/components/main_panel/update.rs +39 -1
- package/src/rust/components/main_panel.rs +97 -59
- package/src/rust/components/new_panel_menu.rs +69 -1
- package/src/rust/components/panel_menu.rs +63 -12
- package/src/rust/components/plugin_tab.rs +3 -2
- package/src/rust/components/render_warning.rs +2 -1
- package/src/rust/components/settings_panel.rs +4 -4
- package/src/rust/components/status_bar.rs +80 -21
- package/src/rust/components/status_indicator.rs +8 -1
- package/src/rust/components/viewer/filters.rs +15 -3
- package/src/rust/components/viewer/msg.rs +8 -0
- package/src/rust/components/viewer/panels.rs +44 -4
- package/src/rust/components/viewer/render.rs +1 -0
- package/src/rust/components/viewer/settings.rs +0 -22
- package/src/rust/components/viewer/snapshots.rs +2 -2
- package/src/rust/components/viewer/wiring.rs +18 -1
- package/src/rust/components/viewer.rs +47 -27
- package/src/rust/components/window_editor.rs +5 -4
- package/src/rust/config/column_config_schema.rs +38 -377
- package/src/rust/config/export_method.rs +24 -0
- package/src/rust/config/number_string_format.rs +0 -94
- package/src/rust/config/options.rs +3 -7
- package/src/rust/config/plugin_static_config.rs +0 -42
- package/src/rust/config/viewer_config.rs +47 -17
- package/src/rust/config/workspace_config.rs +158 -128
- package/src/rust/custom_elements/viewer.rs +189 -129
- package/src/rust/custom_events.rs +33 -18
- package/src/rust/derived.rs +266 -0
- package/src/rust/exprtk/tokenize.rs +0 -54
- package/src/rust/js/plugin.rs +1 -1
- package/src/rust/lib.rs +3 -0
- package/src/rust/presentation.rs +23 -4
- package/src/rust/queries/column_locator.rs +55 -48
- package/src/rust/queries/get_viewer_config.rs +1 -1
- package/src/rust/queries/plugin_column_styles.rs +22 -23
- package/src/rust/renderer/dispatch.rs +2 -0
- package/src/rust/renderer/plugin_config.rs +652 -487
- package/src/rust/renderer/props.rs +4 -0
- package/src/rust/renderer/registry.rs +2 -6
- package/src/rust/renderer/state.rs +205 -0
- package/src/rust/renderer.rs +201 -59
- package/src/rust/session/metadata.rs +35 -19
- package/src/rust/session/op_queue.rs +430 -0
- package/src/rust/session/panel_state.rs +327 -0
- package/src/rust/session/view_subscription.rs +42 -3
- package/src/rust/session.rs +931 -419
- package/src/rust/tasks/apply_global_filters.rs +49 -35
- package/src/rust/tasks/auto_pause.rs +22 -12
- package/src/rust/tasks/copy_export.rs +72 -0
- package/src/rust/tasks/create_panel.rs +46 -21
- package/src/rust/tasks/derive.rs +312 -0
- package/src/rust/tasks/mod.rs +6 -2
- package/src/rust/tasks/pipeline.rs +152 -89
- package/src/rust/tasks/reset_all.rs +31 -20
- package/src/rust/tasks/restore_derived.rs +200 -0
- package/src/rust/tasks/restore_panel.rs +153 -141
- package/src/rust/tasks/send_column_config.rs +56 -29
- package/src/rust/tasks/send_plugin_config.rs +52 -23
- package/src/rust/tasks/set_edit_mode.rs +33 -25
- package/src/rust/tasks/sync_update_panels.rs +40 -13
- package/src/rust/tasks/table_lifecycle.rs +70 -34
- package/src/rust/tasks/transactional_restore.rs +387 -0
- package/src/rust/tasks/update_theme.rs +45 -6
- package/src/rust/ui/containers/scroll_panel.rs +17 -10
- package/src/rust/ui/containers/split_panel.rs +0 -41
- package/src/rust/ui/context_menu.rs +157 -18
- package/src/rust/ui/font_loader.rs +23 -35
- package/src/rust/ui/form/mirrored_textarea.rs +0 -12
- package/src/rust/ui/form/multi_stop_gradient_selector.rs +0 -89
- package/src/rust/ui/form/palette_selector.rs +0 -51
- package/src/rust/ui/portal.rs +4 -10
- package/src/rust/utils/browser/mod.rs +2 -3
- package/src/{ts/perspective-viewer.inline.ts → rust/utils/browser/mouse.rs} +11 -10
- package/src/rust/utils/browser/request_animation_frame.rs +27 -8
- package/src/rust/utils/css.rs +0 -360
- package/src/rust/utils/{tests/mod.rs → in_flight.rs} +62 -2
- package/src/rust/utils/local_fonts.rs +0 -36
- package/src/rust/utils/mod.rs +4 -3
- package/src/rust/utils/modal_position.rs +15 -21
- package/src/rust/utils/pending_effects.rs +6 -30
- package/src/rust/utils/{browser/tests/mod.rs → plugin_host_state.rs} +31 -1
- package/src/rust/utils/pubsub.rs +0 -1
- package/src/rust/workspace.rs +187 -140
- package/src/svg/derived.svg +6 -0
- package/src/themes/icons.css +1 -0
- package/src/themes/intl/ar.css +10 -0
- package/src/themes/intl/de.css +10 -0
- package/src/themes/intl/es.css +10 -0
- package/src/themes/intl/fr.css +10 -0
- package/src/themes/intl/ja.css +10 -0
- package/src/themes/intl/pt.css +10 -0
- package/src/themes/intl/zh.css +10 -0
- package/src/themes/intl.css +10 -0
- package/src/themes/monokai.css +1 -1
- package/src/themes/vaporwave.css +1 -1
- package/src/ts/extensions.ts +3 -36
- package/src/ts/perspective-viewer.ts +1 -1
- package/src/ts/plugin.ts +4 -1
- package/src/{rust/utils/tests/request_animation_frame.rs → ts/select-detail.ts} +32 -26
- package/src/ts/ts-rs/DerivedTableConfig.ts +22 -0
- package/src/ts/ts-rs/ExportMethod.ts +1 -1
- package/src/ts/ts-rs/PanelViewerConfig.ts +7 -6
- package/src/ts/ts-rs/RestoreOptions.ts +3 -7
- package/src/ts/ts-rs/TableRef.ts +9 -0
- package/src/ts/ts-rs/ViewerConfig.ts +7 -6
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +7 -5
- package/src/ts/ts-rs/WorkspaceConfig.ts +7 -1
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +7 -0
- package/dist/esm/perspective-viewer.inline.d.ts +0 -3
- package/dist/esm/perspective-viewer.inline.js +0 -21
- package/dist/esm/perspective-viewer.inline.js.map +0 -7
- package/src/rust/tasks/restore_and_render.rs +0 -107
- package/src/rust/utils/browser/tests/debounce.rs +0 -163
- package/src/rust/utils/tests/pubsub.rs +0 -95
- /package/dist/wasm/snippets/{perspective-viewer-ea71a3990cad35d7 → perspective-viewer-d0d525977a1acba2}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-ea71a3990cad35d7 → perspective-viewer-d0d525977a1acba2}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-ea71a3990cad35d7 → perspective-viewer-d0d525977a1acba2}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-ea71a3990cad35d7 → perspective-viewer-d0d525977a1acba2}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-ea71a3990cad35d7 → perspective-viewer-d0d525977a1acba2}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-ea71a3990cad35d7 → perspective-viewer-d0d525977a1acba2}/inline5.js +0 -0
|
@@ -226,241 +226,3 @@ impl Writer {
|
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
|
-
|
|
230
|
-
#[cfg(test)]
|
|
231
|
-
mod tests {
|
|
232
|
-
use super::events::{Align, Event, Tag};
|
|
233
|
-
|
|
234
|
-
fn parse(text: &str) -> Vec<Event> {
|
|
235
|
-
super::block::parse(text)
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
fn start(tag: Tag) -> Event {
|
|
239
|
-
Event::Start(tag)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
fn text(x: &str) -> Event {
|
|
243
|
-
Event::Text(x.to_owned())
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
#[test]
|
|
247
|
-
fn paragraph_and_emphasis() {
|
|
248
|
-
assert_eq!(parse("**Done!** Key *stats* here."), vec![
|
|
249
|
-
start(Tag::Paragraph),
|
|
250
|
-
start(Tag::Strong),
|
|
251
|
-
text("Done!"),
|
|
252
|
-
Event::End,
|
|
253
|
-
text(" Key "),
|
|
254
|
-
start(Tag::Emphasis),
|
|
255
|
-
text("stats"),
|
|
256
|
-
Event::End,
|
|
257
|
-
text(" here."),
|
|
258
|
-
Event::End,
|
|
259
|
-
]);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
#[test]
|
|
263
|
-
fn snake_case_is_not_emphasis() {
|
|
264
|
-
assert_eq!(parse("call get_schema then set_view_config"), vec![
|
|
265
|
-
start(Tag::Paragraph),
|
|
266
|
-
text("call get_schema then set_view_config"),
|
|
267
|
-
Event::End,
|
|
268
|
-
]);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
#[test]
|
|
272
|
-
fn nested_strong_emphasis() {
|
|
273
|
-
assert_eq!(parse("**bold with *ital* inside**"), vec![
|
|
274
|
-
start(Tag::Paragraph),
|
|
275
|
-
start(Tag::Strong),
|
|
276
|
-
text("bold with "),
|
|
277
|
-
start(Tag::Emphasis),
|
|
278
|
-
text("ital"),
|
|
279
|
-
Event::End,
|
|
280
|
-
text(" inside"),
|
|
281
|
-
Event::End,
|
|
282
|
-
Event::End,
|
|
283
|
-
]);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
#[test]
|
|
287
|
-
fn unpaired_delimiters_stay_literal() {
|
|
288
|
-
// Space on both sides ⇒ the runs can neither open nor close, so
|
|
289
|
-
// they stay in the running text buffer.
|
|
290
|
-
assert_eq!(parse("2 * 3 * 4 and a ~ tilde"), vec![
|
|
291
|
-
start(Tag::Paragraph),
|
|
292
|
-
text("2 * 3 * 4 and a ~ tilde"),
|
|
293
|
-
Event::End,
|
|
294
|
-
]);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
#[test]
|
|
298
|
-
fn code_spans_and_strikethrough() {
|
|
299
|
-
assert_eq!(parse("run `pnpm test` and ~~skip~~ this"), vec![
|
|
300
|
-
start(Tag::Paragraph),
|
|
301
|
-
text("run "),
|
|
302
|
-
Event::Code("pnpm test".to_owned()),
|
|
303
|
-
text(" and "),
|
|
304
|
-
start(Tag::Strikethrough),
|
|
305
|
-
text("skip"),
|
|
306
|
-
Event::End,
|
|
307
|
-
text(" this"),
|
|
308
|
-
Event::End,
|
|
309
|
-
]);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
#[test]
|
|
313
|
-
fn heading_rule_and_fence() {
|
|
314
|
-
assert_eq!(parse("## Stats\n\n---\n\n```sql\nSELECT 1;\n```"), vec![
|
|
315
|
-
start(Tag::Heading(2)),
|
|
316
|
-
text("Stats"),
|
|
317
|
-
Event::End,
|
|
318
|
-
Event::Rule,
|
|
319
|
-
start(Tag::CodeBlock(Some("sql".to_owned()))),
|
|
320
|
-
text("SELECT 1;\n"),
|
|
321
|
-
Event::End,
|
|
322
|
-
]);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
#[test]
|
|
326
|
-
fn nested_list_with_code_block_in_item() {
|
|
327
|
-
assert_eq!(
|
|
328
|
-
parse("- first\n- second:\n ```\n x = 1\n ```\n - inner"),
|
|
329
|
-
vec![
|
|
330
|
-
start(Tag::List(None)),
|
|
331
|
-
start(Tag::Item),
|
|
332
|
-
text("first"),
|
|
333
|
-
Event::End,
|
|
334
|
-
start(Tag::Item),
|
|
335
|
-
text("second:"),
|
|
336
|
-
start(Tag::CodeBlock(None)),
|
|
337
|
-
text("x = 1\n"),
|
|
338
|
-
Event::End,
|
|
339
|
-
start(Tag::List(None)),
|
|
340
|
-
start(Tag::Item),
|
|
341
|
-
text("inner"),
|
|
342
|
-
Event::End,
|
|
343
|
-
Event::End,
|
|
344
|
-
Event::End,
|
|
345
|
-
Event::End,
|
|
346
|
-
]
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
#[test]
|
|
351
|
-
fn ordered_list_start() {
|
|
352
|
-
assert_eq!(parse("3. three\n4. four"), vec![
|
|
353
|
-
start(Tag::List(Some(3))),
|
|
354
|
-
start(Tag::Item),
|
|
355
|
-
text("three"),
|
|
356
|
-
Event::End,
|
|
357
|
-
start(Tag::Item),
|
|
358
|
-
text("four"),
|
|
359
|
-
Event::End,
|
|
360
|
-
Event::End,
|
|
361
|
-
]);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
#[test]
|
|
365
|
-
fn table_with_alignment_and_pipe_in_code() {
|
|
366
|
-
assert_eq!(
|
|
367
|
-
parse("| Region | Sales |\n| :--- | ---: |\n| West | `a\\|b` |"),
|
|
368
|
-
vec![
|
|
369
|
-
start(Tag::Table(vec![Align::Left, Align::Right])),
|
|
370
|
-
start(Tag::TableHead),
|
|
371
|
-
start(Tag::TableCell),
|
|
372
|
-
text("Region"),
|
|
373
|
-
Event::End,
|
|
374
|
-
start(Tag::TableCell),
|
|
375
|
-
text("Sales"),
|
|
376
|
-
Event::End,
|
|
377
|
-
Event::End,
|
|
378
|
-
start(Tag::TableRow),
|
|
379
|
-
start(Tag::TableCell),
|
|
380
|
-
text("West"),
|
|
381
|
-
Event::End,
|
|
382
|
-
start(Tag::TableCell),
|
|
383
|
-
Event::Code("a|b".to_owned()),
|
|
384
|
-
Event::End,
|
|
385
|
-
Event::End,
|
|
386
|
-
Event::End,
|
|
387
|
-
]
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
#[test]
|
|
392
|
-
fn dashes_after_paragraph_are_a_rule_not_a_table() {
|
|
393
|
-
assert_eq!(parse("Title\n---"), vec![
|
|
394
|
-
start(Tag::Paragraph),
|
|
395
|
-
text("Title"),
|
|
396
|
-
Event::End,
|
|
397
|
-
Event::Rule,
|
|
398
|
-
]);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
#[test]
|
|
402
|
-
fn links_images_and_autolinks() {
|
|
403
|
-
assert_eq!(
|
|
404
|
-
parse("[safe](https://example.com \"hi\")  <https://a.co>"),
|
|
405
|
-
vec![
|
|
406
|
-
start(Tag::Paragraph),
|
|
407
|
-
start(Tag::Link {
|
|
408
|
-
dest_url: "https://example.com".to_owned(),
|
|
409
|
-
title: "hi".to_owned(),
|
|
410
|
-
}),
|
|
411
|
-
text("safe"),
|
|
412
|
-
Event::End,
|
|
413
|
-
text(" "),
|
|
414
|
-
start(Tag::Image {
|
|
415
|
-
dest_url: "https://example.com/x.png".to_owned(),
|
|
416
|
-
}),
|
|
417
|
-
text("leak"),
|
|
418
|
-
Event::End,
|
|
419
|
-
text(" "),
|
|
420
|
-
start(Tag::Link {
|
|
421
|
-
dest_url: "https://a.co".to_owned(),
|
|
422
|
-
title: String::new(),
|
|
423
|
-
}),
|
|
424
|
-
text("https://a.co"),
|
|
425
|
-
Event::End,
|
|
426
|
-
Event::End,
|
|
427
|
-
]
|
|
428
|
-
);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
#[test]
|
|
432
|
-
fn raw_html_is_literal_text() {
|
|
433
|
-
assert_eq!(parse("<script>alert(1)</script>"), vec![
|
|
434
|
-
start(Tag::Paragraph),
|
|
435
|
-
text("<script>alert(1)</script>"),
|
|
436
|
-
Event::End,
|
|
437
|
-
]);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
#[test]
|
|
441
|
-
fn blockquote_and_breaks() {
|
|
442
|
-
assert_eq!(parse("> quoted\n> more\n\nafter \nbreak"), vec![
|
|
443
|
-
start(Tag::BlockQuote),
|
|
444
|
-
start(Tag::Paragraph),
|
|
445
|
-
text("quoted"),
|
|
446
|
-
Event::SoftBreak,
|
|
447
|
-
text("more"),
|
|
448
|
-
Event::End,
|
|
449
|
-
Event::End,
|
|
450
|
-
start(Tag::Paragraph),
|
|
451
|
-
text("after"),
|
|
452
|
-
Event::HardBreak,
|
|
453
|
-
text("break"),
|
|
454
|
-
Event::End,
|
|
455
|
-
]);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
#[test]
|
|
459
|
-
fn entities_decode_or_stay_literal() {
|
|
460
|
-
assert_eq!(parse("a & b A &unknown; c"), vec![
|
|
461
|
-
start(Tag::Paragraph),
|
|
462
|
-
text("a & b A &unknown; c"),
|
|
463
|
-
Event::End,
|
|
464
|
-
]);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
@@ -11,6 +11,7 @@ Panels: the viewer is a dashboard that can hold multiple panels (independent sid
|
|
|
11
11
|
|
|
12
12
|
Rules:
|
|
13
13
|
- Column names in configs must match the schema exactly, including case.
|
|
14
|
+
- A `set_view_config` or `add_panel` call that returns an error changed NOTHING - the viewer is exactly as it was, so there is nothing to undo.
|
|
14
15
|
- If a tool returns an error, correct your input and retry. If the same call fails twice with the same error, stop and report the problem instead.
|
|
15
16
|
- You have a fixed budget of model requests per prompt - be economical with tool calls.
|
|
16
17
|
- After acting, answer with a single short sentence describing what changed. If the user asks a question you can answer from tool results, answer it directly.
|
package/src/rust/agent/tools.rs
CHANGED
|
@@ -482,7 +482,7 @@ pub struct ToolError(String);
|
|
|
482
482
|
/// applied config.
|
|
483
483
|
fn retyped_columns(
|
|
484
484
|
session: &crate::session::Session,
|
|
485
|
-
config: &crate::config::ViewerConfig,
|
|
485
|
+
config: &crate::config::ViewerConfig<String, String>,
|
|
486
486
|
) -> Vec<Value> {
|
|
487
487
|
let metadata = session.metadata();
|
|
488
488
|
config
|
|
@@ -873,22 +873,8 @@ impl PerspectiveViewerElement {
|
|
|
873
873
|
async fn tool_set_view_config(&self, ctx: &ToolCtx, args: Value) -> Result<Value, ToolError> {
|
|
874
874
|
let args: SetViewConfigArgs = serde_json::from_value(args)?;
|
|
875
875
|
let target = args.panel.as_deref();
|
|
876
|
-
|
|
877
|
-
let snapshot =
|
|
878
|
-
get_viewer_config(&panel.session, &panel.renderer, &self.presentation).await?;
|
|
879
|
-
|
|
876
|
+
self.agent_panel(target)?;
|
|
880
877
|
if let Err(err) = self.agent_restore(target, &args.config).await {
|
|
881
|
-
let rolled = self
|
|
882
|
-
.agent_restore(target, &serde_json::to_value(&snapshot)?)
|
|
883
|
-
.await;
|
|
884
|
-
|
|
885
|
-
let err = match rolled {
|
|
886
|
-
Ok(()) => err,
|
|
887
|
-
Err(rollback_err) => ToolError(format!(
|
|
888
|
-
"{err} (additionally, restoring the prior config failed: {rollback_err})"
|
|
889
|
-
)),
|
|
890
|
-
};
|
|
891
|
-
|
|
892
878
|
return Err(with_docs_hint(ctx, err));
|
|
893
879
|
}
|
|
894
880
|
|
|
@@ -257,9 +257,9 @@ impl Component for ActiveColumn {
|
|
|
257
257
|
};
|
|
258
258
|
|
|
259
259
|
let ondragenter = ctx.props().ondragenter.reform(move |event: DragEvent| {
|
|
260
|
-
// Safari does not set `relatedTarget` so this event must be allowed
|
|
261
|
-
// bubble so we can count entry/exit stacks to
|
|
262
|
-
// `"dragleave"`.
|
|
260
|
+
// Safari does not set `relatedTarget` so this event must be allowed
|
|
261
|
+
// to bubble so we can count entry/exit stacks to
|
|
262
|
+
// determine true `"dragleave"`.
|
|
263
263
|
if event.related_target().is_some() {
|
|
264
264
|
event.stop_propagation();
|
|
265
265
|
event.prevent_default();
|
|
@@ -328,7 +328,7 @@ impl Component for ActiveColumn {
|
|
|
328
328
|
let remove_column = if is_required {
|
|
329
329
|
None
|
|
330
330
|
} else {
|
|
331
|
-
Some(ctx.link().callback({
|
|
331
|
+
Some(left_click(ctx.link().callback({
|
|
332
332
|
let event_name = name.to_owned();
|
|
333
333
|
move |event: MouseEvent| {
|
|
334
334
|
ActiveColumnMsg::DeactivateColumn(
|
|
@@ -336,7 +336,7 @@ impl Component for ActiveColumn {
|
|
|
336
336
|
event.shift_key(),
|
|
337
337
|
)
|
|
338
338
|
}
|
|
339
|
-
}))
|
|
339
|
+
})))
|
|
340
340
|
};
|
|
341
341
|
|
|
342
342
|
let ondragend = &ctx.props().ondragend.reform(|_| ());
|
|
@@ -367,9 +367,11 @@ impl Component for ActiveColumn {
|
|
|
367
367
|
if is_required {
|
|
368
368
|
class.push("required");
|
|
369
369
|
};
|
|
370
|
+
|
|
370
371
|
if !is_required {
|
|
371
372
|
class.push("shift-alt-icon");
|
|
372
373
|
}
|
|
374
|
+
|
|
373
375
|
html! {
|
|
374
376
|
<div
|
|
375
377
|
class={outer_classes}
|
|
@@ -468,6 +470,14 @@ impl ActiveColumnProps {
|
|
|
468
470
|
fn get_is_required(&self, idx: usize) -> bool {
|
|
469
471
|
let min_cols = self.renderer.metadata().min_config_columns.unwrap_or(0);
|
|
470
472
|
idx < min_cols
|
|
473
|
+
&& (self
|
|
474
|
+
.session
|
|
475
|
+
.get_view_config()
|
|
476
|
+
.columns
|
|
477
|
+
.iter()
|
|
478
|
+
.flatten()
|
|
479
|
+
.count()
|
|
480
|
+
== 1)
|
|
471
481
|
}
|
|
472
482
|
|
|
473
483
|
fn get_aggregate(&self, name: &str) -> Option<Aggregate> {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
use yew::prelude::*;
|
|
14
14
|
|
|
15
15
|
use super::{ColumnLocator, ColumnSettingsTarget};
|
|
16
|
+
use crate::utils::left_click;
|
|
16
17
|
|
|
17
18
|
#[derive(Clone, PartialEq, Properties)]
|
|
18
19
|
pub struct AddExpressionButtonProps {
|
|
@@ -23,41 +24,23 @@ pub struct AddExpressionButtonProps {
|
|
|
23
24
|
pub selected_column: Option<ColumnLocator>,
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
///
|
|
27
|
-
///
|
|
28
|
-
/// causing brief hover effects where the mouse _was_ before the action
|
|
29
|
-
/// initiated. Various methods of correcting this were attempted, settling
|
|
30
|
-
/// on a manual `dragdrop-hover` class toggle, using the `.button()` property
|
|
31
|
-
/// to determine the mis-fired event. This was determined experimentally -
|
|
32
|
-
/// according to my read of the spec, this is a bug in Chrome.
|
|
33
|
-
///
|
|
34
|
-
/// As a result there are 3 hover states `MouseEnter(true)`,
|
|
35
|
-
/// `MouseEnter(false)`, and `MouseLeave`; `MouseEnter(false)` can be
|
|
36
|
-
/// replaced, but it causes an extra render of the DOM un-necessarily.
|
|
27
|
+
/// The "New Column" row; hover is CSS so a drag's stray `mouseover` cannot
|
|
28
|
+
/// pin the highlight.
|
|
37
29
|
#[function_component]
|
|
38
30
|
pub fn AddExpressionButton(p: &AddExpressionButtonProps) -> Html {
|
|
39
|
-
let
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
let onmousedown = left_click(
|
|
32
|
+
p.on_open_expr_panel
|
|
33
|
+
.reform(|_| ColumnSettingsTarget::NewExpression),
|
|
34
|
+
);
|
|
43
35
|
|
|
44
|
-
let
|
|
45
|
-
mo.set(false);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
let onmousedown = p
|
|
49
|
-
.on_open_expr_panel
|
|
50
|
-
.reform(|_| ColumnSettingsTarget::NewExpression);
|
|
51
|
-
|
|
52
|
-
let class = if *is_mouseover || matches!(p.selected_column, Some(ColumnLocator::NewExpression))
|
|
53
|
-
{
|
|
36
|
+
let class = if matches!(p.selected_column, Some(ColumnLocator::NewExpression)) {
|
|
54
37
|
classes!("dragdrop-hover")
|
|
55
38
|
} else {
|
|
56
39
|
classes!()
|
|
57
40
|
};
|
|
58
41
|
|
|
59
42
|
html! {
|
|
60
|
-
<div id="add-expression" data-index="-1" {class} {
|
|
43
|
+
<div id="add-expression" data-index="-1" {class} {onmousedown}>
|
|
61
44
|
<span class="icon" />
|
|
62
45
|
<span id="add-expression-button" />
|
|
63
46
|
</div>
|
|
@@ -24,7 +24,8 @@ use crate::components::column_dropdown::{ColumnDropDownElement, ColumnDropDownPo
|
|
|
24
24
|
use crate::components::dragdrop_list::*;
|
|
25
25
|
use crate::components::filter_dropdown::{FilterDropDownElement, FilterDropDownPortal};
|
|
26
26
|
use crate::config::PluginStaticConfig;
|
|
27
|
-
use crate::presentation::Presentation;
|
|
27
|
+
use crate::presentation::{ColumnLocator, ColumnSettingsTarget, Presentation};
|
|
28
|
+
use crate::queries::has_column_config;
|
|
28
29
|
use crate::renderer::*;
|
|
29
30
|
use crate::session::drag_drop_update::*;
|
|
30
31
|
use crate::session::*;
|
|
@@ -36,6 +37,13 @@ use crate::utils::*;
|
|
|
36
37
|
pub struct ConfigSelectorProps {
|
|
37
38
|
pub onselect: Callback<()>,
|
|
38
39
|
|
|
40
|
+
/// Opens a pivot column's settings, so its format config is reachable.
|
|
41
|
+
pub on_open_expr_panel: Callback<ColumnSettingsTarget>,
|
|
42
|
+
|
|
43
|
+
/// The column whose settings sidebar is open, threaded as a VALUE prop so
|
|
44
|
+
/// closing or retargeting the sidebar clears this pill's open indicator.
|
|
45
|
+
pub selected_column: Option<ColumnLocator>,
|
|
46
|
+
|
|
39
47
|
#[prop_or_default]
|
|
40
48
|
pub ondragenter: Callback<()>,
|
|
41
49
|
|
|
@@ -43,9 +51,11 @@ pub struct ConfigSelectorProps {
|
|
|
43
51
|
/// (group_by, sort, filter, etc.) trigger re-renders via normal prop
|
|
44
52
|
/// diffing rather than a PubSub `view_created` subscription.
|
|
45
53
|
pub view_config: PtrEqRc<ViewConfig>,
|
|
54
|
+
|
|
46
55
|
/// Column currently being dragged — threaded to show `dragdrop-highlight`
|
|
47
56
|
/// without subscribing to `dragstart_received`/`dragend_received`.
|
|
48
57
|
pub drag_column: Option<String>,
|
|
58
|
+
|
|
49
59
|
/// Session metadata snapshot — threaded from `SessionProps`.
|
|
50
60
|
pub metadata: SessionMetadataRc,
|
|
51
61
|
|
|
@@ -69,6 +79,7 @@ pub struct ConfigSelectorProps {
|
|
|
69
79
|
impl PartialEq for ConfigSelectorProps {
|
|
70
80
|
fn eq(&self, other: &Self) -> bool {
|
|
71
81
|
self.view_config == other.view_config
|
|
82
|
+
&& self.selected_column == other.selected_column
|
|
72
83
|
&& self.drag_column == other.drag_column
|
|
73
84
|
&& self.metadata == other.metadata
|
|
74
85
|
&& self.selected_theme == other.selected_theme
|
|
@@ -552,10 +563,10 @@ impl Component for ConfigSelector {
|
|
|
552
563
|
}
|
|
553
564
|
}
|
|
554
565
|
|
|
555
|
-
// /// Should not render on change, as this component only depends on
|
|
556
|
-
// /// state.
|
|
557
|
-
// fn changed(&mut self, _ctx: &Context<Self>, _old: &Self::Properties) ->
|
|
558
|
-
// { false
|
|
566
|
+
// /// Should not render on change, as this component only depends on
|
|
567
|
+
// service /// state.
|
|
568
|
+
// fn changed(&mut self, _ctx: &Context<Self>, _old: &Self::Properties) ->
|
|
569
|
+
// bool { false
|
|
559
570
|
// }
|
|
560
571
|
|
|
561
572
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
@@ -578,7 +589,18 @@ impl Component for ConfigSelector {
|
|
|
578
589
|
)
|
|
579
590
|
};
|
|
580
591
|
|
|
581
|
-
let
|
|
592
|
+
let has_config = |name: &str| {
|
|
593
|
+
has_column_config(name, config, &ctx.props().metadata, &ctx.props().renderer)
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
let editing_column = match &ctx.props().selected_column {
|
|
597
|
+
Some(ColumnLocator::Table(x))
|
|
598
|
+
| Some(ColumnLocator::Expression(x))
|
|
599
|
+
| Some(ColumnLocator::Window(x)) => Some(x.clone()),
|
|
600
|
+
_ => None,
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
let transpose = left_click(ctx.link().callback(|_| ConfigSelectorMsg::TransposePivots));
|
|
582
604
|
let column_dropdown = self.column_dropdown.clone();
|
|
583
605
|
let mut class = classes!();
|
|
584
606
|
|
|
@@ -665,6 +687,9 @@ impl Component for ConfigSelector {
|
|
|
665
687
|
action={DragTarget::GroupBy}
|
|
666
688
|
column={group_by.clone()}
|
|
667
689
|
metadata={metadata.clone()}
|
|
690
|
+
on_open_expr_panel={has_config(group_by)
|
|
691
|
+
.then(|| ctx.props().on_open_expr_panel.clone())}
|
|
692
|
+
is_editing={editing_column.as_deref() == Some(group_by.as_str())}
|
|
668
693
|
{presentation}
|
|
669
694
|
opt_session={session}
|
|
670
695
|
>
|
|
@@ -716,6 +741,9 @@ impl Component for ConfigSelector {
|
|
|
716
741
|
action={ DragTarget::SplitBy }
|
|
717
742
|
column={ split_by.clone() }
|
|
718
743
|
metadata={metadata.clone()}
|
|
744
|
+
on_open_expr_panel={has_config(split_by)
|
|
745
|
+
.then(|| ctx.props().on_open_expr_panel.clone())}
|
|
746
|
+
is_editing={editing_column.as_deref() == Some(split_by.as_str())}
|
|
719
747
|
{presentation}
|
|
720
748
|
opt_session={session}>
|
|
721
749
|
</PivotColumn>
|