shell-mirror 1.5.87 → 1.5.89
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 +139 -3
- package/public/app/dashboard.js +36 -54
package/package.json
CHANGED
package/public/app/dashboard.css
CHANGED
|
@@ -349,12 +349,18 @@ body {
|
|
|
349
349
|
/* Agent Items */
|
|
350
350
|
.agent-item {
|
|
351
351
|
display: flex;
|
|
352
|
-
|
|
353
|
-
align-items: center;
|
|
352
|
+
flex-direction: column;
|
|
354
353
|
padding: 16px 0;
|
|
355
354
|
border-bottom: 1px solid #f0f0f0;
|
|
356
355
|
}
|
|
357
356
|
|
|
357
|
+
.agent-header {
|
|
358
|
+
display: flex;
|
|
359
|
+
justify-content: space-between;
|
|
360
|
+
align-items: center;
|
|
361
|
+
width: 100%;
|
|
362
|
+
}
|
|
363
|
+
|
|
358
364
|
.agent-item:last-child {
|
|
359
365
|
border-bottom: none;
|
|
360
366
|
}
|
|
@@ -406,6 +412,115 @@ body {
|
|
|
406
412
|
font-weight: 500;
|
|
407
413
|
}
|
|
408
414
|
|
|
415
|
+
/* Inline Session List Styles */
|
|
416
|
+
.agent-sessions-inline {
|
|
417
|
+
margin-top: 12px;
|
|
418
|
+
padding-top: 12px;
|
|
419
|
+
border-top: 1px solid #eee;
|
|
420
|
+
width: 100%;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.sessions-label {
|
|
424
|
+
font-size: 0.8rem;
|
|
425
|
+
color: #666;
|
|
426
|
+
font-weight: 500;
|
|
427
|
+
margin-bottom: 8px;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.sessions-list {
|
|
431
|
+
margin-bottom: 10px;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.inline-session-item {
|
|
435
|
+
display: flex;
|
|
436
|
+
align-items: center;
|
|
437
|
+
gap: 10px;
|
|
438
|
+
padding: 10px 12px;
|
|
439
|
+
margin-bottom: 6px;
|
|
440
|
+
background: #f8f9fa;
|
|
441
|
+
border-radius: 8px;
|
|
442
|
+
border: 1px solid #eee;
|
|
443
|
+
transition: all 0.2s ease;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.inline-session-item:hover {
|
|
447
|
+
background: #fff;
|
|
448
|
+
border-color: #4285f4;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.session-status-dot {
|
|
452
|
+
width: 8px;
|
|
453
|
+
height: 8px;
|
|
454
|
+
border-radius: 50%;
|
|
455
|
+
flex-shrink: 0;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.session-status-dot.active {
|
|
459
|
+
background: #34a853;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.session-status-dot.crashed {
|
|
463
|
+
background: #ea4335;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
.session-name {
|
|
467
|
+
font-weight: 500;
|
|
468
|
+
color: #333;
|
|
469
|
+
flex: 1;
|
|
470
|
+
font-size: 0.9rem;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.session-activity {
|
|
474
|
+
font-size: 0.75rem;
|
|
475
|
+
color: #888;
|
|
476
|
+
margin-right: 8px;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.btn-session-connect {
|
|
480
|
+
background: #4285f4;
|
|
481
|
+
color: white;
|
|
482
|
+
border: none;
|
|
483
|
+
border-radius: 6px;
|
|
484
|
+
padding: 6px 14px;
|
|
485
|
+
font-size: 0.8rem;
|
|
486
|
+
font-weight: 500;
|
|
487
|
+
cursor: pointer;
|
|
488
|
+
transition: all 0.2s ease;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.btn-session-connect:hover {
|
|
492
|
+
background: #3367d6;
|
|
493
|
+
transform: translateY(-1px);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.btn-new-session {
|
|
497
|
+
background: #fff;
|
|
498
|
+
color: #4285f4;
|
|
499
|
+
border: 1px dashed #4285f4;
|
|
500
|
+
border-radius: 8px;
|
|
501
|
+
padding: 10px 16px;
|
|
502
|
+
font-size: 0.85rem;
|
|
503
|
+
font-weight: 500;
|
|
504
|
+
cursor: pointer;
|
|
505
|
+
width: 100%;
|
|
506
|
+
transition: all 0.2s ease;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.btn-new-session:hover {
|
|
510
|
+
background: #f0f7ff;
|
|
511
|
+
border-style: solid;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
.agent-offline-message {
|
|
515
|
+
margin-top: 12px;
|
|
516
|
+
padding: 10px;
|
|
517
|
+
background: #f5f5f5;
|
|
518
|
+
border-radius: 6px;
|
|
519
|
+
color: #999;
|
|
520
|
+
font-size: 0.85rem;
|
|
521
|
+
text-align: center;
|
|
522
|
+
}
|
|
523
|
+
|
|
409
524
|
.agent-actions {
|
|
410
525
|
display: flex;
|
|
411
526
|
gap: 8px;
|
|
@@ -751,12 +866,33 @@ body {
|
|
|
751
866
|
align-items: flex-start;
|
|
752
867
|
gap: 12px;
|
|
753
868
|
}
|
|
754
|
-
|
|
869
|
+
|
|
755
870
|
.session-details {
|
|
756
871
|
align-items: flex-start;
|
|
757
872
|
flex-direction: row;
|
|
758
873
|
gap: 12px;
|
|
759
874
|
}
|
|
875
|
+
|
|
876
|
+
/* Mobile inline session styles */
|
|
877
|
+
.inline-session-item {
|
|
878
|
+
flex-wrap: wrap;
|
|
879
|
+
gap: 8px;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
.session-name {
|
|
883
|
+
flex-basis: calc(100% - 30px);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.session-activity {
|
|
887
|
+
order: 3;
|
|
888
|
+
flex-basis: 50%;
|
|
889
|
+
margin-right: 0;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
.btn-session-connect {
|
|
893
|
+
order: 4;
|
|
894
|
+
padding: 8px 16px;
|
|
895
|
+
}
|
|
760
896
|
}
|
|
761
897
|
|
|
762
898
|
/* Modal Styles */
|
package/public/app/dashboard.js
CHANGED
|
@@ -566,26 +566,48 @@ class ShellMirrorDashboard {
|
|
|
566
566
|
? this.formatPreciseLastSeen(agent.timeSinceLastSeen)
|
|
567
567
|
: this.formatLastSeen(agent.lastSeen);
|
|
568
568
|
|
|
569
|
+
// Build inline session list
|
|
570
|
+
const sessionsHtml = sessions.map(session => {
|
|
571
|
+
const sessionStatus = session.status === 'active' ? 'active' : 'crashed';
|
|
572
|
+
const activityText = this.formatLastActivity(session.lastActivity);
|
|
573
|
+
return `
|
|
574
|
+
<div class="inline-session-item">
|
|
575
|
+
<span class="session-status-dot ${sessionStatus}"></span>
|
|
576
|
+
<span class="session-name">${session.name}</span>
|
|
577
|
+
<span class="session-activity">${activityText}</span>
|
|
578
|
+
<button class="btn-session-connect" onclick="dashboard.connectToSession('${agent.agentId}', '${session.id}')">
|
|
579
|
+
Connect
|
|
580
|
+
</button>
|
|
581
|
+
</div>
|
|
582
|
+
`;
|
|
583
|
+
}).join('');
|
|
584
|
+
|
|
569
585
|
return `
|
|
570
586
|
<div class="agent-item ${!isConnectable ? 'agent-offline' : ''}">
|
|
571
|
-
<div class="agent-
|
|
572
|
-
<div class="agent-
|
|
573
|
-
|
|
574
|
-
|
|
587
|
+
<div class="agent-header">
|
|
588
|
+
<div class="agent-info">
|
|
589
|
+
<div class="agent-name">${agent.machineName || agent.agentId}</div>
|
|
590
|
+
<div class="agent-status ${agent.status}">
|
|
591
|
+
${statusIcon} ${statusText}
|
|
592
|
+
</div>
|
|
593
|
+
<div class="agent-last-seen">Last seen: ${lastSeenText}</div>
|
|
575
594
|
</div>
|
|
576
|
-
<div class="agent-last-seen">Last seen: ${lastSeenText}</div>
|
|
577
|
-
${sessionCount > 0 ? `<div class="agent-sessions">${sessionCount} active session${sessionCount !== 1 ? 's' : ''}</div>` : ''}
|
|
578
595
|
</div>
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
596
|
+
${isConnectable ? `
|
|
597
|
+
<div class="agent-sessions-inline">
|
|
598
|
+
${sessionCount > 0 ? `
|
|
599
|
+
<div class="sessions-label">Sessions (${sessionCount})</div>
|
|
600
|
+
<div class="sessions-list">
|
|
601
|
+
${sessionsHtml}
|
|
602
|
+
</div>
|
|
603
|
+
` : ''}
|
|
604
|
+
<button class="btn-new-session" onclick="dashboard.createNewSession('${agent.agentId}')">
|
|
605
|
+
+ New Session
|
|
584
606
|
</button>
|
|
585
|
-
${sessionCount > 0 && isConnectable ? `<button class="btn-sessions" onclick="dashboard.showAgentSessions('${agent.agentId}')">
|
|
586
|
-
All Sessions
|
|
587
|
-
</button>` : ''}
|
|
588
607
|
</div>
|
|
608
|
+
` : `
|
|
609
|
+
<div class="agent-offline-message">Agent offline</div>
|
|
610
|
+
`}
|
|
589
611
|
</div>
|
|
590
612
|
`;
|
|
591
613
|
}).join('');
|
|
@@ -1052,46 +1074,6 @@ class ShellMirrorDashboard {
|
|
|
1052
1074
|
}
|
|
1053
1075
|
}
|
|
1054
1076
|
|
|
1055
|
-
showAgentSessions(agentId) {
|
|
1056
|
-
const sessions = this.agentSessions[agentId] || [];
|
|
1057
|
-
const agent = this.agents.find(a => a.agentId === agentId);
|
|
1058
|
-
const agentName = agent ? (agent.machineName || agent.agentId) : agentId;
|
|
1059
|
-
|
|
1060
|
-
if (sessions.length === 0) {
|
|
1061
|
-
alert(`No active sessions found for ${agentName}`);
|
|
1062
|
-
return;
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
// Create session list modal
|
|
1066
|
-
const sessionsList = sessions.map(session => `
|
|
1067
|
-
<div class="session-list-item" onclick="dashboard.connectToSession('${agentId}', '${session.id}')">
|
|
1068
|
-
<div class="session-list-info">
|
|
1069
|
-
<div class="session-list-name">${session.name}</div>
|
|
1070
|
-
<div class="session-list-details">
|
|
1071
|
-
<span class="session-list-id">${session.id.substring(0, 8)}...</span>
|
|
1072
|
-
<span class="session-list-activity">Last activity: ${this.formatLastActivity(session.lastActivity)}</span>
|
|
1073
|
-
</div>
|
|
1074
|
-
</div>
|
|
1075
|
-
<div class="session-list-status ${session.status}">${session.status}</div>
|
|
1076
|
-
</div>
|
|
1077
|
-
`).join('');
|
|
1078
|
-
|
|
1079
|
-
// Show modal with sessions
|
|
1080
|
-
this.showModal(`Sessions on ${agentName}`, `
|
|
1081
|
-
<div class="sessions-modal-content">
|
|
1082
|
-
<p>Active terminal sessions (${sessions.length}):</p>
|
|
1083
|
-
<div class="session-list">
|
|
1084
|
-
${sessionsList}
|
|
1085
|
-
</div>
|
|
1086
|
-
<div class="sessions-modal-actions">
|
|
1087
|
-
<button class="btn-primary" onclick="dashboard.createNewSession('${agentId}')">
|
|
1088
|
-
+ Create New Session
|
|
1089
|
-
</button>
|
|
1090
|
-
</div>
|
|
1091
|
-
</div>
|
|
1092
|
-
`);
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
1077
|
showModal(title, content) {
|
|
1096
1078
|
// Create modal overlay
|
|
1097
1079
|
const modalOverlay = document.createElement('div');
|