shell-mirror 1.5.112 → 1.5.113
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/package.json +1 -1
- package/public/app/dashboard.css +50 -12
- package/public/app/dashboard.js +76 -11
package/package.json
CHANGED
package/public/app/dashboard.css
CHANGED
|
@@ -249,20 +249,58 @@ body {
|
|
|
249
249
|
color: var(--text-primary);
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
|
|
252
|
+
/* Agent Menu Dropdown */
|
|
253
|
+
.agent-menu {
|
|
254
|
+
position: relative;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.btn-agent-menu {
|
|
253
258
|
background: none;
|
|
254
259
|
border: none;
|
|
260
|
+
color: var(--text-muted);
|
|
261
|
+
font-size: 1.2rem;
|
|
255
262
|
cursor: pointer;
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
transition:
|
|
259
|
-
padding: 4px;
|
|
260
|
-
color: var(--text-secondary);
|
|
263
|
+
padding: 4px 8px;
|
|
264
|
+
border-radius: 4px;
|
|
265
|
+
transition: all 0.15s ease;
|
|
261
266
|
}
|
|
262
267
|
|
|
263
|
-
.btn-
|
|
264
|
-
|
|
268
|
+
.btn-agent-menu:hover {
|
|
269
|
+
color: var(--text-primary);
|
|
270
|
+
background: var(--bg-hover);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.agent-menu-dropdown {
|
|
274
|
+
display: none;
|
|
275
|
+
position: absolute;
|
|
276
|
+
right: 0;
|
|
277
|
+
top: calc(100% + 4px);
|
|
278
|
+
background: var(--bg-secondary);
|
|
279
|
+
border: 1px solid var(--border);
|
|
280
|
+
border-radius: 6px;
|
|
281
|
+
min-width: 160px;
|
|
282
|
+
z-index: 100;
|
|
283
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.agent-menu-dropdown.show {
|
|
287
|
+
display: block;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.agent-menu-dropdown button {
|
|
291
|
+
width: 100%;
|
|
292
|
+
padding: 10px 14px;
|
|
293
|
+
background: none;
|
|
294
|
+
border: none;
|
|
265
295
|
color: var(--danger);
|
|
296
|
+
text-align: left;
|
|
297
|
+
cursor: pointer;
|
|
298
|
+
font-size: 0.85rem;
|
|
299
|
+
transition: background 0.15s ease;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.agent-menu-dropdown button:hover {
|
|
303
|
+
background: var(--bg-hover);
|
|
266
304
|
}
|
|
267
305
|
|
|
268
306
|
.agent-status {
|
|
@@ -275,7 +313,7 @@ body {
|
|
|
275
313
|
}
|
|
276
314
|
|
|
277
315
|
.agent-status.online {
|
|
278
|
-
color: var(--
|
|
316
|
+
color: var(--text-secondary);
|
|
279
317
|
background: none;
|
|
280
318
|
padding: 0;
|
|
281
319
|
}
|
|
@@ -289,7 +327,7 @@ body {
|
|
|
289
327
|
}
|
|
290
328
|
|
|
291
329
|
.agent-status.recent {
|
|
292
|
-
color: var(--
|
|
330
|
+
color: var(--text-secondary);
|
|
293
331
|
background: none;
|
|
294
332
|
padding: 0;
|
|
295
333
|
}
|
|
@@ -303,7 +341,7 @@ body {
|
|
|
303
341
|
}
|
|
304
342
|
|
|
305
343
|
.agent-status.offline {
|
|
306
|
-
color: var(--
|
|
344
|
+
color: var(--text-secondary);
|
|
307
345
|
background: none;
|
|
308
346
|
padding: 0;
|
|
309
347
|
}
|
|
@@ -571,7 +609,7 @@ body {
|
|
|
571
609
|
.command-box code {
|
|
572
610
|
font-family: 'Monaco', 'Menlo', monospace;
|
|
573
611
|
font-size: 0.85rem;
|
|
574
|
-
color: var(--
|
|
612
|
+
color: var(--text-primary);
|
|
575
613
|
flex: 1;
|
|
576
614
|
}
|
|
577
615
|
|
package/public/app/dashboard.js
CHANGED
|
@@ -586,9 +586,12 @@ class ShellMirrorDashboard {
|
|
|
586
586
|
<div class="agent-info">
|
|
587
587
|
<div class="agent-name-row">
|
|
588
588
|
<span class="agent-name">${agent.machineName || agent.agentId}</span>
|
|
589
|
-
<
|
|
590
|
-
|
|
591
|
-
|
|
589
|
+
<div class="agent-menu">
|
|
590
|
+
<button class="btn-agent-menu" onclick="event.stopPropagation(); dashboard.toggleAgentMenu('${agent.agentId}')">⋮</button>
|
|
591
|
+
<div class="agent-menu-dropdown" id="agent-menu-${agent.agentId}">
|
|
592
|
+
<button onclick="dashboard.showShutdownConfirm('${agent.agentId}')">Shut down agent</button>
|
|
593
|
+
</div>
|
|
594
|
+
</div>
|
|
592
595
|
</div>
|
|
593
596
|
<div class="agent-status ${agent.status}">
|
|
594
597
|
${statusText}${sessionCount > 0 ? ` · ${sessionCount} session${sessionCount !== 1 ? 's' : ''}` : ''}
|
|
@@ -1065,13 +1068,66 @@ class ShellMirrorDashboard {
|
|
|
1065
1068
|
return true;
|
|
1066
1069
|
}
|
|
1067
1070
|
|
|
1068
|
-
|
|
1071
|
+
toggleAgentMenu(agentId) {
|
|
1072
|
+
// Close all other menus first
|
|
1073
|
+
document.querySelectorAll('.agent-menu-dropdown.show').forEach(el => {
|
|
1074
|
+
el.classList.remove('show');
|
|
1075
|
+
});
|
|
1076
|
+
const menu = document.getElementById(`agent-menu-${agentId}`);
|
|
1077
|
+
if (menu) {
|
|
1078
|
+
menu.classList.toggle('show');
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
showShutdownConfirm(agentId) {
|
|
1083
|
+
// Close menu
|
|
1084
|
+
document.querySelectorAll('.agent-menu-dropdown.show').forEach(el => {
|
|
1085
|
+
el.classList.remove('show');
|
|
1086
|
+
});
|
|
1087
|
+
this.showShutdownModal(agentId);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
showShutdownModal(agentId) {
|
|
1069
1091
|
const agent = this.agents.find(a => a.agentId === agentId);
|
|
1070
1092
|
const agentName = agent ? (agent.machineName || agentId) : agentId;
|
|
1071
1093
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1094
|
+
const modalOverlay = document.createElement('div');
|
|
1095
|
+
modalOverlay.className = 'modal-overlay';
|
|
1096
|
+
modalOverlay.id = 'shutdown-modal';
|
|
1097
|
+
modalOverlay.onclick = (e) => {
|
|
1098
|
+
if (e.target === modalOverlay) {
|
|
1099
|
+
document.body.removeChild(modalOverlay);
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
modalOverlay.innerHTML = `
|
|
1104
|
+
<div class="modal" onclick="event.stopPropagation()">
|
|
1105
|
+
<div class="modal-header">
|
|
1106
|
+
<h3>Shut down agent</h3>
|
|
1107
|
+
<button class="modal-close" onclick="document.getElementById('shutdown-modal').remove()">×</button>
|
|
1108
|
+
</div>
|
|
1109
|
+
<div class="modal-body">
|
|
1110
|
+
<p style="margin-bottom: 12px; color: var(--text-secondary);">
|
|
1111
|
+
Are you sure you want to shut down <strong style="color: var(--text-primary);">${agentName}</strong>?
|
|
1112
|
+
</p>
|
|
1113
|
+
<p style="font-size: 0.85rem; color: var(--text-muted);">
|
|
1114
|
+
This will unregister the agent from the dashboard. If the agent is still running, it will re-register on next heartbeat.
|
|
1115
|
+
</p>
|
|
1116
|
+
</div>
|
|
1117
|
+
<div class="modal-footer" style="display: flex; justify-content: flex-end; gap: 10px; padding: 16px; border-top: 1px solid var(--border);">
|
|
1118
|
+
<button onclick="document.getElementById('shutdown-modal').remove()" style="padding: 8px 16px; background: var(--bg-tertiary); color: var(--text-secondary); border: 1px solid var(--border); border-radius: 6px; cursor: pointer;">Cancel</button>
|
|
1119
|
+
<button onclick="dashboard.shutdownAgent('${agentId}')" style="padding: 8px 16px; background: var(--danger); color: white; border: none; border-radius: 6px; cursor: pointer;">Shut down</button>
|
|
1120
|
+
</div>
|
|
1121
|
+
</div>
|
|
1122
|
+
`;
|
|
1123
|
+
|
|
1124
|
+
document.body.appendChild(modalOverlay);
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
async shutdownAgent(agentId) {
|
|
1128
|
+
// Close modal
|
|
1129
|
+
const modal = document.getElementById('shutdown-modal');
|
|
1130
|
+
if (modal) modal.remove();
|
|
1075
1131
|
|
|
1076
1132
|
try {
|
|
1077
1133
|
const response = await fetch('/php-backend/api/delete-agent.php', {
|
|
@@ -1083,14 +1139,14 @@ class ShellMirrorDashboard {
|
|
|
1083
1139
|
|
|
1084
1140
|
const data = await response.json();
|
|
1085
1141
|
if (data.success) {
|
|
1086
|
-
console.log('[DASHBOARD] Agent
|
|
1142
|
+
console.log('[DASHBOARD] Agent shut down:', agentId);
|
|
1087
1143
|
await this.refreshDashboardData();
|
|
1088
1144
|
} else {
|
|
1089
|
-
alert('Failed to
|
|
1145
|
+
alert('Failed to shut down agent: ' + (data.message || 'Unknown error'));
|
|
1090
1146
|
}
|
|
1091
1147
|
} catch (error) {
|
|
1092
|
-
console.error('[DASHBOARD]
|
|
1093
|
-
alert('Failed to
|
|
1148
|
+
console.error('[DASHBOARD] Shutdown agent failed:', error);
|
|
1149
|
+
alert('Failed to shut down agent: ' + error.message);
|
|
1094
1150
|
}
|
|
1095
1151
|
}
|
|
1096
1152
|
|
|
@@ -1322,4 +1378,13 @@ window.addEventListener('beforeunload', () => {
|
|
|
1322
1378
|
if (dashboard && dashboard.refreshInterval) {
|
|
1323
1379
|
clearInterval(dashboard.refreshInterval);
|
|
1324
1380
|
}
|
|
1381
|
+
});
|
|
1382
|
+
|
|
1383
|
+
// Close agent menu when clicking outside
|
|
1384
|
+
document.addEventListener('click', (e) => {
|
|
1385
|
+
if (!e.target.closest('.agent-menu')) {
|
|
1386
|
+
document.querySelectorAll('.agent-menu-dropdown.show').forEach(el => {
|
|
1387
|
+
el.classList.remove('show');
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1325
1390
|
});
|