shell-mirror 1.5.37 → 1.5.39
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
CHANGED
package/public/app/dashboard.css
CHANGED
|
@@ -294,6 +294,10 @@ body {
|
|
|
294
294
|
border-bottom: 1px solid #f0f0f0;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
.session-item.compact {
|
|
298
|
+
padding: 12px 0;
|
|
299
|
+
}
|
|
300
|
+
|
|
297
301
|
.session-item:last-child {
|
|
298
302
|
border-bottom: none;
|
|
299
303
|
}
|
|
@@ -345,6 +349,11 @@ body {
|
|
|
345
349
|
color: #f57c00;
|
|
346
350
|
}
|
|
347
351
|
|
|
352
|
+
.session-status.disconnected {
|
|
353
|
+
background: #f5f5f5;
|
|
354
|
+
color: #666;
|
|
355
|
+
}
|
|
356
|
+
|
|
348
357
|
/* Empty States */
|
|
349
358
|
.no-data {
|
|
350
359
|
text-align: center;
|
|
@@ -46,6 +46,13 @@
|
|
|
46
46
|
<p>Loading dashboard...</p>
|
|
47
47
|
</div>
|
|
48
48
|
|
|
49
|
+
<!-- Version Footer -->
|
|
50
|
+
<footer style="background: #ff6b35; color: white; text-align: center; padding: 10px 0; font-size: 0.8rem; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000;">
|
|
51
|
+
<div style="max-width: 1200px; margin: 0 auto;">
|
|
52
|
+
<p id="dashboard-version-info">Shell Mirror Dashboard • Loading version...</p>
|
|
53
|
+
</div>
|
|
54
|
+
</footer>
|
|
55
|
+
|
|
49
56
|
<script src="dashboard.js"></script>
|
|
50
57
|
</body>
|
|
51
58
|
</html>
|
package/public/app/dashboard.js
CHANGED
|
@@ -10,6 +10,7 @@ class ShellMirrorDashboard {
|
|
|
10
10
|
|
|
11
11
|
async init() {
|
|
12
12
|
this.showLoading();
|
|
13
|
+
this.loadVersionInfo(); // Load version info immediately
|
|
13
14
|
|
|
14
15
|
try {
|
|
15
16
|
const authStatus = await this.checkAuthStatus();
|
|
@@ -109,7 +110,10 @@ class ShellMirrorDashboard {
|
|
|
109
110
|
`;
|
|
110
111
|
|
|
111
112
|
// Show centered login button
|
|
112
|
-
document.getElementById('login-button-overlay')
|
|
113
|
+
const loginOverlay = document.getElementById('login-button-overlay');
|
|
114
|
+
if (loginOverlay) {
|
|
115
|
+
loginOverlay.style.display = 'flex';
|
|
116
|
+
}
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
renderAuthenticatedDashboard() {
|
|
@@ -137,12 +141,21 @@ class ShellMirrorDashboard {
|
|
|
137
141
|
`;
|
|
138
142
|
|
|
139
143
|
// Hide login button overlay
|
|
140
|
-
document.getElementById('login-button-overlay')
|
|
144
|
+
const loginOverlay = document.getElementById('login-button-overlay');
|
|
145
|
+
if (loginOverlay) {
|
|
146
|
+
loginOverlay.style.display = 'none';
|
|
147
|
+
}
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
renderActiveAgents() {
|
|
144
|
-
|
|
145
|
-
const
|
|
151
|
+
// Filter for recently active agents (online or seen within last 5 minutes)
|
|
152
|
+
const activeAgents = this.agents.filter(agent => {
|
|
153
|
+
const timeSinceLastSeen = Date.now() / 1000 - agent.lastSeen;
|
|
154
|
+
return agent.onlineStatus === 'online' || timeSinceLastSeen < 300; // 5 minutes
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const agentCount = activeAgents.length;
|
|
158
|
+
const agentsHtml = activeAgents.map(agent => `
|
|
146
159
|
<div class="agent-item">
|
|
147
160
|
<div class="agent-info">
|
|
148
161
|
<div class="agent-name">${agent.machineName || agent.agentId}</div>
|
|
@@ -193,8 +206,31 @@ class ShellMirrorDashboard {
|
|
|
193
206
|
}
|
|
194
207
|
|
|
195
208
|
renderRecentSessions() {
|
|
196
|
-
|
|
197
|
-
|
|
209
|
+
// Get inactive agents (not seen in last 5 minutes and offline)
|
|
210
|
+
const inactiveAgents = this.agents.filter(agent => {
|
|
211
|
+
const timeSinceLastSeen = Date.now() / 1000 - agent.lastSeen;
|
|
212
|
+
return agent.onlineStatus === 'offline' && timeSinceLastSeen >= 300; // More than 5 minutes
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Combine real sessions with inactive agents as past connections
|
|
216
|
+
const allSessions = [
|
|
217
|
+
// Add inactive agents as past connections
|
|
218
|
+
...inactiveAgents.map(agent => ({
|
|
219
|
+
type: 'past_agent',
|
|
220
|
+
agentId: agent.machineName || agent.agentId,
|
|
221
|
+
startTime: new Date(agent.lastSeen * 1000),
|
|
222
|
+
duration: 'Last connection',
|
|
223
|
+
status: 'disconnected'
|
|
224
|
+
})),
|
|
225
|
+
// Add actual session history
|
|
226
|
+
...this.sessions
|
|
227
|
+
];
|
|
228
|
+
|
|
229
|
+
// Sort by most recent
|
|
230
|
+
allSessions.sort((a, b) => b.startTime - a.startTime);
|
|
231
|
+
|
|
232
|
+
const sessionsHtml = allSessions.map(session => `
|
|
233
|
+
<div class="session-item compact">
|
|
198
234
|
<div class="session-info">
|
|
199
235
|
<div class="session-agent">${session.agentId}</div>
|
|
200
236
|
<div class="session-time">${this.formatDate(session.startTime)}</div>
|
|
@@ -210,7 +246,7 @@ class ShellMirrorDashboard {
|
|
|
210
246
|
<div class="dashboard-card full-width">
|
|
211
247
|
<h2>📊 Recent Sessions</h2>
|
|
212
248
|
<div class="card-content">
|
|
213
|
-
${
|
|
249
|
+
${allSessions.length > 0 ? sessionsHtml : '<p class="no-data">No recent sessions</p>'}
|
|
214
250
|
</div>
|
|
215
251
|
</div>
|
|
216
252
|
`;
|
|
@@ -317,6 +353,30 @@ class ShellMirrorDashboard {
|
|
|
317
353
|
}).format(date);
|
|
318
354
|
}
|
|
319
355
|
|
|
356
|
+
// Load version info for footer
|
|
357
|
+
async loadVersionInfo() {
|
|
358
|
+
try {
|
|
359
|
+
const response = await fetch('/build-info.json');
|
|
360
|
+
const buildInfo = await response.json();
|
|
361
|
+
const versionElement = document.getElementById('dashboard-version-info');
|
|
362
|
+
const footerElement = versionElement?.parentElement?.parentElement; // Get the footer element
|
|
363
|
+
|
|
364
|
+
if (versionElement && buildInfo) {
|
|
365
|
+
const buildDateTime = new Date(buildInfo.buildTime).toLocaleString();
|
|
366
|
+
versionElement.textContent = `Shell Mirror Dashboard v${buildInfo.version} • Built ${buildDateTime}`;
|
|
367
|
+
|
|
368
|
+
// Apply random footer color from build info
|
|
369
|
+
if (footerElement && buildInfo.footerColor) {
|
|
370
|
+
footerElement.style.background = buildInfo.footerColor;
|
|
371
|
+
console.log(`🎨 Applied footer color: ${buildInfo.footerColor}`);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
} catch (error) {
|
|
375
|
+
console.log('Could not load build info for dashboard:', error);
|
|
376
|
+
// Keep default version and color if build-info.json not available
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
320
380
|
// Action handlers
|
|
321
381
|
async connectToAgent(agentId) {
|
|
322
382
|
window.location.href = `/app/terminal.html?agent=${agentId}`;
|
package/public/app/terminal.js
CHANGED
|
@@ -79,8 +79,8 @@ async function loadVersionInfo() {
|
|
|
79
79
|
const footerElement = versionElement?.parentElement?.parentElement; // Get the footer element
|
|
80
80
|
|
|
81
81
|
if (versionElement && buildInfo) {
|
|
82
|
-
const
|
|
83
|
-
versionElement.textContent = `Terminal Mirror v${buildInfo.version} • Built ${
|
|
82
|
+
const buildDateTime = new Date(buildInfo.buildTime).toLocaleString();
|
|
83
|
+
versionElement.textContent = `Terminal Mirror v${buildInfo.version} • Built ${buildDateTime}`;
|
|
84
84
|
|
|
85
85
|
// Apply random footer color from build info
|
|
86
86
|
if (footerElement && buildInfo.footerColor) {
|