@perspective-dev/viewer 5.0.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/perspective-viewer.js +6 -6
- package/dist/cdn/perspective-viewer.js.map +2 -2
- package/dist/css/botanical.css +1 -1
- package/dist/css/dracula.css +1 -1
- package/dist/css/gruvbox-dark.css +1 -1
- package/dist/css/gruvbox.css +1 -1
- package/dist/css/icons.css +1 -1
- package/dist/css/intl/de.css +1 -1
- package/dist/css/intl/es.css +1 -1
- package/dist/css/intl/fr.css +1 -1
- package/dist/css/intl/ja.css +1 -1
- package/dist/css/intl/pt.css +1 -1
- package/dist/css/intl/zh.css +1 -1
- package/dist/css/intl.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/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/esm/perspective-viewer.inline.js +9 -9
- package/dist/esm/perspective-viewer.inline.js.map +2 -2
- package/dist/esm/perspective-viewer.js +1 -1
- package/dist/esm/perspective-viewer.js.map +2 -2
- package/dist/esm/ts-rs/PanelViewerConfig.d.ts +2 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +2 -0
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +9 -0
- package/dist/esm/ts-rs/WindowAggregate.d.ts +1 -0
- package/dist/esm/ts-rs/WindowSort.d.ts +7 -0
- package/dist/esm/ts-rs/WindowSortDir.d.ts +6 -0
- package/dist/esm/ts-rs/WindowSpec.d.ts +46 -0
- package/dist/esm/ts-rs/Windows.d.ts +10 -0
- package/dist/wasm/perspective-viewer.d.ts +103 -16
- package/dist/wasm/perspective-viewer.js +118 -108
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +15 -15
- package/package.json +1 -1
- package/src/css/column-selector.css +1 -0
- package/src/css/column-settings-panel.css +67 -2
- package/src/css/column-style.css +4 -3
- package/src/css/config-selector.css +22 -1
- package/src/css/containers/context-menu.css +12 -6
- package/src/css/containers/tabs.css +2 -2
- package/src/css/viewer.css +8 -0
- package/src/rust/components/column_selector/active_column.rs +21 -27
- package/src/rust/components/column_selector/column_selector_column_row.rs +73 -0
- package/src/rust/components/column_selector/config_selector.rs +7 -1
- package/src/rust/components/column_selector/expr_edit_button.rs +7 -1
- package/src/rust/components/column_selector/inactive_column.rs +8 -1
- package/src/rust/components/column_selector.rs +20 -3
- package/src/rust/components/column_settings_sidebar/style_tab.rs +2 -1
- package/src/rust/components/column_settings_sidebar/window_tab.rs +34 -0
- package/src/rust/components/column_settings_sidebar.rs +163 -16
- package/src/rust/components/containers/dragdrop_list.rs +73 -3
- package/src/rust/components/containers/sidebar.rs +99 -22
- package/src/rust/components/containers/split_panel.rs +6 -0
- package/src/rust/components/editable_header.rs +2 -0
- package/src/rust/components/main_panel.rs +5 -0
- package/src/rust/components/mod.rs +1 -0
- package/src/rust/components/panel_menu.rs +7 -0
- package/src/rust/components/panel_tab.rs +5 -0
- package/src/rust/components/portal.rs +7 -0
- package/src/rust/components/viewer/msg.rs +2 -0
- package/src/rust/components/viewer/render.rs +12 -0
- package/src/rust/components/viewer/settings.rs +33 -1
- package/src/rust/components/viewer.rs +2 -0
- package/src/rust/components/window_editor.rs +1013 -0
- package/src/rust/lib.rs +4 -1
- package/src/rust/presentation/column_locator.rs +16 -1
- package/src/rust/queries/columns_iter_set.rs +7 -1
- package/src/rust/renderer/dispatch.rs +85 -58
- package/src/rust/renderer.rs +34 -1
- package/src/rust/session/drag_drop_update.rs +18 -0
- package/src/rust/session/metadata.rs +66 -9
- package/src/rust/session/replace_expression_update.rs +1 -0
- package/src/rust/session.rs +7 -5
- package/src/rust/tasks/edit_window.rs +155 -0
- package/src/rust/tasks/mod.rs +2 -0
- package/src/rust/utils/browser/dragdrop.rs +12 -0
- package/src/rust/utils/browser/tests/debounce.rs +49 -0
- package/src/rust/utils/debounce.rs +76 -27
- package/src/svg/pin-icon.svg +5 -0
- package/src/themes/icons.css +1 -0
- package/src/themes/intl/de.css +7 -0
- package/src/themes/intl/es.css +7 -0
- package/src/themes/intl/fr.css +7 -0
- package/src/themes/intl/ja.css +7 -0
- package/src/themes/intl/pt.css +7 -0
- package/src/themes/intl/zh.css +7 -0
- package/src/themes/intl.css +10 -1
- package/src/ts/ts-rs/PanelViewerConfig.ts +2 -1
- package/src/ts/ts-rs/ViewerConfig.ts +2 -1
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +9 -0
- package/src/ts/ts-rs/WindowAggregate.ts +3 -0
- package/src/ts/ts-rs/WindowSort.ts +9 -0
- package/src/ts/ts-rs/WindowSortDir.ts +8 -0
- package/src/ts/ts-rs/WindowSpec.ts +46 -0
- package/src/ts/ts-rs/Windows.ts +10 -0
- /package/dist/wasm/snippets/{perspective-viewer-daeef4ceb066e6c7 → perspective-viewer-8a8c7d5d696b43ae}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-daeef4ceb066e6c7 → perspective-viewer-8a8c7d5d696b43ae}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-daeef4ceb066e6c7 → perspective-viewer-8a8c7d5d696b43ae}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-daeef4ceb066e6c7 → perspective-viewer-8a8c7d5d696b43ae}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-daeef4ceb066e6c7 → perspective-viewer-8a8c7d5d696b43ae}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-daeef4ceb066e6c7 → perspective-viewer-8a8c7d5d696b43ae}/inline5.js +0 -0
|
@@ -17,6 +17,18 @@ pub enum DragTarget {
|
|
|
17
17
|
SplitBy,
|
|
18
18
|
Sort,
|
|
19
19
|
Filter,
|
|
20
|
+
WindowSource,
|
|
21
|
+
WindowOrderBy,
|
|
22
|
+
WindowPartitionBy,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
impl DragTarget {
|
|
26
|
+
pub fn is_staged(&self) -> bool {
|
|
27
|
+
matches!(
|
|
28
|
+
self,
|
|
29
|
+
Self::WindowSource | Self::WindowOrderBy | Self::WindowPartitionBy
|
|
30
|
+
)
|
|
31
|
+
}
|
|
20
32
|
}
|
|
21
33
|
|
|
22
34
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
@@ -86,6 +86,55 @@ pub async fn test_lock_seq() {
|
|
|
86
86
|
assert_eq!(cell.get(), 10);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/// A dedicated [`DebounceSlot`]'s task must RUN even when the default slot
|
|
90
|
+
/// has a parked runner — coalescing is scoped per slot. Pre-slot (one
|
|
91
|
+
/// shared parked flag), `t4` would resolve via `t2`'s settle without its
|
|
92
|
+
/// closure ever running: the resize-eaten-by-parked-update bug.
|
|
93
|
+
#[wasm_bindgen_test]
|
|
94
|
+
pub async fn test_slot_isolated_from_default_coalescing() {
|
|
95
|
+
let debounce_mutex = DebounceMutex::default();
|
|
96
|
+
let slot = debounce_mutex.slot();
|
|
97
|
+
let defaults: Rc<Cell<u32>> = Rc::new(Cell::new(0));
|
|
98
|
+
let slots: Rc<Cell<u32>> = Rc::new(Cell::new(0));
|
|
99
|
+
|
|
100
|
+
let t1 = debounce_mutex.lock(async {
|
|
101
|
+
set_timeout(10).await.unwrap();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
let t2 = {
|
|
105
|
+
let defaults = defaults.clone();
|
|
106
|
+
debounce_mutex.debounce(async move {
|
|
107
|
+
defaults.set(defaults.get() + 1);
|
|
108
|
+
Ok(())
|
|
109
|
+
})
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
let t3 = {
|
|
113
|
+
let defaults = defaults.clone();
|
|
114
|
+
debounce_mutex.debounce(async move {
|
|
115
|
+
defaults.set(defaults.get() + 100);
|
|
116
|
+
Ok(())
|
|
117
|
+
})
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
let t4 = {
|
|
121
|
+
let slots = slots.clone();
|
|
122
|
+
slot.debounce_with(|_| async move {
|
|
123
|
+
slots.set(slots.get() + 1);
|
|
124
|
+
Ok(())
|
|
125
|
+
})
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
let (_, r2, r3, r4) = futures::join!(t1, t2, t3, t4);
|
|
129
|
+
r2.unwrap();
|
|
130
|
+
r3.unwrap();
|
|
131
|
+
r4.unwrap();
|
|
132
|
+
|
|
133
|
+
// `t3` coalesced onto the parked `t2`; `t4` ran its own closure.
|
|
134
|
+
assert_eq!(defaults.get(), 1);
|
|
135
|
+
assert_eq!(slots.get(), 1);
|
|
136
|
+
}
|
|
137
|
+
|
|
89
138
|
#[wasm_bindgen_test]
|
|
90
139
|
pub async fn test_debounce_seq() {
|
|
91
140
|
let debounce_mutex = DebounceMutex::default();
|
|
@@ -33,16 +33,27 @@ pub struct RenderGuard {
|
|
|
33
33
|
_private: (),
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/// The per-slot debounce bookkeeping: one running + one parked evaluation,
|
|
37
|
+
/// with coalesced callers awaiting the parked runner's settle. Kept
|
|
38
|
+
/// per-[`DebounceSlot`] so coalescing is only expressible WITHIN a kind —
|
|
39
|
+
/// a caller can never be absorbed by a parked runner of a different kind
|
|
40
|
+
/// whose work does not subsume it (the resize-eaten-by-parked-update bug).
|
|
36
41
|
#[derive(Default)]
|
|
37
|
-
struct
|
|
42
|
+
struct SlotState {
|
|
38
43
|
id: Cell<u64>,
|
|
39
|
-
|
|
40
|
-
mutex: Mutex<u64>,
|
|
44
|
+
last: Cell<u64>,
|
|
41
45
|
parked: Cell<bool>,
|
|
42
46
|
settled_id: Cell<u64>,
|
|
43
47
|
on_settle: PubSub<()>,
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
#[derive(Default)]
|
|
51
|
+
struct DebounceMutexData {
|
|
52
|
+
held: Cell<bool>,
|
|
53
|
+
mutex: Mutex<()>,
|
|
54
|
+
default_slot: Rc<SlotState>,
|
|
55
|
+
}
|
|
56
|
+
|
|
46
57
|
/// Clears the `held` flag on drop, so cancellation of a locked task (its
|
|
47
58
|
/// future dropped mid-await) can't leave [`DebounceMutex::is_held`] stuck
|
|
48
59
|
/// `true`.
|
|
@@ -67,25 +78,25 @@ impl Drop for HeldFlag<'_> {
|
|
|
67
78
|
/// mid-run still frees the parked slot and releases its coalesced waiters,
|
|
68
79
|
/// so they can never be stranded awaiting a settle that no task will emit.
|
|
69
80
|
struct SettleGuard<'a> {
|
|
70
|
-
|
|
81
|
+
state: &'a SlotState,
|
|
71
82
|
next: u64,
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
impl<'a> SettleGuard<'a> {
|
|
75
|
-
fn park(
|
|
76
|
-
|
|
77
|
-
Self {
|
|
86
|
+
fn park(state: &'a SlotState, next: u64) -> Self {
|
|
87
|
+
state.parked.set(true);
|
|
88
|
+
Self { state, next }
|
|
78
89
|
}
|
|
79
90
|
}
|
|
80
91
|
|
|
81
92
|
impl Drop for SettleGuard<'_> {
|
|
82
93
|
fn drop(&mut self) {
|
|
83
|
-
self.
|
|
84
|
-
if self.
|
|
85
|
-
self.
|
|
94
|
+
self.state.parked.set(false);
|
|
95
|
+
if self.state.settled_id.get() < self.next {
|
|
96
|
+
self.state.settled_id.set(self.next);
|
|
86
97
|
}
|
|
87
98
|
|
|
88
|
-
self.
|
|
99
|
+
self.state.on_settle.emit(());
|
|
89
100
|
}
|
|
90
101
|
}
|
|
91
102
|
|
|
@@ -123,12 +134,11 @@ impl DebounceMutex {
|
|
|
123
134
|
F: FnOnce(RenderGuard) -> Fut,
|
|
124
135
|
Fut: Future<Output = T>,
|
|
125
136
|
{
|
|
126
|
-
let
|
|
127
|
-
let next = self.0.id.get();
|
|
137
|
+
let guard = self.0.mutex.lock().await;
|
|
128
138
|
let held = HeldFlag::set(&self.0.held);
|
|
129
139
|
let result = f(RenderGuard { _private: () }).await;
|
|
130
140
|
drop(held);
|
|
131
|
-
|
|
141
|
+
drop(guard);
|
|
132
142
|
result
|
|
133
143
|
}
|
|
134
144
|
|
|
@@ -144,23 +154,62 @@ impl DebounceMutex {
|
|
|
144
154
|
F: FnOnce(RenderGuard) -> Fut,
|
|
145
155
|
Fut: Future<Output = ApiResult<T>>,
|
|
146
156
|
{
|
|
147
|
-
|
|
148
|
-
|
|
157
|
+
DebounceSlot {
|
|
158
|
+
mutex: self.clone(),
|
|
159
|
+
state: self.0.default_slot.clone(),
|
|
160
|
+
}
|
|
161
|
+
.debounce_with(f)
|
|
162
|
+
.await
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/// A NEW debounce slot over this mutex: its tasks serialize against
|
|
166
|
+
/// every other locked task, but coalesce only among themselves.
|
|
167
|
+
pub fn slot(&self) -> DebounceSlot {
|
|
168
|
+
DebounceSlot {
|
|
169
|
+
mutex: self.clone(),
|
|
170
|
+
state: Default::default(),
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// One debounce KIND over a shared [`DebounceMutex`]. Execution is
|
|
176
|
+
/// exclusive across the whole mutex; coalescing (a caller resolving via a
|
|
177
|
+
/// parked runner instead of queueing) is scoped to the slot. A coalesced
|
|
178
|
+
/// caller's work must be subsumable by any same-slot runner that runs no
|
|
179
|
+
/// earlier than the call — which is why parameterized tasks sharing a slot
|
|
180
|
+
/// must read their parameters at RUN time (e.g. the [`Renderer`] geometry
|
|
181
|
+
/// command cell), never capture them at call time.
|
|
182
|
+
#[derive(Clone)]
|
|
183
|
+
pub struct DebounceSlot {
|
|
184
|
+
mutex: DebounceMutex,
|
|
185
|
+
state: Rc<SlotState>,
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
impl DebounceSlot {
|
|
189
|
+
pub async fn debounce_with<T, F, Fut>(&self, f: F) -> ApiResult<T>
|
|
190
|
+
where
|
|
191
|
+
T: Default,
|
|
192
|
+
F: FnOnce(RenderGuard) -> Fut,
|
|
193
|
+
Fut: Future<Output = ApiResult<T>>,
|
|
194
|
+
{
|
|
195
|
+
let state = &self.state;
|
|
196
|
+
let next = state.id.get() + 1;
|
|
197
|
+
if state.parked.get() {
|
|
149
198
|
self.await_settled(next).await;
|
|
150
199
|
return Ok(T::default());
|
|
151
200
|
}
|
|
152
201
|
|
|
153
|
-
let settle = SettleGuard::park(
|
|
154
|
-
let
|
|
155
|
-
|
|
156
|
-
let result = if
|
|
157
|
-
let next =
|
|
158
|
-
|
|
159
|
-
let held = HeldFlag::set(&self.0.held);
|
|
202
|
+
let settle = SettleGuard::park(state, next);
|
|
203
|
+
let guard = self.mutex.0.mutex.lock().await;
|
|
204
|
+
state.parked.set(false);
|
|
205
|
+
let result = if state.last.get() < next {
|
|
206
|
+
let next = state.id.get() + 1;
|
|
207
|
+
state.id.set(next);
|
|
208
|
+
let held = HeldFlag::set(&self.mutex.0.held);
|
|
160
209
|
let result = f(RenderGuard { _private: () }).await;
|
|
161
210
|
drop(held);
|
|
162
211
|
if result.is_ok() {
|
|
163
|
-
|
|
212
|
+
state.last.set(next);
|
|
164
213
|
}
|
|
165
214
|
|
|
166
215
|
result
|
|
@@ -168,14 +217,14 @@ impl DebounceMutex {
|
|
|
168
217
|
Ok(T::default())
|
|
169
218
|
};
|
|
170
219
|
|
|
171
|
-
drop(
|
|
220
|
+
drop(guard);
|
|
172
221
|
drop(settle);
|
|
173
222
|
result
|
|
174
223
|
}
|
|
175
224
|
|
|
176
225
|
async fn await_settled(&self, next: u64) {
|
|
177
|
-
while self.
|
|
178
|
-
if self.
|
|
226
|
+
while self.state.settled_id.get() < next {
|
|
227
|
+
if self.state.on_settle.read_next().await.is_err() {
|
|
179
228
|
break;
|
|
180
229
|
}
|
|
181
230
|
}
|
package/src/themes/icons.css
CHANGED
|
@@ -52,6 +52,7 @@ perspective-viewer-tab {
|
|
|
52
52
|
--psp-icon--sort-none--mask-image: url("../svg/sort-none-icon.svg");
|
|
53
53
|
--psp-icon--add-expression--mask-image: url("../svg/expression.svg");
|
|
54
54
|
--psp-icon--close--mask-image: url("../svg/close-icon.svg");
|
|
55
|
+
--psp-icon--pin--mask-image: url("../svg/pin-icon.svg");
|
|
55
56
|
--psp-label--inactive-column-selector--content: url("../svg/checkbox-unchecked-icon.svg");
|
|
56
57
|
--psp-label--active-column-selector--content: url("../svg/checkbox-checked-icon.svg");
|
|
57
58
|
--psp-icon--select-arrow-light--mask-image: url("../svg/dropdown-selector-light.svg");
|
package/src/themes/intl/de.css
CHANGED
|
@@ -108,6 +108,13 @@ perspective-dropdown {
|
|
|
108
108
|
/* Tabs */
|
|
109
109
|
--psp-label--style-tab--content: "Stil";
|
|
110
110
|
--psp-label--attributes-tab--content: "Attribute";
|
|
111
|
+
--psp-label--window-tab--content: "Fenster";
|
|
112
|
+
--psp-label--window-source--content: "Spalte";
|
|
113
|
+
--psp-label--window-order-by--content: "Sortieren nach";
|
|
114
|
+
--psp-label--window-partition-by--content: "Partitionieren nach";
|
|
115
|
+
--psp-label--window-frame--content: "Rahmen";
|
|
116
|
+
--psp-label--window-offset--content: "Versatz";
|
|
117
|
+
--psp-label--window-alpha--content: "Alpha";
|
|
111
118
|
--psp-label--query-tab--content: "Abfrage";
|
|
112
119
|
--psp-label--plugin-tab--content: "Plugin";
|
|
113
120
|
--psp-label--debug-tab--content: "JSON";
|
package/src/themes/intl/es.css
CHANGED
|
@@ -108,6 +108,13 @@ perspective-dropdown {
|
|
|
108
108
|
/* Tabs */
|
|
109
109
|
--psp-label--style-tab--content: "Estilo";
|
|
110
110
|
--psp-label--attributes-tab--content: "Atributos";
|
|
111
|
+
--psp-label--window-tab--content: "Ventana";
|
|
112
|
+
--psp-label--window-source--content: "Columna";
|
|
113
|
+
--psp-label--window-order-by--content: "Ordenar por";
|
|
114
|
+
--psp-label--window-partition-by--content: "Particionar por";
|
|
115
|
+
--psp-label--window-frame--content: "Marco";
|
|
116
|
+
--psp-label--window-offset--content: "Desplazamiento";
|
|
117
|
+
--psp-label--window-alpha--content: "Alfa";
|
|
111
118
|
--psp-label--query-tab--content: "Consulta";
|
|
112
119
|
--psp-label--plugin-tab--content: "Plugin";
|
|
113
120
|
--psp-label--debug-tab--content: "JSON";
|
package/src/themes/intl/fr.css
CHANGED
|
@@ -108,6 +108,13 @@ perspective-dropdown {
|
|
|
108
108
|
/* Tabs */
|
|
109
109
|
--psp-label--style-tab--content: "Style";
|
|
110
110
|
--psp-label--attributes-tab--content: "Les attributs";
|
|
111
|
+
--psp-label--window-tab--content: "Fenêtre";
|
|
112
|
+
--psp-label--window-source--content: "Colonne";
|
|
113
|
+
--psp-label--window-order-by--content: "Commandé par";
|
|
114
|
+
--psp-label--window-partition-by--content: "Partitionner par";
|
|
115
|
+
--psp-label--window-frame--content: "Cadre";
|
|
116
|
+
--psp-label--window-offset--content: "Décalage";
|
|
117
|
+
--psp-label--window-alpha--content: "Alpha";
|
|
111
118
|
--psp-label--query-tab--content: "Requête";
|
|
112
119
|
--psp-label--plugin-tab--content: "Plugin";
|
|
113
120
|
--psp-label--debug-tab--content: "JSON";
|
package/src/themes/intl/ja.css
CHANGED
|
@@ -108,6 +108,13 @@ perspective-dropdown {
|
|
|
108
108
|
/* Tabs */
|
|
109
109
|
--psp-label--style-tab--content: "スタイル";
|
|
110
110
|
--psp-label--attributes-tab--content: "属性";
|
|
111
|
+
--psp-label--window-tab--content: "ウィンドウ";
|
|
112
|
+
--psp-label--window-source--content: "列";
|
|
113
|
+
--psp-label--window-order-by--content: "注文方法";
|
|
114
|
+
--psp-label--window-partition-by--content: "パーティション";
|
|
115
|
+
--psp-label--window-frame--content: "フレーム";
|
|
116
|
+
--psp-label--window-offset--content: "オフセット";
|
|
117
|
+
--psp-label--window-alpha--content: "アルファ";
|
|
111
118
|
--psp-label--query-tab--content: "クエリ";
|
|
112
119
|
--psp-label--plugin-tab--content: "プラグイン";
|
|
113
120
|
--psp-label--debug-tab--content: "JSON";
|
package/src/themes/intl/pt.css
CHANGED
|
@@ -108,6 +108,13 @@ perspective-dropdown {
|
|
|
108
108
|
/* Tabs */
|
|
109
109
|
--psp-label--style-tab--content: "Estilo";
|
|
110
110
|
--psp-label--attributes-tab--content: "Atributos";
|
|
111
|
+
--psp-label--window-tab--content: "Janela";
|
|
112
|
+
--psp-label--window-source--content: "Coluna";
|
|
113
|
+
--psp-label--window-order-by--content: "Ordenar por";
|
|
114
|
+
--psp-label--window-partition-by--content: "Particionar por";
|
|
115
|
+
--psp-label--window-frame--content: "Quadro";
|
|
116
|
+
--psp-label--window-offset--content: "Deslocamento";
|
|
117
|
+
--psp-label--window-alpha--content: "Alfa";
|
|
111
118
|
--psp-label--query-tab--content: "Consulta";
|
|
112
119
|
--psp-label--plugin-tab--content: "Plugin";
|
|
113
120
|
--psp-label--debug-tab--content: "JSON";
|
package/src/themes/intl/zh.css
CHANGED
|
@@ -108,6 +108,13 @@ perspective-dropdown {
|
|
|
108
108
|
/* Tabs */
|
|
109
109
|
--psp-label--style-tab--content: "风格";
|
|
110
110
|
--psp-label--attributes-tab--content: "属性";
|
|
111
|
+
--psp-label--window-tab--content: "窗口";
|
|
112
|
+
--psp-label--window-source--content: "列";
|
|
113
|
+
--psp-label--window-order-by--content: "订购依据";
|
|
114
|
+
--psp-label--window-partition-by--content: "分区依据";
|
|
115
|
+
--psp-label--window-frame--content: "框架";
|
|
116
|
+
--psp-label--window-offset--content: "偏移";
|
|
117
|
+
--psp-label--window-alpha--content: "Alpha";
|
|
111
118
|
--psp-label--query-tab--content: "查询";
|
|
112
119
|
--psp-label--plugin-tab--content: "插件";
|
|
113
120
|
--psp-label--debug-tab--content: "JSON";
|
package/src/themes/intl.css
CHANGED
|
@@ -103,11 +103,20 @@ perspective-dropdown {
|
|
|
103
103
|
|
|
104
104
|
/* Tabs */
|
|
105
105
|
--psp-label--style-tab--content: "Style";
|
|
106
|
-
--psp-label--attributes-tab--content: "
|
|
106
|
+
--psp-label--attributes-tab--content: "Expression";
|
|
107
|
+
--psp-label--window-tab--content: "Window";
|
|
107
108
|
--psp-label--query-tab--content: "Query";
|
|
108
109
|
--psp-label--plugin-tab--content: "Plugin";
|
|
109
110
|
--psp-label--debug-tab--content: "JSON";
|
|
110
111
|
|
|
112
|
+
/* Window editor */
|
|
113
|
+
--psp-label--window-source--content: "Column";
|
|
114
|
+
--psp-label--window-order-by--content: "Order By";
|
|
115
|
+
--psp-label--window-partition-by--content: "Partition By";
|
|
116
|
+
--psp-label--window-frame--content: "Frame";
|
|
117
|
+
--psp-label--window-offset--content: "Offset";
|
|
118
|
+
--psp-label--window-alpha--content: "Alpha";
|
|
119
|
+
|
|
111
120
|
/* Plugin settings */
|
|
112
121
|
--psp-label--edit-mode--content: "Edit mode";
|
|
113
122
|
--psp-label--scroll-lock--content: "Scroll lock";
|
|
@@ -5,6 +5,7 @@ import type { Filter } from "./Filter.js";
|
|
|
5
5
|
import type { FilterReducer } from "./FilterReducer.js";
|
|
6
6
|
import type { GroupRollupMode } from "./GroupRollupMode.js";
|
|
7
7
|
import type { Sort } from "./Sort.js";
|
|
8
|
+
import type { Windows } from "./Windows.js";
|
|
8
9
|
import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -12,4 +13,4 @@ import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
|
12
13
|
* element-level `settings` flag. This is the `panels` entry type of the
|
|
13
14
|
* whole-element config format.
|
|
14
15
|
*/
|
|
15
|
-
export type PanelViewerConfig<V = string> = { version: V, columns_config: { [key in string]?: { [key in string]?: JsonValue } }, plugin: string, plugin_config: { [key in string]?: JsonValue }, table: string | null, theme: string | null, title: string | null, group_by: Array<string>, split_by: Array<string>, sort: Array<Sort>, filter: Array<Filter>, group_rollup_mode: GroupRollupMode, filter_op?: FilterReducer, expressions: Expressions, columns: Array<string | null>, aggregates: { [key in string]?: Aggregate }, group_by_depth?: number | null, };
|
|
16
|
+
export type PanelViewerConfig<V = string> = { version: V, columns_config: { [key in string]?: { [key in string]?: JsonValue } }, plugin: string, plugin_config: { [key in string]?: JsonValue }, table: string | null, theme: string | null, title: string | null, group_by: Array<string>, split_by: Array<string>, sort: Array<Sort>, filter: Array<Filter>, group_rollup_mode: GroupRollupMode, filter_op?: FilterReducer, expressions: Expressions, windows?: Windows, columns: Array<string | null>, aggregates: { [key in string]?: Aggregate }, group_by_depth?: number | null, };
|
|
@@ -5,6 +5,7 @@ import type { Filter } from "./Filter.js";
|
|
|
5
5
|
import type { FilterReducer } from "./FilterReducer.js";
|
|
6
6
|
import type { GroupRollupMode } from "./GroupRollupMode.js";
|
|
7
7
|
import type { Sort } from "./Sort.js";
|
|
8
|
+
import type { Windows } from "./Windows.js";
|
|
8
9
|
import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -15,4 +16,4 @@ import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
|
15
16
|
* state there, carried by the top-level `active` field instead), while the
|
|
16
17
|
* single-panel format flattens back to the legacy shape.
|
|
17
18
|
*/
|
|
18
|
-
export type ViewerConfig<V = string> = { settings: boolean, version: V, columns_config: { [key in string]?: { [key in string]?: JsonValue } }, plugin: string, plugin_config: { [key in string]?: JsonValue }, table: string | null, theme: string | null, title: string | null, group_by: Array<string>, split_by: Array<string>, sort: Array<Sort>, filter: Array<Filter>, group_rollup_mode: GroupRollupMode, filter_op?: FilterReducer, expressions: Expressions, columns: Array<string | null>, aggregates: { [key in string]?: Aggregate }, group_by_depth?: number | null, };
|
|
19
|
+
export type ViewerConfig<V = string> = { settings: boolean, version: V, columns_config: { [key in string]?: { [key in string]?: JsonValue } }, plugin: string, plugin_config: { [key in string]?: JsonValue }, table: string | null, theme: string | null, title: string | null, group_by: Array<string>, split_by: Array<string>, sort: Array<Sort>, filter: Array<Filter>, group_rollup_mode: GroupRollupMode, filter_op?: FilterReducer, expressions: Expressions, windows?: Windows, columns: Array<string | null>, aggregates: { [key in string]?: Aggregate }, group_by_depth?: number | null, };
|
|
@@ -6,6 +6,7 @@ import type { FilterReducer } from "./FilterReducer.js";
|
|
|
6
6
|
import type { GroupRollupMode } from "./GroupRollupMode.js";
|
|
7
7
|
import type { OptionalUpdate } from "./OptionalUpdate.js";
|
|
8
8
|
import type { Sort } from "./Sort.js";
|
|
9
|
+
import type { Windows } from "./Windows.js";
|
|
9
10
|
import type { JsonValue } from "./serde_json/JsonValue.js";
|
|
10
11
|
|
|
11
12
|
export type ViewerConfigUpdate = { version?: OptionalUpdate<string>, plugin?: OptionalUpdate<string>, title?: OptionalUpdate<string>, table?: OptionalUpdate<string>, theme?: OptionalUpdate<string>, settings?: OptionalUpdate<boolean>, plugin_config?: OptionalUpdate<{ [key in string]?: JsonValue }>, columns_config?: OptionalUpdate<{ [key in string]?: { [key in string]?: JsonValue } }>,
|
|
@@ -74,6 +75,14 @@ sort?: Array<Sort>,
|
|
|
74
75
|
* panel.
|
|
75
76
|
*/
|
|
76
77
|
expressions?: Expressions,
|
|
78
|
+
/**
|
|
79
|
+
* The `windows` property declares ordered, partitioned rolling
|
|
80
|
+
* computations (moving aggregates, cumulative sums) as _new_ columns
|
|
81
|
+
* keyed by output alias (`{"name": {...spec}}`, symmetric with
|
|
82
|
+
* `expressions`), analogous to SQL window functions. See
|
|
83
|
+
* [`crate::config::WindowSpec`].
|
|
84
|
+
*/
|
|
85
|
+
windows?: Windows,
|
|
77
86
|
/**
|
|
78
87
|
* Aggregates perform a calculation over an entire column, and are
|
|
79
88
|
* displayed when one or more [Group By](#group-by) are applied to the
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { WindowSortDir } from "./WindowSortDir.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `Table` column which orders each partition, with its direction -
|
|
6
|
+
* serialized as a two-element array (`["ts", "desc"]`), symmetric with the
|
|
7
|
+
* `ViewConfig`'s `sort` field.
|
|
8
|
+
*/
|
|
9
|
+
export type WindowSort = [string, WindowSortDir];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A window's order direction. A dedicated two-variant enum rather than
|
|
5
|
+
* [`crate::config::SortDir`] - the column-sort extras (`col asc`, `abs`,
|
|
6
|
+
* `none`) are meaningless inside a window frame and unrepresentable here.
|
|
7
|
+
*/
|
|
8
|
+
export type WindowSortDir = "asc" | "desc";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { WindowAggregate } from "./WindowAggregate.js";
|
|
3
|
+
import type { WindowSort } from "./WindowSort.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The serialized form of [`WindowSpec`].
|
|
7
|
+
*/
|
|
8
|
+
export type WindowSpec = {
|
|
9
|
+
/**
|
|
10
|
+
* The input column - either a real `Table` column or an expression
|
|
11
|
+
* alias from the same `ViewConfig`.
|
|
12
|
+
*/
|
|
13
|
+
column: string, aggregate: WindowAggregate,
|
|
14
|
+
/**
|
|
15
|
+
* Columns whose distinct value tuples partition the rows; empty
|
|
16
|
+
* partitions the whole `Table` as one group.
|
|
17
|
+
*/
|
|
18
|
+
partition_by?: Array<string>,
|
|
19
|
+
/**
|
|
20
|
+
* The `Table` column which orders each partition, and the direction.
|
|
21
|
+
*/
|
|
22
|
+
order_by?: WindowSort | null,
|
|
23
|
+
/**
|
|
24
|
+
* A frame of the `rows` preceding each row, plus the row itself.
|
|
25
|
+
* Mutually exclusive with `range` and `cumulative`.
|
|
26
|
+
*/
|
|
27
|
+
rows?: number | null,
|
|
28
|
+
/**
|
|
29
|
+
* A frame of the rows whose `order_by` value lies within `range` of
|
|
30
|
+
* each row's, requiring a numeric or temporal `order_by`. Mutually
|
|
31
|
+
* exclusive with `rows` and `cumulative`.
|
|
32
|
+
*/
|
|
33
|
+
range?: number | null,
|
|
34
|
+
/**
|
|
35
|
+
* `true` frames all rows from the partition start through each row.
|
|
36
|
+
* Default can be omitted.
|
|
37
|
+
*/
|
|
38
|
+
cumulative?: boolean | null,
|
|
39
|
+
/**
|
|
40
|
+
* Row offset for `lag`/`lead` (default 1).
|
|
41
|
+
*/
|
|
42
|
+
offset?: number | null,
|
|
43
|
+
/**
|
|
44
|
+
* Smoothing factor in `(0, 1]` for `ema`.
|
|
45
|
+
*/
|
|
46
|
+
alpha?: number | null, };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
|
2
|
+
import type { WindowSpec } from "./WindowSpec.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The window columns of a `ViewConfig`, keyed by output column alias -
|
|
6
|
+
* symmetric with `expressions` (`{"name": {...spec}}`). An alias must not
|
|
7
|
+
* collide with a `Table` column, expression alias, or another window's
|
|
8
|
+
* key.
|
|
9
|
+
*/
|
|
10
|
+
export type Windows = { [key in string]?: WindowSpec };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|