sidekick-docker 0.2.2 → 0.2.3
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 +3 -0
- package/dist/sidekick-docker.mjs +460 -182
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,6 +83,8 @@ The dashboard has 5 panels, each mapped to a number key:
|
|
|
83
83
|
| `x` | Open context menu (actions for selected item) |
|
|
84
84
|
| `f` | Open log filter (when on Logs tab) |
|
|
85
85
|
| `/` | Open filter |
|
|
86
|
+
| `m` | Pin/unpin item for log comparison (Containers/Services) |
|
|
87
|
+
| `J` / `K` | Scroll compare pane (when in detail focus) |
|
|
86
88
|
| `z` | Toggle expanded layout |
|
|
87
89
|
| `?` | Show help overlay |
|
|
88
90
|
| `V` | Show version |
|
|
@@ -112,6 +114,7 @@ The dashboard has 5 panels, each mapped to a number key:
|
|
|
112
114
|
## Features
|
|
113
115
|
|
|
114
116
|
- **Real-time log streaming** — follows container logs with token-level syntax highlighting (HTTP methods, status codes, URLs, IPs, timestamps, JSON keys)
|
|
117
|
+
- **Dual-log compare** — pin a second container or service with `m` to view both log streams side by side
|
|
115
118
|
- **Log search & filter** — press `f` on the Logs tab to search within log output with exact or fuzzy matching and match highlighting
|
|
116
119
|
- **Log analytics** — severity count badges, severity sparkline over time, and pattern clustering that groups similar logs into templates with `<*>` wildcards
|
|
117
120
|
- **Live stats with sparklines** — CPU, memory, network I/O, block I/O, and log severity charted as inline sparklines (60-sample history)
|
package/dist/sidekick-docker.mjs
CHANGED
|
@@ -56511,7 +56511,7 @@ var require_LogFilter = __commonJS({
|
|
|
56511
56511
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
56512
56512
|
exports2.exactMatch = exactMatch;
|
|
56513
56513
|
exports2.fuzzyMatch = fuzzyMatch;
|
|
56514
|
-
exports2.filterLine =
|
|
56514
|
+
exports2.filterLine = filterLine4;
|
|
56515
56515
|
function exactMatch(line, query) {
|
|
56516
56516
|
if (!query)
|
|
56517
56517
|
return { matched: true, matches: [] };
|
|
@@ -56546,7 +56546,7 @@ var require_LogFilter = __commonJS({
|
|
|
56546
56546
|
matches.sort((a, b) => a.start - b.start);
|
|
56547
56547
|
return { matched: true, matches };
|
|
56548
56548
|
}
|
|
56549
|
-
function
|
|
56549
|
+
function filterLine4(line, query, mode) {
|
|
56550
56550
|
return mode === "exact" ? exactMatch(line, query) : fuzzyMatch(line, query);
|
|
56551
56551
|
}
|
|
56552
56552
|
}
|
|
@@ -94290,6 +94290,8 @@ var DockerState = class {
|
|
|
94290
94290
|
composeProjects = [];
|
|
94291
94291
|
selectedLogs = [];
|
|
94292
94292
|
selectedComposeLogs = [];
|
|
94293
|
+
secondaryLogs = [];
|
|
94294
|
+
secondaryComposeLogs = [];
|
|
94293
94295
|
inspectedEnv = /* @__PURE__ */ new Map();
|
|
94294
94296
|
containerChanges = /* @__PURE__ */ new Map();
|
|
94295
94297
|
imageLayers = /* @__PURE__ */ new Map();
|
|
@@ -94400,6 +94402,18 @@ var DockerState = class {
|
|
|
94400
94402
|
clearComposeLogs() {
|
|
94401
94403
|
this.selectedComposeLogs = [];
|
|
94402
94404
|
}
|
|
94405
|
+
setSecondaryLogs(logs) {
|
|
94406
|
+
this.secondaryLogs = logs;
|
|
94407
|
+
}
|
|
94408
|
+
clearSecondaryLogs() {
|
|
94409
|
+
this.secondaryLogs = [];
|
|
94410
|
+
}
|
|
94411
|
+
setSecondaryComposeLogs(logs) {
|
|
94412
|
+
this.secondaryComposeLogs = logs;
|
|
94413
|
+
}
|
|
94414
|
+
clearSecondaryComposeLogs() {
|
|
94415
|
+
this.secondaryComposeLogs = [];
|
|
94416
|
+
}
|
|
94403
94417
|
getStatsCollector() {
|
|
94404
94418
|
return this.statsCollector;
|
|
94405
94419
|
}
|
|
@@ -94434,13 +94448,17 @@ var DockerState = class {
|
|
|
94434
94448
|
imageLayers: this.imageLayers,
|
|
94435
94449
|
selectedContainerLogs: [...this.selectedLogs],
|
|
94436
94450
|
selectedComposeLogs: [...this.selectedComposeLogs],
|
|
94451
|
+
secondaryContainerLogs: [...this.secondaryLogs],
|
|
94452
|
+
secondaryComposeLogs: [...this.secondaryComposeLogs],
|
|
94437
94453
|
lastRefresh: this.lastRefresh,
|
|
94438
94454
|
daemonConnected: this.daemonConnected,
|
|
94439
94455
|
logFilterString: "",
|
|
94440
94456
|
logFilterMode: "exact",
|
|
94441
94457
|
logSeverityCounts: null,
|
|
94442
94458
|
logSeverityTimeSeries: [],
|
|
94443
|
-
logTemplates: []
|
|
94459
|
+
logTemplates: [],
|
|
94460
|
+
secondaryLogSeverityCounts: null,
|
|
94461
|
+
secondaryLogSeverityTimeSeries: []
|
|
94444
94462
|
};
|
|
94445
94463
|
}
|
|
94446
94464
|
};
|
|
@@ -94661,6 +94679,64 @@ function colorizeNetworkContainer(name, id) {
|
|
|
94661
94679
|
function stripCursorEscapes(text) {
|
|
94662
94680
|
return text.replace(/\x1b\[\d*[ABCD]/g, "").replace(/\x1b\[\d*(?:;\d*)?[Hf]/g, "").replace(/\x1b\[\d*[JK]/g, "").replace(/\x1b\[\?\d+[hl]/g, "").replace(/\x1b\[[su]/g, "").replace(/\x1b[78]/g, "").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "").replace(/\r/g, "");
|
|
94663
94681
|
}
|
|
94682
|
+
function renderLogLines(logs, filterString, filterMode, severityCounts) {
|
|
94683
|
+
const lines = [];
|
|
94684
|
+
if (severityCounts && severityCounts.total > 0) {
|
|
94685
|
+
const parts = [];
|
|
94686
|
+
if (severityCounts.error > 0) parts.push(`\x1B[31mE:${severityCounts.error}\x1B[39m`);
|
|
94687
|
+
if (severityCounts.warn > 0) parts.push(`\x1B[33mW:${severityCounts.warn}\x1B[39m`);
|
|
94688
|
+
if (severityCounts.info > 0) parts.push(`\x1B[38;2;43;76;126mI:${severityCounts.info}\x1B[39m`);
|
|
94689
|
+
if (severityCounts.debug > 0) parts.push(`\x1B[90mD:${severityCounts.debug}\x1B[39m`);
|
|
94690
|
+
if (parts.length > 0) lines.push(parts.join(" "));
|
|
94691
|
+
}
|
|
94692
|
+
if (filterString) {
|
|
94693
|
+
let matchCount = 0;
|
|
94694
|
+
for (const l of logs) {
|
|
94695
|
+
const result = (0, import_sidekick_docker_shared2.filterLine)(l.message, filterString, filterMode);
|
|
94696
|
+
if (result.matched) {
|
|
94697
|
+
matchCount++;
|
|
94698
|
+
lines.push(colorizeLogEntry(l, result.matches));
|
|
94699
|
+
}
|
|
94700
|
+
}
|
|
94701
|
+
if (lines.length <= (severityCounts ? 1 : 0)) {
|
|
94702
|
+
lines.push(`\x1B[90mNo logs matching "${filterString}"\x1B[39m`);
|
|
94703
|
+
} else {
|
|
94704
|
+
const headerIdx = severityCounts ? 1 : 0;
|
|
94705
|
+
lines.splice(headerIdx, 0, `\x1B[90m${matchCount} matches (f to filter, Tab to toggle mode)\x1B[39m`);
|
|
94706
|
+
}
|
|
94707
|
+
} else {
|
|
94708
|
+
for (const l of logs) {
|
|
94709
|
+
lines.push(colorizeLogEntry(l));
|
|
94710
|
+
}
|
|
94711
|
+
}
|
|
94712
|
+
return lines;
|
|
94713
|
+
}
|
|
94714
|
+
function clipAnsi(str, maxWidth) {
|
|
94715
|
+
let visible = 0;
|
|
94716
|
+
let i = 0;
|
|
94717
|
+
let result = "";
|
|
94718
|
+
while (i < str.length && visible < maxWidth) {
|
|
94719
|
+
if (str[i] === "\x1B") {
|
|
94720
|
+
const start = i;
|
|
94721
|
+
i++;
|
|
94722
|
+
if (i < str.length && str[i] === "[") {
|
|
94723
|
+
i++;
|
|
94724
|
+
while (i < str.length && str[i] !== "m" && !/[A-Za-z]/.test(str[i])) i++;
|
|
94725
|
+
if (i < str.length) i++;
|
|
94726
|
+
}
|
|
94727
|
+
result += str.slice(start, i);
|
|
94728
|
+
} else {
|
|
94729
|
+
result += str[i];
|
|
94730
|
+
visible++;
|
|
94731
|
+
i++;
|
|
94732
|
+
}
|
|
94733
|
+
}
|
|
94734
|
+
if (visible < maxWidth) {
|
|
94735
|
+
result += " ".repeat(maxWidth - visible);
|
|
94736
|
+
}
|
|
94737
|
+
result += "\x1B[0m";
|
|
94738
|
+
return result;
|
|
94739
|
+
}
|
|
94664
94740
|
|
|
94665
94741
|
// src/dashboard/panels/ContainersPanel.ts
|
|
94666
94742
|
var ContainersPanel = class {
|
|
@@ -94687,41 +94763,10 @@ var ContainersPanel = class {
|
|
|
94687
94763
|
detailTabs = [
|
|
94688
94764
|
{
|
|
94689
94765
|
label: "Logs",
|
|
94690
|
-
render: (
|
|
94766
|
+
render: (_item, metrics) => {
|
|
94691
94767
|
const logs = metrics.selectedContainerLogs;
|
|
94692
94768
|
if (logs.length === 0) return "No logs available. Select a container to view logs.";
|
|
94693
|
-
|
|
94694
|
-
if (metrics.logSeverityCounts && metrics.logSeverityCounts.total > 0) {
|
|
94695
|
-
const c = metrics.logSeverityCounts;
|
|
94696
|
-
const parts = [];
|
|
94697
|
-
if (c.error > 0) parts.push(`\x1B[31mE:${c.error}\x1B[39m`);
|
|
94698
|
-
if (c.warn > 0) parts.push(`\x1B[33mW:${c.warn}\x1B[39m`);
|
|
94699
|
-
if (c.info > 0) parts.push(`\x1B[38;2;43;76;126mI:${c.info}\x1B[39m`);
|
|
94700
|
-
if (c.debug > 0) parts.push(`\x1B[90mD:${c.debug}\x1B[39m`);
|
|
94701
|
-
if (parts.length > 0) lines.push(parts.join(" "));
|
|
94702
|
-
}
|
|
94703
|
-
const query = metrics.logFilterString;
|
|
94704
|
-
const mode = metrics.logFilterMode;
|
|
94705
|
-
if (query) {
|
|
94706
|
-
let matchCount = 0;
|
|
94707
|
-
for (const l of logs) {
|
|
94708
|
-
const result = (0, import_sidekick_docker_shared4.filterLine)(l.message, query, mode);
|
|
94709
|
-
if (result.matched) {
|
|
94710
|
-
matchCount++;
|
|
94711
|
-
lines.push(colorizeLogEntry(l, result.matches));
|
|
94712
|
-
}
|
|
94713
|
-
}
|
|
94714
|
-
if (lines.length <= 1) {
|
|
94715
|
-
lines.push(`\x1B[90mNo logs matching "${query}"\x1B[39m`);
|
|
94716
|
-
} else {
|
|
94717
|
-
lines.splice(1, 0, `\x1B[90m${matchCount} matches (f to filter, Tab to toggle mode)\x1B[39m`);
|
|
94718
|
-
}
|
|
94719
|
-
} else {
|
|
94720
|
-
for (const l of logs) {
|
|
94721
|
-
lines.push(colorizeLogEntry(l));
|
|
94722
|
-
}
|
|
94723
|
-
}
|
|
94724
|
-
return lines.join("\n");
|
|
94769
|
+
return renderLogLines(logs, metrics.logFilterString, metrics.logFilterMode, metrics.logSeverityCounts).join("\n");
|
|
94725
94770
|
},
|
|
94726
94771
|
autoScrollBottom: true
|
|
94727
94772
|
},
|
|
@@ -95021,7 +95066,7 @@ var ServicesPanel = class {
|
|
|
95021
95066
|
render: (_item, metrics) => {
|
|
95022
95067
|
const logs = metrics.selectedComposeLogs;
|
|
95023
95068
|
if (logs.length === 0) return "No compose logs. Logs will appear when a service produces output.";
|
|
95024
|
-
return logs.
|
|
95069
|
+
return renderLogLines(logs, metrics.logFilterString, metrics.logFilterMode).join("\n");
|
|
95025
95070
|
},
|
|
95026
95071
|
autoScrollBottom: true
|
|
95027
95072
|
}
|
|
@@ -95764,7 +95809,7 @@ function handleFilterInput(input, key, opts) {
|
|
|
95764
95809
|
}
|
|
95765
95810
|
function useKeyboardHandler(ctx) {
|
|
95766
95811
|
const { exit } = use_app_default();
|
|
95767
|
-
const { state, dispatch, panels, panel, selectedItem, contextActions, clampedSelection, currentItems, detailLines, detailViewportHeight, detailTabs, tabIdx, panelActions, sideScroll, addToast, removeToast, rotatePhrase } = ctx;
|
|
95812
|
+
const { state, dispatch, panels, panel, selectedItem, contextActions, clampedSelection, currentItems, detailLines, detailViewportHeight, detailTabs, tabIdx, panelActions, sideScroll, addToast, removeToast, rotatePhrase, secondaryDetailLineCount } = ctx;
|
|
95768
95813
|
use_input_default((input, key) => {
|
|
95769
95814
|
if (state.overlay === "exec") return;
|
|
95770
95815
|
rotatePhrase();
|
|
@@ -95935,6 +95980,18 @@ function useKeyboardHandler(ctx) {
|
|
|
95935
95980
|
addToast(`Sort: ${state.sortReversed ? "ascending" : "descending"}`, "info");
|
|
95936
95981
|
return;
|
|
95937
95982
|
}
|
|
95983
|
+
if (input === "m" && selectedItem && (panel.id === "containers" || panel.id === "services")) {
|
|
95984
|
+
const currentCompare = state.compareItemIds[panel.id] ?? null;
|
|
95985
|
+
if (currentCompare === selectedItem.id) {
|
|
95986
|
+
dispatch({ type: "PIN_COMPARE", panelId: panel.id, itemId: selectedItem.id });
|
|
95987
|
+
addToast("Unpinned comparison", "info");
|
|
95988
|
+
} else {
|
|
95989
|
+
dispatch({ type: "PIN_COMPARE", panelId: panel.id, itemId: selectedItem.id });
|
|
95990
|
+
const label = selectedItem.label.replace(/^[^\w]*/, "").trim();
|
|
95991
|
+
addToast(`Pinned ${label} for comparison`, "info");
|
|
95992
|
+
}
|
|
95993
|
+
return;
|
|
95994
|
+
}
|
|
95938
95995
|
if (input === "x") {
|
|
95939
95996
|
if (selectedItem && panelActions.length > 0) {
|
|
95940
95997
|
dispatch({ type: "SET_OVERLAY", overlay: "context-menu" });
|
|
@@ -95980,6 +96037,14 @@ function useKeyboardHandler(ctx) {
|
|
|
95980
96037
|
}
|
|
95981
96038
|
}
|
|
95982
96039
|
if (state.focusTarget === "detail") {
|
|
96040
|
+
if (input === "J" && secondaryDetailLineCount > 0) {
|
|
96041
|
+
dispatch({ type: "SCROLL_SECONDARY_DETAIL_DELTA", delta: 1, totalLines: secondaryDetailLineCount, viewportHeight: detailViewportHeight });
|
|
96042
|
+
return;
|
|
96043
|
+
}
|
|
96044
|
+
if (input === "K" && secondaryDetailLineCount > 0) {
|
|
96045
|
+
dispatch({ type: "SCROLL_SECONDARY_DETAIL_DELTA", delta: -1, totalLines: secondaryDetailLineCount, viewportHeight: detailViewportHeight });
|
|
96046
|
+
return;
|
|
96047
|
+
}
|
|
95983
96048
|
if (input === "j" || key.downArrow) {
|
|
95984
96049
|
dispatch({ type: "SCROLL_DETAIL_DELTA", delta: 1, totalLines: detailLines.length, viewportHeight: detailViewportHeight });
|
|
95985
96050
|
return;
|
|
@@ -96147,7 +96212,7 @@ var EMPTY_HINTS = {
|
|
|
96147
96212
|
networks: ["Create a network to get started:", " docker network create my-net"],
|
|
96148
96213
|
services: ["Start a compose project:", " docker compose up -d"]
|
|
96149
96214
|
};
|
|
96150
|
-
function SideList({ items, selectedIndex, scrollOffset, focused, width, viewportHeight, panelTitle, filterString, panelId, totalCount, runningCount }) {
|
|
96215
|
+
function SideList({ items, selectedIndex, scrollOffset, focused, width, viewportHeight, panelTitle, filterString, panelId, totalCount, runningCount, compareItemId }) {
|
|
96151
96216
|
const hasScrollUp = scrollOffset > 0;
|
|
96152
96217
|
const hasScrollDown = scrollOffset + viewportHeight < items.length;
|
|
96153
96218
|
const aboveCount = scrollOffset;
|
|
@@ -96174,7 +96239,8 @@ function SideList({ items, selectedIndex, scrollOffset, focused, width, viewport
|
|
|
96174
96239
|
const segments = [...trimmed];
|
|
96175
96240
|
const icon = segments[0] || "";
|
|
96176
96241
|
const rest = segments.slice(1).join("");
|
|
96177
|
-
const
|
|
96242
|
+
const isPinned = compareItemId != null && item.id === compareItemId;
|
|
96243
|
+
const rightLabel = isPinned ? `\u{1F4CC}${item.rightLabel ? " " + item.rightLabel : ""}` : item.rightLabel || "";
|
|
96178
96244
|
const rightLen = rightLabel.length;
|
|
96179
96245
|
const leftWidth = innerWidth - rightLen - (rightLen ? 1 : 0);
|
|
96180
96246
|
if (isSelected && focused) {
|
|
@@ -96253,11 +96319,67 @@ function DetailPane({ lines, scrollOffset, viewportHeight, focused }) {
|
|
|
96253
96319
|
] });
|
|
96254
96320
|
}
|
|
96255
96321
|
|
|
96322
|
+
// src/dashboard/ink/CompareDetailPane.tsx
|
|
96323
|
+
await init_build2();
|
|
96324
|
+
var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
|
|
96325
|
+
function CompareDetailPane({
|
|
96326
|
+
primaryLines,
|
|
96327
|
+
secondaryLines,
|
|
96328
|
+
primaryScrollOffset,
|
|
96329
|
+
secondaryScrollOffset,
|
|
96330
|
+
viewportHeight,
|
|
96331
|
+
totalWidth,
|
|
96332
|
+
focused,
|
|
96333
|
+
primaryLabel,
|
|
96334
|
+
secondaryLabel
|
|
96335
|
+
}) {
|
|
96336
|
+
const colWidth = Math.max(10, Math.floor((totalWidth - 5) / 2));
|
|
96337
|
+
const headerLeft = clipAnsi(`\x1B[1m${primaryLabel}\x1B[22m`, colWidth);
|
|
96338
|
+
const headerRight = clipAnsi(`\x1B[1m${secondaryLabel}\x1B[22m`, colWidth);
|
|
96339
|
+
const leftVisible = primaryLines.slice(primaryScrollOffset, primaryScrollOffset + viewportHeight);
|
|
96340
|
+
const rightVisible = secondaryLines.slice(secondaryScrollOffset, secondaryScrollOffset + viewportHeight);
|
|
96341
|
+
const leftHasUp = primaryScrollOffset > 0;
|
|
96342
|
+
const leftHasDown = primaryScrollOffset + viewportHeight < primaryLines.length;
|
|
96343
|
+
const rightHasUp = secondaryScrollOffset > 0;
|
|
96344
|
+
const rightHasDown = secondaryScrollOffset + viewportHeight < secondaryLines.length;
|
|
96345
|
+
const maxRows = Math.max(leftVisible.length, rightVisible.length, viewportHeight);
|
|
96346
|
+
const rows = [];
|
|
96347
|
+
for (let i = 0; i < maxRows && i < viewportHeight; i++) {
|
|
96348
|
+
const left = leftVisible[i] ?? "";
|
|
96349
|
+
const right = rightVisible[i] ?? "";
|
|
96350
|
+
rows.push(
|
|
96351
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
|
|
96352
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { wrap: "truncate", children: clipAnsi(left, colWidth) }),
|
|
96353
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", dimColor: true, children: " \u2502 " }),
|
|
96354
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { wrap: "truncate", children: clipAnsi(right, colWidth) })
|
|
96355
|
+
] }, i)
|
|
96356
|
+
);
|
|
96357
|
+
}
|
|
96358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, borderStyle: focused ? "bold" : "single", borderColor: focused ? "#2B4C7E" : "gray", children: [
|
|
96359
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
|
|
96360
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { wrap: "truncate", children: headerLeft }),
|
|
96361
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", dimColor: true, children: " \u2502 " }),
|
|
96362
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { wrap: "truncate", children: headerRight })
|
|
96363
|
+
] }),
|
|
96364
|
+
(leftHasUp || rightHasUp) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
|
|
96365
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", children: leftHasUp ? clipAnsi(`\u25B2 (${primaryScrollOffset} more)`, colWidth) : " ".repeat(colWidth) }),
|
|
96366
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", dimColor: true, children: " \u2502 " }),
|
|
96367
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", children: rightHasUp ? clipAnsi(`\u25B2 (${secondaryScrollOffset} more)`, colWidth) : " ".repeat(colWidth) })
|
|
96368
|
+
] }),
|
|
96369
|
+
rows,
|
|
96370
|
+
(leftHasDown || rightHasDown) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Box_default, { children: [
|
|
96371
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", children: leftHasDown ? clipAnsi(`\u25BC (${Math.max(0, primaryLines.length - primaryScrollOffset - viewportHeight)} more)`, colWidth) : " ".repeat(colWidth) }),
|
|
96372
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", dimColor: true, children: " \u2502 " }),
|
|
96373
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", children: rightHasDown ? clipAnsi(`\u25BC (${Math.max(0, secondaryLines.length - secondaryScrollOffset - viewportHeight)} more)`, colWidth) : " ".repeat(colWidth) })
|
|
96374
|
+
] })
|
|
96375
|
+
] });
|
|
96376
|
+
}
|
|
96377
|
+
|
|
96256
96378
|
// src/dashboard/ink/StatusBar.tsx
|
|
96257
96379
|
var import_react32 = __toESM(require_react(), 1);
|
|
96258
96380
|
await init_build2();
|
|
96259
96381
|
var import_sidekick_docker_shared9 = __toESM(require_dist(), 1);
|
|
96260
|
-
var
|
|
96382
|
+
var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
|
|
96261
96383
|
function formatAgo(date) {
|
|
96262
96384
|
const secs = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
96263
96385
|
if (secs < 5) return { text: "just now", stale: false };
|
|
@@ -96273,33 +96395,33 @@ function StatusBar({ daemonConnected, focusTarget, panelActionHints, filterStrin
|
|
|
96273
96395
|
return () => clearInterval(timer);
|
|
96274
96396
|
}, []);
|
|
96275
96397
|
const ago = lastRefresh ? formatAgo(lastRefresh) : null;
|
|
96276
|
-
return /* @__PURE__ */ (0,
|
|
96277
|
-
/* @__PURE__ */ (0,
|
|
96278
|
-
/* @__PURE__ */ (0,
|
|
96279
|
-
/* @__PURE__ */ (0,
|
|
96280
|
-
/* @__PURE__ */ (0,
|
|
96281
|
-
ago && /* @__PURE__ */ (0,
|
|
96282
|
-
/* @__PURE__ */ (0,
|
|
96283
|
-
panelActionHints.length > 0 && /* @__PURE__ */ (0,
|
|
96284
|
-
panelActionHints.map((hint, i) => /* @__PURE__ */ (0,
|
|
96285
|
-
i > 0 && /* @__PURE__ */ (0,
|
|
96286
|
-
/* @__PURE__ */ (0,
|
|
96398
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { children: [
|
|
96399
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { bold: true, color: "magenta", children: ` \u26A1 ${import_sidekick_docker_shared9.BRAND_INLINE}` }),
|
|
96400
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "gray", dimColor: true, children: ` ${import_sidekick_docker_shared9.BRAND_TAGLINE} v${version2}` }),
|
|
96401
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "gray", dimColor: true, children: ` ${SEP2} ` }),
|
|
96402
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: daemonConnected ? "green" : "red", children: daemonConnected ? `\u25CF ${runningCount ?? 0}/${containerCount ?? 0}` : "\u25CB disconnected" }),
|
|
96403
|
+
ago && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: ago.stale ? "yellow" : "gray", dimColor: !ago.stale, children: ` \u21BB ${ago.text}` }),
|
|
96404
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "gray", dimColor: true, children: ` ${SEP2} ` }),
|
|
96405
|
+
panelActionHints.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
96406
|
+
panelActionHints.map((hint, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react32.default.Fragment, { children: [
|
|
96407
|
+
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { children: " " }),
|
|
96408
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: hint.destructive ? "red" : "#2B4C7E", children: `${hint.key}:${hint.label}` })
|
|
96287
96409
|
] }, hint.key)),
|
|
96288
|
-
/* @__PURE__ */ (0,
|
|
96410
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "gray", dimColor: true, children: ` ${SEP2} ` })
|
|
96289
96411
|
] }),
|
|
96290
|
-
/* @__PURE__ */ (0,
|
|
96291
|
-
/* @__PURE__ */ (0,
|
|
96292
|
-
/* @__PURE__ */ (0,
|
|
96293
|
-
/* @__PURE__ */ (0,
|
|
96294
|
-
contextHint ? /* @__PURE__ */ (0,
|
|
96295
|
-
filterString ? /* @__PURE__ */ (0,
|
|
96412
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: focusTarget === "side" ? "#2B4C7E" : "gray", bold: focusTarget === "side", children: "\u25C0" }),
|
|
96413
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "gray", dimColor: true, children: "/" }),
|
|
96414
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: focusTarget === "detail" ? "#2B4C7E" : "gray", bold: focusTarget === "detail", children: "\u25B6" }),
|
|
96415
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "gray", dimColor: true, children: " j/k Tab / ?" }),
|
|
96416
|
+
contextHint ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "cyan", dimColor: true, children: ` ${contextHint}` }) : null,
|
|
96417
|
+
filterString ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { color: "yellow", bold: true, children: ` \u25C9 "${filterString}"${matchCount !== void 0 && totalCount !== void 0 ? ` ${matchCount}/${totalCount}` : ""}` }) : null
|
|
96296
96418
|
] });
|
|
96297
96419
|
}
|
|
96298
96420
|
|
|
96299
96421
|
// src/dashboard/ink/HelpOverlay.tsx
|
|
96300
96422
|
await init_build2();
|
|
96301
96423
|
var import_sidekick_docker_shared10 = __toESM(require_dist(), 1);
|
|
96302
|
-
var
|
|
96424
|
+
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
96303
96425
|
var GLOBAL_BINDINGS = [
|
|
96304
96426
|
{ key: "1-5", label: "Switch panel" },
|
|
96305
96427
|
{ key: "j/k", label: "Navigate / scroll" },
|
|
@@ -96312,66 +96434,69 @@ var GLOBAL_BINDINGS = [
|
|
|
96312
96434
|
{ key: "a", label: "Toggle all/running (Containers)" },
|
|
96313
96435
|
{ key: "o", label: "Sort menu (Containers)" },
|
|
96314
96436
|
{ key: "R", label: "Reverse sort (Containers)" },
|
|
96437
|
+
{ key: "f", label: "Log filter (Logs tab)" },
|
|
96438
|
+
{ key: "m", label: "Pin/unpin log comparison" },
|
|
96439
|
+
{ key: "J/K", label: "Scroll compare pane" },
|
|
96315
96440
|
{ key: "V", label: "Version info" },
|
|
96316
96441
|
{ key: "?", label: "This help" },
|
|
96317
96442
|
{ key: "q", label: "Quit" }
|
|
96318
96443
|
];
|
|
96319
96444
|
function KeyBadge({ k }) {
|
|
96320
|
-
return /* @__PURE__ */ (0,
|
|
96445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "white", backgroundColor: "#2B4C7E", bold: true, children: ` ${k} ` });
|
|
96321
96446
|
}
|
|
96322
96447
|
function HelpOverlay({ panels, activePanelIndex, version: version2 }) {
|
|
96323
96448
|
const panel = panels[activePanelIndex];
|
|
96324
96449
|
const actions = panel.getActions();
|
|
96325
|
-
return /* @__PURE__ */ (0,
|
|
96326
|
-
/* @__PURE__ */ (0,
|
|
96327
|
-
/* @__PURE__ */ (0,
|
|
96328
|
-
/* @__PURE__ */ (0,
|
|
96450
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, padding: 1, children: [
|
|
96451
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { children: [
|
|
96452
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { bold: true, color: "magenta", children: `\u26A1 ${import_sidekick_docker_shared10.BRAND_INLINE} ${import_sidekick_docker_shared10.BRAND_TAGLINE}` }),
|
|
96453
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "gray", dimColor: true, children: ` v${version2}` })
|
|
96329
96454
|
] }),
|
|
96330
|
-
/* @__PURE__ */ (0,
|
|
96331
|
-
/* @__PURE__ */ (0,
|
|
96332
|
-
/* @__PURE__ */ (0,
|
|
96333
|
-
/* @__PURE__ */ (0,
|
|
96455
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: "" }),
|
|
96456
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { children: [
|
|
96457
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { bold: true, color: "yellow", children: "\u2500\u2500 Navigation " }),
|
|
96458
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "gray", dimColor: true, children: "\u2500".repeat(30) })
|
|
96334
96459
|
] }),
|
|
96335
|
-
/* @__PURE__ */ (0,
|
|
96336
|
-
GLOBAL_BINDINGS.map((b) => /* @__PURE__ */ (0,
|
|
96337
|
-
/* @__PURE__ */ (0,
|
|
96338
|
-
/* @__PURE__ */ (0,
|
|
96460
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: "" }),
|
|
96461
|
+
GLOBAL_BINDINGS.map((b) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { children: [
|
|
96462
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Box_default, { width: 10, justifyContent: "flex-end", marginRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(KeyBadge, { k: b.key }) }),
|
|
96463
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "gray", children: b.label })
|
|
96339
96464
|
] }, b.key)),
|
|
96340
|
-
actions.length > 0 && /* @__PURE__ */ (0,
|
|
96341
|
-
/* @__PURE__ */ (0,
|
|
96342
|
-
/* @__PURE__ */ (0,
|
|
96343
|
-
/* @__PURE__ */ (0,
|
|
96344
|
-
/* @__PURE__ */ (0,
|
|
96465
|
+
actions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
96466
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: "" }),
|
|
96467
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { children: [
|
|
96468
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { bold: true, color: "yellow", children: `\u2500\u2500 ${panel.title} Actions ` }),
|
|
96469
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "gray", dimColor: true, children: "\u2500".repeat(24) })
|
|
96345
96470
|
] }),
|
|
96346
|
-
/* @__PURE__ */ (0,
|
|
96347
|
-
actions.map((a) => /* @__PURE__ */ (0,
|
|
96348
|
-
/* @__PURE__ */ (0,
|
|
96349
|
-
/* @__PURE__ */ (0,
|
|
96350
|
-
a.confirm && /* @__PURE__ */ (0,
|
|
96471
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: "" }),
|
|
96472
|
+
actions.map((a) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { children: [
|
|
96473
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Box_default, { width: 10, justifyContent: "flex-end", marginRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(KeyBadge, { k: a.key }) }),
|
|
96474
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: a.confirm ? "red" : "gray", children: a.label }),
|
|
96475
|
+
a.confirm && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "red", dimColor: true, children: " \u26A0" })
|
|
96351
96476
|
] }, a.key))
|
|
96352
96477
|
] }),
|
|
96353
|
-
/* @__PURE__ */ (0,
|
|
96354
|
-
/* @__PURE__ */ (0,
|
|
96478
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: "" }),
|
|
96479
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "gray", dimColor: true, children: "Press ? or Esc to close" })
|
|
96355
96480
|
] });
|
|
96356
96481
|
}
|
|
96357
96482
|
|
|
96358
96483
|
// src/dashboard/ink/FilterOverlay.tsx
|
|
96359
96484
|
await init_build2();
|
|
96360
|
-
var
|
|
96485
|
+
var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
|
|
96361
96486
|
function FilterOverlay({ filterString, matchCount, totalCount, panelTitle }) {
|
|
96362
96487
|
const countInfo = matchCount !== void 0 && totalCount !== void 0 && panelTitle ? ` ${matchCount} of ${totalCount} ${panelTitle.toLowerCase()}` : "";
|
|
96363
|
-
return /* @__PURE__ */ (0,
|
|
96364
|
-
/* @__PURE__ */ (0,
|
|
96365
|
-
countInfo && /* @__PURE__ */ (0,
|
|
96366
|
-
/* @__PURE__ */ (0,
|
|
96488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { position: "absolute", marginTop: 1, marginLeft: 1, children: [
|
|
96489
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { backgroundColor: "#2B4C7E", color: "white", bold: true, children: ` \u2315 ${filterString}\u2588 ` }),
|
|
96490
|
+
countInfo && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "gray", dimColor: true, children: countInfo }),
|
|
96491
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "gray", dimColor: true, children: " Enter: apply Esc: clear" })
|
|
96367
96492
|
] });
|
|
96368
96493
|
}
|
|
96369
96494
|
|
|
96370
96495
|
// src/dashboard/ink/ContextMenuOverlay.tsx
|
|
96371
96496
|
await init_build2();
|
|
96372
|
-
var
|
|
96497
|
+
var import_jsx_runtime9 = __toESM(require_jsx_runtime(), 1);
|
|
96373
96498
|
function ContextMenuOverlay({ actions, selectedIndex }) {
|
|
96374
|
-
return /* @__PURE__ */ (0,
|
|
96499
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
96375
96500
|
Box_default,
|
|
96376
96501
|
{
|
|
96377
96502
|
position: "absolute",
|
|
@@ -96382,13 +96507,13 @@ function ContextMenuOverlay({ actions, selectedIndex }) {
|
|
|
96382
96507
|
borderColor: "#2B4C7E",
|
|
96383
96508
|
paddingX: 1,
|
|
96384
96509
|
children: [
|
|
96385
|
-
/* @__PURE__ */ (0,
|
|
96510
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { bold: true, color: "#2B4C7E", children: "\u2630 Actions" }),
|
|
96386
96511
|
actions.map((action, i) => {
|
|
96387
96512
|
const isSelected = i === selectedIndex;
|
|
96388
96513
|
const isDanger = !!action.confirm;
|
|
96389
96514
|
const color = isSelected ? isDanger ? "red" : "#2B4C7E" : isDanger ? "red" : "white";
|
|
96390
|
-
return /* @__PURE__ */ (0,
|
|
96391
|
-
/* @__PURE__ */ (0,
|
|
96515
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box_default, { children: [
|
|
96516
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
96392
96517
|
Text,
|
|
96393
96518
|
{
|
|
96394
96519
|
color,
|
|
@@ -96397,7 +96522,7 @@ function ContextMenuOverlay({ actions, selectedIndex }) {
|
|
|
96397
96522
|
children: ` ${action.key} `
|
|
96398
96523
|
}
|
|
96399
96524
|
),
|
|
96400
|
-
/* @__PURE__ */ (0,
|
|
96525
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
96401
96526
|
Text,
|
|
96402
96527
|
{
|
|
96403
96528
|
color,
|
|
@@ -96408,8 +96533,8 @@ function ContextMenuOverlay({ actions, selectedIndex }) {
|
|
|
96408
96533
|
)
|
|
96409
96534
|
] }, action.key);
|
|
96410
96535
|
}),
|
|
96411
|
-
/* @__PURE__ */ (0,
|
|
96412
|
-
/* @__PURE__ */ (0,
|
|
96536
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { children: "" }),
|
|
96537
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { color: "gray", dimColor: true, children: "j/k select Enter run Esc close" })
|
|
96413
96538
|
]
|
|
96414
96539
|
}
|
|
96415
96540
|
);
|
|
@@ -96417,7 +96542,7 @@ function ContextMenuOverlay({ actions, selectedIndex }) {
|
|
|
96417
96542
|
|
|
96418
96543
|
// src/dashboard/ink/ConfirmOverlay.tsx
|
|
96419
96544
|
await init_build2();
|
|
96420
|
-
var
|
|
96545
|
+
var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
|
|
96421
96546
|
var SEVERITY_CONFIG = {
|
|
96422
96547
|
low: { borderColor: "yellow", icon: "\u26A0", title: "Confirm", warning: "" },
|
|
96423
96548
|
high: { borderColor: "red", icon: "\u2717", title: "Destructive Action", warning: " This cannot be undone." },
|
|
@@ -96426,7 +96551,7 @@ var SEVERITY_CONFIG = {
|
|
|
96426
96551
|
function ConfirmOverlay({ message, severity }) {
|
|
96427
96552
|
const config = SEVERITY_CONFIG[severity];
|
|
96428
96553
|
const color = config.borderColor;
|
|
96429
|
-
return /* @__PURE__ */ (0,
|
|
96554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
96430
96555
|
Box_default,
|
|
96431
96556
|
{
|
|
96432
96557
|
position: "absolute",
|
|
@@ -96438,19 +96563,19 @@ function ConfirmOverlay({ message, severity }) {
|
|
|
96438
96563
|
paddingX: 2,
|
|
96439
96564
|
paddingY: 1,
|
|
96440
96565
|
children: [
|
|
96441
|
-
/* @__PURE__ */ (0,
|
|
96442
|
-
/* @__PURE__ */ (0,
|
|
96443
|
-
/* @__PURE__ */ (0,
|
|
96566
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { children: [
|
|
96567
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color, bold: true, children: `${config.icon} ` }),
|
|
96568
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { bold: true, color, children: config.title })
|
|
96444
96569
|
] }),
|
|
96445
|
-
/* @__PURE__ */ (0,
|
|
96446
|
-
/* @__PURE__ */ (0,
|
|
96447
|
-
config.warning ? /* @__PURE__ */ (0,
|
|
96448
|
-
/* @__PURE__ */ (0,
|
|
96449
|
-
/* @__PURE__ */ (0,
|
|
96450
|
-
/* @__PURE__ */ (0,
|
|
96451
|
-
/* @__PURE__ */ (0,
|
|
96452
|
-
/* @__PURE__ */ (0,
|
|
96453
|
-
/* @__PURE__ */ (0,
|
|
96570
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: "" }),
|
|
96571
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { bold: true, children: ` ${message}` }),
|
|
96572
|
+
config.warning ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "gray", dimColor: true, children: config.warning }) : null,
|
|
96573
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: "" }),
|
|
96574
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Box_default, { children: [
|
|
96575
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { backgroundColor: severity === "low" ? "yellow" : "green", color: severity === "low" ? "black" : "white", bold: true, children: " y Yes " }),
|
|
96576
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { children: " " }),
|
|
96577
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { backgroundColor: "red", color: "white", bold: true, children: " n No " }),
|
|
96578
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Text, { color: "gray", dimColor: true, children: " or Esc to cancel" })
|
|
96454
96579
|
] })
|
|
96455
96580
|
]
|
|
96456
96581
|
}
|
|
@@ -96460,7 +96585,7 @@ function ConfirmOverlay({ message, severity }) {
|
|
|
96460
96585
|
// src/dashboard/ink/ToastNotification.tsx
|
|
96461
96586
|
var import_react33 = __toESM(require_react(), 1);
|
|
96462
96587
|
await init_build2();
|
|
96463
|
-
var
|
|
96588
|
+
var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
|
|
96464
96589
|
var SEVERITY_COLORS2 = {
|
|
96465
96590
|
error: "red",
|
|
96466
96591
|
warning: "yellow",
|
|
@@ -96488,43 +96613,43 @@ function ToastNotification({ toast }) {
|
|
|
96488
96613
|
};
|
|
96489
96614
|
const icon = SEVERITY_ICONS[toast.severity] || "";
|
|
96490
96615
|
const textColor = toast.severity === "warning" ? "black" : "white";
|
|
96491
|
-
return /* @__PURE__ */ (0,
|
|
96616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Box_default, { position: "absolute", marginTop: 0, justifyContent: "flex-end", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { backgroundColor: SEVERITY_COLORS2[toast.severity] || "white", color: textColor, bold: true, children: ` ${icon} ${toast.message} ` }) });
|
|
96492
96617
|
}
|
|
96493
96618
|
|
|
96494
96619
|
// src/dashboard/ink/TooSmallOverlay.tsx
|
|
96495
96620
|
await init_build2();
|
|
96496
96621
|
var import_sidekick_docker_shared11 = __toESM(require_dist(), 1);
|
|
96497
|
-
var
|
|
96622
|
+
var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
|
|
96498
96623
|
function TooSmallOverlay({ columns, rows }) {
|
|
96499
96624
|
const needWidth = Math.max(0, 60 - columns);
|
|
96500
96625
|
const needHeight = Math.max(0, 15 - rows);
|
|
96501
96626
|
const hints = [];
|
|
96502
96627
|
if (needWidth > 0) hints.push(`${needWidth} col${needWidth > 1 ? "s" : ""} wider`);
|
|
96503
96628
|
if (needHeight > 0) hints.push(`${needHeight} row${needHeight > 1 ? "s" : ""} taller`);
|
|
96504
|
-
return /* @__PURE__ */ (0,
|
|
96505
|
-
/* @__PURE__ */ (0,
|
|
96506
|
-
/* @__PURE__ */ (0,
|
|
96507
|
-
/* @__PURE__ */ (0,
|
|
96508
|
-
/* @__PURE__ */ (0,
|
|
96509
|
-
/* @__PURE__ */ (0,
|
|
96510
|
-
/* @__PURE__ */ (0,
|
|
96629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Box_default, { flexDirection: "column", justifyContent: "center", alignItems: "center", height: rows, width: columns, children: [
|
|
96630
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { bold: true, color: "magenta", children: `\u26A1 ${import_sidekick_docker_shared11.BRAND_INLINE}` }),
|
|
96631
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { children: "" }),
|
|
96632
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "yellow", bold: true, children: "Terminal too small" }),
|
|
96633
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "gray", children: `${columns}\xD7${rows} \u2192 need ${hints.join(" and ")}` }),
|
|
96634
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { children: "" }),
|
|
96635
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { color: "gray", dimColor: true, children: "Resize to at least 60\xD715 to continue." })
|
|
96511
96636
|
] });
|
|
96512
96637
|
}
|
|
96513
96638
|
|
|
96514
96639
|
// src/dashboard/ink/ExecOverlay.tsx
|
|
96515
96640
|
await init_build2();
|
|
96516
|
-
var
|
|
96641
|
+
var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
|
|
96517
96642
|
function ExecOverlay({ containerName, outputLines }) {
|
|
96518
96643
|
const { rows } = useTerminalSize();
|
|
96519
96644
|
const viewportHeight = Math.max(1, rows - 3);
|
|
96520
96645
|
const scrollOffset = Math.max(0, outputLines.length - viewportHeight);
|
|
96521
96646
|
const visibleLines = outputLines.slice(scrollOffset, scrollOffset + viewportHeight);
|
|
96522
|
-
return /* @__PURE__ */ (0,
|
|
96523
|
-
/* @__PURE__ */ (0,
|
|
96524
|
-
/* @__PURE__ */ (0,
|
|
96525
|
-
/* @__PURE__ */ (0,
|
|
96647
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
96648
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Box_default, { children: [
|
|
96649
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { bold: true, color: "#2B4C7E", children: ` Exec: ${containerName} ` }),
|
|
96650
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { color: "gray", children: " (Ctrl+] to detach)" })
|
|
96526
96651
|
] }),
|
|
96527
|
-
/* @__PURE__ */ (0,
|
|
96652
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { flexDirection: "column", flexGrow: 1, children: visibleLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { children: line || " " }, scrollOffset + i)) })
|
|
96528
96653
|
] });
|
|
96529
96654
|
}
|
|
96530
96655
|
|
|
@@ -96598,7 +96723,7 @@ function parseMouseEvent(data) {
|
|
|
96598
96723
|
// src/dashboard/ink/mouse/MouseProvider.tsx
|
|
96599
96724
|
var import_react34 = __toESM(require_react(), 1);
|
|
96600
96725
|
await init_build2();
|
|
96601
|
-
var
|
|
96726
|
+
var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
|
|
96602
96727
|
function InputSink() {
|
|
96603
96728
|
use_input_default(() => {
|
|
96604
96729
|
});
|
|
@@ -96622,20 +96747,20 @@ function MouseProvider({ onMouse, children }) {
|
|
|
96622
96747
|
disableMouse();
|
|
96623
96748
|
};
|
|
96624
96749
|
}, [onMouse]);
|
|
96625
|
-
return /* @__PURE__ */ (0,
|
|
96626
|
-
/* @__PURE__ */ (0,
|
|
96750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
96751
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(InputSink, {}),
|
|
96627
96752
|
children
|
|
96628
96753
|
] });
|
|
96629
96754
|
}
|
|
96630
96755
|
|
|
96631
96756
|
// src/dashboard/ink/LogFilterOverlay.tsx
|
|
96632
96757
|
await init_build2();
|
|
96633
|
-
var
|
|
96758
|
+
var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
|
|
96634
96759
|
function LogFilterOverlay({ filterString, filterMode }) {
|
|
96635
96760
|
const modeLabel = filterMode === "exact" ? "exact" : "fuzzy";
|
|
96636
|
-
return /* @__PURE__ */ (0,
|
|
96637
|
-
/* @__PURE__ */ (0,
|
|
96638
|
-
/* @__PURE__ */ (0,
|
|
96761
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Box_default, { position: "absolute", marginTop: 1, marginLeft: 1, children: [
|
|
96762
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { backgroundColor: "#2B4C7E", color: "white", bold: true, children: ` Log filter (${modeLabel}): ${filterString}\u2588 ` }),
|
|
96763
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Text, { color: "gray", children: " Tab: toggle mode Enter: apply Esc: clear" })
|
|
96639
96764
|
] });
|
|
96640
96765
|
}
|
|
96641
96766
|
|
|
@@ -96643,26 +96768,26 @@ function LogFilterOverlay({ filterString, filterMode }) {
|
|
|
96643
96768
|
var import_react35 = __toESM(require_react(), 1);
|
|
96644
96769
|
await init_build2();
|
|
96645
96770
|
var import_sidekick_docker_shared12 = __toESM(require_dist(), 1);
|
|
96646
|
-
var
|
|
96771
|
+
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
96647
96772
|
function VersionOverlay({ version: version2 }) {
|
|
96648
96773
|
const phrase = import_react35.default.useMemo(() => (0, import_sidekick_docker_shared12.getRandomPhrase)(), []);
|
|
96649
|
-
return /* @__PURE__ */ (0,
|
|
96650
|
-
/* @__PURE__ */ (0,
|
|
96651
|
-
/* @__PURE__ */ (0,
|
|
96652
|
-
/* @__PURE__ */ (0,
|
|
96653
|
-
/* @__PURE__ */ (0,
|
|
96654
|
-
/* @__PURE__ */ (0,
|
|
96655
|
-
/* @__PURE__ */ (0,
|
|
96656
|
-
/* @__PURE__ */ (0,
|
|
96657
|
-
/* @__PURE__ */ (0,
|
|
96658
|
-
/* @__PURE__ */ (0,
|
|
96659
|
-
/* @__PURE__ */ (0,
|
|
96774
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, padding: 1, children: [
|
|
96775
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { bold: true, color: "magenta", children: `\u26A1 ${import_sidekick_docker_shared12.BRAND_INLINE}` }),
|
|
96776
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: "#2B4C7E", bold: true, children: `${import_sidekick_docker_shared12.BRAND_TAGLINE} v${version2}` }),
|
|
96777
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { children: "" }),
|
|
96778
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: "gray", dimColor: true, children: "\u2500".repeat(40) }),
|
|
96779
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { children: "" }),
|
|
96780
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: "gray", italic: true, children: ` "${phrase}"` }),
|
|
96781
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { children: "" }),
|
|
96782
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: "gray", dimColor: true, children: "\u2500".repeat(40) }),
|
|
96783
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { children: "" }),
|
|
96784
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: "gray", dimColor: true, children: "Press V or Esc to close" })
|
|
96660
96785
|
] });
|
|
96661
96786
|
}
|
|
96662
96787
|
|
|
96663
96788
|
// src/dashboard/ink/SortOverlay.tsx
|
|
96664
96789
|
await init_build2();
|
|
96665
|
-
var
|
|
96790
|
+
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
96666
96791
|
var SORT_OPTIONS = [
|
|
96667
96792
|
{ field: "state", label: "State (running first)" },
|
|
96668
96793
|
{ field: "name", label: "Name" },
|
|
@@ -96673,7 +96798,7 @@ var SORT_OPTIONS = [
|
|
|
96673
96798
|
{ field: "pids", label: "PIDs" }
|
|
96674
96799
|
];
|
|
96675
96800
|
function SortOverlay({ selectedIndex, currentField, reversed }) {
|
|
96676
|
-
return /* @__PURE__ */ (0,
|
|
96801
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
96677
96802
|
Box_default,
|
|
96678
96803
|
{
|
|
96679
96804
|
position: "absolute",
|
|
@@ -96684,12 +96809,12 @@ function SortOverlay({ selectedIndex, currentField, reversed }) {
|
|
|
96684
96809
|
borderColor: "#2B4C7E",
|
|
96685
96810
|
paddingX: 1,
|
|
96686
96811
|
children: [
|
|
96687
|
-
/* @__PURE__ */ (0,
|
|
96812
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { bold: true, color: "#2B4C7E", children: "\u2195 Sort by" }),
|
|
96688
96813
|
SORT_OPTIONS.map((opt, i) => {
|
|
96689
96814
|
const isSelected = i === selectedIndex;
|
|
96690
96815
|
const isCurrent = opt.field === currentField;
|
|
96691
96816
|
const indicator = isCurrent ? reversed ? " \u25B2" : " \u25BC" : "";
|
|
96692
|
-
return /* @__PURE__ */ (0,
|
|
96817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
96693
96818
|
Text,
|
|
96694
96819
|
{
|
|
96695
96820
|
color: isSelected ? "#2B4C7E" : isCurrent ? "yellow" : "white",
|
|
@@ -96699,8 +96824,8 @@ function SortOverlay({ selectedIndex, currentField, reversed }) {
|
|
|
96699
96824
|
}
|
|
96700
96825
|
) }, opt.field);
|
|
96701
96826
|
}),
|
|
96702
|
-
/* @__PURE__ */ (0,
|
|
96703
|
-
/* @__PURE__ */ (0,
|
|
96827
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { children: "" }),
|
|
96828
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text, { color: "gray", dimColor: true, children: "j/k select Enter apply R reverse Esc close" })
|
|
96704
96829
|
]
|
|
96705
96830
|
}
|
|
96706
96831
|
);
|
|
@@ -96764,7 +96889,7 @@ var ExecManager = class {
|
|
|
96764
96889
|
};
|
|
96765
96890
|
|
|
96766
96891
|
// src/dashboard/ink/Dashboard.tsx
|
|
96767
|
-
var
|
|
96892
|
+
var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
|
|
96768
96893
|
var SORT_FIELDS2 = ["state", "name", "cpu", "mem", "net", "io", "pids"];
|
|
96769
96894
|
var SIDE_PANEL_WIDTH = 28;
|
|
96770
96895
|
var SIDE_PANEL_WIDTH_WIDE = 42;
|
|
@@ -96787,7 +96912,7 @@ function reducer(state, action) {
|
|
|
96787
96912
|
detailScrollPerTab: {}
|
|
96788
96913
|
};
|
|
96789
96914
|
case "SELECT_ITEM":
|
|
96790
|
-
return { ...state, selectedItemIndex: action.index, detailTabIndex: 0, detailScrollOffset: 0, detailScrollPerTab: {} };
|
|
96915
|
+
return { ...state, selectedItemIndex: action.index, detailTabIndex: 0, detailScrollOffset: 0, detailScrollPerTab: {}, secondaryDetailScrollOffset: 0 };
|
|
96791
96916
|
case "SET_DETAIL_TAB": {
|
|
96792
96917
|
const saved = { ...state.detailScrollPerTab, [state.detailTabIndex]: state.detailScrollOffset };
|
|
96793
96918
|
return { ...state, detailTabIndex: action.index, detailScrollOffset: saved[action.index] ?? 0, detailScrollPerTab: saved };
|
|
@@ -96866,6 +96991,22 @@ function reducer(state, action) {
|
|
|
96866
96991
|
const next = (state.sortMenuIndex + action.delta + SORT_FIELDS2.length) % SORT_FIELDS2.length;
|
|
96867
96992
|
return { ...state, sortMenuIndex: next };
|
|
96868
96993
|
}
|
|
96994
|
+
case "PIN_COMPARE": {
|
|
96995
|
+
const current = state.compareItemIds[action.panelId] ?? null;
|
|
96996
|
+
const newId = current === action.itemId ? null : action.itemId;
|
|
96997
|
+
return {
|
|
96998
|
+
...state,
|
|
96999
|
+
compareItemIds: { ...state.compareItemIds, [action.panelId]: newId },
|
|
97000
|
+
secondaryDetailScrollOffset: 0
|
|
97001
|
+
};
|
|
97002
|
+
}
|
|
97003
|
+
case "SCROLL_SECONDARY_DETAIL":
|
|
97004
|
+
return { ...state, secondaryDetailScrollOffset: action.offset };
|
|
97005
|
+
case "SCROLL_SECONDARY_DETAIL_DELTA": {
|
|
97006
|
+
const maxOffset = Math.max(0, action.totalLines - action.viewportHeight);
|
|
97007
|
+
const next = Math.max(0, Math.min(state.secondaryDetailScrollOffset + action.delta, maxOffset));
|
|
97008
|
+
return { ...state, secondaryDetailScrollOffset: next };
|
|
97009
|
+
}
|
|
96869
97010
|
default:
|
|
96870
97011
|
return state;
|
|
96871
97012
|
}
|
|
@@ -96893,7 +97034,9 @@ var initialState = {
|
|
|
96893
97034
|
showAllContainers: true,
|
|
96894
97035
|
sortField: "state",
|
|
96895
97036
|
sortReversed: false,
|
|
96896
|
-
sortMenuIndex: 0
|
|
97037
|
+
sortMenuIndex: 0,
|
|
97038
|
+
compareItemIds: {},
|
|
97039
|
+
secondaryDetailScrollOffset: 0
|
|
96897
97040
|
};
|
|
96898
97041
|
function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecFallback }) {
|
|
96899
97042
|
const [state, dispatch] = (0, import_react36.useReducer)(reducer, initialState);
|
|
@@ -97059,14 +97202,21 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97059
97202
|
const selectedItem = currentItems[clampedSelection];
|
|
97060
97203
|
const detailTabs = panel.detailTabs;
|
|
97061
97204
|
const tabIdx = Math.min(state.detailTabIndex, detailTabs.length - 1);
|
|
97205
|
+
const compareItemId = state.compareItemIds[panel.id] ?? null;
|
|
97206
|
+
(0, import_react36.useEffect)(() => {
|
|
97207
|
+
if (compareItemId && selectedItem?.id === compareItemId) {
|
|
97208
|
+
dispatch({ type: "PIN_COMPARE", panelId: panel.id, itemId: compareItemId });
|
|
97209
|
+
}
|
|
97210
|
+
}, [selectedItem?.id, compareItemId, panel.id]);
|
|
97062
97211
|
(0, import_react36.useEffect)(() => {
|
|
97063
97212
|
onViewStateChange?.({
|
|
97064
97213
|
panelId: panel.id,
|
|
97065
97214
|
itemId: selectedItem?.id ?? null,
|
|
97066
97215
|
detailTabIndex: tabIdx,
|
|
97067
|
-
sortField: state.sortField
|
|
97216
|
+
sortField: state.sortField,
|
|
97217
|
+
compareItemId
|
|
97068
97218
|
});
|
|
97069
|
-
}, [panel.id, selectedItem?.id, tabIdx, state.sortField]);
|
|
97219
|
+
}, [panel.id, selectedItem?.id, tabIdx, state.sortField, compareItemId]);
|
|
97070
97220
|
const enrichedMetrics = {
|
|
97071
97221
|
...metrics,
|
|
97072
97222
|
logFilterString: state.logFilterString,
|
|
@@ -97087,6 +97237,31 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97087
97237
|
dispatch({ type: "SCROLL_DETAIL", offset: detailLines.length - detailViewportHeight });
|
|
97088
97238
|
}
|
|
97089
97239
|
}, [shouldAutoScroll, detailLines.length, detailViewportHeight]);
|
|
97240
|
+
const isCompareActive = compareItemId != null && shouldAutoScroll;
|
|
97241
|
+
const secondaryDetailLines = import_react36.default.useMemo(() => {
|
|
97242
|
+
if (!isCompareActive) return [];
|
|
97243
|
+
if (panel.id === "containers") {
|
|
97244
|
+
const logs = enrichedMetrics.secondaryContainerLogs;
|
|
97245
|
+
if (logs.length === 0) return ["Waiting for logs..."];
|
|
97246
|
+
return renderLogLines(logs, state.logFilterString, state.logFilterMode, enrichedMetrics.secondaryLogSeverityCounts);
|
|
97247
|
+
}
|
|
97248
|
+
if (panel.id === "services") {
|
|
97249
|
+
const logs = enrichedMetrics.secondaryComposeLogs;
|
|
97250
|
+
if (logs.length === 0) return ["Waiting for logs..."];
|
|
97251
|
+
return renderLogLines(logs, state.logFilterString, state.logFilterMode);
|
|
97252
|
+
}
|
|
97253
|
+
return [];
|
|
97254
|
+
}, [isCompareActive, panel.id, enrichedMetrics.secondaryContainerLogs, enrichedMetrics.secondaryComposeLogs, enrichedMetrics.secondaryLogSeverityCounts, state.logFilterString, state.logFilterMode]);
|
|
97255
|
+
(0, import_react36.useEffect)(() => {
|
|
97256
|
+
if (isCompareActive && secondaryDetailLines.length > detailViewportHeight) {
|
|
97257
|
+
dispatch({ type: "SCROLL_SECONDARY_DETAIL", offset: secondaryDetailLines.length - detailViewportHeight });
|
|
97258
|
+
}
|
|
97259
|
+
}, [isCompareActive, secondaryDetailLines.length, detailViewportHeight]);
|
|
97260
|
+
const compareItemLabel = import_react36.default.useMemo(() => {
|
|
97261
|
+
if (!compareItemId) return "";
|
|
97262
|
+
const item = currentItems.find((it) => it.id === compareItemId);
|
|
97263
|
+
return item ? item.label.replace(/^[^\w]*/, "").trim() : compareItemId.slice(0, 12);
|
|
97264
|
+
}, [compareItemId, currentItems]);
|
|
97090
97265
|
const panelActions = panel.getActions();
|
|
97091
97266
|
const applicableActions = selectedItem ? panelActions.filter((a) => !a.condition || a.condition(selectedItem)) : [];
|
|
97092
97267
|
const contextActions = state.overlay === "context-menu" ? applicableActions : [];
|
|
@@ -97134,27 +97309,35 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97134
97309
|
sideScroll,
|
|
97135
97310
|
addToast,
|
|
97136
97311
|
removeToast,
|
|
97137
|
-
rotatePhrase
|
|
97312
|
+
rotatePhrase,
|
|
97313
|
+
secondaryDetailLineCount: secondaryDetailLines.length
|
|
97138
97314
|
});
|
|
97139
97315
|
if (tooSmall) {
|
|
97140
|
-
return /* @__PURE__ */ (0,
|
|
97316
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TooSmallOverlay, { columns, rows });
|
|
97141
97317
|
}
|
|
97142
97318
|
const showNormalLayout = state.overlay !== "help" && state.overlay !== "exec" && state.overlay !== "version";
|
|
97143
97319
|
const panelActionHints = applicableActions.length > 0 ? [{ key: "x", label: "Actions", destructive: false }] : [];
|
|
97144
97320
|
const contextHint = (() => {
|
|
97145
97321
|
if (panel.id === "containers") {
|
|
97146
97322
|
const parts = [];
|
|
97147
|
-
if (tabIdx === 0)
|
|
97323
|
+
if (tabIdx === 0) {
|
|
97324
|
+
parts.push("f:Filter", "c:Copy", "m:Compare");
|
|
97325
|
+
}
|
|
97148
97326
|
parts.push(state.showAllContainers ? "a:All" : "a:Running");
|
|
97149
97327
|
parts.push(`o:\u2195${state.sortField}`);
|
|
97150
97328
|
return parts.join(" ");
|
|
97151
97329
|
}
|
|
97330
|
+
if (panel.id === "services") {
|
|
97331
|
+
const parts = [];
|
|
97332
|
+
if (tabIdx === 1) parts.push("m:Compare");
|
|
97333
|
+
return parts.join(" ");
|
|
97334
|
+
}
|
|
97152
97335
|
return "";
|
|
97153
97336
|
})();
|
|
97154
|
-
return /* @__PURE__ */ (0,
|
|
97155
|
-
showNormalLayout && /* @__PURE__ */ (0,
|
|
97156
|
-
showNormalLayout && /* @__PURE__ */ (0,
|
|
97157
|
-
sideWidth > 0 && /* @__PURE__ */ (0,
|
|
97337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(MouseProvider, { onMouse: handleMouse, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Box_default, { flexDirection: "column", height: rows, width: columns, children: [
|
|
97338
|
+
showNormalLayout && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TabBar, { panels, activeIndex: state.activePanelIndex, layoutMode: state.layoutMode, phrase, panelCounts }),
|
|
97339
|
+
showNormalLayout && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Box_default, { flexGrow: 1, flexDirection: "row", children: [
|
|
97340
|
+
sideWidth > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97158
97341
|
SideList,
|
|
97159
97342
|
{
|
|
97160
97343
|
items: currentItems,
|
|
@@ -97167,12 +97350,26 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97167
97350
|
filterString: state.filterString || void 0,
|
|
97168
97351
|
panelId: panel.id,
|
|
97169
97352
|
totalCount: totalItemCount,
|
|
97170
|
-
runningCount: panel.id === "containers" ? runningCount : void 0
|
|
97353
|
+
runningCount: panel.id === "containers" ? runningCount : void 0,
|
|
97354
|
+
compareItemId: compareItemId || void 0
|
|
97171
97355
|
}
|
|
97172
97356
|
),
|
|
97173
|
-
/* @__PURE__ */ (0,
|
|
97174
|
-
/* @__PURE__ */ (0,
|
|
97175
|
-
/* @__PURE__ */ (0,
|
|
97357
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
97358
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DetailTabBar, { tabs: detailTabs, activeIndex: state.detailTabIndex }),
|
|
97359
|
+
isCompareActive ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97360
|
+
CompareDetailPane,
|
|
97361
|
+
{
|
|
97362
|
+
primaryLines: detailLines,
|
|
97363
|
+
secondaryLines: secondaryDetailLines,
|
|
97364
|
+
primaryScrollOffset: state.detailScrollOffset,
|
|
97365
|
+
secondaryScrollOffset: state.secondaryDetailScrollOffset,
|
|
97366
|
+
viewportHeight: detailViewportHeight,
|
|
97367
|
+
totalWidth: columns - sideWidth,
|
|
97368
|
+
focused: state.focusTarget === "detail",
|
|
97369
|
+
primaryLabel: selectedItem?.label.replace(/^[^\w]*/, "").trim() ?? "",
|
|
97370
|
+
secondaryLabel: compareItemLabel
|
|
97371
|
+
}
|
|
97372
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97176
97373
|
DetailPane,
|
|
97177
97374
|
{
|
|
97178
97375
|
lines: detailLines,
|
|
@@ -97183,16 +97380,16 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97183
97380
|
)
|
|
97184
97381
|
] })
|
|
97185
97382
|
] }),
|
|
97186
|
-
state.overlay === "help" && /* @__PURE__ */ (0,
|
|
97187
|
-
state.overlay === "version" && /* @__PURE__ */ (0,
|
|
97188
|
-
state.overlay === "exec" && /* @__PURE__ */ (0,
|
|
97383
|
+
state.overlay === "help" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(HelpOverlay, { panels, activePanelIndex: state.activePanelIndex, version: "0.2.3" }),
|
|
97384
|
+
state.overlay === "version" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VersionOverlay, { version: "0.2.3" }),
|
|
97385
|
+
state.overlay === "exec" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97189
97386
|
ExecOverlay,
|
|
97190
97387
|
{
|
|
97191
97388
|
containerName: state.execContainerName,
|
|
97192
97389
|
outputLines: state.execOutputLines
|
|
97193
97390
|
}
|
|
97194
97391
|
),
|
|
97195
|
-
state.overlay !== "exec" && /* @__PURE__ */ (0,
|
|
97392
|
+
state.overlay !== "exec" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97196
97393
|
StatusBar,
|
|
97197
97394
|
{
|
|
97198
97395
|
daemonConnected: metrics.daemonConnected,
|
|
@@ -97201,15 +97398,15 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97201
97398
|
filterString: state.filterString,
|
|
97202
97399
|
containerCount: metrics.containers.length,
|
|
97203
97400
|
runningCount,
|
|
97204
|
-
version: "0.2.
|
|
97401
|
+
version: "0.2.3",
|
|
97205
97402
|
matchCount: state.filterString ? currentItems.length : void 0,
|
|
97206
97403
|
totalCount: state.filterString ? totalItemCount : void 0,
|
|
97207
97404
|
lastRefresh: metrics.lastRefresh,
|
|
97208
97405
|
contextHint
|
|
97209
97406
|
}
|
|
97210
97407
|
),
|
|
97211
|
-
state.overlay === "context-menu" && /* @__PURE__ */ (0,
|
|
97212
|
-
state.overlay === "filter" && /* @__PURE__ */ (0,
|
|
97408
|
+
state.overlay === "context-menu" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ContextMenuOverlay, { actions: contextActions, selectedIndex: state.contextMenuIndex }),
|
|
97409
|
+
state.overlay === "filter" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97213
97410
|
FilterOverlay,
|
|
97214
97411
|
{
|
|
97215
97412
|
filterString: state.filterString,
|
|
@@ -97218,15 +97415,15 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97218
97415
|
panelTitle: panel.title
|
|
97219
97416
|
}
|
|
97220
97417
|
),
|
|
97221
|
-
state.overlay === "log-filter" && /* @__PURE__ */ (0,
|
|
97418
|
+
state.overlay === "log-filter" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97222
97419
|
LogFilterOverlay,
|
|
97223
97420
|
{
|
|
97224
97421
|
filterString: state.logFilterString,
|
|
97225
97422
|
filterMode: state.logFilterMode
|
|
97226
97423
|
}
|
|
97227
97424
|
),
|
|
97228
|
-
state.overlay === "sort" && /* @__PURE__ */ (0,
|
|
97229
|
-
state.overlay === "confirm" && /* @__PURE__ */ (0,
|
|
97425
|
+
state.overlay === "sort" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SortOverlay, { selectedIndex: state.sortMenuIndex, currentField: state.sortField, reversed: state.sortReversed }),
|
|
97426
|
+
state.overlay === "confirm" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97230
97427
|
ConfirmOverlay,
|
|
97231
97428
|
{
|
|
97232
97429
|
message: state.confirmMessage,
|
|
@@ -97238,7 +97435,7 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97238
97435
|
onCancel: () => dispatch({ type: "SET_CONFIRM", action: null, message: "" })
|
|
97239
97436
|
}
|
|
97240
97437
|
),
|
|
97241
|
-
state.toasts.length > 0 && /* @__PURE__ */ (0,
|
|
97438
|
+
state.toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ToastNotification, { toast: state.toasts[state.toasts.length - 1] })
|
|
97242
97439
|
] }) });
|
|
97243
97440
|
}
|
|
97244
97441
|
|
|
@@ -97264,6 +97461,8 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97264
97461
|
};
|
|
97265
97462
|
let logFlushTimer = null;
|
|
97266
97463
|
let composeLogFlushTimer = null;
|
|
97464
|
+
let secondaryLogFlushTimer = null;
|
|
97465
|
+
let secondaryComposeLogFlushTimer = null;
|
|
97267
97466
|
const logManager = new LogStreamManager(client, () => {
|
|
97268
97467
|
if (logFlushTimer) return;
|
|
97269
97468
|
logFlushTimer = setTimeout(() => {
|
|
@@ -97283,6 +97482,25 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97283
97482
|
scheduleRender();
|
|
97284
97483
|
};
|
|
97285
97484
|
let logSeverityCounts = logManager.getSeverityCounts();
|
|
97485
|
+
const secondaryLogManager = new LogStreamManager(client, () => {
|
|
97486
|
+
if (secondaryLogFlushTimer) return;
|
|
97487
|
+
secondaryLogFlushTimer = setTimeout(() => {
|
|
97488
|
+
secondaryLogFlushTimer = null;
|
|
97489
|
+
state.setSecondaryLogs(secondaryLogManager.getLogs());
|
|
97490
|
+
secondaryLogSeverityCounts = secondaryLogManager.getSeverityCounts();
|
|
97491
|
+
scheduleRender();
|
|
97492
|
+
}, 100);
|
|
97493
|
+
});
|
|
97494
|
+
const flushSecondaryLogsNow = () => {
|
|
97495
|
+
if (secondaryLogFlushTimer) {
|
|
97496
|
+
clearTimeout(secondaryLogFlushTimer);
|
|
97497
|
+
secondaryLogFlushTimer = null;
|
|
97498
|
+
}
|
|
97499
|
+
state.setSecondaryLogs(secondaryLogManager.getLogs());
|
|
97500
|
+
secondaryLogSeverityCounts = secondaryLogManager.getSeverityCounts();
|
|
97501
|
+
scheduleRender();
|
|
97502
|
+
};
|
|
97503
|
+
let secondaryLogSeverityCounts = secondaryLogManager.getSeverityCounts();
|
|
97286
97504
|
const statsManager = new StatsStreamManager(client, state.getStatsCollector(), () => {
|
|
97287
97505
|
scheduleRender();
|
|
97288
97506
|
});
|
|
@@ -97308,15 +97526,35 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97308
97526
|
}
|
|
97309
97527
|
scheduleRender();
|
|
97310
97528
|
};
|
|
97529
|
+
const secondaryComposeLogManager = new ComposeLogStreamManager(composeClient, () => {
|
|
97530
|
+
if (secondaryComposeLogFlushTimer) return;
|
|
97531
|
+
secondaryComposeLogFlushTimer = setTimeout(() => {
|
|
97532
|
+
secondaryComposeLogFlushTimer = null;
|
|
97533
|
+
state.setSecondaryComposeLogs(secondaryComposeLogManager.getLogs());
|
|
97534
|
+
scheduleRender();
|
|
97535
|
+
}, 100);
|
|
97536
|
+
});
|
|
97537
|
+
const flushSecondaryComposeLogsNow = () => {
|
|
97538
|
+
if (secondaryComposeLogFlushTimer) {
|
|
97539
|
+
clearTimeout(secondaryComposeLogFlushTimer);
|
|
97540
|
+
secondaryComposeLogFlushTimer = null;
|
|
97541
|
+
}
|
|
97542
|
+
state.setSecondaryComposeLogs(secondaryComposeLogManager.getLogs());
|
|
97543
|
+
scheduleRender();
|
|
97544
|
+
};
|
|
97311
97545
|
const onViewStateChange = (viewState) => {
|
|
97312
|
-
const { panelId, itemId, detailTabIndex, sortField } = viewState;
|
|
97546
|
+
const { panelId, itemId, detailTabIndex, sortField, compareItemId } = viewState;
|
|
97313
97547
|
const wantsLiveStats = sortField === "cpu" || sortField === "mem" || sortField === "net" || sortField === "io" || sortField === "pids";
|
|
97314
97548
|
if (panelId === "containers") {
|
|
97315
97549
|
void logManager.select(detailTabIndex === 0 ? itemId : null);
|
|
97316
97550
|
void statsManager.select(itemId && (detailTabIndex === 1 || wantsLiveStats) ? itemId : null);
|
|
97317
97551
|
void composeLogManager.selectCompose(null, null);
|
|
97552
|
+
void secondaryLogManager.select(detailTabIndex === 0 && compareItemId ? compareItemId : null);
|
|
97553
|
+
void secondaryComposeLogManager.selectCompose(null, null);
|
|
97318
97554
|
flushLogsNow();
|
|
97319
97555
|
flushComposeLogsNow();
|
|
97556
|
+
flushSecondaryLogsNow();
|
|
97557
|
+
flushSecondaryComposeLogsNow();
|
|
97320
97558
|
if (itemId && !state.getInspectedEnv(itemId)) {
|
|
97321
97559
|
client.getContainerEnv(itemId).then((env3) => {
|
|
97322
97560
|
state.setInspectedEnv(itemId, env3);
|
|
@@ -97332,6 +97570,7 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97332
97570
|
} else if (panelId === "services" && itemId) {
|
|
97333
97571
|
void logManager.select(null);
|
|
97334
97572
|
void statsManager.select(null);
|
|
97573
|
+
void secondaryLogManager.select(null);
|
|
97335
97574
|
if (detailTabIndex === 1) {
|
|
97336
97575
|
const parts = itemId.split(":");
|
|
97337
97576
|
if (parts[0] === "project") {
|
|
@@ -97339,17 +97578,34 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97339
97578
|
} else if (parts[0] === "service") {
|
|
97340
97579
|
void composeLogManager.selectCompose(parts[1], parts.slice(2).join(":"));
|
|
97341
97580
|
}
|
|
97581
|
+
if (compareItemId) {
|
|
97582
|
+
const cParts = compareItemId.split(":");
|
|
97583
|
+
if (cParts[0] === "project") {
|
|
97584
|
+
void secondaryComposeLogManager.selectCompose(cParts.slice(1).join(":"), null);
|
|
97585
|
+
} else if (cParts[0] === "service") {
|
|
97586
|
+
void secondaryComposeLogManager.selectCompose(cParts[1], cParts.slice(2).join(":"));
|
|
97587
|
+
}
|
|
97588
|
+
} else {
|
|
97589
|
+
void secondaryComposeLogManager.selectCompose(null, null);
|
|
97590
|
+
}
|
|
97342
97591
|
} else {
|
|
97343
97592
|
void composeLogManager.selectCompose(null, null);
|
|
97593
|
+
void secondaryComposeLogManager.selectCompose(null, null);
|
|
97344
97594
|
}
|
|
97345
97595
|
flushLogsNow();
|
|
97346
97596
|
flushComposeLogsNow();
|
|
97597
|
+
flushSecondaryLogsNow();
|
|
97598
|
+
flushSecondaryComposeLogsNow();
|
|
97347
97599
|
} else if (panelId === "images") {
|
|
97348
97600
|
void logManager.select(null);
|
|
97349
97601
|
void statsManager.select(null);
|
|
97350
97602
|
void composeLogManager.selectCompose(null, null);
|
|
97603
|
+
void secondaryLogManager.select(null);
|
|
97604
|
+
void secondaryComposeLogManager.selectCompose(null, null);
|
|
97351
97605
|
flushLogsNow();
|
|
97352
97606
|
flushComposeLogsNow();
|
|
97607
|
+
flushSecondaryLogsNow();
|
|
97608
|
+
flushSecondaryComposeLogsNow();
|
|
97353
97609
|
if (itemId && !state.getImageLayers(itemId)) {
|
|
97354
97610
|
client.getImageHistory(itemId).then((layers) => {
|
|
97355
97611
|
state.setImageLayers(itemId, layers);
|
|
@@ -97360,8 +97616,12 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97360
97616
|
void logManager.select(null);
|
|
97361
97617
|
void statsManager.select(null);
|
|
97362
97618
|
void composeLogManager.selectCompose(null, null);
|
|
97619
|
+
void secondaryLogManager.select(null);
|
|
97620
|
+
void secondaryComposeLogManager.selectCompose(null, null);
|
|
97363
97621
|
flushLogsNow();
|
|
97364
97622
|
flushComposeLogsNow();
|
|
97623
|
+
flushSecondaryLogsNow();
|
|
97624
|
+
flushSecondaryComposeLogsNow();
|
|
97365
97625
|
}
|
|
97366
97626
|
};
|
|
97367
97627
|
const panels = [
|
|
@@ -97436,6 +97696,8 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97436
97696
|
m.logSeverityCounts = logSeverityCounts;
|
|
97437
97697
|
m.logSeverityTimeSeries = logManager.getSeverityTimeSeries();
|
|
97438
97698
|
m.logTemplates = logManager.getTemplates();
|
|
97699
|
+
m.secondaryLogSeverityCounts = secondaryLogSeverityCounts;
|
|
97700
|
+
m.secondaryLogSeverityTimeSeries = secondaryLogManager.getSeverityTimeSeries();
|
|
97439
97701
|
return m;
|
|
97440
97702
|
}
|
|
97441
97703
|
function scheduleRender() {
|
|
@@ -97461,6 +97723,10 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97461
97723
|
logManager.dispose();
|
|
97462
97724
|
} catch {
|
|
97463
97725
|
}
|
|
97726
|
+
try {
|
|
97727
|
+
secondaryLogManager.dispose();
|
|
97728
|
+
} catch {
|
|
97729
|
+
}
|
|
97464
97730
|
try {
|
|
97465
97731
|
statsManager.dispose();
|
|
97466
97732
|
} catch {
|
|
@@ -97469,14 +97735,26 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97469
97735
|
composeLogManager.dispose();
|
|
97470
97736
|
} catch {
|
|
97471
97737
|
}
|
|
97738
|
+
try {
|
|
97739
|
+
secondaryComposeLogManager.dispose();
|
|
97740
|
+
} catch {
|
|
97741
|
+
}
|
|
97472
97742
|
try {
|
|
97473
97743
|
if (logFlushTimer) clearTimeout(logFlushTimer);
|
|
97474
97744
|
} catch {
|
|
97475
97745
|
}
|
|
97746
|
+
try {
|
|
97747
|
+
if (secondaryLogFlushTimer) clearTimeout(secondaryLogFlushTimer);
|
|
97748
|
+
} catch {
|
|
97749
|
+
}
|
|
97476
97750
|
try {
|
|
97477
97751
|
if (composeLogFlushTimer) clearTimeout(composeLogFlushTimer);
|
|
97478
97752
|
} catch {
|
|
97479
97753
|
}
|
|
97754
|
+
try {
|
|
97755
|
+
if (secondaryComposeLogFlushTimer) clearTimeout(secondaryComposeLogFlushTimer);
|
|
97756
|
+
} catch {
|
|
97757
|
+
}
|
|
97480
97758
|
try {
|
|
97481
97759
|
clearInterval(refreshInterval);
|
|
97482
97760
|
} catch {
|
|
@@ -97561,7 +97839,7 @@ async function logsAction(container, opts) {
|
|
|
97561
97839
|
|
|
97562
97840
|
// src/cli.ts
|
|
97563
97841
|
var program2 = new Command();
|
|
97564
|
-
program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.2.
|
|
97842
|
+
program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.2.3").option("--socket <path>", "Docker socket path").action(async (_opts, cmd) => {
|
|
97565
97843
|
await dashboardAction(_opts, cmd);
|
|
97566
97844
|
});
|
|
97567
97845
|
program2.command("ps").description("List containers").option("-a, --all", "Show all containers (default: running only)", false).action(async (opts) => {
|