@perspective-dev/viewer 5.5.1 → 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/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 +115 -35
- package/dist/wasm/perspective-viewer.js +314 -190
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +21 -17
- package/package.json +31 -18
- 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/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 +74 -24
- package/src/rust/components/status_indicator.rs +8 -1
- package/src/rust/components/viewer/filters.rs +13 -1
- package/src/rust/components/viewer/msg.rs +4 -0
- package/src/rust/components/viewer/panels.rs +41 -1
- 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 +14 -0
- package/src/rust/components/viewer.rs +45 -25
- package/src/rust/components/window_editor.rs +5 -4
- package/src/rust/config/column_config_schema.rs +38 -377
- 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 +187 -131
- 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 +30 -9
- 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 +900 -395
- 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 +5 -0
- package/src/rust/tasks/create_panel.rs +34 -9
- package/src/rust/tasks/derive.rs +312 -0
- package/src/rust/tasks/mod.rs +6 -2
- package/src/rust/tasks/pipeline.rs +145 -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 +39 -12
- 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/local_fonts.rs +0 -36
- package/src/rust/utils/mod.rs +2 -3
- package/src/rust/utils/modal_position.rs +15 -21
- 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/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/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/mod.rs +0 -14
- package/src/rust/utils/tests/pubsub.rs +0 -95
- /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline5.js +0 -0
package/src/rust/workspace.rs
CHANGED
|
@@ -13,13 +13,16 @@
|
|
|
13
13
|
//! The multi-panel model backing a single `<perspective-viewer>`.
|
|
14
14
|
|
|
15
15
|
use std::cell::{Cell, RefCell};
|
|
16
|
+
use std::collections::BTreeMap;
|
|
16
17
|
use std::rc::Rc;
|
|
17
18
|
|
|
18
19
|
use perspective_client::Client;
|
|
19
20
|
use perspective_client::config::Filter;
|
|
20
21
|
|
|
22
|
+
use crate::config::{DerivedTableConfig, TableRef};
|
|
23
|
+
use crate::derived::{DerivedRegistry, DerivedTable};
|
|
21
24
|
use crate::renderer::Renderer;
|
|
22
|
-
use crate::session::Session;
|
|
25
|
+
use crate::session::{OverlayClause, Session};
|
|
23
26
|
use crate::utils::{EffectLedger, PubSub, Subscription, spawn_owned};
|
|
24
27
|
|
|
25
28
|
/// A unique identifier for a [`Panel`] within a [`Workspace`].
|
|
@@ -54,22 +57,37 @@ impl From<&str> for PanelId {
|
|
|
54
57
|
#[derive(Default)]
|
|
55
58
|
struct GlobalFilterSet {
|
|
56
59
|
restored: Vec<Filter>,
|
|
57
|
-
|
|
60
|
+
|
|
61
|
+
/// Each master's selection, every clause typed as the MASTER types its
|
|
62
|
+
/// column — what decides which listeners it applies to.
|
|
63
|
+
contributions: Vec<(PanelId, Vec<OverlayClause>)>,
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
impl GlobalFilterSet {
|
|
61
67
|
/// The effective set: `restored`, then each contribution in order,
|
|
62
68
|
/// deduped by clause equality.
|
|
63
69
|
fn flatten(&self) -> Vec<Filter> {
|
|
64
|
-
|
|
70
|
+
self.overlay().into_iter().map(|x| x.filter).collect()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// [`Self::flatten`] with each clause's broadcaster type — untyped for the
|
|
74
|
+
/// restored bucket, which has no broadcaster.
|
|
75
|
+
fn overlay(&self) -> Vec<OverlayClause> {
|
|
76
|
+
let mut flat: Vec<OverlayClause> = Vec::new();
|
|
65
77
|
let all = self
|
|
66
78
|
.restored
|
|
67
79
|
.iter()
|
|
68
|
-
.
|
|
80
|
+
.cloned()
|
|
81
|
+
.map(OverlayClause::from)
|
|
82
|
+
.chain(
|
|
83
|
+
self.contributions
|
|
84
|
+
.iter()
|
|
85
|
+
.flat_map(|(_, fs)| fs.iter().cloned()),
|
|
86
|
+
);
|
|
69
87
|
|
|
70
|
-
for
|
|
71
|
-
if !flat.
|
|
72
|
-
flat.push(
|
|
88
|
+
for clause in all {
|
|
89
|
+
if !flat.iter().any(|x| x.filter == clause.filter) {
|
|
90
|
+
flat.push(clause);
|
|
73
91
|
}
|
|
74
92
|
}
|
|
75
93
|
|
|
@@ -86,7 +104,8 @@ impl GlobalFilterSet {
|
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
/// Replace `id`'s contribution.
|
|
89
|
-
fn set_contribution(&mut self, id: &PanelId, filters: Vec<
|
|
107
|
+
fn set_contribution(&mut self, id: &PanelId, filters: Vec<impl Into<OverlayClause>>) -> bool {
|
|
108
|
+
let filters = filters.into_iter().map(Into::into).collect::<Vec<_>>();
|
|
90
109
|
self.with_change(|s| {
|
|
91
110
|
if filters.is_empty() {
|
|
92
111
|
s.contributions.retain(|(pid, _)| pid != id);
|
|
@@ -109,14 +128,14 @@ impl GlobalFilterSet {
|
|
|
109
128
|
let owners = self
|
|
110
129
|
.contributions
|
|
111
130
|
.iter()
|
|
112
|
-
.filter(|(_, fs)| fs.
|
|
131
|
+
.filter(|(_, fs)| fs.iter().any(|f| f.filter == clause))
|
|
113
132
|
.map(|(pid, _)| pid.clone())
|
|
114
133
|
.collect();
|
|
115
134
|
|
|
116
135
|
let changed = self.with_change(|s| {
|
|
117
136
|
s.restored.retain(|f| f != &clause);
|
|
118
137
|
for (_, fs) in s.contributions.iter_mut() {
|
|
119
|
-
fs.retain(|f| f !=
|
|
138
|
+
fs.retain(|f| f.filter != clause);
|
|
120
139
|
}
|
|
121
140
|
|
|
122
141
|
s.contributions.retain(|(_, fs)| !fs.is_empty());
|
|
@@ -308,9 +327,22 @@ struct WorkspaceData {
|
|
|
308
327
|
filters: GlobalFilterSet,
|
|
309
328
|
filters_changed: Rc<PubSub<()>>,
|
|
310
329
|
|
|
330
|
+
/// The set of hosted `Table`s changed: a client pushed a hosted-tables
|
|
331
|
+
/// update (observed post-sweep), or a derived `Table` was registered or
|
|
332
|
+
/// removed.
|
|
333
|
+
hosted_tables_changed: Rc<PubSub<()>>,
|
|
334
|
+
|
|
335
|
+
/// A panel's table binding changed (a rebind/pend committed, or a panel
|
|
336
|
+
/// entered or left the placed set), which is the input to per-table
|
|
337
|
+
/// consumer counts ([`Workspace::derived_consumers`]).
|
|
338
|
+
bindings_changed: Rc<PubSub<()>>,
|
|
339
|
+
|
|
311
340
|
/// The loaded-clients registry + default designation.
|
|
312
341
|
clients: ClientRegistry,
|
|
313
342
|
|
|
343
|
+
/// The live derived `Table`s this workspace owns.
|
|
344
|
+
derived: DerivedRegistry,
|
|
345
|
+
|
|
314
346
|
/// Monotonic counter backing [`Workspace::generate_id`].
|
|
315
347
|
next_id: usize,
|
|
316
348
|
|
|
@@ -356,7 +388,10 @@ impl Workspace {
|
|
|
356
388
|
active: None,
|
|
357
389
|
filters: GlobalFilterSet::default(),
|
|
358
390
|
filters_changed: Rc::new(PubSub::default()),
|
|
391
|
+
hosted_tables_changed: Rc::new(PubSub::default()),
|
|
392
|
+
bindings_changed: Rc::new(PubSub::default()),
|
|
359
393
|
clients: ClientRegistry::default(),
|
|
394
|
+
derived: DerivedRegistry::default(),
|
|
360
395
|
next_id: 0,
|
|
361
396
|
reservation: Reservation::Idle,
|
|
362
397
|
pending_layout: None,
|
|
@@ -477,12 +512,26 @@ impl Workspace {
|
|
|
477
512
|
self.0.borrow().filters.flatten()
|
|
478
513
|
}
|
|
479
514
|
|
|
515
|
+
/// [`Self::global_filters`] as broadcast to the panels: each clause with
|
|
516
|
+
/// the type its column has in the master that selected it.
|
|
517
|
+
pub fn overlay(&self) -> Vec<OverlayClause> {
|
|
518
|
+
self.0.borrow().filters.overlay()
|
|
519
|
+
}
|
|
520
|
+
|
|
480
521
|
/// A handle to the `filters_changed` PubSub (fires after any change to the
|
|
481
522
|
/// global filter set).
|
|
482
523
|
pub fn filters_changed(&self) -> Rc<PubSub<()>> {
|
|
483
524
|
self.0.borrow().filters_changed.clone()
|
|
484
525
|
}
|
|
485
526
|
|
|
527
|
+
pub fn hosted_tables_changed(&self) -> Rc<PubSub<()>> {
|
|
528
|
+
self.0.borrow().hosted_tables_changed.clone()
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
pub fn bindings_changed(&self) -> Rc<PubSub<()>> {
|
|
532
|
+
self.0.borrow().bindings_changed.clone()
|
|
533
|
+
}
|
|
534
|
+
|
|
486
535
|
/// Run `f` against the filter set inside the borrow, then emit
|
|
487
536
|
/// `filters_changed` — outside it — iff the effective set changed.
|
|
488
537
|
/// Returns `f`'s auxiliary payload.
|
|
@@ -507,13 +556,13 @@ impl Workspace {
|
|
|
507
556
|
|
|
508
557
|
/// Replace master `id`'s contribution with a new selection (empty =
|
|
509
558
|
/// deselect). See [`GlobalFilterSet::set_contribution`].
|
|
510
|
-
pub fn set_contribution(&self, id: &PanelId, filters: Vec<
|
|
559
|
+
pub fn set_contribution(&self, id: &PanelId, filters: Vec<OverlayClause>) {
|
|
511
560
|
self.mutate_filters(|s| (s.set_contribution(id, filters), ()));
|
|
512
561
|
}
|
|
513
562
|
|
|
514
563
|
/// Drop master `id`'s contribution (deselect / demote / close).
|
|
515
564
|
pub fn clear_contribution(&self, id: &PanelId) {
|
|
516
|
-
self.mutate_filters(|s| (s.set_contribution(id, Vec
|
|
565
|
+
self.mutate_filters(|s| (s.set_contribution(id, Vec::<OverlayClause>::new()), ()));
|
|
517
566
|
}
|
|
518
567
|
|
|
519
568
|
/// Remove the effective-set clause at `index`.
|
|
@@ -574,12 +623,19 @@ impl Workspace {
|
|
|
574
623
|
}
|
|
575
624
|
}
|
|
576
625
|
|
|
577
|
-
/// Generate a fresh [`PanelId`], unique within this workspace
|
|
626
|
+
/// Generate a fresh [`PanelId`], unique within this workspace — skipping
|
|
627
|
+
/// any taken by a placed panel (a restored config may carry saved
|
|
628
|
+
/// generated ids).
|
|
578
629
|
pub fn generate_id(&self) -> PanelId {
|
|
579
630
|
let mut data = self.0.borrow_mut();
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
631
|
+
loop {
|
|
632
|
+
let n = data.next_id;
|
|
633
|
+
data.next_id += 1;
|
|
634
|
+
let id = PanelId(format!("PERSPECTIVE_GENERATED_ID_{n}"));
|
|
635
|
+
if !data.panels.iter().any(|p| p.panel.id == id) {
|
|
636
|
+
return id;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
583
639
|
}
|
|
584
640
|
|
|
585
641
|
/// The id of the active panel, or `None` with zero panels.
|
|
@@ -702,6 +758,8 @@ impl Workspace {
|
|
|
702
758
|
if let Some(pubsub) = staged_pubsub {
|
|
703
759
|
pubsub.emit(());
|
|
704
760
|
}
|
|
761
|
+
|
|
762
|
+
self.bindings_changed().emit(());
|
|
705
763
|
}
|
|
706
764
|
|
|
707
765
|
/// Hold `panel` in the reservation slot ([`Reservation::Pending`]):
|
|
@@ -805,7 +863,9 @@ impl Workspace {
|
|
|
805
863
|
pub fn remove_panel(&self, id: &PanelId) -> Option<Panel> {
|
|
806
864
|
let (removed, changed, filters_pubsub, was_staged, staged_pubsub) = {
|
|
807
865
|
let mut data = self.0.borrow_mut();
|
|
808
|
-
let changed = data
|
|
866
|
+
let changed = data
|
|
867
|
+
.filters
|
|
868
|
+
.set_contribution(id, Vec::<OverlayClause>::new());
|
|
809
869
|
let (removed, was_staged) = match data.panels.iter().position(|p| &p.panel.id == id) {
|
|
810
870
|
Some(idx) => {
|
|
811
871
|
let entry = data.panels.remove(idx);
|
|
@@ -838,6 +898,10 @@ impl Workspace {
|
|
|
838
898
|
staged_pubsub.emit(());
|
|
839
899
|
}
|
|
840
900
|
|
|
901
|
+
if removed.is_some() {
|
|
902
|
+
self.bindings_changed().emit(());
|
|
903
|
+
}
|
|
904
|
+
|
|
841
905
|
removed
|
|
842
906
|
}
|
|
843
907
|
|
|
@@ -1013,136 +1077,119 @@ impl Workspace {
|
|
|
1013
1077
|
None => current.is_none().then(|| self.default_client()).flatten(),
|
|
1014
1078
|
}
|
|
1015
1079
|
}
|
|
1016
|
-
}
|
|
1017
1080
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
use super::*;
|
|
1023
|
-
|
|
1024
|
-
fn f(col: &str, term: &str) -> Filter {
|
|
1025
|
-
Filter::new(col, "==", FilterTerm::Scalar(term.into()))
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
fn p(id: &str) -> PanelId {
|
|
1029
|
-
PanelId::from(id)
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
#[test]
|
|
1033
|
-
fn flatten_orders_and_dedups_across_buckets() {
|
|
1034
|
-
let mut s = GlobalFilterSet::default();
|
|
1035
|
-
assert!(s.set_restored(vec![f("a", "1"), f("b", "2")]));
|
|
1036
|
-
// A non-empty contribution drops the restored bucket entirely.
|
|
1037
|
-
assert!(s.set_contribution(&p("x"), vec![f("b", "2"), f("c", "3")]));
|
|
1038
|
-
assert_eq!(s.flatten(), vec![f("b", "2"), f("c", "3")]);
|
|
1039
|
-
assert!(s.set_contribution(&p("y"), vec![f("c", "3"), f("d", "4")]));
|
|
1040
|
-
assert_eq!(s.flatten(), vec![f("b", "2"), f("c", "3"), f("d", "4")]);
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
#[test]
|
|
1044
|
-
fn set_contribution_replaces_not_accumulates() {
|
|
1045
|
-
let mut s = GlobalFilterSet::default();
|
|
1046
|
-
assert!(s.set_contribution(&p("x"), vec![f("a", "1")]));
|
|
1047
|
-
assert!(s.set_contribution(&p("x"), vec![f("a", "2")]));
|
|
1048
|
-
assert_eq!(s.flatten(), vec![f("a", "2")]);
|
|
1049
|
-
// Re-selecting the same value reports no visible change.
|
|
1050
|
-
assert!(!s.set_contribution(&p("x"), vec![f("a", "2")]));
|
|
1051
|
-
// Empty = deselect: the entry is removed.
|
|
1052
|
-
assert!(s.set_contribution(&p("x"), Vec::new()));
|
|
1053
|
-
assert_eq!(s.flatten(), Vec::<Filter>::new());
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
#[test]
|
|
1057
|
-
fn contributions_are_per_panel() {
|
|
1058
|
-
let mut s = GlobalFilterSet::default();
|
|
1059
|
-
s.set_contribution(&p("x"), vec![f("a", "1")]);
|
|
1060
|
-
s.set_contribution(&p("y"), vec![f("b", "2")]);
|
|
1061
|
-
// Clearing one master's contribution leaves the other's intact.
|
|
1062
|
-
assert!(s.set_contribution(&p("x"), Vec::new()));
|
|
1063
|
-
assert_eq!(s.flatten(), vec![f("b", "2")]);
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
#[test]
|
|
1067
|
-
fn remove_clause_removes_from_every_bucket_and_reports_owners() {
|
|
1068
|
-
let mut s = GlobalFilterSet::default();
|
|
1069
|
-
s.set_contribution(&p("x"), vec![f("a", "1"), f("b", "2")]);
|
|
1070
|
-
s.set_contribution(&p("y"), vec![f("a", "1")]);
|
|
1071
|
-
// flatten = [a==1, b==2]; removing index 0 must drop BOTH copies of
|
|
1072
|
-
// a==1 (owners x AND y), and the now-empty "y" entry with it.
|
|
1073
|
-
let (changed, owners) = s.remove_clause(0);
|
|
1074
|
-
assert!(changed);
|
|
1075
|
-
assert_eq!(owners, vec![p("x"), p("y")]);
|
|
1076
|
-
assert_eq!(s.flatten(), vec![f("b", "2")]);
|
|
1077
|
-
// Out-of-range is a no-op.
|
|
1078
|
-
assert_eq!(s.remove_clause(5), (false, Vec::new()));
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
#[test]
|
|
1082
|
-
fn restored_bucket_survives_deselect_but_not_selection() {
|
|
1083
|
-
let mut s = GlobalFilterSet::default();
|
|
1084
|
-
s.set_restored(vec![f("a", "1")]);
|
|
1085
|
-
// A deselect (empty contribution) does NOT drop the restored bucket.
|
|
1086
|
-
assert!(!s.set_contribution(&p("x"), Vec::new()));
|
|
1087
|
-
assert_eq!(s.flatten(), vec![f("a", "1")]);
|
|
1088
|
-
// A real selection replaces it.
|
|
1089
|
-
assert!(s.set_contribution(&p("x"), vec![f("b", "2")]));
|
|
1090
|
-
assert_eq!(s.flatten(), vec![f("b", "2")]);
|
|
1091
|
-
assert!(s.restored.is_empty());
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
#[test]
|
|
1095
|
-
fn clear_drops_everything_and_reports_owners() {
|
|
1096
|
-
let mut s = GlobalFilterSet::default();
|
|
1097
|
-
s.set_restored(vec![f("a", "1")]);
|
|
1098
|
-
s.set_contribution(&p("x"), vec![f("b", "2")]);
|
|
1099
|
-
let (changed, owners) = s.clear();
|
|
1100
|
-
assert!(changed);
|
|
1101
|
-
assert_eq!(owners, vec![p("x")]);
|
|
1102
|
-
assert_eq!(s.flatten(), Vec::<Filter>::new());
|
|
1103
|
-
assert_eq!(s.clear(), (false, Vec::new()));
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
#[test]
|
|
1107
|
-
fn flush_state_spawns_exactly_once_per_cycle() {
|
|
1108
|
-
let (state, spawn) = FlushState::Idle.mark(true, false);
|
|
1109
|
-
assert!(spawn);
|
|
1110
|
-
assert_eq!(state, FlushState::Queued {
|
|
1111
|
-
layout: true,
|
|
1112
|
-
active: false
|
|
1113
|
-
});
|
|
1081
|
+
/// Every derivation's persisted definition, for `saveWorkspace`.
|
|
1082
|
+
pub fn derived_configs(&self) -> BTreeMap<String, DerivedTableConfig> {
|
|
1083
|
+
self.0.borrow().derived.configs()
|
|
1084
|
+
}
|
|
1114
1085
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
assert_eq!(state, FlushState::Queued {
|
|
1119
|
-
layout: true,
|
|
1120
|
-
active: true
|
|
1121
|
-
});
|
|
1086
|
+
pub fn is_derived(&self, name: &str) -> bool {
|
|
1087
|
+
self.0.borrow().derived.contains(name)
|
|
1088
|
+
}
|
|
1122
1089
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
assert_eq!(state, FlushState::Queued {
|
|
1126
|
-
layout: true,
|
|
1127
|
-
active: true
|
|
1128
|
-
});
|
|
1090
|
+
pub fn derived_names(&self) -> Vec<String> {
|
|
1091
|
+
self.0.borrow().derived.names()
|
|
1129
1092
|
}
|
|
1130
1093
|
|
|
1131
|
-
|
|
1132
|
-
fn
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1094
|
+
/// The recorded definition of a derived `Table`.
|
|
1095
|
+
pub fn derived_config(&self, name: &str) -> Option<DerivedTableConfig> {
|
|
1096
|
+
self.0.borrow().derived.get(name).map(|x| x.config())
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
/// The name of a live derivation structurally equal to `config`.
|
|
1100
|
+
pub fn derived_find_structural(&self, config: &DerivedTableConfig) -> Option<String> {
|
|
1101
|
+
self.0.borrow().derived.find_structural(config)
|
|
1102
|
+
}
|
|
1138
1103
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1104
|
+
/// `name`'s definition as a self-contained [`TableRef`], recursively
|
|
1105
|
+
/// inlining each derived ancestor down to a concrete table name.
|
|
1106
|
+
pub fn inline_table_ref(&self, name: &str) -> TableRef {
|
|
1107
|
+
let ancestors = self.derived_ancestors(name);
|
|
1108
|
+
let Some(base) = ancestors.last() else {
|
|
1109
|
+
return TableRef::Name(name.to_owned());
|
|
1142
1110
|
};
|
|
1143
1111
|
|
|
1144
|
-
let
|
|
1145
|
-
|
|
1146
|
-
|
|
1112
|
+
let mut out = TableRef::Name(base.clone());
|
|
1113
|
+
let chain = std::iter::once(name)
|
|
1114
|
+
.chain(ancestors[..ancestors.len() - 1].iter().map(String::as_str))
|
|
1115
|
+
.collect::<Vec<_>>();
|
|
1116
|
+
|
|
1117
|
+
for level in chain.into_iter().rev() {
|
|
1118
|
+
match self.derived_config(level) {
|
|
1119
|
+
Some(config) => {
|
|
1120
|
+
out = TableRef::Derived(Box::new(DerivedTableConfig {
|
|
1121
|
+
table: out,
|
|
1122
|
+
view_config: config.view_config,
|
|
1123
|
+
}));
|
|
1124
|
+
},
|
|
1125
|
+
None => return TableRef::Name(name.to_owned()),
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
out
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
/// The `Table` names `name` derives from, nearest first.
|
|
1133
|
+
pub fn derived_ancestors(&self, name: &str) -> Vec<String> {
|
|
1134
|
+
self.0.borrow().derived.ancestors(name)
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
/// How many panels and derivations read `name`.
|
|
1138
|
+
pub fn derived_consumers(&self, name: &str) -> usize {
|
|
1139
|
+
let panels = self.panels();
|
|
1140
|
+
let data = self.0.borrow();
|
|
1141
|
+
let bound = panels
|
|
1142
|
+
.iter()
|
|
1143
|
+
.filter(|panel| {
|
|
1144
|
+
panel
|
|
1145
|
+
.session
|
|
1146
|
+
.get_table()
|
|
1147
|
+
.map(|table| table.get_name().to_owned())
|
|
1148
|
+
.or_else(|| panel.session.pending_table())
|
|
1149
|
+
.is_some_and(|bound| bound == name)
|
|
1150
|
+
})
|
|
1151
|
+
.count();
|
|
1152
|
+
|
|
1153
|
+
bound + data.derived.children(name).len()
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
pub fn register_derived(&self, name: String, table: DerivedTable) {
|
|
1157
|
+
self.0.borrow_mut().derived.insert(name, table);
|
|
1158
|
+
self.hosted_tables_changed().emit(());
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
/// Take a derivation out of the registry so the caller can await its
|
|
1162
|
+
/// deletion outside the borrow.
|
|
1163
|
+
pub fn take_derived(&self, name: &str) -> Option<DerivedTable> {
|
|
1164
|
+
let derived = self.0.borrow_mut().derived.remove(name);
|
|
1165
|
+
if derived.is_some() {
|
|
1166
|
+
self.hosted_tables_changed().emit(());
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
derived
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
/// Which of `order` may be reused rather than rebuilt.
|
|
1173
|
+
pub fn derived_reusable(
|
|
1174
|
+
&self,
|
|
1175
|
+
order: &[String],
|
|
1176
|
+
configs: &BTreeMap<String, DerivedTableConfig>,
|
|
1177
|
+
) -> std::collections::BTreeSet<String> {
|
|
1178
|
+
crate::derived::reusable(order, configs, &self.0.borrow().derived)
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/// The definitions waiting on a parent that is not yet hosted.
|
|
1182
|
+
pub fn derived_pending(&self) -> BTreeMap<String, DerivedTableConfig> {
|
|
1183
|
+
self.0.borrow().derived.pending()
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
/// Whether `name` is a derived definition awaiting its parent, which a
|
|
1187
|
+
/// panel bind must PEND on rather than reject as unknown.
|
|
1188
|
+
pub fn is_derived_pending(&self, name: &str) -> bool {
|
|
1189
|
+
self.0.borrow().derived.pending().contains_key(name)
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
pub fn set_derived_pending(&self, pending: BTreeMap<String, DerivedTableConfig>) {
|
|
1193
|
+
self.0.borrow_mut().derived.set_pending(pending);
|
|
1147
1194
|
}
|
|
1148
1195
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 13 13" fill="none" stroke="#042121"
|
|
2
|
+
stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
|
3
|
+
<circle cx="3.5" cy="3.5" r="1.75"/>
|
|
4
|
+
<circle cx="9.5" cy="9.5" r="1.75"/>
|
|
5
|
+
<path d="M3.5 5.25v2.25a2 2 0 0 0 2 2h2.25"/>
|
|
6
|
+
</svg>
|
package/src/themes/icons.css
CHANGED
|
@@ -63,6 +63,7 @@ perspective-viewer-tab {
|
|
|
63
63
|
--psp-icon--reset--mask-image: url("../svg/revert-icon.svg");
|
|
64
64
|
--psp-icon--copy--mask-image: url("../svg/duplicate-icon.svg");
|
|
65
65
|
--psp-icon--new-panel--mask-image: url("../svg/new-panel-icon.svg");
|
|
66
|
+
--psp-derived--mask-image: url("../svg/derived.svg");
|
|
66
67
|
--psp-icon--theme--mask-image: url("../svg/theme-icon.svg");
|
|
67
68
|
|
|
68
69
|
--psp-icon--drawer-tab--mask-image: url(../svg/drawer-tab.svg);
|
package/src/themes/intl/ar.css
CHANGED
|
@@ -69,6 +69,8 @@ perspective-viewer {
|
|
|
69
69
|
--psp-label--scroll-lock-alt-toggle--content: "تمرير محاذى";
|
|
70
70
|
|
|
71
71
|
--psp-label--color--content: "اللون";
|
|
72
|
+
--psp-label--palette--content: "لوحة الألوان";
|
|
73
|
+
--psp-label--gradient--content: "تدرج";
|
|
72
74
|
--psp-label--timezone--content: "المنطقة الزمنية";
|
|
73
75
|
--psp-label--date-style--content: "نمط التاريخ";
|
|
74
76
|
--psp-label--time-style--content: "نمط الوقت";
|
|
@@ -195,4 +197,12 @@ perspective-viewer {
|
|
|
195
197
|
--psp-label--legend-opacity--content: "العتامة";
|
|
196
198
|
--psp-label--tooltip-max-column-px--content: "أقصى عرض للعمود";
|
|
197
199
|
--psp-label--tooltip-opacity--content: "العتامة";
|
|
200
|
+
|
|
201
|
+
/* Derived tables */
|
|
202
|
+
--psp-label--derive-table--content: "اشتقاق جدول";
|
|
203
|
+
--psp-label--derive-table-title--content: "اشتقاق جدول جديد من هذا العرض";
|
|
204
|
+
--psp-label--derived-snapshot--content: "لقطة";
|
|
205
|
+
--psp-label--derived-snapshot-title--content: "مصدر البيانات هذا لا يبث التحديثات - بيانات هذا الجدول ثابتة عند لحظة اشتقاقه.";
|
|
206
|
+
--psp-label--derived-release-title--content: "العودة إلى الجدول الأصل";
|
|
207
|
+
--psp-label--derived-release-delete-title--content: "العودة إلى الجدول الأصل - انقر مع الضغط على Shift لحذفه";
|
|
198
208
|
}
|
package/src/themes/intl/de.css
CHANGED
|
@@ -74,6 +74,8 @@ perspective-viewer {
|
|
|
74
74
|
|
|
75
75
|
/* Column Settings */
|
|
76
76
|
--psp-label--color--content: "Farbe";
|
|
77
|
+
--psp-label--palette--content: "Palette";
|
|
78
|
+
--psp-label--gradient--content: "Gradient";
|
|
77
79
|
--psp-label--timezone--content: "Zeitzone";
|
|
78
80
|
--psp-label--date-style--content: "Datumsstil";
|
|
79
81
|
--psp-label--time-style--content: "Zeitstil";
|
|
@@ -204,4 +206,12 @@ perspective-viewer {
|
|
|
204
206
|
--psp-label--group-column--content: "Spalte";
|
|
205
207
|
--psp-label--group-format--content: "Format";
|
|
206
208
|
--psp-label--column-size-override--content: "Spaltenbreite";
|
|
209
|
+
|
|
210
|
+
/* Derived tables */
|
|
211
|
+
--psp-label--derive-table--content: "Tabelle ableiten";
|
|
212
|
+
--psp-label--derive-table-title--content: "Eine neue Tabelle aus dieser Ansicht ableiten";
|
|
213
|
+
--psp-label--derived-snapshot--content: "Snapshot";
|
|
214
|
+
--psp-label--derived-snapshot-title--content: "Diese Datenquelle streamt nicht - die Daten dieser Tabelle sind auf den Stand ihrer Ableitung eingefroren.";
|
|
215
|
+
--psp-label--derived-release-title--content: "Zurück zur übergeordneten Tabelle";
|
|
216
|
+
--psp-label--derived-release-delete-title--content: "Zurück zur übergeordneten Tabelle - Umschalt-Klick löscht sie";
|
|
207
217
|
}
|
package/src/themes/intl/es.css
CHANGED
|
@@ -74,6 +74,8 @@ perspective-viewer {
|
|
|
74
74
|
|
|
75
75
|
/* Column Settings */
|
|
76
76
|
--psp-label--color--content: "Color";
|
|
77
|
+
--psp-label--palette--content: "Paleta";
|
|
78
|
+
--psp-label--gradient--content: "Gradiente";
|
|
77
79
|
--psp-label--timezone--content: "Zona horaria";
|
|
78
80
|
--psp-label--date-style--content: "Estilo de fecha";
|
|
79
81
|
--psp-label--time-style--content: "Estilo de hora";
|
|
@@ -204,4 +206,12 @@ perspective-viewer {
|
|
|
204
206
|
--psp-label--group-column--content: "Columna";
|
|
205
207
|
--psp-label--group-format--content: "Formato";
|
|
206
208
|
--psp-label--column-size-override--content: "Ancho de columna";
|
|
209
|
+
|
|
210
|
+
/* Derived tables */
|
|
211
|
+
--psp-label--derive-table--content: "Derivar tabla";
|
|
212
|
+
--psp-label--derive-table-title--content: "Derivar una nueva tabla a partir de esta vista";
|
|
213
|
+
--psp-label--derived-snapshot--content: "instantánea";
|
|
214
|
+
--psp-label--derived-snapshot-title--content: "Esta fuente de datos no transmite en continuo - los datos de esta tabla quedan fijados en el momento de su derivación.";
|
|
215
|
+
--psp-label--derived-release-title--content: "Volver a la tabla padre";
|
|
216
|
+
--psp-label--derived-release-delete-title--content: "Volver a la tabla padre - mayús+clic para eliminarla";
|
|
207
217
|
}
|
package/src/themes/intl/fr.css
CHANGED
|
@@ -74,6 +74,8 @@ perspective-viewer {
|
|
|
74
74
|
|
|
75
75
|
/* Column Settings */
|
|
76
76
|
--psp-label--color--content: "Couleur";
|
|
77
|
+
--psp-label--palette--content: "Palette";
|
|
78
|
+
--psp-label--gradient--content: "Dégradé";
|
|
77
79
|
--psp-label--timezone--content: "Fuseau horaire";
|
|
78
80
|
--psp-label--date-style--content: "Style de date";
|
|
79
81
|
--psp-label--time-style--content: "Style d'heure";
|
|
@@ -204,4 +206,12 @@ perspective-viewer {
|
|
|
204
206
|
--psp-label--group-column--content: "Colonne";
|
|
205
207
|
--psp-label--group-format--content: "Format";
|
|
206
208
|
--psp-label--column-size-override--content: "Largeur de colonne";
|
|
209
|
+
|
|
210
|
+
/* Derived tables */
|
|
211
|
+
--psp-label--derive-table--content: "Dériver une table";
|
|
212
|
+
--psp-label--derive-table-title--content: "Dériver une nouvelle table à partir de cette vue";
|
|
213
|
+
--psp-label--derived-snapshot--content: "instantané";
|
|
214
|
+
--psp-label--derived-snapshot-title--content: "Cette source de données ne diffuse pas en continu - les données de cette table sont figées au moment de sa dérivation.";
|
|
215
|
+
--psp-label--derived-release-title--content: "Revenir à la table parente";
|
|
216
|
+
--psp-label--derived-release-delete-title--content: "Revenir à la table parente - maj-clic pour la supprimer";
|
|
207
217
|
}
|
package/src/themes/intl/ja.css
CHANGED
|
@@ -75,6 +75,8 @@ perspective-viewer {
|
|
|
75
75
|
|
|
76
76
|
/* Column Settings */
|
|
77
77
|
--psp-label--color--content: "色";
|
|
78
|
+
--psp-label--palette--content: "パレット";
|
|
79
|
+
--psp-label--gradient--content: "グラデーション";
|
|
78
80
|
--psp-label--timezone--content: "タイムゾーン";
|
|
79
81
|
--psp-label--date-style--content: "日付スタイル";
|
|
80
82
|
--psp-label--time-style--content: "時間スタイル";
|
|
@@ -204,4 +206,12 @@ perspective-viewer {
|
|
|
204
206
|
--psp-label--group-column--content: "列";
|
|
205
207
|
--psp-label--group-format--content: "書式";
|
|
206
208
|
--psp-label--column-size-override--content: "列の幅";
|
|
209
|
+
|
|
210
|
+
/* Derived tables */
|
|
211
|
+
--psp-label--derive-table--content: "テーブルを派生";
|
|
212
|
+
--psp-label--derive-table-title--content: "このビューから新しいテーブルを派生します";
|
|
213
|
+
--psp-label--derived-snapshot--content: "スナップショット";
|
|
214
|
+
--psp-label--derived-snapshot-title--content: "このデータソースはストリーミングしません - このテーブルのデータは派生した時点で固定されます。";
|
|
215
|
+
--psp-label--derived-release-title--content: "親テーブルに戻る";
|
|
216
|
+
--psp-label--derived-release-delete-title--content: "親テーブルに戻る - Shiftクリックで削除";
|
|
207
217
|
}
|
package/src/themes/intl/pt.css
CHANGED
|
@@ -74,6 +74,8 @@ perspective-viewer {
|
|
|
74
74
|
|
|
75
75
|
/* Column Settings */
|
|
76
76
|
--psp-label--color--content: "Cor";
|
|
77
|
+
--psp-label--palette--content: "Paleta";
|
|
78
|
+
--psp-label--gradient--content: "Gradiente";
|
|
77
79
|
--psp-label--timezone--content: "Fuso horário";
|
|
78
80
|
--psp-label--date-style--content: "Estilo de data";
|
|
79
81
|
--psp-label--time-style--content: "Estilo de tempo";
|
|
@@ -204,4 +206,12 @@ perspective-viewer {
|
|
|
204
206
|
--psp-label--group-column--content: "Coluna";
|
|
205
207
|
--psp-label--group-format--content: "Formato";
|
|
206
208
|
--psp-label--column-size-override--content: "Largura da coluna";
|
|
209
|
+
|
|
210
|
+
/* Derived tables */
|
|
211
|
+
--psp-label--derive-table--content: "Derivar tabela";
|
|
212
|
+
--psp-label--derive-table-title--content: "Derivar uma nova tabela a partir desta visualização";
|
|
213
|
+
--psp-label--derived-snapshot--content: "instantâneo";
|
|
214
|
+
--psp-label--derived-snapshot-title--content: "Esta fonte de dados não transmite em contínuo - os dados desta tabela ficam fixados no momento da derivação.";
|
|
215
|
+
--psp-label--derived-release-title--content: "Voltar à tabela pai";
|
|
216
|
+
--psp-label--derived-release-delete-title--content: "Voltar à tabela pai - shift+clique para excluí-la";
|
|
207
217
|
}
|
package/src/themes/intl/zh.css
CHANGED
|
@@ -74,6 +74,8 @@ perspective-viewer {
|
|
|
74
74
|
|
|
75
75
|
/* Column Settings */
|
|
76
76
|
--psp-label--color--content: "颜色";
|
|
77
|
+
--psp-label--palette--content: "调色板";
|
|
78
|
+
--psp-label--gradient--content: "渐变";
|
|
77
79
|
--psp-label--timezone--content: "时区";
|
|
78
80
|
--psp-label--date-style--content: "日期样式";
|
|
79
81
|
--psp-label--time-style--content: "时间风格";
|
|
@@ -204,4 +206,12 @@ perspective-viewer {
|
|
|
204
206
|
--psp-label--group-column--content: "列";
|
|
205
207
|
--psp-label--group-format--content: "格式";
|
|
206
208
|
--psp-label--column-size-override--content: "列宽";
|
|
209
|
+
|
|
210
|
+
/* Derived tables */
|
|
211
|
+
--psp-label--derive-table--content: "派生表";
|
|
212
|
+
--psp-label--derive-table-title--content: "从此视图派生新表";
|
|
213
|
+
--psp-label--derived-snapshot--content: "快照";
|
|
214
|
+
--psp-label--derived-snapshot-title--content: "此数据源不支持流式更新 - 该表的数据固定在派生时的状态。";
|
|
215
|
+
--psp-label--derived-release-title--content: "返回父表";
|
|
216
|
+
--psp-label--derived-release-delete-title--content: "返回父表 - Shift+点击可将其删除";
|
|
207
217
|
}
|
package/src/themes/intl.css
CHANGED
|
@@ -74,6 +74,8 @@ perspective-viewer {
|
|
|
74
74
|
|
|
75
75
|
/* Column Settings */
|
|
76
76
|
--psp-label--color--content: "Color";
|
|
77
|
+
--psp-label--palette--content: "Palette";
|
|
78
|
+
--psp-label--gradient--content: "Gradient";
|
|
77
79
|
--psp-label--timezone--content: "Timezone";
|
|
78
80
|
--psp-label--date-style--content: "Date Style";
|
|
79
81
|
--psp-label--time-style--content: "Time Style";
|
|
@@ -206,4 +208,12 @@ perspective-viewer {
|
|
|
206
208
|
--psp-label--legend-opacity--content: "Opacity";
|
|
207
209
|
--psp-label--tooltip-max-column-px--content: "Max column width";
|
|
208
210
|
--psp-label--tooltip-opacity--content: "Opacity";
|
|
211
|
+
|
|
212
|
+
/* Derived tables */
|
|
213
|
+
--psp-label--derive-table--content: "Derive table";
|
|
214
|
+
--psp-label--derive-table-title--content: "Derive a new table from this view";
|
|
215
|
+
--psp-label--derived-snapshot--content: "snapshot";
|
|
216
|
+
--psp-label--derived-snapshot-title--content: "This data source does not stream - this table's data is fixed at the point it was derived.";
|
|
217
|
+
--psp-label--derived-release-title--content: "Back to the parent table";
|
|
218
|
+
--psp-label--derived-release-delete-title--content: "Back to the parent table - shift-click to delete this one";
|
|
209
219
|
}
|