sidekick-docker 0.1.3 → 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 +366 -55
- 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
|
}
|
|
@@ -77965,6 +78026,29 @@ var import_react37 = __toESM(require_react(), 1);
|
|
|
77965
78026
|
var import_sidekick_docker_shared13 = __toESM(require_dist(), 1);
|
|
77966
78027
|
import { spawnSync } from "child_process";
|
|
77967
78028
|
|
|
78029
|
+
// src/utils/clipboard.ts
|
|
78030
|
+
import { execSync } from "child_process";
|
|
78031
|
+
function copyToClipboard(text) {
|
|
78032
|
+
try {
|
|
78033
|
+
if (process.platform === "darwin") {
|
|
78034
|
+
execSync("pbcopy", { input: text });
|
|
78035
|
+
} else {
|
|
78036
|
+
try {
|
|
78037
|
+
execSync("xclip -selection clipboard", { input: text });
|
|
78038
|
+
} catch {
|
|
78039
|
+
try {
|
|
78040
|
+
execSync("xsel --clipboard --input", { input: text });
|
|
78041
|
+
} catch {
|
|
78042
|
+
execSync("wl-copy", { input: text });
|
|
78043
|
+
}
|
|
78044
|
+
}
|
|
78045
|
+
}
|
|
78046
|
+
return true;
|
|
78047
|
+
} catch {
|
|
78048
|
+
return false;
|
|
78049
|
+
}
|
|
78050
|
+
}
|
|
78051
|
+
|
|
77968
78052
|
// src/dashboard/DockerState.ts
|
|
77969
78053
|
var import_sidekick_docker_shared = __toESM(require_dist(), 1);
|
|
77970
78054
|
var DockerState = class {
|
|
@@ -78271,6 +78355,16 @@ function colorizeDetailKey(line) {
|
|
|
78271
78355
|
if (!match) return line;
|
|
78272
78356
|
return ansi.brand(match[1]) + line.substring(match[1].length);
|
|
78273
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
|
+
}
|
|
78274
78368
|
function colorizeState(state) {
|
|
78275
78369
|
switch (state) {
|
|
78276
78370
|
case "running":
|
|
@@ -78316,6 +78410,8 @@ var ContainersPanel = class {
|
|
|
78316
78410
|
onAction;
|
|
78317
78411
|
onError;
|
|
78318
78412
|
onExec;
|
|
78413
|
+
onCopyLogs;
|
|
78414
|
+
lastMetrics = null;
|
|
78319
78415
|
constructor(client, onAction, onError) {
|
|
78320
78416
|
this.client = client;
|
|
78321
78417
|
this.onAction = onAction;
|
|
@@ -78324,6 +78420,9 @@ var ContainersPanel = class {
|
|
|
78324
78420
|
setOnExec(handler) {
|
|
78325
78421
|
this.onExec = handler;
|
|
78326
78422
|
}
|
|
78423
|
+
setOnCopyLogs(handler) {
|
|
78424
|
+
this.onCopyLogs = handler;
|
|
78425
|
+
}
|
|
78327
78426
|
detailTabs = [
|
|
78328
78427
|
{
|
|
78329
78428
|
label: "Logs",
|
|
@@ -78389,7 +78488,22 @@ var ContainersPanel = class {
|
|
|
78389
78488
|
lines.push(` ${coloredSparkline(memSeries, "memory")}`);
|
|
78390
78489
|
}
|
|
78391
78490
|
lines.push(
|
|
78392
|
-
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(
|
|
78393
78507
|
colorizeDetailKey(`PIDs: ${latest.pids}`)
|
|
78394
78508
|
);
|
|
78395
78509
|
if (metrics.logSeverityTimeSeries.length > 1) {
|
|
@@ -78423,6 +78537,7 @@ var ContainersPanel = class {
|
|
|
78423
78537
|
sectionHeader("Status"),
|
|
78424
78538
|
colorizeDetailKey(` State: ${colorizeState(c.state)}`),
|
|
78425
78539
|
colorizeDetailKey(` Status: ${c.status}`),
|
|
78540
|
+
...c.healthStatus ? [colorizeDetailKey(` Health: ${colorizeHealth(c.healthStatus)}`)] : [],
|
|
78426
78541
|
colorizeDetailKey(` Created: ${c.created.toLocaleString()}`),
|
|
78427
78542
|
"",
|
|
78428
78543
|
sectionHeader("Network"),
|
|
@@ -78453,13 +78568,15 @@ var ContainersPanel = class {
|
|
|
78453
78568
|
}
|
|
78454
78569
|
];
|
|
78455
78570
|
getItems(metrics) {
|
|
78571
|
+
this.lastMetrics = metrics;
|
|
78456
78572
|
return metrics.containers.map((c) => {
|
|
78457
78573
|
const uptime = compactUptime(c.status);
|
|
78458
78574
|
const portHint = c.state === "running" && c.ports.length > 0 ? `:${c.ports[0].hostPort || c.ports[0].containerPort}` : "";
|
|
78459
|
-
const
|
|
78575
|
+
const healthBadge = c.healthStatus ? ` ${colorizeHealth(c.healthStatus)}` : "";
|
|
78576
|
+
const namePart = portHint ? `${(0, import_sidekick_docker_shared3.truncate)(c.name, 34)} ${portHint}` : (0, import_sidekick_docker_shared3.truncate)(c.name, 38);
|
|
78460
78577
|
return {
|
|
78461
78578
|
id: c.id,
|
|
78462
|
-
label: `${(0, import_sidekick_docker_shared3.stateIcon)(c.state)} ${namePart}`,
|
|
78579
|
+
label: `${(0, import_sidekick_docker_shared3.stateIcon)(c.state)} ${namePart}${healthBadge}`,
|
|
78463
78580
|
sortKey: c.state === "running" ? 0 : 1,
|
|
78464
78581
|
data: c,
|
|
78465
78582
|
iconColor: (0, import_sidekick_docker_shared3.stateColor)(c.state),
|
|
@@ -78497,6 +78614,24 @@ var ContainersPanel = class {
|
|
|
78497
78614
|
},
|
|
78498
78615
|
condition: (item) => item.data.state === "running"
|
|
78499
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
|
+
},
|
|
78500
78635
|
{
|
|
78501
78636
|
key: "d",
|
|
78502
78637
|
label: "Remove",
|
|
@@ -78515,6 +78650,23 @@ var ContainersPanel = class {
|
|
|
78515
78650
|
this.onExec?.(c.id);
|
|
78516
78651
|
},
|
|
78517
78652
|
condition: (item) => item.data.state === "running"
|
|
78653
|
+
},
|
|
78654
|
+
{
|
|
78655
|
+
key: "c",
|
|
78656
|
+
label: "Copy Logs",
|
|
78657
|
+
handler: () => {
|
|
78658
|
+
if (!this.lastMetrics || !this.onCopyLogs) return;
|
|
78659
|
+
const logs = this.lastMetrics.selectedContainerLogs;
|
|
78660
|
+
const query = this.lastMetrics.logFilterString;
|
|
78661
|
+
const mode = this.lastMetrics.logFilterMode;
|
|
78662
|
+
let lines;
|
|
78663
|
+
if (query) {
|
|
78664
|
+
lines = logs.filter((l) => (0, import_sidekick_docker_shared4.filterLine)(l.message, query, mode).matched).map((l) => l.message);
|
|
78665
|
+
} else {
|
|
78666
|
+
lines = logs.map((l) => l.message);
|
|
78667
|
+
}
|
|
78668
|
+
this.onCopyLogs(lines.join("\n"));
|
|
78669
|
+
}
|
|
78518
78670
|
}
|
|
78519
78671
|
];
|
|
78520
78672
|
}
|
|
@@ -78600,7 +78752,7 @@ var ServicesPanel = class {
|
|
|
78600
78752
|
const icon = (0, import_sidekick_docker_shared3.stateIcon)(service.state);
|
|
78601
78753
|
items.push({
|
|
78602
78754
|
id: `service:${project.name}:${service.name}`,
|
|
78603
|
-
label: ` ${icon} ${(0, import_sidekick_docker_shared3.truncate)(service.name,
|
|
78755
|
+
label: ` ${icon} ${(0, import_sidekick_docker_shared3.truncate)(service.name, 36)}`,
|
|
78604
78756
|
sortKey: sortKey++,
|
|
78605
78757
|
data: { type: "service", service },
|
|
78606
78758
|
iconColor: (0, import_sidekick_docker_shared3.stateColor)(service.state)
|
|
@@ -78709,7 +78861,7 @@ var ImagesPanel = class {
|
|
|
78709
78861
|
const icon = img.isDangling ? "\u25CB" : "\u25CF";
|
|
78710
78862
|
return {
|
|
78711
78863
|
id: img.id,
|
|
78712
|
-
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(tag,
|
|
78864
|
+
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(tag, 38)}`,
|
|
78713
78865
|
sortKey: img.isDangling ? 1 : 0,
|
|
78714
78866
|
data: img,
|
|
78715
78867
|
iconColor: img.isDangling ? "gray" : "#2B4C7E",
|
|
@@ -78780,7 +78932,7 @@ var VolumesPanel = class {
|
|
|
78780
78932
|
const icon = vol.isInUse ? "\u25CF" : "\u25CB";
|
|
78781
78933
|
return {
|
|
78782
78934
|
id: vol.name,
|
|
78783
|
-
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(vol.name,
|
|
78935
|
+
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(vol.name, 38)}`,
|
|
78784
78936
|
sortKey: vol.isInUse ? 0 : 1,
|
|
78785
78937
|
data: vol,
|
|
78786
78938
|
iconColor: vol.isInUse ? "green" : "gray",
|
|
@@ -78862,7 +79014,7 @@ var NetworksPanel = class {
|
|
|
78862
79014
|
const countLabel = net.containers.length > 0 ? `${net.containers.length}` : "";
|
|
78863
79015
|
return {
|
|
78864
79016
|
id: net.id,
|
|
78865
|
-
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(net.name,
|
|
79017
|
+
label: `${icon} ${(0, import_sidekick_docker_shared3.truncate)(net.name, 38)}`,
|
|
78866
79018
|
sortKey: net.isDefault ? 0 : 1,
|
|
78867
79019
|
data: net,
|
|
78868
79020
|
iconColor: net.isDefault ? "#2B4C7E" : "gray",
|
|
@@ -79207,6 +79359,7 @@ function useWindowedScroll({ totalItems, viewportHeight }) {
|
|
|
79207
79359
|
|
|
79208
79360
|
// src/dashboard/ink/useKeyboardHandler.ts
|
|
79209
79361
|
await init_build2();
|
|
79362
|
+
var SORT_FIELDS = ["state", "name", "cpu", "mem", "net", "io", "pids"];
|
|
79210
79363
|
function executeAction(action, item, dispatch, addToast) {
|
|
79211
79364
|
if (action.confirm) {
|
|
79212
79365
|
dispatch({ type: "SET_CONFIRM", action: () => {
|
|
@@ -79330,6 +79483,32 @@ function useKeyboardHandler(ctx) {
|
|
|
79330
79483
|
}
|
|
79331
79484
|
return;
|
|
79332
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
|
+
}
|
|
79333
79512
|
if (key.escape) {
|
|
79334
79513
|
if (state.filterString) {
|
|
79335
79514
|
dispatch({ type: "SET_FILTER", value: "" });
|
|
@@ -79362,7 +79541,8 @@ function useKeyboardHandler(ctx) {
|
|
|
79362
79541
|
}
|
|
79363
79542
|
if (input === "z") {
|
|
79364
79543
|
dispatch({ type: "CYCLE_LAYOUT" });
|
|
79365
|
-
|
|
79544
|
+
const nextMode = state.layoutMode === "normal" ? "Wide" : state.layoutMode === "wide" ? "Expanded" : "Normal";
|
|
79545
|
+
addToast(`Layout: ${nextMode}`, "info");
|
|
79366
79546
|
return;
|
|
79367
79547
|
}
|
|
79368
79548
|
if (input === "/") {
|
|
@@ -79375,6 +79555,20 @@ function useKeyboardHandler(ctx) {
|
|
|
79375
79555
|
return;
|
|
79376
79556
|
}
|
|
79377
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
|
+
}
|
|
79378
79572
|
if (input === "x") {
|
|
79379
79573
|
if (selectedItem && panelActions.length > 0) {
|
|
79380
79574
|
dispatch({ type: "SET_OVERLAY", overlay: "context-menu" });
|
|
@@ -79573,7 +79767,7 @@ function TabBar({ panels, activeIndex, layoutMode, phrase, panelCounts }) {
|
|
|
79573
79767
|
] }, panel.id);
|
|
79574
79768
|
}),
|
|
79575
79769
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box_default, { flexGrow: 1, marginLeft: 1, children: phrase && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: "gray", wrap: "truncate", children: phrase }) }),
|
|
79576
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: layoutMode
|
|
79770
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { color: layoutMode !== "normal" ? "#2B4C7E" : "gray", children: `z: ${layoutMode === "expanded" ? "Expanded" : layoutMode === "wide" ? "Wide" : "Normal"} \u25B8` })
|
|
79577
79771
|
] });
|
|
79578
79772
|
}
|
|
79579
79773
|
|
|
@@ -79746,9 +79940,12 @@ var GLOBAL_BINDINGS = [
|
|
|
79746
79940
|
{ key: "g/G", label: "Jump to first / last" },
|
|
79747
79941
|
{ key: "Tab", label: "Toggle focus" },
|
|
79748
79942
|
{ key: "[/]", label: "Cycle detail tabs" },
|
|
79749
|
-
{ key: "z", label: "
|
|
79943
|
+
{ key: "z", label: "Cycle layout (Normal/Wide/Expanded)" },
|
|
79750
79944
|
{ key: "/", label: "Filter items" },
|
|
79751
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)" },
|
|
79752
79949
|
{ key: "V", label: "Version info" },
|
|
79753
79950
|
{ key: "?", label: "This help" },
|
|
79754
79951
|
{ key: "q", label: "Quit" }
|
|
@@ -80087,6 +80284,52 @@ function VersionOverlay({ version: version2 }) {
|
|
|
80087
80284
|
] });
|
|
80088
80285
|
}
|
|
80089
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
|
+
|
|
80090
80333
|
// src/dashboard/ink/Dashboard.tsx
|
|
80091
80334
|
var import_sidekick_docker_shared12 = __toESM(require_dist(), 1);
|
|
80092
80335
|
|
|
@@ -80145,8 +80388,10 @@ var ExecManager = class {
|
|
|
80145
80388
|
};
|
|
80146
80389
|
|
|
80147
80390
|
// src/dashboard/ink/Dashboard.tsx
|
|
80148
|
-
var
|
|
80391
|
+
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
80392
|
+
var SORT_FIELDS2 = ["state", "name", "cpu", "mem", "net", "io", "pids"];
|
|
80149
80393
|
var SIDE_PANEL_WIDTH = 28;
|
|
80394
|
+
var SIDE_PANEL_WIDTH_WIDE = 42;
|
|
80150
80395
|
var MIN_SCREEN_WIDTH = 60;
|
|
80151
80396
|
var MIN_SCREEN_HEIGHT = 15;
|
|
80152
80397
|
var RESERVED_UI_ROWS = 5;
|
|
@@ -80174,7 +80419,7 @@ function reducer(state, action) {
|
|
|
80174
80419
|
return { ...state, detailTabIndex: next, detailScrollOffset: 0 };
|
|
80175
80420
|
}
|
|
80176
80421
|
case "CYCLE_LAYOUT": {
|
|
80177
|
-
const next = state.layoutMode === "normal" ? "expanded" : "normal";
|
|
80422
|
+
const next = state.layoutMode === "normal" ? "wide" : state.layoutMode === "wide" ? "expanded" : "normal";
|
|
80178
80423
|
return { ...state, layoutMode: next, focusTarget: next === "expanded" ? "detail" : state.focusTarget };
|
|
80179
80424
|
}
|
|
80180
80425
|
case "TOGGLE_FOCUS":
|
|
@@ -80231,6 +80476,16 @@ function reducer(state, action) {
|
|
|
80231
80476
|
return { ...state, logFilterString: action.value };
|
|
80232
80477
|
case "TOGGLE_LOG_FILTER_MODE":
|
|
80233
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
|
+
}
|
|
80234
80489
|
default:
|
|
80235
80490
|
return state;
|
|
80236
80491
|
}
|
|
@@ -80252,7 +80507,11 @@ var initialState = {
|
|
|
80252
80507
|
execContainerId: null,
|
|
80253
80508
|
execContainerName: "",
|
|
80254
80509
|
logFilterString: "",
|
|
80255
|
-
logFilterMode: "exact"
|
|
80510
|
+
logFilterMode: "exact",
|
|
80511
|
+
showAllContainers: true,
|
|
80512
|
+
sortField: "state",
|
|
80513
|
+
sortReversed: false,
|
|
80514
|
+
sortMenuIndex: 0
|
|
80256
80515
|
};
|
|
80257
80516
|
function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecFallback }) {
|
|
80258
80517
|
const [state, dispatch] = (0, import_react36.useReducer)(reducer, initialState);
|
|
@@ -80261,17 +80520,19 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80261
80520
|
const execManagerRef = (0, import_react36.useRef)(null);
|
|
80262
80521
|
const [phrase, setPhrase] = import_react36.default.useState(() => (0, import_sidekick_docker_shared12.getRandomPhrase)());
|
|
80263
80522
|
const phraseTimerRef = (0, import_react36.useRef)(null);
|
|
80264
|
-
const
|
|
80523
|
+
const rotatePhraseRef = (0, import_react36.useRef)(void 0);
|
|
80524
|
+
rotatePhraseRef.current = () => {
|
|
80265
80525
|
setPhrase((0, import_sidekick_docker_shared12.getRandomPhrase)());
|
|
80266
80526
|
if (phraseTimerRef.current) clearTimeout(phraseTimerRef.current);
|
|
80267
|
-
phraseTimerRef.current = setTimeout(
|
|
80268
|
-
}
|
|
80527
|
+
phraseTimerRef.current = setTimeout(() => rotatePhraseRef.current?.(), 7e3);
|
|
80528
|
+
};
|
|
80529
|
+
const rotatePhrase = (0, import_react36.useCallback)(() => rotatePhraseRef.current?.(), []);
|
|
80269
80530
|
(0, import_react36.useEffect)(() => {
|
|
80270
|
-
phraseTimerRef.current = setTimeout(
|
|
80531
|
+
phraseTimerRef.current = setTimeout(() => rotatePhraseRef.current?.(), 7e3);
|
|
80271
80532
|
return () => {
|
|
80272
80533
|
if (phraseTimerRef.current) clearTimeout(phraseTimerRef.current);
|
|
80273
80534
|
};
|
|
80274
|
-
}, [
|
|
80535
|
+
}, []);
|
|
80275
80536
|
(0, import_react36.useEffect)(() => {
|
|
80276
80537
|
if (!execTriggerRef) return;
|
|
80277
80538
|
execTriggerRef.current = (containerId, containerName) => {
|
|
@@ -80336,11 +80597,17 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80336
80597
|
}, []);
|
|
80337
80598
|
const panel = panels[state.activePanelIndex];
|
|
80338
80599
|
const tooSmall = columns < MIN_SCREEN_WIDTH || rows < MIN_SCREEN_HEIGHT;
|
|
80339
|
-
const sideWidth = state.layoutMode === "expanded" ? 0 : SIDE_PANEL_WIDTH;
|
|
80600
|
+
const sideWidth = state.layoutMode === "expanded" ? 0 : state.layoutMode === "wide" ? SIDE_PANEL_WIDTH_WIDE : SIDE_PANEL_WIDTH;
|
|
80340
80601
|
const allItems = panel.getItems(metrics);
|
|
80341
80602
|
const totalItemCount = allItems.length;
|
|
80342
80603
|
const currentItems = (() => {
|
|
80343
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
|
+
}
|
|
80344
80611
|
if (state.filterString) {
|
|
80345
80612
|
const f = state.filterString.toLowerCase();
|
|
80346
80613
|
items = items.filter((it) => {
|
|
@@ -80348,7 +80615,47 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80348
80615
|
return text.toLowerCase().includes(f);
|
|
80349
80616
|
});
|
|
80350
80617
|
}
|
|
80351
|
-
|
|
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
|
+
}
|
|
80352
80659
|
return items;
|
|
80353
80660
|
})();
|
|
80354
80661
|
const clampedSelection = Math.min(state.selectedItemIndex, Math.max(0, currentItems.length - 1));
|
|
@@ -80437,14 +80744,14 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80437
80744
|
rotatePhrase
|
|
80438
80745
|
});
|
|
80439
80746
|
if (tooSmall) {
|
|
80440
|
-
return /* @__PURE__ */ (0,
|
|
80747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooSmallOverlay, { columns, rows });
|
|
80441
80748
|
}
|
|
80442
80749
|
const showNormalLayout = state.overlay !== "help" && state.overlay !== "exec" && state.overlay !== "version";
|
|
80443
80750
|
const panelActionHints = applicableActions.map((a) => ({ key: a.key, label: a.label, destructive: !!a.confirm }));
|
|
80444
|
-
return /* @__PURE__ */ (0,
|
|
80445
|
-
showNormalLayout && /* @__PURE__ */ (0,
|
|
80446
|
-
showNormalLayout && /* @__PURE__ */ (0,
|
|
80447
|
-
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)(
|
|
80448
80755
|
SideList,
|
|
80449
80756
|
{
|
|
80450
80757
|
items: currentItems,
|
|
@@ -80460,9 +80767,9 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80460
80767
|
runningCount: panel.id === "containers" ? runningCount : void 0
|
|
80461
80768
|
}
|
|
80462
80769
|
),
|
|
80463
|
-
/* @__PURE__ */ (0,
|
|
80464
|
-
/* @__PURE__ */ (0,
|
|
80465
|
-
/* @__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)(
|
|
80466
80773
|
DetailPane,
|
|
80467
80774
|
{
|
|
80468
80775
|
content: detailContent,
|
|
@@ -80473,16 +80780,16 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80473
80780
|
)
|
|
80474
80781
|
] })
|
|
80475
80782
|
] }),
|
|
80476
|
-
state.overlay === "help" && /* @__PURE__ */ (0,
|
|
80477
|
-
state.overlay === "version" && /* @__PURE__ */ (0,
|
|
80478
|
-
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)(
|
|
80479
80786
|
ExecOverlay,
|
|
80480
80787
|
{
|
|
80481
80788
|
containerName: state.execContainerName,
|
|
80482
80789
|
outputLines: state.execOutputLines
|
|
80483
80790
|
}
|
|
80484
80791
|
),
|
|
80485
|
-
state.overlay !== "exec" && /* @__PURE__ */ (0,
|
|
80792
|
+
state.overlay !== "exec" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80486
80793
|
StatusBar,
|
|
80487
80794
|
{
|
|
80488
80795
|
daemonConnected: metrics.daemonConnected,
|
|
@@ -80491,14 +80798,14 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80491
80798
|
filterString: state.filterString,
|
|
80492
80799
|
containerCount: metrics.containers.length,
|
|
80493
80800
|
runningCount,
|
|
80494
|
-
version: "0.1.
|
|
80801
|
+
version: "0.1.5",
|
|
80495
80802
|
matchCount: state.filterString ? currentItems.length : void 0,
|
|
80496
80803
|
totalCount: state.filterString ? totalItemCount : void 0,
|
|
80497
80804
|
lastRefresh: metrics.lastRefresh
|
|
80498
80805
|
}
|
|
80499
80806
|
),
|
|
80500
|
-
state.overlay === "context-menu" && /* @__PURE__ */ (0,
|
|
80501
|
-
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)(
|
|
80502
80809
|
FilterOverlay,
|
|
80503
80810
|
{
|
|
80504
80811
|
filterString: state.filterString,
|
|
@@ -80507,14 +80814,15 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80507
80814
|
panelTitle: panel.title
|
|
80508
80815
|
}
|
|
80509
80816
|
),
|
|
80510
|
-
state.overlay === "log-filter" && /* @__PURE__ */ (0,
|
|
80817
|
+
state.overlay === "log-filter" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
80511
80818
|
LogFilterOverlay,
|
|
80512
80819
|
{
|
|
80513
80820
|
filterString: state.logFilterString,
|
|
80514
80821
|
filterMode: state.logFilterMode
|
|
80515
80822
|
}
|
|
80516
80823
|
),
|
|
80517
|
-
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)(
|
|
80518
80826
|
ConfirmOverlay,
|
|
80519
80827
|
{
|
|
80520
80828
|
message: state.confirmMessage,
|
|
@@ -80525,7 +80833,7 @@ function Dashboard({ panels, metrics, onSelectionChange, execTriggerRef, onExecF
|
|
|
80525
80833
|
onCancel: () => dispatch({ type: "SET_CONFIRM", action: null, message: "" })
|
|
80526
80834
|
}
|
|
80527
80835
|
),
|
|
80528
|
-
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] })
|
|
80529
80837
|
] }) });
|
|
80530
80838
|
}
|
|
80531
80839
|
|
|
@@ -80650,6 +80958,9 @@ async function dashboardAction(_opts, cmd) {
|
|
|
80650
80958
|
onExecFallback(containerId);
|
|
80651
80959
|
}
|
|
80652
80960
|
});
|
|
80961
|
+
containersPanel.setOnCopyLogs((text) => {
|
|
80962
|
+
copyToClipboard(text);
|
|
80963
|
+
});
|
|
80653
80964
|
let renderTimer = null;
|
|
80654
80965
|
function getEnrichedMetrics() {
|
|
80655
80966
|
const m = state.getMetrics();
|
|
@@ -80773,7 +81084,7 @@ async function logsAction(container, opts) {
|
|
|
80773
81084
|
|
|
80774
81085
|
// src/cli.ts
|
|
80775
81086
|
var program2 = new Command();
|
|
80776
|
-
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) => {
|
|
80777
81088
|
await dashboardAction(_opts, cmd);
|
|
80778
81089
|
});
|
|
80779
81090
|
program2.command("ps").description("List containers").option("-a, --all", "Show all containers (default: running only)", false).action(async (opts) => {
|