sidekick-docker 0.1.4 → 0.1.5
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/sidekick-docker.mjs +298 -40
- package/package.json +1 -1
package/dist/sidekick-docker.mjs
CHANGED
|
@@ -39518,22 +39518,32 @@ var require_DockerClient = __commonJS({
|
|
|
39518
39518
|
}
|
|
39519
39519
|
async listContainers(all = true) {
|
|
39520
39520
|
const containers = await this.docker.listContainers({ all });
|
|
39521
|
-
return containers.map((c) =>
|
|
39522
|
-
|
|
39523
|
-
|
|
39524
|
-
|
|
39525
|
-
|
|
39526
|
-
|
|
39527
|
-
|
|
39528
|
-
|
|
39529
|
-
|
|
39530
|
-
|
|
39531
|
-
|
|
39532
|
-
|
|
39533
|
-
|
|
39534
|
-
|
|
39535
|
-
|
|
39536
|
-
|
|
39521
|
+
return containers.map((c) => {
|
|
39522
|
+
let healthStatus;
|
|
39523
|
+
if (/\(healthy\)/.test(c.Status))
|
|
39524
|
+
healthStatus = "healthy";
|
|
39525
|
+
else if (/\(unhealthy\)/.test(c.Status))
|
|
39526
|
+
healthStatus = "unhealthy";
|
|
39527
|
+
else if (/\(health: starting\)/.test(c.Status))
|
|
39528
|
+
healthStatus = "starting";
|
|
39529
|
+
return {
|
|
39530
|
+
id: c.Id,
|
|
39531
|
+
name: (c.Names[0] || "").replace(/^\//, ""),
|
|
39532
|
+
image: c.Image,
|
|
39533
|
+
state: c.State,
|
|
39534
|
+
status: c.Status,
|
|
39535
|
+
ports: (c.Ports || []).map((p) => ({
|
|
39536
|
+
hostIp: p.IP || "0.0.0.0",
|
|
39537
|
+
hostPort: p.PublicPort || 0,
|
|
39538
|
+
containerPort: p.PrivatePort,
|
|
39539
|
+
protocol: p.Type || "tcp"
|
|
39540
|
+
})),
|
|
39541
|
+
created: new Date(c.Created * 1e3),
|
|
39542
|
+
composeProject: c.Labels?.["com.docker.compose.project"],
|
|
39543
|
+
composeService: c.Labels?.["com.docker.compose.service"],
|
|
39544
|
+
healthStatus
|
|
39545
|
+
};
|
|
39546
|
+
});
|
|
39537
39547
|
}
|
|
39538
39548
|
async startContainer(id) {
|
|
39539
39549
|
await this.docker.getContainer(id).start();
|
|
@@ -39544,6 +39554,12 @@ var require_DockerClient = __commonJS({
|
|
|
39544
39554
|
async restartContainer(id) {
|
|
39545
39555
|
await this.docker.getContainer(id).restart();
|
|
39546
39556
|
}
|
|
39557
|
+
async pauseContainer(id) {
|
|
39558
|
+
await this.docker.getContainer(id).pause();
|
|
39559
|
+
}
|
|
39560
|
+
async unpauseContainer(id) {
|
|
39561
|
+
await this.docker.getContainer(id).unpause();
|
|
39562
|
+
}
|
|
39547
39563
|
async removeContainer(id, force = false) {
|
|
39548
39564
|
await this.docker.getContainer(id).remove({ force });
|
|
39549
39565
|
}
|
|
@@ -39605,6 +39621,7 @@ var require_DockerClient = __commonJS({
|
|
|
39605
39621
|
const memStats = raw.memory_stats;
|
|
39606
39622
|
const netStats = raw.networks;
|
|
39607
39623
|
const pidsStats = raw.pids_stats;
|
|
39624
|
+
const blkioStats = raw.blkio_stats;
|
|
39608
39625
|
const cpuUsage = cpuStats?.cpu_usage?.total_usage ?? 0;
|
|
39609
39626
|
const systemUsage = cpuStats?.system_cpu_usage ?? 0;
|
|
39610
39627
|
const numCpus = cpuStats?.cpu_usage?.percpu_usage?.length ?? cpuStats?.online_cpus ?? 1;
|
|
@@ -39622,6 +39639,18 @@ var require_DockerClient = __commonJS({
|
|
|
39622
39639
|
netTx += iface.tx_bytes ?? 0;
|
|
39623
39640
|
}
|
|
39624
39641
|
}
|
|
39642
|
+
let blockRead = 0;
|
|
39643
|
+
let blockWrite = 0;
|
|
39644
|
+
const ioServiceBytes = blkioStats?.io_service_bytes_recursive;
|
|
39645
|
+
if (ioServiceBytes) {
|
|
39646
|
+
for (const entry of ioServiceBytes) {
|
|
39647
|
+
const op = (entry.op || "").toLowerCase();
|
|
39648
|
+
if (op === "read")
|
|
39649
|
+
blockRead += entry.value ?? 0;
|
|
39650
|
+
else if (op === "write")
|
|
39651
|
+
blockWrite += entry.value ?? 0;
|
|
39652
|
+
}
|
|
39653
|
+
}
|
|
39625
39654
|
return {
|
|
39626
39655
|
stats: {
|
|
39627
39656
|
cpuPercent: Math.round(cpuPercent * 100) / 100,
|
|
@@ -39630,6 +39659,8 @@ var require_DockerClient = __commonJS({
|
|
|
39630
39659
|
memoryPercent: Math.round(memPercent * 100) / 100,
|
|
39631
39660
|
networkRx: netRx,
|
|
39632
39661
|
networkTx: netTx,
|
|
39662
|
+
blockRead,
|
|
39663
|
+
blockWrite,
|
|
39633
39664
|
pids: pidsStats?.current ?? 0,
|
|
39634
39665
|
timestamp: /* @__PURE__ */ new Date()
|
|
39635
39666
|
},
|
|
@@ -40131,6 +40162,36 @@ var require_StatsCollector = __commonJS({
|
|
|
40131
40162
|
return void 0;
|
|
40132
40163
|
return history.samples[history.samples.length - 1];
|
|
40133
40164
|
}
|
|
40165
|
+
getNetworkRxRateSeries(containerId) {
|
|
40166
|
+
return this.computeRateSeries(containerId, (s) => s.networkRx);
|
|
40167
|
+
}
|
|
40168
|
+
getNetworkTxRateSeries(containerId) {
|
|
40169
|
+
return this.computeRateSeries(containerId, (s) => s.networkTx);
|
|
40170
|
+
}
|
|
40171
|
+
getBlockReadRateSeries(containerId) {
|
|
40172
|
+
return this.computeRateSeries(containerId, (s) => s.blockRead);
|
|
40173
|
+
}
|
|
40174
|
+
getBlockWriteRateSeries(containerId) {
|
|
40175
|
+
return this.computeRateSeries(containerId, (s) => s.blockWrite);
|
|
40176
|
+
}
|
|
40177
|
+
computeRateSeries(containerId, extractor) {
|
|
40178
|
+
const history = this.histories.get(containerId);
|
|
40179
|
+
if (!history || history.samples.length < 2)
|
|
40180
|
+
return [];
|
|
40181
|
+
const rates = [];
|
|
40182
|
+
for (let i = 1; i < history.samples.length; i++) {
|
|
40183
|
+
const prev = history.samples[i - 1];
|
|
40184
|
+
const curr = history.samples[i];
|
|
40185
|
+
const dt = (curr.timestamp.getTime() - prev.timestamp.getTime()) / 1e3;
|
|
40186
|
+
if (dt > 0) {
|
|
40187
|
+
const delta = extractor(curr) - extractor(prev);
|
|
40188
|
+
rates.push(Math.max(0, delta / dt));
|
|
40189
|
+
} else {
|
|
40190
|
+
rates.push(0);
|
|
40191
|
+
}
|
|
40192
|
+
}
|
|
40193
|
+
return rates;
|
|
40194
|
+
}
|
|
40134
40195
|
remove(containerId) {
|
|
40135
40196
|
this.histories.delete(containerId);
|
|
40136
40197
|
}
|
|
@@ -78294,6 +78355,16 @@ function colorizeDetailKey(line) {
|
|
|
78294
78355
|
if (!match) return line;
|
|
78295
78356
|
return ansi.brand(match[1]) + line.substring(match[1].length);
|
|
78296
78357
|
}
|
|
78358
|
+
function colorizeHealth(status) {
|
|
78359
|
+
switch (status) {
|
|
78360
|
+
case "healthy":
|
|
78361
|
+
return ansi.green(status);
|
|
78362
|
+
case "unhealthy":
|
|
78363
|
+
return ansi.red(status);
|
|
78364
|
+
case "starting":
|
|
78365
|
+
return ansi.yellow(status);
|
|
78366
|
+
}
|
|
78367
|
+
}
|
|
78297
78368
|
function colorizeState(state) {
|
|
78298
78369
|
switch (state) {
|
|
78299
78370
|
case "running":
|
|
@@ -78417,7 +78488,22 @@ var ContainersPanel = class {
|
|
|
78417
78488
|
lines.push(` ${coloredSparkline(memSeries, "memory")}`);
|
|
78418
78489
|
}
|
|
78419
78490
|
lines.push(
|
|
78420
|
-
colorizeDetailKey(`Net: \u25BC ${(0, import_sidekick_docker_shared3.formatBytes)(latest.networkRx)} \u25B2 ${(0, import_sidekick_docker_shared3.formatBytes)(latest.networkTx)}`)
|
|
78491
|
+
colorizeDetailKey(`Net: \u25BC ${(0, import_sidekick_docker_shared3.formatBytes)(latest.networkRx)} \u25B2 ${(0, import_sidekick_docker_shared3.formatBytes)(latest.networkTx)}`)
|
|
78492
|
+
);
|
|
78493
|
+
const rxRates = metrics.statsCollector.getNetworkRxRateSeries(c.id);
|
|
78494
|
+
const txRates = metrics.statsCollector.getNetworkTxRateSeries(c.id);
|
|
78495
|
+
if (rxRates.length > 1) {
|
|
78496
|
+
lines.push(` \u25BC ${coloredSparkline(rxRates, "cpu")} \u25B2 ${coloredSparkline(txRates, "memory")}`);
|
|
78497
|
+
}
|
|
78498
|
+
lines.push(
|
|
78499
|
+
colorizeDetailKey(`IO: R ${(0, import_sidekick_docker_shared3.formatBytes)(latest.blockRead)} W ${(0, import_sidekick_docker_shared3.formatBytes)(latest.blockWrite)}`)
|
|
78500
|
+
);
|
|
78501
|
+
const brRates = metrics.statsCollector.getBlockReadRateSeries(c.id);
|
|
78502
|
+
const bwRates = metrics.statsCollector.getBlockWriteRateSeries(c.id);
|
|
78503
|
+
if (brRates.length > 1) {
|
|
78504
|
+
lines.push(` R ${coloredSparkline(brRates, "cpu")} W ${coloredSparkline(bwRates, "memory")}`);
|
|
78505
|
+
}
|
|
78506
|
+
lines.push(
|
|
78421
78507
|
colorizeDetailKey(`PIDs: ${latest.pids}`)
|
|
78422
78508
|
);
|
|
78423
78509
|
if (metrics.logSeverityTimeSeries.length > 1) {
|
|
@@ -78451,6 +78537,7 @@ var ContainersPanel = class {
|
|
|
78451
78537
|
sectionHeader("Status"),
|
|
78452
78538
|
colorizeDetailKey(` State: ${colorizeState(c.state)}`),
|
|
78453
78539
|
colorizeDetailKey(` Status: ${c.status}`),
|
|
78540
|
+
...c.healthStatus ? [colorizeDetailKey(` Health: ${colorizeHealth(c.healthStatus)}`)] : [],
|
|
78454
78541
|
colorizeDetailKey(` Created: ${c.created.toLocaleString()}`),
|
|
78455
78542
|
"",
|
|
78456
78543
|
sectionHeader("Network"),
|
|
@@ -78485,10 +78572,11 @@ var ContainersPanel = class {
|
|
|
78485
78572
|
return metrics.containers.map((c) => {
|
|
78486
78573
|
const uptime = compactUptime(c.status);
|
|
78487
78574
|
const portHint = c.state === "running" && c.ports.length > 0 ? `:${c.ports[0].hostPort || c.ports[0].containerPort}` : "";
|
|
78575
|
+
const healthBadge = c.healthStatus ? ` ${colorizeHealth(c.healthStatus)}` : "";
|
|
78488
78576
|
const namePart = portHint ? `${(0, import_sidekick_docker_shared3.truncate)(c.name, 34)} ${portHint}` : (0, import_sidekick_docker_shared3.truncate)(c.name, 38);
|
|
78489
78577
|
return {
|
|
78490
78578
|
id: c.id,
|
|
78491
|
-
label: `${(0, import_sidekick_docker_shared3.stateIcon)(c.state)} ${namePart}`,
|
|
78579
|
+
label: `${(0, import_sidekick_docker_shared3.stateIcon)(c.state)} ${namePart}${healthBadge}`,
|
|
78492
78580
|
sortKey: c.state === "running" ? 0 : 1,
|
|
78493
78581
|
data: c,
|
|
78494
78582
|
iconColor: (0, import_sidekick_docker_shared3.stateColor)(c.state),
|
|
@@ -78526,6 +78614,24 @@ var ContainersPanel = class {
|
|
|
78526
78614
|
},
|
|
78527
78615
|
condition: (item) => item.data.state === "running"
|
|
78528
78616
|
},
|
|
78617
|
+
{
|
|
78618
|
+
key: "p",
|
|
78619
|
+
label: "Pause",
|
|
78620
|
+
handler: (item) => {
|
|
78621
|
+
const c = item.data;
|
|
78622
|
+
this.client.pauseContainer(c.id).then(() => this.onAction()).catch((e) => this.onError(String(e)));
|
|
78623
|
+
},
|
|
78624
|
+
condition: (item) => item.data.state === "running"
|
|
78625
|
+
},
|
|
78626
|
+
{
|
|
78627
|
+
key: "u",
|
|
78628
|
+
label: "Unpause",
|
|
78629
|
+
handler: (item) => {
|
|
78630
|
+
const c = item.data;
|
|
78631
|
+
this.client.unpauseContainer(c.id).then(() => this.onAction()).catch((e) => this.onError(String(e)));
|
|
78632
|
+
},
|
|
78633
|
+
condition: (item) => item.data.state === "paused"
|
|
78634
|
+
},
|
|
78529
78635
|
{
|
|
78530
78636
|
key: "d",
|
|
78531
78637
|
label: "Remove",
|
|
@@ -79253,6 +79359,7 @@ function useWindowedScroll({ totalItems, viewportHeight }) {
|
|
|
79253
79359
|
|
|
79254
79360
|
// src/dashboard/ink/useKeyboardHandler.ts
|
|
79255
79361
|
await init_build2();
|
|
79362
|
+
var SORT_FIELDS = ["state", "name", "cpu", "mem", "net", "io", "pids"];
|
|
79256
79363
|
function executeAction(action, item, dispatch, addToast) {
|
|
79257
79364
|
if (action.confirm) {
|
|
79258
79365
|
dispatch({ type: "SET_CONFIRM", action: () => {
|
|
@@ -79376,6 +79483,32 @@ function useKeyboardHandler(ctx) {
|
|
|
79376
79483
|
}
|
|
79377
79484
|
return;
|
|
79378
79485
|
}
|
|
79486
|
+
if (state.overlay === "sort") {
|
|
79487
|
+
if (key.escape) {
|
|
79488
|
+
dispatch({ type: "SET_OVERLAY", overlay: null });
|
|
79489
|
+
return;
|
|
79490
|
+
}
|
|
79491
|
+
if (input === "j" || key.downArrow) {
|
|
79492
|
+
dispatch({ type: "SORT_MENU_NAV", delta: 1 });
|
|
79493
|
+
return;
|
|
79494
|
+
}
|
|
79495
|
+
if (input === "k" || key.upArrow) {
|
|
79496
|
+
dispatch({ type: "SORT_MENU_NAV", delta: -1 });
|
|
79497
|
+
return;
|
|
79498
|
+
}
|
|
79499
|
+
if (input === "R") {
|
|
79500
|
+
dispatch({ type: "TOGGLE_SORT_REVERSE" });
|
|
79501
|
+
addToast(`Sort: ${state.sortReversed ? "ascending" : "descending"}`, "info");
|
|
79502
|
+
return;
|
|
79503
|
+
}
|
|
79504
|
+
if (key.return) {
|
|
79505
|
+
const field = SORT_FIELDS[state.sortMenuIndex];
|
|
79506
|
+
dispatch({ type: "SET_SORT_FIELD", field });
|
|
79507
|
+
addToast(`Sort: ${field}`, "info");
|
|
79508
|
+
return;
|
|
79509
|
+
}
|
|
79510
|
+
return;
|
|
79511
|
+
}
|
|
79379
79512
|
if (key.escape) {
|
|
79380
79513
|
if (state.filterString) {
|
|
79381
79514
|
dispatch({ type: "SET_FILTER", value: "" });
|
|
@@ -79422,6 +79555,20 @@ function useKeyboardHandler(ctx) {
|
|
|
79422
79555
|
return;
|
|
79423
79556
|
}
|
|
79424
79557
|
}
|
|
79558
|
+
if (input === "a" && panel.id === "containers") {
|
|
79559
|
+
dispatch({ type: "TOGGLE_SHOW_ALL" });
|
|
79560
|
+
addToast(state.showAllContainers ? "Running only" : "Show all", "info");
|
|
79561
|
+
return;
|
|
79562
|
+
}
|
|
79563
|
+
if (input === "o" && panel.id === "containers") {
|
|
79564
|
+
dispatch({ type: "SET_OVERLAY", overlay: "sort" });
|
|
79565
|
+
return;
|
|
79566
|
+
}
|
|
79567
|
+
if (input === "R" && panel.id === "containers") {
|
|
79568
|
+
dispatch({ type: "TOGGLE_SORT_REVERSE" });
|
|
79569
|
+
addToast(`Sort: ${state.sortReversed ? "ascending" : "descending"}`, "info");
|
|
79570
|
+
return;
|
|
79571
|
+
}
|
|
79425
79572
|
if (input === "x") {
|
|
79426
79573
|
if (selectedItem && panelActions.length > 0) {
|
|
79427
79574
|
dispatch({ type: "SET_OVERLAY", overlay: "context-menu" });
|
|
@@ -79796,6 +79943,9 @@ var GLOBAL_BINDINGS = [
|
|
|
79796
79943
|
{ key: "z", label: "Cycle layout (Normal/Wide/Expanded)" },
|
|
79797
79944
|
{ key: "/", label: "Filter items" },
|
|
79798
79945
|
{ key: "x", label: "Actions menu" },
|
|
79946
|
+
{ key: "a", label: "Toggle all/running (Containers)" },
|
|
79947
|
+
{ key: "o", label: "Sort menu (Containers)" },
|
|
79948
|
+
{ key: "R", label: "Reverse sort (Containers)" },
|
|
79799
79949
|
{ key: "V", label: "Version info" },
|
|
79800
79950
|
{ key: "?", label: "This help" },
|
|
79801
79951
|
{ key: "q", label: "Quit" }
|
|
@@ -80134,6 +80284,52 @@ function VersionOverlay({ version: version2 }) {
|
|
|
80134
80284
|
] });
|
|
80135
80285
|
}
|
|
80136
80286
|
|
|
80287
|
+
// src/dashboard/ink/SortOverlay.tsx
|
|
80288
|
+
await init_build2();
|
|
80289
|
+
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
80290
|
+
var SORT_OPTIONS = [
|
|
80291
|
+
{ field: "state", label: "State (running first)" },
|
|
80292
|
+
{ field: "name", label: "Name" },
|
|
80293
|
+
{ field: "cpu", label: "CPU %" },
|
|
80294
|
+
{ field: "mem", label: "Memory %" },
|
|
80295
|
+
{ field: "net", label: "Network I/O" },
|
|
80296
|
+
{ field: "io", label: "Block I/O" },
|
|
80297
|
+
{ field: "pids", label: "PIDs" }
|
|
80298
|
+
];
|
|
80299
|
+
function SortOverlay({ selectedIndex, currentField, reversed }) {
|
|
80300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
80301
|
+
Box_default,
|
|
80302
|
+
{
|
|
80303
|
+
position: "absolute",
|
|
80304
|
+
marginTop: 2,
|
|
80305
|
+
marginLeft: 2,
|
|
80306
|
+
flexDirection: "column",
|
|
80307
|
+
borderStyle: "single",
|
|
80308
|
+
borderColor: "#2B4C7E",
|
|
80309
|
+
paddingX: 1,
|
|
80310
|
+
children: [
|
|
80311
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { bold: true, color: "#2B4C7E", children: "\u2195 Sort by" }),
|
|
80312
|
+
SORT_OPTIONS.map((opt, i) => {
|
|
80313
|
+
const isSelected = i === selectedIndex;
|
|
80314
|
+
const isCurrent = opt.field === currentField;
|
|
80315
|
+
const indicator = isCurrent ? reversed ? " \u25B2" : " \u25BC" : "";
|
|
80316
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
80317
|
+
Text,
|
|
80318
|
+
{
|
|
80319
|
+
color: isSelected ? "#2B4C7E" : isCurrent ? "yellow" : "white",
|
|
80320
|
+
bold: isSelected,
|
|
80321
|
+
inverse: isSelected,
|
|
80322
|
+
children: ` ${opt.label}${indicator} `
|
|
80323
|
+
}
|
|
80324
|
+
) }, opt.field);
|
|
80325
|
+
}),
|
|
80326
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { children: "" }),
|
|
80327
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text, { color: "gray", dimColor: true, children: "j/k select Enter apply R reverse Esc close" })
|
|
80328
|
+
]
|
|
80329
|
+
}
|
|
80330
|
+
);
|
|
80331
|
+
}
|
|
80332
|
+
|
|
80137
80333
|
// src/dashboard/ink/Dashboard.tsx
|
|
80138
80334
|
var import_sidekick_docker_shared12 = __toESM(require_dist(), 1);
|
|
80139
80335
|
|
|
@@ -80192,7 +80388,8 @@ var ExecManager = class {
|
|
|
80192
80388
|
};
|
|
80193
80389
|
|
|
80194
80390
|
// src/dashboard/ink/Dashboard.tsx
|
|
80195
|
-
var
|
|
80391
|
+
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
80392
|
+
var SORT_FIELDS2 = ["state", "name", "cpu", "mem", "net", "io", "pids"];
|
|
80196
80393
|
var SIDE_PANEL_WIDTH = 28;
|
|
80197
80394
|
var SIDE_PANEL_WIDTH_WIDE = 42;
|
|
80198
80395
|
var MIN_SCREEN_WIDTH = 60;
|
|
@@ -80279,6 +80476,16 @@ function reducer(state, action) {
|
|
|
80279
80476
|
return { ...state, logFilterString: action.value };
|
|
80280
80477
|
case "TOGGLE_LOG_FILTER_MODE":
|
|
80281
80478
|
return { ...state, logFilterMode: state.logFilterMode === "exact" ? "fuzzy" : "exact" };
|
|
80479
|
+
case "TOGGLE_SHOW_ALL":
|
|
80480
|
+
return { ...state, showAllContainers: !state.showAllContainers, selectedItemIndex: 0 };
|
|
80481
|
+
case "SET_SORT_FIELD":
|
|
80482
|
+
return { ...state, sortField: action.field, overlay: null };
|
|
80483
|
+
case "TOGGLE_SORT_REVERSE":
|
|
80484
|
+
return { ...state, sortReversed: !state.sortReversed };
|
|
80485
|
+
case "SORT_MENU_NAV": {
|
|
80486
|
+
const next = (state.sortMenuIndex + action.delta + SORT_FIELDS2.length) % SORT_FIELDS2.length;
|
|
80487
|
+
return { ...state, sortMenuIndex: next };
|
|
80488
|
+
}
|
|
80282
80489
|
default:
|
|
80283
80490
|
return state;
|
|
80284
80491
|
}
|
|
@@ -80300,7 +80507,11 @@ var initialState = {
|
|
|
80300
80507
|
execContainerId: null,
|
|
80301
80508
|
execContainerName: "",
|
|
80302
80509
|
logFilterString: "",
|
|
80303
|
-
logFilterMode: "exact"
|
|
80510
|
+
logFilterMode: "exact",
|
|
80511
|
+
showAllContainers: true,
|
|
80512
|
+
sortField: "state",
|
|
80513
|
+
sortReversed: false,
|
|
80514
|
+
sortMenuIndex: 0
|
|
80304
80515
|
};
|
|
80305
80516
|
function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecFallback }) {
|
|
80306
80517
|
const [state, dispatch] = (0, import_react36.useReducer)(reducer, initialState);
|
|
@@ -80391,6 +80602,12 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80391
80602
|
const totalItemCount = allItems.length;
|
|
80392
80603
|
const currentItems = (() => {
|
|
80393
80604
|
let items = allItems;
|
|
80605
|
+
if (panel.id === "containers" && !state.showAllContainers) {
|
|
80606
|
+
items = items.filter((it) => {
|
|
80607
|
+
const c = it.data;
|
|
80608
|
+
return c.state === "running" || c.state === "paused";
|
|
80609
|
+
});
|
|
80610
|
+
}
|
|
80394
80611
|
if (state.filterString) {
|
|
80395
80612
|
const f = state.filterString.toLowerCase();
|
|
80396
80613
|
items = items.filter((it) => {
|
|
@@ -80398,7 +80615,47 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80398
80615
|
return text.toLowerCase().includes(f);
|
|
80399
80616
|
});
|
|
80400
80617
|
}
|
|
80401
|
-
|
|
80618
|
+
if (panel.id === "containers" && state.sortField !== "state") {
|
|
80619
|
+
const dir = state.sortReversed ? -1 : 1;
|
|
80620
|
+
items.sort((a, b) => {
|
|
80621
|
+
const ca = a.data;
|
|
80622
|
+
const cb = b.data;
|
|
80623
|
+
switch (state.sortField) {
|
|
80624
|
+
case "name":
|
|
80625
|
+
return dir * ca.name.localeCompare(cb.name);
|
|
80626
|
+
case "cpu": {
|
|
80627
|
+
const sa = metrics.statsCollector.getLatest(ca.id)?.cpuPercent ?? 0;
|
|
80628
|
+
const sb = metrics.statsCollector.getLatest(cb.id)?.cpuPercent ?? 0;
|
|
80629
|
+
return dir * (sb - sa);
|
|
80630
|
+
}
|
|
80631
|
+
case "mem": {
|
|
80632
|
+
const sa = metrics.statsCollector.getLatest(ca.id)?.memoryPercent ?? 0;
|
|
80633
|
+
const sb = metrics.statsCollector.getLatest(cb.id)?.memoryPercent ?? 0;
|
|
80634
|
+
return dir * (sb - sa);
|
|
80635
|
+
}
|
|
80636
|
+
case "net": {
|
|
80637
|
+
const sa = metrics.statsCollector.getLatest(ca.id);
|
|
80638
|
+
const sb = metrics.statsCollector.getLatest(cb.id);
|
|
80639
|
+
return dir * ((sb?.networkRx ?? 0) + (sb?.networkTx ?? 0) - ((sa?.networkRx ?? 0) + (sa?.networkTx ?? 0)));
|
|
80640
|
+
}
|
|
80641
|
+
case "io": {
|
|
80642
|
+
const sa = metrics.statsCollector.getLatest(ca.id);
|
|
80643
|
+
const sb = metrics.statsCollector.getLatest(cb.id);
|
|
80644
|
+
return dir * ((sb?.blockRead ?? 0) + (sb?.blockWrite ?? 0) - ((sa?.blockRead ?? 0) + (sa?.blockWrite ?? 0)));
|
|
80645
|
+
}
|
|
80646
|
+
case "pids": {
|
|
80647
|
+
const sa = metrics.statsCollector.getLatest(ca.id)?.pids ?? 0;
|
|
80648
|
+
const sb = metrics.statsCollector.getLatest(cb.id)?.pids ?? 0;
|
|
80649
|
+
return dir * (sb - sa);
|
|
80650
|
+
}
|
|
80651
|
+
default:
|
|
80652
|
+
return a.sortKey - b.sortKey;
|
|
80653
|
+
}
|
|
80654
|
+
});
|
|
80655
|
+
} else {
|
|
80656
|
+
const dir = state.sortReversed ? -1 : 1;
|
|
80657
|
+
items.sort((a, b) => dir * (a.sortKey - b.sortKey));
|
|
80658
|
+
}
|
|
80402
80659
|
return items;
|
|
80403
80660
|
})();
|
|
80404
80661
|
const clampedSelection = Math.min(state.selectedItemIndex, Math.max(0, currentItems.length - 1));
|
|
@@ -80487,14 +80744,14 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80487
80744
|
rotatePhrase
|
|
80488
80745
|
});
|
|
80489
80746
|
if (tooSmall) {
|
|
80490
|
-
return /* @__PURE__ */ (0,
|
|
80747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooSmallOverlay, { columns, rows });
|
|
80491
80748
|
}
|
|
80492
80749
|
const showNormalLayout = state.overlay !== "help" && state.overlay !== "exec" && state.overlay !== "version";
|
|
80493
80750
|
const panelActionHints = applicableActions.map((a) => ({ key: a.key, label: a.label, destructive: !!a.confirm }));
|
|
80494
|
-
return /* @__PURE__ */ (0,
|
|
80495
|
-
showNormalLayout && /* @__PURE__ */ (0,
|
|
80496
|
-
showNormalLayout && /* @__PURE__ */ (0,
|
|
80497
|
-
sideWidth > 0 && /* @__PURE__ */ (0,
|
|
80751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MouseProvider, { onMouse: handleMouse, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexDirection: "column", height: rows, width: columns, children: [
|
|
80752
|
+
showNormalLayout && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TabBar, { panels, activeIndex: state.activePanelIndex, layoutMode: state.layoutMode, phrase, panelCounts }),
|
|
80753
|
+
showNormalLayout && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexGrow: 1, flexDirection: "row", children: [
|
|
80754
|
+
sideWidth > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80498
80755
|
SideList,
|
|
80499
80756
|
{
|
|
80500
80757
|
items: currentItems,
|
|
@@ -80510,9 +80767,9 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80510
80767
|
runningCount: panel.id === "containers" ? runningCount : void 0
|
|
80511
80768
|
}
|
|
80512
80769
|
),
|
|
80513
|
-
/* @__PURE__ */ (0,
|
|
80514
|
-
/* @__PURE__ */ (0,
|
|
80515
|
-
/* @__PURE__ */ (0,
|
|
80770
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
80771
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DetailTabBar, { tabs: detailTabs, activeIndex: state.detailTabIndex }),
|
|
80772
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80516
80773
|
DetailPane,
|
|
80517
80774
|
{
|
|
80518
80775
|
content: detailContent,
|
|
@@ -80523,16 +80780,16 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80523
80780
|
)
|
|
80524
80781
|
] })
|
|
80525
80782
|
] }),
|
|
80526
|
-
state.overlay === "help" && /* @__PURE__ */ (0,
|
|
80527
|
-
state.overlay === "version" && /* @__PURE__ */ (0,
|
|
80528
|
-
state.overlay === "exec" && /* @__PURE__ */ (0,
|
|
80783
|
+
state.overlay === "help" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(HelpOverlay, { panels, activePanelIndex: state.activePanelIndex, version: "0.1.5" }),
|
|
80784
|
+
state.overlay === "version" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(VersionOverlay, { version: "0.1.5" }),
|
|
80785
|
+
state.overlay === "exec" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80529
80786
|
ExecOverlay,
|
|
80530
80787
|
{
|
|
80531
80788
|
containerName: state.execContainerName,
|
|
80532
80789
|
outputLines: state.execOutputLines
|
|
80533
80790
|
}
|
|
80534
80791
|
),
|
|
80535
|
-
state.overlay !== "exec" && /* @__PURE__ */ (0,
|
|
80792
|
+
state.overlay !== "exec" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80536
80793
|
StatusBar,
|
|
80537
80794
|
{
|
|
80538
80795
|
daemonConnected: metrics.daemonConnected,
|
|
@@ -80541,14 +80798,14 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80541
80798
|
filterString: state.filterString,
|
|
80542
80799
|
containerCount: metrics.containers.length,
|
|
80543
80800
|
runningCount,
|
|
80544
|
-
version: "0.1.
|
|
80801
|
+
version: "0.1.5",
|
|
80545
80802
|
matchCount: state.filterString ? currentItems.length : void 0,
|
|
80546
80803
|
totalCount: state.filterString ? totalItemCount : void 0,
|
|
80547
80804
|
lastRefresh: metrics.lastRefresh
|
|
80548
80805
|
}
|
|
80549
80806
|
),
|
|
80550
|
-
state.overlay === "context-menu" && /* @__PURE__ */ (0,
|
|
80551
|
-
state.overlay === "filter" && /* @__PURE__ */ (0,
|
|
80807
|
+
state.overlay === "context-menu" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ContextMenuOverlay, { actions: contextActions, selectedIndex: state.contextMenuIndex }),
|
|
80808
|
+
state.overlay === "filter" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80552
80809
|
FilterOverlay,
|
|
80553
80810
|
{
|
|
80554
80811
|
filterString: state.filterString,
|
|
@@ -80557,14 +80814,15 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80557
80814
|
panelTitle: panel.title
|
|
80558
80815
|
}
|
|
80559
80816
|
),
|
|
80560
|
-
state.overlay === "log-filter" && /* @__PURE__ */ (0,
|
|
80817
|
+
state.overlay === "log-filter" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80561
80818
|
LogFilterOverlay,
|
|
80562
80819
|
{
|
|
80563
80820
|
filterString: state.logFilterString,
|
|
80564
80821
|
filterMode: state.logFilterMode
|
|
80565
80822
|
}
|
|
80566
80823
|
),
|
|
80567
|
-
state.overlay === "
|
|
80824
|
+
state.overlay === "sort" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SortOverlay, { selectedIndex: state.sortMenuIndex, currentField: state.sortField, reversed: state.sortReversed }),
|
|
80825
|
+
state.overlay === "confirm" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80568
80826
|
ConfirmOverlay,
|
|
80569
80827
|
{
|
|
80570
80828
|
message: state.confirmMessage,
|
|
@@ -80575,7 +80833,7 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80575
80833
|
onCancel: () => dispatch({ type: "SET_CONFIRM", action: null, message: "" })
|
|
80576
80834
|
}
|
|
80577
80835
|
),
|
|
80578
|
-
state.toasts.length > 0 && /* @__PURE__ */ (0,
|
|
80836
|
+
state.toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ToastNotification, { toast: state.toasts[state.toasts.length - 1] })
|
|
80579
80837
|
] }) });
|
|
80580
80838
|
}
|
|
80581
80839
|
|
|
@@ -80826,7 +81084,7 @@ async function logsAction(container, opts) {
|
|
|
80826
81084
|
|
|
80827
81085
|
// src/cli.ts
|
|
80828
81086
|
var program2 = new Command();
|
|
80829
|
-
program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.1.
|
|
81087
|
+
program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.1.5").option("--socket <path>", "Docker socket path").action(async (_opts, cmd) => {
|
|
80830
81088
|
await dashboardAction(_opts, cmd);
|
|
80831
81089
|
});
|
|
80832
81090
|
program2.command("ps").description("List containers").option("-a, --all", "Show all containers (default: running only)", false).action(async (opts) => {
|