dockza.app 0.2.0
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/LICENSE +22 -0
- package/NOTICE +69 -0
- package/README.md +203 -0
- package/dist/cli.js +33 -0
- package/dist/docker/client.js +76 -0
- package/dist/docker/containers.js +180 -0
- package/dist/docker/images.js +41 -0
- package/dist/docker/networks.js +66 -0
- package/dist/docker/volumes.js +44 -0
- package/dist/models/docker.js +2 -0
- package/dist/theme.js +55 -0
- package/dist/ui/app.js +517 -0
- package/dist/ui/containers/confirm-dialog.js +84 -0
- package/dist/ui/containers/container-detail.js +189 -0
- package/dist/ui/containers/container-list.js +120 -0
- package/dist/ui/containers/containers-tab.js +314 -0
- package/dist/ui/containers/log-viewer.js +190 -0
- package/dist/ui/footer.js +193 -0
- package/dist/ui/help-overlay.js +122 -0
- package/dist/ui/images/images-tab.js +37 -0
- package/dist/ui/networks/networks-tab.js +45 -0
- package/dist/ui/resource-list-tab.js +183 -0
- package/dist/ui/side-rail.js +132 -0
- package/dist/ui/stacks/stack-tree.js +346 -0
- package/dist/ui/stacks/stacks-tab.js +392 -0
- package/dist/ui/top-bar.js +78 -0
- package/dist/ui/volumes/volumes-tab.js +40 -0
- package/dist/ui/widgets.js +61 -0
- package/dist/utils/external-terminal.js +84 -0
- package/dist/utils/format.js +65 -0
- package/dist/utils/stacks.js +76 -0
- package/dist/utils/stats.js +12 -0
- package/dist/utils/status.js +80 -0
- package/dist/utils/term-caps.js +14 -0
- package/package.json +77 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ConfirmDialog = void 0;
|
|
7
|
+
const neo_blessed_1 = __importDefault(require("neo-blessed"));
|
|
8
|
+
const _theme_1 = require("../../theme");
|
|
9
|
+
class ConfirmDialog {
|
|
10
|
+
screen;
|
|
11
|
+
box;
|
|
12
|
+
visible = false;
|
|
13
|
+
onConfirm = null;
|
|
14
|
+
onCancel = null;
|
|
15
|
+
handleConfirm = () => {
|
|
16
|
+
if (!this.visible)
|
|
17
|
+
return;
|
|
18
|
+
this.hide();
|
|
19
|
+
this.onConfirm?.();
|
|
20
|
+
};
|
|
21
|
+
handleCancel = () => {
|
|
22
|
+
if (!this.visible)
|
|
23
|
+
return;
|
|
24
|
+
this.hide();
|
|
25
|
+
this.onCancel?.();
|
|
26
|
+
};
|
|
27
|
+
constructor(screen) {
|
|
28
|
+
this.screen = screen;
|
|
29
|
+
this.box = neo_blessed_1.default.box({
|
|
30
|
+
parent: screen,
|
|
31
|
+
width: 52,
|
|
32
|
+
height: 9,
|
|
33
|
+
top: 'center',
|
|
34
|
+
left: 'center',
|
|
35
|
+
tags: true,
|
|
36
|
+
border: { type: 'line' },
|
|
37
|
+
style: {
|
|
38
|
+
bg: _theme_1.C.selection,
|
|
39
|
+
border: { fg: _theme_1.C.purple },
|
|
40
|
+
},
|
|
41
|
+
hidden: true,
|
|
42
|
+
});
|
|
43
|
+
screen.append(this.box);
|
|
44
|
+
}
|
|
45
|
+
show(options) {
|
|
46
|
+
this.onConfirm = options.onConfirm;
|
|
47
|
+
this.onCancel = options.onCancel;
|
|
48
|
+
const danger = options.danger ?? false;
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
this.box.style.border.fg = danger ? _theme_1.C.red : _theme_1.C.purple;
|
|
51
|
+
const confirmBtn = danger
|
|
52
|
+
? `${_theme_1.t.red('[y]')} ${_theme_1.t.fg('Yes, proceed')}`
|
|
53
|
+
: `${_theme_1.t.green('[y]')} ${_theme_1.t.fg('Yes')}`;
|
|
54
|
+
const lines = [
|
|
55
|
+
'',
|
|
56
|
+
` {bold}${danger ? _theme_1.t.red(options.title) : _theme_1.t.fg(options.title)}{/bold}`,
|
|
57
|
+
'',
|
|
58
|
+
` ${_theme_1.t.comment(options.message)}`,
|
|
59
|
+
'',
|
|
60
|
+
` ${confirmBtn} ${_theme_1.t.comment('[n] Cancel')}`,
|
|
61
|
+
` ${_theme_1.t.comment('y:confirm n / Esc:cancel')}`,
|
|
62
|
+
];
|
|
63
|
+
this.box.setContent(lines.join('\n'));
|
|
64
|
+
this.visible = true;
|
|
65
|
+
this.box.show();
|
|
66
|
+
this.box.focus();
|
|
67
|
+
this.screen.key(['y', 'S-y'], this.handleConfirm);
|
|
68
|
+
this.screen.key(['n', 'S-n', 'escape'], this.handleCancel);
|
|
69
|
+
this.screen.render();
|
|
70
|
+
}
|
|
71
|
+
hide() {
|
|
72
|
+
this.visible = false;
|
|
73
|
+
this.box.hide();
|
|
74
|
+
for (const k of ['y', 'S-y'])
|
|
75
|
+
this.screen.removeKey(k, this.handleConfirm);
|
|
76
|
+
for (const k of ['n', 'S-n', 'escape'])
|
|
77
|
+
this.screen.removeKey(k, this.handleCancel);
|
|
78
|
+
this.screen.render();
|
|
79
|
+
}
|
|
80
|
+
isVisible() {
|
|
81
|
+
return this.visible;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.ConfirmDialog = ConfirmDialog;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ContainerDetail = void 0;
|
|
7
|
+
const neo_blessed_1 = __importDefault(require("neo-blessed"));
|
|
8
|
+
const _theme_1 = require("../../theme");
|
|
9
|
+
const format_1 = require("../../utils/format");
|
|
10
|
+
const status_1 = require("../../utils/status");
|
|
11
|
+
const widgets_1 = require("../widgets");
|
|
12
|
+
const BAR_WIDTH = 20;
|
|
13
|
+
class ContainerDetail {
|
|
14
|
+
screen;
|
|
15
|
+
wrapper;
|
|
16
|
+
headerBox;
|
|
17
|
+
box;
|
|
18
|
+
container = null;
|
|
19
|
+
lastStats;
|
|
20
|
+
envExpanded = false;
|
|
21
|
+
visible = false;
|
|
22
|
+
closeHandlers = [];
|
|
23
|
+
handleClose = () => {
|
|
24
|
+
if (!this.visible)
|
|
25
|
+
return;
|
|
26
|
+
this.hide();
|
|
27
|
+
this.closeHandlers.forEach((h) => h());
|
|
28
|
+
};
|
|
29
|
+
handleE = () => {
|
|
30
|
+
if (!this.visible || !this.container)
|
|
31
|
+
return;
|
|
32
|
+
this.envExpanded = !this.envExpanded;
|
|
33
|
+
this.render();
|
|
34
|
+
this.screen.render();
|
|
35
|
+
};
|
|
36
|
+
constructor(screen, dims) {
|
|
37
|
+
this.screen = screen;
|
|
38
|
+
this.wrapper = neo_blessed_1.default.box({
|
|
39
|
+
parent: screen,
|
|
40
|
+
top: dims.top,
|
|
41
|
+
left: dims.left,
|
|
42
|
+
width: dims.width,
|
|
43
|
+
height: dims.height,
|
|
44
|
+
style: { bg: _theme_1.C.bg },
|
|
45
|
+
hidden: true,
|
|
46
|
+
});
|
|
47
|
+
this.headerBox = (0, widgets_1.createHeaderBar)(this.wrapper);
|
|
48
|
+
this.box = neo_blessed_1.default.box({
|
|
49
|
+
parent: this.wrapper,
|
|
50
|
+
top: 1,
|
|
51
|
+
left: 0,
|
|
52
|
+
height: '100%-1',
|
|
53
|
+
width: '100%',
|
|
54
|
+
scrollable: true,
|
|
55
|
+
keys: true,
|
|
56
|
+
mouse: true,
|
|
57
|
+
tags: true,
|
|
58
|
+
alwaysScroll: true,
|
|
59
|
+
scrollbar: { ch: '│', style: { fg: _theme_1.C.comment } },
|
|
60
|
+
style: { fg: _theme_1.C.fg, bg: _theme_1.C.bg },
|
|
61
|
+
padding: { left: 2, right: 2 },
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
on(event, handler) {
|
|
65
|
+
if (event === 'close')
|
|
66
|
+
this.closeHandlers.push(handler);
|
|
67
|
+
}
|
|
68
|
+
show(container, stats) {
|
|
69
|
+
this.container = container;
|
|
70
|
+
if (stats !== undefined)
|
|
71
|
+
this.lastStats = stats;
|
|
72
|
+
this.envExpanded = false;
|
|
73
|
+
this.visible = true;
|
|
74
|
+
this.render();
|
|
75
|
+
this.updateHeader();
|
|
76
|
+
this.wrapper.show();
|
|
77
|
+
this.box.focus();
|
|
78
|
+
this.screen.key(['e'], this.handleE);
|
|
79
|
+
this.screen.key(['escape'], this.handleClose);
|
|
80
|
+
this.screen.render();
|
|
81
|
+
}
|
|
82
|
+
hide() {
|
|
83
|
+
this.visible = false;
|
|
84
|
+
this.wrapper.hide();
|
|
85
|
+
this.screen.removeKey('e', this.handleE);
|
|
86
|
+
this.screen.removeKey('escape', this.handleClose);
|
|
87
|
+
this.screen.render();
|
|
88
|
+
}
|
|
89
|
+
update(container, stats) {
|
|
90
|
+
this.container = container;
|
|
91
|
+
if (stats !== undefined)
|
|
92
|
+
this.lastStats = stats;
|
|
93
|
+
if (this.visible) {
|
|
94
|
+
this.render();
|
|
95
|
+
this.updateHeader();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
isVisible() {
|
|
99
|
+
return this.visible;
|
|
100
|
+
}
|
|
101
|
+
getContainerId() {
|
|
102
|
+
return this.container?.id ?? null;
|
|
103
|
+
}
|
|
104
|
+
updateHeader() {
|
|
105
|
+
if (!this.container)
|
|
106
|
+
return;
|
|
107
|
+
this.headerBox.setContent(` ${_theme_1.t.purple('DETAIL')} — ${_theme_1.t.fg(this.container.name)}`);
|
|
108
|
+
}
|
|
109
|
+
render() {
|
|
110
|
+
if (!this.container)
|
|
111
|
+
return;
|
|
112
|
+
this.box.setContent(this.buildContent(this.container, this.lastStats));
|
|
113
|
+
}
|
|
114
|
+
buildContent(c, stats) {
|
|
115
|
+
const lines = [];
|
|
116
|
+
lines.push(`{bold}${_theme_1.t.purple(c.name)}{/bold} ${_theme_1.t.comment(`${c.image} · ${c.id.slice(0, 12)}`)}`);
|
|
117
|
+
lines.push((0, status_1.colorByStatus)(c, `● ${(0, status_1.statusLabel)(c)}`));
|
|
118
|
+
lines.push('');
|
|
119
|
+
lines.push(`${_theme_1.t.comment('Uptime:')} ${(0, status_1.colorByStatus)(c, c.uptime)}`);
|
|
120
|
+
lines.push(`${_theme_1.t.comment('Restart:')} ${c.restartPolicy}`);
|
|
121
|
+
lines.push(`${_theme_1.t.comment('PIDs:')} ${c.status === 'running' ? String(c.pids) : _theme_1.t.comment('—')}`);
|
|
122
|
+
if (c.ports.length > 0) {
|
|
123
|
+
lines.push('');
|
|
124
|
+
lines.push(_theme_1.t.comment('Ports:'));
|
|
125
|
+
for (const p of c.ports)
|
|
126
|
+
lines.push(` ${_theme_1.t.pink(p)}`);
|
|
127
|
+
}
|
|
128
|
+
if (c.networks.length > 0) {
|
|
129
|
+
lines.push('');
|
|
130
|
+
const info = c.ip ? `${c.networks[0]} · ${c.ip}` : c.networks[0];
|
|
131
|
+
lines.push(`${_theme_1.t.comment('Network:')} ${_theme_1.t.cyan(info)}`);
|
|
132
|
+
for (const n of c.networks.slice(1))
|
|
133
|
+
lines.push(` ${_theme_1.t.cyan(n)}`);
|
|
134
|
+
}
|
|
135
|
+
if (stats && c.status === 'running') {
|
|
136
|
+
lines.push('');
|
|
137
|
+
lines.push(this.cpuBar(stats.cpuPercent));
|
|
138
|
+
lines.push(this.memBar(stats.memPercent, stats.memUsageMB, stats.memLimitMB));
|
|
139
|
+
lines.push(this.diskLine(stats.diskReadMB, stats.diskWriteMB));
|
|
140
|
+
}
|
|
141
|
+
if (c.mounts.length > 0) {
|
|
142
|
+
lines.push('');
|
|
143
|
+
lines.push(_theme_1.t.comment('MOUNTS'));
|
|
144
|
+
for (const m of c.mounts) {
|
|
145
|
+
lines.push(_theme_1.t.comment(`${m.source} → ${m.destination} (${m.rw ? 'rw' : 'ro'})`));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
lines.push('');
|
|
149
|
+
const arrow = this.envExpanded ? '▼' : '▶';
|
|
150
|
+
lines.push(_theme_1.t.comment(`ENV (${c.env.length}) ${arrow} — press e to toggle`));
|
|
151
|
+
if (this.envExpanded) {
|
|
152
|
+
for (const entry of c.env) {
|
|
153
|
+
const eq = entry.indexOf('=');
|
|
154
|
+
if (eq >= 0) {
|
|
155
|
+
lines.push(_theme_1.t.yellow(`${entry.slice(0, eq)}=${(0, format_1.truncate)(entry.slice(eq + 1), 55)}`));
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
lines.push(_theme_1.t.yellow(entry));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
lines.push('');
|
|
163
|
+
lines.push(this.actionsLine(c));
|
|
164
|
+
return lines.join('\n');
|
|
165
|
+
}
|
|
166
|
+
cpuBar(cpu) {
|
|
167
|
+
const filled = Math.min(BAR_WIDTH, Math.round((cpu / 100) * BAR_WIDTH));
|
|
168
|
+
const color = (0, status_1.cpuColor)(cpu);
|
|
169
|
+
const bar = `[${color('█'.repeat(filled))}${_theme_1.t.comment('░'.repeat(BAR_WIDTH - filled))}]`;
|
|
170
|
+
return `${_theme_1.t.comment('CPU')} ${bar} ${color(`${cpu.toFixed(1)}%`)}`;
|
|
171
|
+
}
|
|
172
|
+
memBar(mem, usageMB, limitMB) {
|
|
173
|
+
const filled = Math.min(BAR_WIDTH, Math.round((mem / 100) * BAR_WIDTH));
|
|
174
|
+
const color = (0, status_1.memColor)(mem);
|
|
175
|
+
const bar = `[${color('█'.repeat(filled))}${_theme_1.t.comment('░'.repeat(BAR_WIDTH - filled))}]`;
|
|
176
|
+
const label = `(${(0, format_1.humanSizeMB)(usageMB)} / ${(0, format_1.humanSizeMB)(limitMB)})`;
|
|
177
|
+
return `${_theme_1.t.comment('MEM')} ${bar} ${color(`${mem.toFixed(1)}%`)} ${_theme_1.t.comment(label)}`;
|
|
178
|
+
}
|
|
179
|
+
diskLine(readMB, writeMB) {
|
|
180
|
+
return `${_theme_1.t.comment('DISK')} ${_theme_1.t.comment('R:')}${_theme_1.t.cyan((0, format_1.humanSizeMB)(readMB))} ${_theme_1.t.comment('W:')}${_theme_1.t.orange((0, format_1.humanSizeMB)(writeMB))}`;
|
|
181
|
+
}
|
|
182
|
+
actionsLine(c) {
|
|
183
|
+
if ((0, status_1.isActive)(c.status)) {
|
|
184
|
+
return ` ${_theme_1.t.red('[s] Stop')} ${_theme_1.t.green('[r] Restart')} ${_theme_1.t.orange('[k] Kill')} ${_theme_1.t.purple('[x] Shell')} ${_theme_1.t.cyan('[l] Logs')} ${_theme_1.t.yellow('[e] Env')} ${_theme_1.t.comment('Esc close')}`;
|
|
185
|
+
}
|
|
186
|
+
return ` ${_theme_1.t.green('[S] Start')} ${_theme_1.t.red('[d] Remove')} ${_theme_1.t.cyan('[l] Logs')} ${_theme_1.t.yellow('[e] Env')} ${_theme_1.t.comment('Esc close')}`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
exports.ContainerDetail = ContainerDetail;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ContainerList = void 0;
|
|
7
|
+
const neo_blessed_1 = __importDefault(require("neo-blessed"));
|
|
8
|
+
const _theme_1 = require("../../theme");
|
|
9
|
+
const format_1 = require("../../utils/format");
|
|
10
|
+
const status_1 = require("../../utils/status");
|
|
11
|
+
const widgets_1 = require("../widgets");
|
|
12
|
+
class ContainerList {
|
|
13
|
+
wrapper;
|
|
14
|
+
header;
|
|
15
|
+
list;
|
|
16
|
+
messageBox;
|
|
17
|
+
containers = [];
|
|
18
|
+
selectHandlers = [];
|
|
19
|
+
navigateHandlers = [];
|
|
20
|
+
constructor(parent, dims) {
|
|
21
|
+
this.wrapper = neo_blessed_1.default.box({
|
|
22
|
+
parent,
|
|
23
|
+
top: dims.top,
|
|
24
|
+
left: dims.left,
|
|
25
|
+
width: dims.width,
|
|
26
|
+
height: dims.height,
|
|
27
|
+
});
|
|
28
|
+
this.header = (0, widgets_1.createHeaderBar)(this.wrapper);
|
|
29
|
+
this.list = (0, widgets_1.createListWidget)(this.wrapper);
|
|
30
|
+
this.messageBox = (0, widgets_1.createCenteredMessage)(this.wrapper);
|
|
31
|
+
this.list.on('select', (_item, index) => {
|
|
32
|
+
const container = this.containers[index];
|
|
33
|
+
if (container)
|
|
34
|
+
this.selectHandlers.forEach((h) => h(container));
|
|
35
|
+
});
|
|
36
|
+
this.list.on('select item', (_item, index) => {
|
|
37
|
+
const container = this.containers[index] ?? null;
|
|
38
|
+
this.navigateHandlers.forEach((h) => h(container));
|
|
39
|
+
});
|
|
40
|
+
this.list.on('click', () => {
|
|
41
|
+
const container = this.containers[(0, widgets_1.listSelected)(this.list)];
|
|
42
|
+
if (container)
|
|
43
|
+
this.selectHandlers.forEach((h) => h(container));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
on(event, handler) {
|
|
47
|
+
if (event === 'select')
|
|
48
|
+
this.selectHandlers.push(handler);
|
|
49
|
+
if (event === 'navigate')
|
|
50
|
+
this.navigateHandlers.push(handler);
|
|
51
|
+
}
|
|
52
|
+
showLoading() {
|
|
53
|
+
this.messageBox.setContent(_theme_1.t.comment(' Loading...'));
|
|
54
|
+
this.messageBox.show();
|
|
55
|
+
}
|
|
56
|
+
setData(containers, stats) {
|
|
57
|
+
this.containers = containers;
|
|
58
|
+
this.messageBox.hide();
|
|
59
|
+
const innerWidth = Math.max(10, this.list.width - 2);
|
|
60
|
+
const cols = this.calcColWidths(innerWidth);
|
|
61
|
+
this.renderHeader(cols);
|
|
62
|
+
const items = containers.map((c) => this.buildRow(c, cols, stats?.get(c.id)));
|
|
63
|
+
this.list.setItems(items);
|
|
64
|
+
if (containers.length === 0) {
|
|
65
|
+
this.messageBox.setContent(_theme_1.t.comment(' No containers'));
|
|
66
|
+
this.messageBox.show();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
getSelected() {
|
|
70
|
+
return this.containers[(0, widgets_1.listSelected)(this.list)] ?? null;
|
|
71
|
+
}
|
|
72
|
+
getSelectedIndex() {
|
|
73
|
+
return (0, widgets_1.listSelected)(this.list);
|
|
74
|
+
}
|
|
75
|
+
focus() {
|
|
76
|
+
this.list.focus();
|
|
77
|
+
}
|
|
78
|
+
show() {
|
|
79
|
+
this.wrapper.show();
|
|
80
|
+
}
|
|
81
|
+
hide() {
|
|
82
|
+
this.wrapper.hide();
|
|
83
|
+
}
|
|
84
|
+
calcColWidths(inner) {
|
|
85
|
+
const c1 = Math.floor(inner * 0.21);
|
|
86
|
+
const c2 = Math.floor(inner * 0.17);
|
|
87
|
+
const c3 = Math.floor(inner * 0.22);
|
|
88
|
+
const c4 = Math.floor(inner * 0.1);
|
|
89
|
+
const c5 = Math.floor(inner * 0.08);
|
|
90
|
+
const c6 = Math.floor(inner * 0.08);
|
|
91
|
+
const c7 = Math.max(1, inner - c1 - c2 - c3 - c4 - c5 - c6);
|
|
92
|
+
return [c1, c2, c3, c4, c5, c6, c7];
|
|
93
|
+
}
|
|
94
|
+
renderHeader([c1, c2, c3, c4, c5, c6]) {
|
|
95
|
+
const h1 = (0, format_1.padEnd)(_theme_1.t.comment(' NAME'), c1 + 1);
|
|
96
|
+
const h2 = (0, format_1.padEnd)(_theme_1.t.comment('IMAGE'), c2);
|
|
97
|
+
const h3 = (0, format_1.padEnd)(_theme_1.t.comment('STATUS & UPTIME'), c3);
|
|
98
|
+
const h4 = (0, format_1.padEnd)(_theme_1.t.comment('NET'), c4);
|
|
99
|
+
const h5 = (0, format_1.padEnd)(_theme_1.t.comment('CPU'), c5);
|
|
100
|
+
const h6 = (0, format_1.padEnd)(_theme_1.t.comment('MEM'), c6);
|
|
101
|
+
const h7 = _theme_1.t.comment('PORTS');
|
|
102
|
+
this.header.setContent(`${h1}${h2}${h3}${h4}${h5}${h6}${h7}`);
|
|
103
|
+
}
|
|
104
|
+
buildRow(c, [c1, c2, c3, c4, c5, c6, c7], stats) {
|
|
105
|
+
const nameRaw = (0, format_1.truncate)(c.name, Math.max(1, c1 - 2));
|
|
106
|
+
const col1 = (0, format_1.padEnd)(`${(0, status_1.statusDot)(c)} ${nameRaw}`, c1);
|
|
107
|
+
const imageRaw = (0, format_1.truncate)(c.image, Math.max(1, c2 - 1));
|
|
108
|
+
const col2 = (0, format_1.padEnd)(_theme_1.t.comment(imageRaw), c2);
|
|
109
|
+
const stateRaw = `${(0, status_1.statusLabel)(c)} · ${c.uptime}`;
|
|
110
|
+
const col3 = (0, format_1.padEnd)((0, status_1.colorByStatus)(c, (0, format_1.truncate)(stateRaw, c3 - 1)), c3);
|
|
111
|
+
const netRaw = c.networks.length > 0 ? (0, format_1.truncate)(c.networks[0], c4 - 1) : '—';
|
|
112
|
+
const col4 = (0, format_1.padEnd)(c.networks.length > 0 ? _theme_1.t.cyan(netRaw) : _theme_1.t.comment(netRaw), c4);
|
|
113
|
+
const col5 = (0, format_1.padEnd)((0, status_1.formatCpuCell)(c, stats?.cpuPercent), c5);
|
|
114
|
+
const col6 = (0, format_1.padEnd)((0, status_1.formatMemCell)(c, stats?.memPercent), c6);
|
|
115
|
+
const rawPort = c.ports.length > 0 ? (0, format_1.truncate)(c.ports[0], c7 - 1) : '';
|
|
116
|
+
const col7 = rawPort ? _theme_1.t.pink(rawPort) : _theme_1.t.comment('—');
|
|
117
|
+
return `${col1}${col2}${col3}${col4}${col5}${col6}${col7}`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.ContainerList = ContainerList;
|