@h-rig/omp-extension-plugin 0.0.6-alpha.191 → 0.0.6-alpha.192
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/src/cockpit/board-views.d.ts +10 -0
- package/dist/src/cockpit/board-views.js +110 -27
- package/dist/src/cockpit/extension.d.ts +1 -1
- package/dist/src/cockpit/extension.js +362 -128
- package/dist/src/cockpit/plugin.js +361 -128
- package/dist/src/cockpit/screen-catalog.js +2 -2
- package/dist/src/plugin.js +361 -128
- package/package.json +4 -4
|
@@ -16,6 +16,7 @@ export declare function hairline(width: number): string;
|
|
|
16
16
|
* sort modes. Selection tracks the run, not the row index. */
|
|
17
17
|
/** Board-styled menu/detail rows, used for every non-live family surface. */
|
|
18
18
|
export declare class BoardSettingsList implements Component {
|
|
19
|
+
#private;
|
|
19
20
|
items: BoardSettingItem[];
|
|
20
21
|
selected: number;
|
|
21
22
|
title: string;
|
|
@@ -26,6 +27,10 @@ export declare class BoardSettingsList implements Component {
|
|
|
26
27
|
private firstSelectable;
|
|
27
28
|
moveSelection(delta: number): void;
|
|
28
29
|
selectedItem(): BoardSettingItem | null;
|
|
30
|
+
/** Item index under a rendered line, when that line is a selectable row. */
|
|
31
|
+
hitTest(line: number): number | undefined;
|
|
32
|
+
/** Select the item at `index` (mouse click); true when the selection moved. */
|
|
33
|
+
selectIndex(index: number): boolean;
|
|
29
34
|
invalidate(): void;
|
|
30
35
|
render(width: number): string[];
|
|
31
36
|
private renderLines;
|
|
@@ -84,6 +89,7 @@ export type DetailModel = {
|
|
|
84
89
|
actions: DetailAction[];
|
|
85
90
|
};
|
|
86
91
|
export declare class DetailComposer implements Component {
|
|
92
|
+
#private;
|
|
87
93
|
model: DetailModel;
|
|
88
94
|
selected: number;
|
|
89
95
|
tick: number;
|
|
@@ -93,6 +99,10 @@ export declare class DetailComposer implements Component {
|
|
|
93
99
|
private clamp;
|
|
94
100
|
moveSelection(delta: number): void;
|
|
95
101
|
selectedAction(): DetailAction | null;
|
|
102
|
+
/** Enabled-action index under a rendered line (mouse hit-testing). */
|
|
103
|
+
hitTestAction(line: number): number | undefined;
|
|
104
|
+
/** Select the enabled action at `index` (mouse click); true when it moved. */
|
|
105
|
+
selectAction(index: number): boolean;
|
|
96
106
|
scrollBody(delta: number): void;
|
|
97
107
|
resetScroll(): void;
|
|
98
108
|
invalidate(): void;
|
|
@@ -4,6 +4,7 @@ import { truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
|
4
4
|
import {
|
|
5
5
|
accent,
|
|
6
6
|
accentDim,
|
|
7
|
+
bgPanel,
|
|
7
8
|
bold,
|
|
8
9
|
cyan,
|
|
9
10
|
ink,
|
|
@@ -11,10 +12,6 @@ import {
|
|
|
11
12
|
ink3,
|
|
12
13
|
ink4,
|
|
13
14
|
red,
|
|
14
|
-
DRONE_WIDTH,
|
|
15
|
-
renderDroneFrame,
|
|
16
|
-
renderMicroDroneFrame,
|
|
17
|
-
RIG_SPINNER_FRAMES,
|
|
18
15
|
screenGlyph,
|
|
19
16
|
sectionDivider,
|
|
20
17
|
statusColor,
|
|
@@ -26,11 +23,13 @@ import {
|
|
|
26
23
|
function hairline(width) {
|
|
27
24
|
return ink4("\u2500".repeat(Math.max(0, width)));
|
|
28
25
|
}
|
|
26
|
+
|
|
29
27
|
class BoardSettingsList {
|
|
30
28
|
items = [];
|
|
31
29
|
selected = 0;
|
|
32
30
|
title = "";
|
|
33
31
|
emptyMessage = "nothing to show";
|
|
32
|
+
#rowToIndex = new Map;
|
|
34
33
|
setItems(items) {
|
|
35
34
|
this.items = [...items];
|
|
36
35
|
if (!this.selectableAt(this.selected))
|
|
@@ -61,44 +60,77 @@ class BoardSettingsList {
|
|
|
61
60
|
selectedItem() {
|
|
62
61
|
return this.selectableAt(this.selected) ? this.items[this.selected] : null;
|
|
63
62
|
}
|
|
63
|
+
hitTest(line) {
|
|
64
|
+
const index = this.#rowToIndex.get(line);
|
|
65
|
+
return index !== undefined && this.selectableAt(index) ? index : undefined;
|
|
66
|
+
}
|
|
67
|
+
selectIndex(index) {
|
|
68
|
+
if (!this.selectableAt(index))
|
|
69
|
+
return false;
|
|
70
|
+
const moved = this.selected !== index;
|
|
71
|
+
this.selected = index;
|
|
72
|
+
return moved;
|
|
73
|
+
}
|
|
64
74
|
invalidate() {}
|
|
65
75
|
render(width) {
|
|
66
76
|
return this.renderLines(width).map((line) => truncateToWidth(line, Math.max(10, width - 1)));
|
|
67
77
|
}
|
|
68
78
|
renderLines(width) {
|
|
79
|
+
this.#rowToIndex.clear();
|
|
69
80
|
if (this.items.length === 0) {
|
|
70
81
|
return ["", ` ${ink2(this.emptyMessage)}`, ""];
|
|
71
82
|
}
|
|
72
|
-
const maxVisible = Math.max(8, Math.min(
|
|
83
|
+
const maxVisible = Math.max(8, Math.min(18, (process.stdout.rows ?? 30) - 10));
|
|
73
84
|
const start = Math.max(0, Math.min(this.selected - Math.floor(maxVisible / 2), this.items.length - maxVisible));
|
|
74
85
|
const window = this.items.slice(start, start + maxVisible);
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
const labelWidth = Math.min(28, Math.max(10, ...window.map((item) => {
|
|
87
|
+
const navGlyph = item.id.startsWith("to:") ? 2 : 0;
|
|
88
|
+
return item.label.length + navGlyph;
|
|
89
|
+
})));
|
|
90
|
+
const actionWidth = Math.max(0, ...window.map((item) => item.values?.[0] && item.values[0] !== item.currentValue ? item.values[0].length + 2 : 0));
|
|
91
|
+
const valueWidth = Math.max(12, width - labelWidth - actionWidth - 8);
|
|
92
|
+
const lines = [""];
|
|
93
|
+
for (let index = 0;index < window.length; index += 1) {
|
|
94
|
+
const item = window[index];
|
|
78
95
|
const absolute = start + index;
|
|
79
96
|
const isSelected = absolute === this.selected;
|
|
80
|
-
|
|
97
|
+
if (item.id === "title") {
|
|
98
|
+
lines.push(` ${accent("\u258D")}${bold(ink(item.label))}${item.currentValue ? ` ${ink3(item.currentValue)}` : ""}`);
|
|
99
|
+
if (item.description)
|
|
100
|
+
lines.push(` ${ink4(truncateToWidth(item.description, Math.max(12, width - 4)))}`);
|
|
101
|
+
lines.push("");
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (item.heading && !item.currentValue) {
|
|
105
|
+
lines.push(sectionDivider(item.label.toLowerCase(), width));
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
81
108
|
const navGlyph = item.id.startsWith("to:") ? `${screenGlyph(item.id.slice(3))} ` : "";
|
|
82
|
-
const
|
|
83
|
-
const isTitle = item.id === "title";
|
|
109
|
+
const labelPlain = truncateToWidth(`${navGlyph}${item.label}`, labelWidth).padEnd(labelWidth);
|
|
84
110
|
const isStatus = item.id.endsWith(":status");
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
const
|
|
111
|
+
const valuePlain = truncateToWidth(item.currentValue ?? "", valueWidth).padEnd(valueWidth);
|
|
112
|
+
const label = isSelected ? ink(labelPlain) : item.heading ? ink3(labelPlain) : ink2(labelPlain);
|
|
113
|
+
const value = !item.currentValue ? ink4(valuePlain) : isStatus ? statusColor(item.currentValue)(truncateToWidth(`${statusGlyph(item.currentValue)} ${item.currentValue}`, valueWidth).padEnd(valueWidth)) : item.heading ? ink2(valuePlain) : ink3(valuePlain);
|
|
114
|
+
const actionText = item.values?.[0] && item.values[0] !== item.currentValue ? item.values[0] : "";
|
|
115
|
+
const action = actionText ? isSelected ? accent(`${actionText} \u203A`) : accentDim(actionText) : "";
|
|
116
|
+
const rail = isSelected ? accent("\u258C") : " ";
|
|
117
|
+
const body = `${rail} ${label} ${value}${action ? ` ${action}` : ""}`;
|
|
118
|
+
if (!item.heading)
|
|
119
|
+
this.#rowToIndex.set(lines.length, absolute);
|
|
120
|
+
lines.push(isSelected ? bgPanel(body) : body);
|
|
89
121
|
if (isSelected && item.description) {
|
|
90
|
-
|
|
122
|
+
if (!item.heading)
|
|
123
|
+
this.#rowToIndex.set(lines.length, absolute);
|
|
124
|
+
lines.push(` ${ink4("\u21B3")} ${ink4(truncateToWidth(item.description, Math.max(12, width - 6)))}`);
|
|
91
125
|
}
|
|
92
|
-
|
|
93
|
-
});
|
|
126
|
+
}
|
|
94
127
|
const meta = [];
|
|
95
128
|
if (this.items.length > maxVisible)
|
|
96
|
-
meta.push(`${this.selected + 1}
|
|
97
|
-
if (this.title)
|
|
98
|
-
meta.push(this.title);
|
|
129
|
+
meta.push(`${this.selected + 1} of ${this.items.length}`);
|
|
99
130
|
if (meta.length > 0)
|
|
100
|
-
lines.push(ink4(` ${meta.join(" \xB7 ")}`));
|
|
101
|
-
|
|
131
|
+
lines.push("", ink4(` ${meta.join(" \xB7 ")}`));
|
|
132
|
+
lines.push("");
|
|
133
|
+
return lines;
|
|
102
134
|
}
|
|
103
135
|
}
|
|
104
136
|
|
|
@@ -190,6 +222,7 @@ class DetailComposer {
|
|
|
190
222
|
selected = 0;
|
|
191
223
|
tick = 0;
|
|
192
224
|
bodyScroll = 0;
|
|
225
|
+
#lineToAction = new Map;
|
|
193
226
|
setModel(model) {
|
|
194
227
|
const prevId = this.enabledActions()[this.selected]?.id;
|
|
195
228
|
this.model = model;
|
|
@@ -214,6 +247,17 @@ class DetailComposer {
|
|
|
214
247
|
selectedAction() {
|
|
215
248
|
return this.enabledActions()[this.selected] ?? null;
|
|
216
249
|
}
|
|
250
|
+
hitTestAction(line) {
|
|
251
|
+
return this.#lineToAction.get(line);
|
|
252
|
+
}
|
|
253
|
+
selectAction(index) {
|
|
254
|
+
const count = this.enabledActions().length;
|
|
255
|
+
if (index < 0 || index >= count)
|
|
256
|
+
return false;
|
|
257
|
+
const moved = this.selected !== index;
|
|
258
|
+
this.selected = index;
|
|
259
|
+
return moved;
|
|
260
|
+
}
|
|
217
261
|
scrollBody(delta) {
|
|
218
262
|
this.bodyScroll = Math.max(0, this.bodyScroll + delta);
|
|
219
263
|
}
|
|
@@ -243,21 +287,45 @@ class DetailComposer {
|
|
|
243
287
|
}
|
|
244
288
|
if (model.stages && model.stages.length > 0) {
|
|
245
289
|
bottom.push(sectionDivider("pipeline", width));
|
|
246
|
-
|
|
247
|
-
|
|
290
|
+
let linePlain = " ";
|
|
291
|
+
let linePainted = " ";
|
|
292
|
+
for (let i = 0;i < model.stages.length; i += 1) {
|
|
293
|
+
const stage = model.stages[i];
|
|
294
|
+
const sepPlain = linePlain.trim().length > 0 ? " \u2192 " : " ";
|
|
295
|
+
const cellPlain = `${sepPlain}? ${stage.label}`;
|
|
296
|
+
if (linePlain.length + cellPlain.length > inner - 2 && linePlain.trim().length > 0) {
|
|
297
|
+
bottom.push(linePainted);
|
|
298
|
+
linePlain = " ";
|
|
299
|
+
linePainted = " ";
|
|
300
|
+
}
|
|
301
|
+
const sep = linePlain.trim().length > 0 ? ink4(" \u2192 ") : " ";
|
|
302
|
+
linePlain += cellPlain;
|
|
303
|
+
linePainted += `${sep}${statusColor(stage.status)(statusGlyph(stage.status))} ${ink3(stage.label)}`;
|
|
304
|
+
}
|
|
305
|
+
if (linePainted.trim().length > 0)
|
|
306
|
+
bottom.push(linePainted);
|
|
248
307
|
bottom.push("");
|
|
249
308
|
}
|
|
309
|
+
const actionLines = [];
|
|
250
310
|
if (model.actions.length > 0) {
|
|
251
311
|
bottom.push(sectionDivider("actions", width));
|
|
252
312
|
const selId = this.selectedAction()?.id;
|
|
313
|
+
let enabledIndex = -1;
|
|
253
314
|
for (const action of model.actions) {
|
|
254
315
|
const on = action.enabled !== false;
|
|
316
|
+
if (on)
|
|
317
|
+
enabledIndex += 1;
|
|
255
318
|
const isSel = on && action.id === selId;
|
|
256
319
|
const rail = isSel ? accent("\u258C") : " ";
|
|
257
320
|
const labelText = `${action.glyph ? `${action.glyph} ` : ""}${action.label}`;
|
|
258
321
|
const label = !on ? ink4(labelText) : action.danger ? red(labelText) : isSel ? accent(labelText) : ink2(labelText);
|
|
259
322
|
const tail = !on ? ink4(action.value ?? "unavailable") : isSel ? ink3(action.hint ?? action.value ?? "") : ink3(action.value ?? "");
|
|
260
|
-
|
|
323
|
+
const row = `${rail} ${label}${tail ? ` ${tail}` : ""}`;
|
|
324
|
+
if (on)
|
|
325
|
+
actionLines.push(enabledIndex);
|
|
326
|
+
else
|
|
327
|
+
actionLines.push(-1);
|
|
328
|
+
bottom.push(isSel ? bgPanel(row) : row);
|
|
261
329
|
}
|
|
262
330
|
}
|
|
263
331
|
const body = [];
|
|
@@ -282,10 +350,25 @@ class DetailComposer {
|
|
|
282
350
|
}
|
|
283
351
|
}
|
|
284
352
|
const out = [...top, ...body, ...bottom];
|
|
353
|
+
const mapActions = (linesOut) => {
|
|
354
|
+
this.#lineToAction.clear();
|
|
355
|
+
if (actionLines.length === 0)
|
|
356
|
+
return;
|
|
357
|
+
const actionCount = model.actions.length;
|
|
358
|
+
const firstActionLine = linesOut.length - actionCount;
|
|
359
|
+
for (let i = 0;i < actionCount; i += 1) {
|
|
360
|
+
const enabledIdx = actionLines[i];
|
|
361
|
+
if (enabledIdx >= 0)
|
|
362
|
+
this.#lineToAction.set(firstActionLine + i, enabledIdx);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
285
365
|
if (out.length > budget) {
|
|
286
366
|
const keepTail = Math.min(bottom.length, budget - top.length);
|
|
287
|
-
|
|
367
|
+
const clipped = [...top, ...out.slice(out.length - keepTail)];
|
|
368
|
+
mapActions(clipped);
|
|
369
|
+
return clipped.map((line) => truncateToWidth(line, Math.max(10, width - 1)));
|
|
288
370
|
}
|
|
371
|
+
mapActions(out);
|
|
289
372
|
return out.map((line) => truncateToWidth(line, Math.max(10, width - 1)));
|
|
290
373
|
}
|
|
291
374
|
}
|
|
@@ -68,7 +68,7 @@ declare function runListActionHints(run: RunRecord, source?: RunClassificationSo
|
|
|
68
68
|
}[];
|
|
69
69
|
declare function taskDetailModel(state: RigFlowState, server: RigServerState | null, projection: TaskProjectionCapability): DetailModel;
|
|
70
70
|
declare function runDetailModel(run: RunRecord, source?: RunClassificationSource): DetailModel;
|
|
71
|
-
declare function itemsFor(screen: RigScreen, runs: readonly RunRecord[], actionRowsEnabled: boolean, _selectedRunId: string | null, state?: RigFlowState, catalog?: readonly ScreenDescriptor[],
|
|
71
|
+
declare function itemsFor(screen: RigScreen, runs: readonly RunRecord[], actionRowsEnabled: boolean, _selectedRunId: string | null, state?: RigFlowState, catalog?: readonly ScreenDescriptor[], _projection?: TaskProjectionCapability): SettingItem[];
|
|
72
72
|
export declare const __rigExtensionTest: {
|
|
73
73
|
itemsFor: typeof itemsFor;
|
|
74
74
|
taskDetailModel: typeof taskDetailModel;
|