All checks were successful
Dev Build / build-test (pull_request) Successful in 2m5s
140 lines
5.0 KiB
HTML
140 lines
5.0 KiB
HTML
<!-- ============================================================================
|
|
Agent Session Drawer — CUB-26
|
|
Desktop: 480px side drawer slides from right with modal overlay.
|
|
Mobile: Bottom sheet slides up from bottom.
|
|
Shows: Agent name, status badge, session key, live log tail,
|
|
recent messages, and action buttons.
|
|
============================================================================-->
|
|
|
|
<!-- Backdrop overlay -->
|
|
@if (isOpen()) {
|
|
<div
|
|
class="session-drawer-backdrop"
|
|
(click)="onBackdropClick()"
|
|
[class.session-drawer-backdrop--visible]="isOpen()"
|
|
></div>
|
|
}
|
|
|
|
<!-- Drawer panel -->
|
|
<div
|
|
#drawerPanel
|
|
class="session-drawer"
|
|
[class.session-drawer--open]="isOpen()"
|
|
[class.session-drawer--mobile]="isMobile"
|
|
(keydown)="onDrawerKeydown($event)"
|
|
role="dialog"
|
|
aria-label="Agent session details"
|
|
[attr.aria-hidden]="!isOpen()"
|
|
>
|
|
<!-- Header -->
|
|
<div class="session-drawer__header">
|
|
@if (agent) {
|
|
<div class="session-drawer__header-identity">
|
|
<span class="status-dot {{ getStatusClass(agent.status) }}" [attr.aria-label]="getStatusLabel(agent.status)"></span>
|
|
<div class="session-drawer__header-text">
|
|
<h2 class="session-drawer__title">{{ agent.displayName }}</h2>
|
|
<span class="session-drawer__role">{{ agent.role }}</span>
|
|
</div>
|
|
</div>
|
|
}
|
|
<button
|
|
class="session-drawer__close-btn"
|
|
type="button"
|
|
aria-label="Close drawer"
|
|
(click)="close()"
|
|
matIconButton
|
|
>
|
|
<mat-icon>close</mat-icon>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Content area -->
|
|
@if (agent) {
|
|
<div class="session-drawer__content">
|
|
|
|
<!-- Status & Session Key Section -->
|
|
<section class="session-drawer__section">
|
|
<div class="session-drawer__meta-row">
|
|
<span class="session-drawer__status-chip {{ getStatusChipColor(agent.status) }}">
|
|
{{ getStatusLabel(agent.status) }}
|
|
</span>
|
|
@if (agent.channel) {
|
|
<span class="session-drawer__channel-badge">
|
|
<mat-icon class="session-drawer__channel-icon">chat</mat-icon>
|
|
{{ agent.channel }}
|
|
</span>
|
|
}
|
|
</div>
|
|
<div class="session-drawer__session-key">
|
|
<span class="session-drawer__label">Session Key</span>
|
|
<code class="session-drawer__key-value">{{ agent.sessionKey }}</code>
|
|
</div>
|
|
@if (agent.currentTask) {
|
|
<div class="session-drawer__task-info">
|
|
<span class="session-drawer__label">Current Task</span>
|
|
<span class="session-drawer__task-text">{{ agent.currentTask }}</span>
|
|
</div>
|
|
}
|
|
<div class="session-drawer__last-activity">
|
|
<span class="session-drawer__label">Last Activity</span>
|
|
<span class="session-drawer__activity-time">{{ formatRelativeTime(agent.lastActivity) }}</span>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Recent Messages Section -->
|
|
<section class="session-drawer__section">
|
|
<h3 class="session-drawer__section-title">Recent Messages</h3>
|
|
<div class="session-drawer__messages">
|
|
@for (msg of recentMessages(); track msg.id) {
|
|
<div class="session-drawer__message session-drawer__message--{{ msg.sender }}">
|
|
<span class="session-drawer__message-sender">
|
|
{{ msg.sender === 'agent' ? agent.displayName : 'You' }}
|
|
</span>
|
|
<p class="session-drawer__message-text">{{ msg.content }}</p>
|
|
<span class="session-drawer__message-time">{{ formatTime(msg.timestamp) }}</span>
|
|
</div>
|
|
} @empty {
|
|
<p class="session-drawer__empty-state">No recent messages</p>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Live Log Tail Section -->
|
|
<section class="session-drawer__section">
|
|
<h3 class="session-drawer__section-title">Live Log</h3>
|
|
<div class="session-drawer__log-container">
|
|
@for (line of logLines(); track $index) {
|
|
<div class="session-drawer__log-line {{ getLogLevelClass(line.level) }}">
|
|
<span class="session-drawer__log-time">{{ formatTime(line.timestamp) }}</span>
|
|
<span class="session-drawer__log-level">{{ line.level.toUpperCase() }}</span>
|
|
<span class="session-drawer__log-message">{{ line.message }}</span>
|
|
</div>
|
|
} @empty {
|
|
<p class="session-drawer__empty-state">No log output</p>
|
|
}
|
|
</div>
|
|
</section>
|
|
</div>
|
|
}
|
|
|
|
<!-- Action buttons (sticky footer) -->
|
|
<div class="session-drawer__actions">
|
|
<button
|
|
class="session-drawer__action-btn session-drawer__action-btn--primary"
|
|
mat-raised-button
|
|
color="primary"
|
|
(click)="onOpenSession()"
|
|
>
|
|
<mat-icon>open_in_new</mat-icon>
|
|
Open Full Session
|
|
</button>
|
|
<button
|
|
class="session-drawer__action-btn session-drawer__action-btn--secondary"
|
|
mat-stroked-button
|
|
(click)="onPinToDashboard()"
|
|
>
|
|
<mat-icon>push_pin</mat-icon>
|
|
Pin to Dashboard
|
|
</button>
|
|
</div>
|
|
</div> |