flexdesk 0.16.1 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +112 -0
- package/LICENSE +0 -0
- package/README.md +2435 -42
- package/THIRD_PARTY_LICENSES.md +0 -0
- package/canvas.js +18 -0
- package/charts.js +21 -0
- package/core.js +14 -0
- package/css/base.css +1834 -75
- package/css/flexdesk.css +3165 -159
- package/css/overrides.css +16 -0
- package/css/reset.css +0 -0
- package/css/tokens.css +0 -0
- package/dist/canvas.js +6 -239
- package/dist/canvas.js.map +3 -3
- package/dist/charts.js +707 -18
- package/dist/charts.js.map +4 -4
- package/dist/chunk-3PHCPZHT.js +0 -0
- package/dist/chunk-3PHCPZHT.js.map +0 -0
- package/dist/chunk-4A7SJC3T.js +503 -0
- package/dist/chunk-4A7SJC3T.js.map +7 -0
- package/dist/{chunk-6JSOVNID.js → chunk-CVMCZZX2.js} +635 -10
- package/dist/chunk-CVMCZZX2.js.map +7 -0
- package/dist/chunk-D3COLZZ2.js +1311 -0
- package/dist/chunk-D3COLZZ2.js.map +7 -0
- package/dist/chunk-FOOS3T5L.js +0 -0
- package/dist/chunk-FOOS3T5L.js.map +0 -0
- package/dist/{chunk-SN4LSOAR.js → chunk-GOQLR5WR.js} +452 -2
- package/dist/chunk-GOQLR5WR.js.map +7 -0
- package/dist/{chunk-FL5KFNQH.js → chunk-HNU6MM2B.js} +52 -17
- package/dist/chunk-HNU6MM2B.js.map +7 -0
- package/dist/chunk-HYJYYEPK.js +375 -0
- package/dist/chunk-HYJYYEPK.js.map +7 -0
- package/dist/chunk-JKZLNKG6.js +2041 -0
- package/dist/chunk-JKZLNKG6.js.map +7 -0
- package/dist/chunk-JYWURG5T.js +0 -0
- package/dist/chunk-JYWURG5T.js.map +0 -0
- package/dist/{chunk-FBGP5KN5.js → chunk-LWV23YVE.js} +5073 -532
- package/dist/chunk-LWV23YVE.js.map +7 -0
- package/dist/chunk-N7HC3ADV.js +30 -0
- package/dist/chunk-N7HC3ADV.js.map +7 -0
- package/dist/{chunk-RQM5Z2MU.js → chunk-RMTRWWEO.js} +633 -311
- package/dist/chunk-RMTRWWEO.js.map +7 -0
- package/dist/{chunk-NLTOY57M.js → chunk-UURZ37SD.js} +28 -48
- package/dist/chunk-UURZ37SD.js.map +7 -0
- package/dist/{chunk-B5Q53LAJ.js → chunk-UWO43BZU.js} +2 -2
- package/dist/chunk-UWO43BZU.js.map +7 -0
- package/dist/chunk-WVFGV5FT.js +0 -0
- package/dist/chunk-WVFGV5FT.js.map +0 -0
- package/dist/core.js +170 -118
- package/dist/core.js.map +2 -2
- package/dist/editor.js +156 -70
- package/dist/editor.js.map +2 -2
- package/dist/flexdesk.css +3165 -159
- package/dist/flow.js +2789 -306
- package/dist/flow.js.map +4 -4
- package/dist/host.js +109 -3
- package/dist/host.js.map +3 -3
- package/dist/reset.css +0 -0
- package/dist/tile_registry-6WZPTUZV.js +0 -0
- package/dist/tile_registry-6WZPTUZV.js.map +0 -0
- package/dist/tiles.js +657 -234
- package/dist/tiles.js.map +4 -4
- package/dist/tokens.css +0 -0
- package/dist/widgets.js +3290 -2124
- package/dist/widgets.js.map +4 -4
- package/dist/wm.js +1227 -347
- package/dist/wm.js.map +4 -4
- package/editor.js +20 -0
- package/flow.js +21 -0
- package/host.js +14 -0
- package/package.json +12 -1
- package/src/canvas/canvas_adapter.js +5 -0
- package/src/canvas/edge_router.js +0 -0
- package/src/canvas/graph/connector_router.js +0 -0
- package/src/canvas/graph/history_service.js +0 -0
- package/src/canvas/graph/node_platform.js +0 -0
- package/src/canvas/index.js +1 -0
- package/src/canvas/layered_layout.js +244 -0
- package/src/charts/chart_types.js +0 -0
- package/src/charts/data_series_plot_window.js +0 -0
- package/src/charts/downsample.js +2 -2
- package/src/charts/plot_config.js +53 -29
- package/src/charts/plot_config_editor.js +627 -0
- package/src/charts/plot_grid.js +449 -0
- package/src/charts/plot_popout_window.js +103 -317
- package/src/charts/plotly_wrapper.js +22 -2
- package/src/charts/series_transforms.js +206 -0
- package/src/core/event_bus.js +0 -0
- package/src/core/logging.js +1 -1
- package/src/core/settings.js +105 -19
- package/src/core/state_guard.js +93 -51
- package/src/core/state_guard_config.js +85 -74
- package/src/core/state_machine.js +0 -0
- package/src/editor/editor_pane.js +3 -3
- package/src/editor/monaco_editor_factory.js +124 -60
- package/src/editor/monaco_loader.js +103 -28
- package/src/editor/notebook_search.js +0 -0
- package/src/editor/notebook_tab_bar.js +38 -52
- package/src/editor/notebook_undo_manager.js +0 -0
- package/src/editor/split_pane_container.js +6 -3
- package/src/flow/canvas_editor/connections.js +90 -0
- package/src/flow/canvas_editor/editor.js +2351 -153
- package/src/flow/canvas_editor/index.js +2 -1
- package/src/flow/canvas_editor/layout.js +119 -12
- package/src/flow/canvas_editor/strings.js +80 -0
- package/src/flow/kit/always_before.js +0 -0
- package/src/flow/kit/catalogue.js +97 -3
- package/src/flow/kit/chip_input.js +0 -0
- package/src/flow/kit/dom.js +0 -0
- package/src/flow/kit/findings.js +0 -0
- package/src/flow/kit/history.js +0 -0
- package/src/flow/kit/index.js +3 -3
- package/src/flow/kit/keys.js +7 -1
- package/src/flow/kit/logic_graph.js +97 -15
- package/src/flow/kit/references.js +0 -0
- package/src/flow/kit/settings_panel.js +0 -0
- package/src/flow/kit/settings_schema.js +2 -1
- package/src/flow/kit/step_picker.js +0 -0
- package/src/flow/kit/strings.js +3 -1
- package/src/flow/kit/value_picker.js +0 -0
- package/src/flow/kit/widgets.js +86 -109
- package/src/flow/lanes/editor.js +136 -14
- package/src/flow/lanes/index.js +3 -1
- package/src/flow/lanes/layout.js +0 -0
- package/src/flow/lanes/pipeline.js +44 -2
- package/src/flow/lanes/preview.js +0 -0
- package/src/flow/lanes/strings.js +1 -0
- package/src/flow/outline/editor.js +0 -0
- package/src/flow/outline/index.js +0 -0
- package/src/flow/outline/mapping.js +0 -0
- package/src/flow/outline/menu.js +0 -0
- package/src/flow/outline/operations.js +0 -0
- package/src/flow/outline/recognise.js +0 -0
- package/src/flow/outline/strings.js +0 -0
- package/src/help/help_modal.js +168 -42
- package/src/help/help_registry.js +12 -1
- package/src/host/external_links.js +0 -0
- package/src/host/file_picker.js +117 -0
- package/src/host/host.js +10 -2
- package/src/host/photino_host.js +9 -0
- package/src/host/photino_host.md +21 -3
- package/src/host/pywebview_host.js +10 -0
- package/src/tiles/chart_tiles.js +53 -245
- package/src/tiles/config_schema.js +8 -0
- package/src/tiles/figure_tile.js +322 -0
- package/src/tiles/layout_persistence.js +3 -3
- package/src/tiles/list_tiles.js +7 -7
- package/src/tiles/scope_picker.js +0 -0
- package/src/tiles/tile_base.js +1 -1
- package/src/tiles/tile_config_form.js +442 -0
- package/src/tiles/tile_grid.js +2 -0
- package/src/tiles/tile_registry.js +0 -0
- package/src/tiling/bottom_panel_tabs.js +67 -99
- package/src/tiling/command_palette.js +64 -19
- package/src/tiling/content_registry.js +4 -1
- package/src/tiling/desktops.js +11 -1
- package/src/tiling/entity_sources.js +0 -0
- package/src/tiling/keymap.js +403 -128
- package/src/tiling/kind_taxonomy.js +78 -0
- package/src/tiling/landing_table.js +0 -0
- package/src/tiling/loading_overlay.js +0 -0
- package/src/tiling/nav_panel.js +59 -10
- package/src/tiling/page_factory.js +5 -5
- package/src/tiling/panel_availability.js +49 -0
- package/src/tiling/panel_keys.js +0 -0
- package/src/tiling/shell.js +114 -12
- package/src/tiling/tab_strip.js +0 -0
- package/src/tiling/tile_breadcrumb.js +0 -0
- package/src/tiling/tile_renderer.js +105 -9
- package/src/tiling/tile_tab_menu.js +0 -0
- package/src/tiling/tile_tree.js +0 -0
- package/src/tiling/wm.js +562 -30
- package/src/tiling/zoom.js +0 -0
- package/src/ui/base/component_base.js +0 -0
- package/src/ui/base/controller_base.js +0 -0
- package/src/ui/base/page_base.js +0 -0
- package/src/ui/components/about_dialog.js +0 -0
- package/src/ui/components/action_dropdown.js +30 -2
- package/src/ui/components/alert_log.js +0 -0
- package/src/ui/components/alerts_pane.js +0 -0
- package/src/ui/components/attribute_list_editor.js +0 -0
- package/src/ui/components/autocomplete_field.js +0 -0
- package/src/ui/components/cell_editor_host.js +293 -0
- package/src/ui/components/cell_editors.js +480 -0
- package/src/ui/components/cell_grid.js +761 -0
- package/src/ui/components/cell_paste.js +243 -0
- package/src/ui/components/cell_selection.js +220 -0
- package/src/ui/components/choice_controls.js +351 -0
- package/src/ui/components/color_field.js +211 -0
- package/src/ui/components/color_list_field.js +210 -0
- package/src/ui/components/column_fit.js +0 -0
- package/src/ui/components/column_groups.js +314 -0
- package/src/ui/components/column_order.js +142 -0
- package/src/ui/components/computing_status_window.js +98 -25
- package/src/ui/components/confirm_dialog.js +81 -38
- package/src/ui/components/context_menu.js +2 -2
- package/src/ui/components/conversation_view.js +440 -0
- package/src/ui/components/crosstab.js +289 -0
- package/src/ui/components/data_table.js +696 -71
- package/src/ui/components/detail_header.js +22 -11
- package/src/ui/components/document_outline.js +397 -0
- package/src/ui/components/drag_reorder.js +0 -0
- package/src/ui/components/fact_table.js +0 -0
- package/src/ui/components/fill_handle.js +322 -0
- package/src/ui/components/gallery_picker.js +19 -8
- package/src/ui/components/header_actions.js +55 -0
- package/src/ui/components/inline_renamer.js +0 -0
- package/src/ui/components/job_progress.js +51 -0
- package/src/ui/components/managed_window.js +27 -4
- package/src/ui/components/menu_bar.js +745 -0
- package/src/ui/components/modal.js +449 -75
- package/src/ui/components/notification_history.js +3 -3
- package/src/ui/components/progress.js +483 -0
- package/src/ui/components/record_list.js +0 -0
- package/src/ui/components/row_activation.js +0 -0
- package/src/ui/components/section_stack.js +298 -0
- package/src/ui/components/series.js +173 -0
- package/src/ui/components/settings_view.js +634 -0
- package/src/ui/components/slide_out_panel.js +43 -6
- package/src/ui/components/slider_field.js +275 -18
- package/src/ui/components/sortable_list.js +0 -0
- package/src/ui/components/staged_edits.js +361 -0
- package/src/ui/components/staged_history.js +172 -0
- package/src/ui/components/table_filter_chips.js +0 -0
- package/src/ui/components/table_state_store.js +0 -0
- package/src/ui/components/table_structure.js +182 -0
- package/src/ui/components/table_values.js +0 -0
- package/src/ui/components/tabs.js +497 -0
- package/src/ui/components/tag_input.js +215 -0
- package/src/ui/components/toast.js +25 -8
- package/src/ui/components/toggle_field.js +175 -0
- package/src/ui/components/tree_view.js +55 -34
- package/src/ui/components/tsv.js +74 -0
- package/src/ui/components/window_taskbar.js +0 -0
- package/src/ui/components/wizard.js +563 -0
- package/src/ui/controllers/window_chrome_controller.js +2 -2
- package/src/ui/notification_center.js +375 -119
- package/src/ui/utils/auto_scrollbars.js +0 -0
- package/src/ui/utils/markdown.js +709 -0
- package/src/ui/utils/native_context_menu.js +0 -0
- package/src/ui/utils/overlay_scrollbar.js +16 -12
- package/src/ui/utils/raf_resize_observer.js +0 -0
- package/src/ui/utils/scroll_lock.js +0 -0
- package/src/ui/utils/strip_scroll.js +55 -0
- package/src/ui/utils/tooltip_service.js +0 -8
- package/tiles.js +27 -0
- package/widgets.js +69 -0
- package/wm.js +28 -0
- package/dist/chunk-6JSOVNID.js.map +0 -7
- package/dist/chunk-B5Q53LAJ.js.map +0 -7
- package/dist/chunk-FBGP5KN5.js.map +0 -7
- package/dist/chunk-FL5KFNQH.js.map +0 -7
- package/dist/chunk-NLTOY57M.js.map +0 -7
- package/dist/chunk-NNFTETK3.js +0 -633
- package/dist/chunk-NNFTETK3.js.map +0 -7
- package/dist/chunk-O5OHMWBB.js +0 -284
- package/dist/chunk-O5OHMWBB.js.map +0 -7
- package/dist/chunk-RQM5Z2MU.js.map +0 -7
- package/dist/chunk-SN4LSOAR.js.map +0 -7
- package/dist/chunk-W6FBJLPW.js +0 -367
- package/dist/chunk-W6FBJLPW.js.map +0 -7
- package/src/ui/controllers/panel_state_machine.js +0 -634
|
@@ -1,53 +1,102 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Computing Status Window
|
|
3
3
|
*
|
|
4
|
-
* Lightweight ManagedWindow that shows a spinner and
|
|
5
|
-
* while a long-running computation is in progress. Returns a
|
|
6
|
-
* with update()
|
|
4
|
+
* Lightweight ManagedWindow that shows a spinner (or a progress bar) and a
|
|
5
|
+
* status message while a long-running computation is in progress. Returns a
|
|
6
|
+
* handle with update(), setProgress(), setStep(), complete(), cancelled(),
|
|
7
|
+
* close() and a `result` promise.
|
|
7
8
|
*
|
|
8
9
|
* Optionally shows a Cancel button when an onCancel callback is provided.
|
|
10
|
+
* Only one is open at a time: opening another closes the first, which then
|
|
11
|
+
* settles as cancelled (its onCancel is not called).
|
|
9
12
|
*/
|
|
10
13
|
|
|
11
14
|
import { ManagedWindow } from './managed_window.js';
|
|
15
|
+
import { mountJobProgress } from './job_progress.js';
|
|
12
16
|
|
|
13
17
|
let _activeWindow = null;
|
|
14
18
|
|
|
15
19
|
/**
|
|
16
20
|
* Show a computing status window.
|
|
21
|
+
*
|
|
22
|
+
* `result` settles once: `complete({ok, message})` gives `done` or `error`
|
|
23
|
+
* (the window stays, with a Close button, until closed), `cancelled()` gives
|
|
24
|
+
* `cancelled`, and so does closing the window while it runs (by its ×,
|
|
25
|
+
* Escape, `close()` or opening another). Closing never calls `onCancel`: only
|
|
26
|
+
* the Cancel button does. `progress` and `steps` are fixed when the window
|
|
27
|
+
* opens: `setProgress` throws if it was opened without `progress`, and
|
|
28
|
+
* `setStep` if it was opened without `steps`.
|
|
29
|
+
*
|
|
17
30
|
* @param {Object} options
|
|
18
31
|
* @param {string} [options.title='Computing...'] - Window title
|
|
19
|
-
* @param {string} [options.message=''] - Status message below spinner
|
|
32
|
+
* @param {string} [options.message=''] - Status message below spinner (markup; `update` takes text)
|
|
20
33
|
* @param {string} [options.icon='hourglass_top'] - Material icon name
|
|
21
34
|
* @param {Function} [options.onCancel] - If provided, shows a Cancel button. Called once when clicked.
|
|
22
|
-
* @
|
|
35
|
+
* @param {boolean|Object} [options.progress] - A ProgressBar in place of the spinner: `true` or its options.
|
|
36
|
+
* @param {Array} [options.steps] - StepProgress steps, shown above the message.
|
|
37
|
+
* @returns {{ update(msg: string): void, setProgress(next: number|Object): void,
|
|
38
|
+
* setStep(which: string|number, opts?: {pass?: number, passes?: number}): void,
|
|
39
|
+
* complete(result: {ok: boolean, message?: string}): void, cancelled(msg?: string): void,
|
|
40
|
+
* close(): void, result: Promise<{status: 'done'|'error'|'cancelled', message: string}> }}
|
|
23
41
|
*/
|
|
24
|
-
export function showComputingWindow({
|
|
42
|
+
export function showComputingWindow({
|
|
43
|
+
title = 'Computing...', message = '', icon = 'hourglass_top', onCancel,
|
|
44
|
+
progress = null, steps = null,
|
|
45
|
+
} = {}) {
|
|
25
46
|
if (_activeWindow) {
|
|
26
47
|
_activeWindow.close();
|
|
27
48
|
_activeWindow = null;
|
|
28
49
|
}
|
|
29
50
|
|
|
51
|
+
let finished = false;
|
|
52
|
+
let settle;
|
|
53
|
+
const result = new Promise((resolve) => { settle = resolve; });
|
|
54
|
+
|
|
30
55
|
const content = document.createElement('div');
|
|
31
56
|
content.className = 'twm-computing-status';
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
57
|
+
const spinnerEl = document.createElement('div');
|
|
58
|
+
spinnerEl.className = 'twm-computing-status__spinner';
|
|
59
|
+
const msgEl = document.createElement('div');
|
|
60
|
+
msgEl.className = 'twm-computing-status__message';
|
|
61
|
+
// The opening message is markup, as it always was; every later one is text.
|
|
62
|
+
msgEl.innerHTML = message;
|
|
63
|
+
content.appendChild(spinnerEl);
|
|
64
|
+
const job = mountJobProgress(content, { progress, steps, spinner: spinnerEl });
|
|
65
|
+
content.appendChild(msgEl);
|
|
36
66
|
|
|
67
|
+
let cancelBtn = null;
|
|
37
68
|
if (typeof onCancel === 'function') {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (msgEl) msgEl.textContent = 'Cancelling...';
|
|
69
|
+
cancelBtn = document.createElement('button');
|
|
70
|
+
cancelBtn.className = 'twm-computing-status__cancel-btn';
|
|
71
|
+
cancelBtn.textContent = 'Cancel';
|
|
72
|
+
cancelBtn.addEventListener('click', () => {
|
|
73
|
+
cancelBtn.disabled = true;
|
|
74
|
+
msgEl.textContent = 'Cancelling...';
|
|
45
75
|
onCancel();
|
|
46
76
|
}, { once: true });
|
|
47
|
-
content.appendChild(
|
|
77
|
+
content.appendChild(cancelBtn);
|
|
48
78
|
}
|
|
49
79
|
|
|
50
|
-
|
|
80
|
+
const closeBtn = document.createElement('button');
|
|
81
|
+
closeBtn.type = 'button';
|
|
82
|
+
closeBtn.className = 'twm-computing-status__cancel-btn twm-computing-status__close-btn';
|
|
83
|
+
closeBtn.textContent = 'Close';
|
|
84
|
+
closeBtn.hidden = true;
|
|
85
|
+
content.appendChild(closeBtn);
|
|
86
|
+
|
|
87
|
+
const finish = (status, text) => {
|
|
88
|
+
finished = true;
|
|
89
|
+
spinnerEl.hidden = true;
|
|
90
|
+
if (cancelBtn) cancelBtn.hidden = true;
|
|
91
|
+
msgEl.textContent = text;
|
|
92
|
+
msgEl.classList.toggle('is-ok', status === 'done');
|
|
93
|
+
msgEl.classList.toggle('is-err', status === 'error');
|
|
94
|
+
msgEl.classList.toggle('is-cancelled', status === 'cancelled');
|
|
95
|
+
job.finish(status);
|
|
96
|
+
settle({ status, message: text });
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const win = new ManagedWindow({
|
|
51
100
|
id: 'computing-status-window',
|
|
52
101
|
title,
|
|
53
102
|
icon,
|
|
@@ -55,21 +104,45 @@ export function showComputingWindow({ title = 'Computing...', message = '', icon
|
|
|
55
104
|
minWidth: 320,
|
|
56
105
|
minHeight: 140,
|
|
57
106
|
defaultWidth: 380,
|
|
58
|
-
defaultHeight: onCancel ? 190 : 160,
|
|
107
|
+
defaultHeight: (onCancel ? 190 : 160) + (job.bar ? 30 : 0) + (job.steps ? 40 : 0),
|
|
59
108
|
canMinimize: true,
|
|
60
109
|
canMaximize: false,
|
|
61
110
|
canResize: false,
|
|
62
111
|
canDrag: true,
|
|
63
112
|
modal: false,
|
|
64
|
-
onClose: () => {
|
|
113
|
+
onClose: () => {
|
|
114
|
+
if (_activeWindow === win) _activeWindow = null;
|
|
115
|
+
if (finished) return;
|
|
116
|
+
finish('cancelled', 'Cancelled.');
|
|
117
|
+
},
|
|
65
118
|
});
|
|
66
|
-
|
|
67
|
-
_activeWindow
|
|
119
|
+
closeBtn.addEventListener('click', () => win.close());
|
|
120
|
+
_activeWindow = win;
|
|
121
|
+
win.show();
|
|
68
122
|
|
|
69
123
|
return {
|
|
124
|
+
result,
|
|
70
125
|
update(msg) {
|
|
71
|
-
|
|
72
|
-
|
|
126
|
+
if (finished) return;
|
|
127
|
+
msgEl.textContent = msg;
|
|
128
|
+
},
|
|
129
|
+
setProgress(next) {
|
|
130
|
+
if (finished) return;
|
|
131
|
+
job.setProgress(next);
|
|
132
|
+
},
|
|
133
|
+
setStep(which, opts) {
|
|
134
|
+
if (finished) return;
|
|
135
|
+
job.setStep(which, opts);
|
|
136
|
+
},
|
|
137
|
+
complete(res) {
|
|
138
|
+
if (finished) return;
|
|
139
|
+
finish(res?.ok ? 'done' : 'error', res?.message || '');
|
|
140
|
+
closeBtn.hidden = false;
|
|
141
|
+
},
|
|
142
|
+
cancelled(msg) {
|
|
143
|
+
if (finished) return;
|
|
144
|
+
finish('cancelled', msg || 'Cancelled.');
|
|
145
|
+
closeBtn.hidden = false;
|
|
73
146
|
},
|
|
74
147
|
close() {
|
|
75
148
|
if (_activeWindow) {
|
|
@@ -11,12 +11,14 @@
|
|
|
11
11
|
* action, square frame, Tab focus trap).
|
|
12
12
|
*
|
|
13
13
|
* The one custom case is `showRunProgressDialog`, which exposes an
|
|
14
|
-
* imperative `update /
|
|
14
|
+
* imperative `update / setProgress / setStep / complete / cancelled /
|
|
15
|
+
* close` API and a `result` promise, and so
|
|
15
16
|
* stays as a direct `ManagedWindow` build — but it still benefits
|
|
16
17
|
* from the focus trap + chrome by virtue of `modal: true`.
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
20
|
import { ManagedWindow } from './managed_window.js';
|
|
21
|
+
import { mountJobProgress } from './job_progress.js';
|
|
20
22
|
import {
|
|
21
23
|
openConfirm, openForm, openModal,
|
|
22
24
|
} from './modal.js';
|
|
@@ -65,10 +67,12 @@ export async function showDeleteConfirmDialog(options = {}) {
|
|
|
65
67
|
itemType = 'item',
|
|
66
68
|
additionalMessage = '',
|
|
67
69
|
} = options;
|
|
70
|
+
// `openConfirm` renders the message as text, so a user-named item
|
|
71
|
+
// (`<b>x</b>`, an unclosed `<`) is shown exactly as it was typed.
|
|
68
72
|
let message = `Delete ${itemType}`;
|
|
69
73
|
if (itemName) message += ` "${itemName}"`;
|
|
70
74
|
message += '?';
|
|
71
|
-
if (additionalMessage) message +=
|
|
75
|
+
if (additionalMessage) message += `\n\n${additionalMessage}`;
|
|
72
76
|
return openConfirm({
|
|
73
77
|
title: `Delete ${capitalize(itemType)}`,
|
|
74
78
|
message,
|
|
@@ -189,41 +193,73 @@ function capitalize(str) {
|
|
|
189
193
|
}
|
|
190
194
|
|
|
191
195
|
|
|
192
|
-
// ─── showRunProgressDialog (
|
|
196
|
+
// ─── showRunProgressDialog (custom build) ───────────────────────────
|
|
193
197
|
//
|
|
194
|
-
// This one exposes an imperative API (`update`, `
|
|
195
|
-
// `close`) that the openModal/openForm/openConfirm
|
|
196
|
-
// — they're one-shot promise-returning. Keep the direct
|
|
197
|
-
// build, but it still gets the TUI chrome + focus trap for free
|
|
198
|
-
// `modal: true`.
|
|
198
|
+
// This one exposes an imperative API (`update`, `setProgress`, `setStep`,
|
|
199
|
+
// `complete`, `cancelled`, `close`) that the openModal/openForm/openConfirm
|
|
200
|
+
// helpers don't model — they're one-shot promise-returning. Keep the direct
|
|
201
|
+
// ManagedWindow build, but it still gets the TUI chrome + focus trap for free
|
|
202
|
+
// via `modal: true`.
|
|
199
203
|
|
|
200
204
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
|
|
205
|
+
* @typedef {Object} RunProgressResult
|
|
206
|
+
* @property {'done'|'error'|'cancelled'} status
|
|
207
|
+
* @property {string} message
|
|
208
|
+
*/
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Show a run progress dialog with a spinner (or a bar), live message
|
|
212
|
+
* updates, optional phases, and a final status.
|
|
213
|
+
*
|
|
214
|
+
* `progress` (`true` or ProgressBar options) shows a determinate bar in place
|
|
215
|
+
* of the spinner; `steps` (StepProgress steps) shows the phases above it.
|
|
216
|
+
* Both are fixed when the dialog opens: `setProgress` throws if it was opened
|
|
217
|
+
* without `progress`, and `setStep` if it was opened without `steps`.
|
|
218
|
+
* `result` settles once, with the final state: `complete({ok})` gives `done`
|
|
219
|
+
* or `error`, `cancelled()` gives `cancelled`, and so does closing the dialog
|
|
220
|
+
* while it runs (by its ×, Escape or `close()`). Closing never calls
|
|
221
|
+
* `onCancel`: only the Stop button does.
|
|
222
|
+
*
|
|
223
|
+
* @param {Object} [options]
|
|
224
|
+
* @param {string} [options.title='Running Pipeline']
|
|
225
|
+
* @param {string} [options.message='Starting…']
|
|
226
|
+
* @param {Function} [options.onCancel] - Shows a Stop button.
|
|
227
|
+
* @param {boolean|Object} [options.progress] - A ProgressBar, `true` or its options.
|
|
228
|
+
* @param {Array} [options.steps] - StepProgress steps.
|
|
229
|
+
* @returns {{ update(msg: string): void, setProgress(next: number|Object): void,
|
|
230
|
+
* setStep(which: string|number, opts?: {pass?: number, passes?: number}): void,
|
|
231
|
+
* complete(result: {ok: boolean, message: string}): void, cancelled(msg?: string): void,
|
|
232
|
+
* close(): void, result: Promise<RunProgressResult> }}
|
|
205
233
|
*/
|
|
206
234
|
export function showRunProgressDialog(options = {}) {
|
|
207
235
|
const {
|
|
208
236
|
title = 'Running Pipeline',
|
|
209
237
|
message = 'Starting…',
|
|
210
238
|
onCancel,
|
|
239
|
+
progress = null,
|
|
240
|
+
steps = null,
|
|
211
241
|
} = options;
|
|
212
242
|
|
|
213
243
|
const dialogId = `run-progress-${++dialogIdCounter}`;
|
|
214
244
|
let finished = false;
|
|
245
|
+
let settle;
|
|
246
|
+
const result = new Promise((resolve) => { settle = resolve; });
|
|
215
247
|
|
|
216
248
|
const contentEl = document.createElement('div');
|
|
217
249
|
contentEl.className = 'twm-confirm-dialog__content run-progress';
|
|
218
250
|
|
|
219
251
|
const bodyEl = document.createElement('div');
|
|
220
252
|
bodyEl.className = 'twm-run-progress__body';
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
253
|
+
const spinnerEl = document.createElement('div');
|
|
254
|
+
spinnerEl.className = 'twm-run-progress__spinner';
|
|
255
|
+
const messageEl = document.createElement('div');
|
|
256
|
+
messageEl.className = 'twm-run-progress__message';
|
|
257
|
+
messageEl.textContent = message;
|
|
258
|
+
bodyEl.append(spinnerEl, messageEl);
|
|
225
259
|
contentEl.appendChild(bodyEl);
|
|
226
260
|
|
|
261
|
+
const job = mountJobProgress(contentEl, { progress, steps, spinner: spinnerEl });
|
|
262
|
+
|
|
227
263
|
let stopBtn = null;
|
|
228
264
|
if (typeof onCancel === 'function') {
|
|
229
265
|
const stopActionsEl = document.createElement('div');
|
|
@@ -253,6 +289,17 @@ export function showRunProgressDialog(options = {}) {
|
|
|
253
289
|
actionsEl.appendChild(closeBtn);
|
|
254
290
|
contentEl.appendChild(actionsEl);
|
|
255
291
|
|
|
292
|
+
const finish = (status, text, cls) => {
|
|
293
|
+
finished = true;
|
|
294
|
+
spinnerEl.style.display = 'none';
|
|
295
|
+
if (stopBtn) stopBtn.parentElement.style.display = 'none';
|
|
296
|
+
messageEl.textContent = text;
|
|
297
|
+
messageEl.className = `twm-run-progress__message ${cls}`;
|
|
298
|
+
job.finish(status);
|
|
299
|
+
actionsEl.style.display = '';
|
|
300
|
+
settle({ status, message: text });
|
|
301
|
+
};
|
|
302
|
+
|
|
256
303
|
const dialogWindow = new ManagedWindow({
|
|
257
304
|
id: dialogId,
|
|
258
305
|
title,
|
|
@@ -261,44 +308,40 @@ export function showRunProgressDialog(options = {}) {
|
|
|
261
308
|
minWidth: 320,
|
|
262
309
|
minHeight: 120,
|
|
263
310
|
defaultWidth: 420,
|
|
264
|
-
defaultHeight: 200,
|
|
311
|
+
defaultHeight: 200 + (job.bar ? 40 : 0) + (job.steps ? 40 : 0),
|
|
265
312
|
canMinimize: false,
|
|
266
313
|
canMaximize: false,
|
|
267
314
|
canResize: false,
|
|
268
315
|
canDrag: false,
|
|
269
316
|
modal: true,
|
|
317
|
+
onClose: () => {
|
|
318
|
+
if (finished) return;
|
|
319
|
+
finish('cancelled', 'Cancelled.', 'is-cancelled');
|
|
320
|
+
},
|
|
270
321
|
});
|
|
271
322
|
dialogWindow.show();
|
|
272
323
|
|
|
273
|
-
const messageEl = bodyEl.querySelector('.twm-run-progress__message');
|
|
274
|
-
const spinnerEl = bodyEl.querySelector('.twm-run-progress__spinner');
|
|
275
|
-
|
|
276
324
|
return {
|
|
325
|
+
result,
|
|
277
326
|
update(msg) {
|
|
278
|
-
if (finished
|
|
327
|
+
if (finished) return;
|
|
279
328
|
messageEl.textContent = msg;
|
|
280
329
|
},
|
|
281
|
-
|
|
330
|
+
setProgress(next) {
|
|
331
|
+
if (finished) return;
|
|
332
|
+
job.setProgress(next);
|
|
333
|
+
},
|
|
334
|
+
setStep(which, opts) {
|
|
335
|
+
if (finished) return;
|
|
336
|
+
job.setStep(which, opts);
|
|
337
|
+
},
|
|
338
|
+
complete(res) {
|
|
282
339
|
if (finished) return;
|
|
283
|
-
|
|
284
|
-
if (spinnerEl) spinnerEl.style.display = 'none';
|
|
285
|
-
if (stopBtn) stopBtn.parentElement.style.display = 'none';
|
|
286
|
-
if (messageEl) {
|
|
287
|
-
messageEl.textContent = result?.message || '';
|
|
288
|
-
messageEl.className = `twm-run-progress__message ${result?.ok ? 'is-ok' : 'is-err'}`;
|
|
289
|
-
}
|
|
290
|
-
actionsEl.style.display = '';
|
|
340
|
+
finish(res?.ok ? 'done' : 'error', res?.message || '', res?.ok ? 'is-ok' : 'is-err');
|
|
291
341
|
},
|
|
292
342
|
cancelled(msg) {
|
|
293
343
|
if (finished) return;
|
|
294
|
-
|
|
295
|
-
if (spinnerEl) spinnerEl.style.display = 'none';
|
|
296
|
-
if (stopBtn) stopBtn.parentElement.style.display = 'none';
|
|
297
|
-
if (messageEl) {
|
|
298
|
-
messageEl.textContent = msg || 'Cancelled.';
|
|
299
|
-
messageEl.className = 'twm-run-progress__message is-cancelled';
|
|
300
|
-
}
|
|
301
|
-
actionsEl.style.display = '';
|
|
344
|
+
finish('cancelled', msg || 'Cancelled.', 'is-cancelled');
|
|
302
345
|
},
|
|
303
346
|
close() {
|
|
304
347
|
try { dialogWindow.close(); } catch { /* already closed */ }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* context_menu.js — small popup menu
|
|
3
|
-
*
|
|
2
|
+
* context_menu.js — small popup menu in the `.context-menu` idiom the
|
|
3
|
+
* DataTable's own right-click menu uses (./data_table.js).
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
6
|
* showContextMenu(x, y, [
|