frontend: enhance recording lists component with improved empty state messaging and filter handling
This commit is contained in:
parent
5f289d12b8
commit
3513733071
@ -1,10 +1,18 @@
|
|||||||
<!-- Loading Spinner -->
|
@if (!loading && recordings.length === 0 && !showEmptyFilterMessage) {
|
||||||
@if (loading) {
|
<!-- Empty State -->
|
||||||
<div class="loading-container">
|
<div class="no-recordings-state">
|
||||||
<mat-spinner diameter="40"></mat-spinner>
|
<div class="empty-content">
|
||||||
<span>Loading recordings...</span>
|
<h3>No recordings yet</h3>
|
||||||
|
<p>Recordings from your meetings will appear here. Start a recording in any room to see them listed.</p>
|
||||||
|
<div class="getting-started-actions">
|
||||||
|
<button mat-button (click)="refresh.emit()" class="refresh-recordings-btn primary-button">
|
||||||
|
<mat-icon>refresh</mat-icon>
|
||||||
|
Refresh Recordings
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} @else if (recordings.length > 0) {
|
} @else {
|
||||||
<!-- Recordings Toolbar -->
|
<!-- Recordings Toolbar -->
|
||||||
<mat-toolbar class="recordings-toolbar">
|
<mat-toolbar class="recordings-toolbar">
|
||||||
<!-- Left Section: Search -->
|
<!-- Left Section: Search -->
|
||||||
@ -52,14 +60,26 @@
|
|||||||
|
|
||||||
<!-- Right Section: Filters -->
|
<!-- Right Section: Filters -->
|
||||||
<div class="toolbar-right">
|
<div class="toolbar-right">
|
||||||
|
@if (hasActiveFilters()) {
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="clear-btn"
|
||||||
|
(click)="clearFilters()"
|
||||||
|
[disabled]="loading"
|
||||||
|
matTooltip="Clear all filters"
|
||||||
|
>
|
||||||
|
<mat-icon>filter_alt_off</mat-icon>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
class="refresh-btn"
|
class="refresh-btn"
|
||||||
(click)="refresh.emit()"
|
(click)="refreshRecordings()"
|
||||||
[disabled]="loading"
|
[disabled]="loading"
|
||||||
matTooltip="Refresh recordings"
|
matTooltip="Refresh recordings"
|
||||||
>
|
>
|
||||||
<mat-icon> refresh </mat-icon>
|
<mat-icon>refresh</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@if (showFilters) {
|
@if (showFilters) {
|
||||||
@ -84,222 +104,220 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
|
|
||||||
<div class="table-container">
|
<!-- Loading Spinner -->
|
||||||
<table mat-table [dataSource]="recordings" class="recordings-table">
|
@if (loading) {
|
||||||
<!-- Selection Column -->
|
<div class="loading-container">
|
||||||
@if (showSelection) {
|
<mat-spinner diameter="40"></mat-spinner>
|
||||||
<ng-container matColumnDef="select">
|
<span>Loading recordings...</span>
|
||||||
<th mat-header-cell *matHeaderCellDef>
|
|
||||||
<mat-checkbox
|
|
||||||
[checked]="allSelected()"
|
|
||||||
[indeterminate]="someSelected()"
|
|
||||||
(change)="toggleAllSelection()"
|
|
||||||
[disabled]="loading"
|
|
||||||
>
|
|
||||||
</mat-checkbox>
|
|
||||||
</th>
|
|
||||||
<td mat-cell *matCellDef="let recording">
|
|
||||||
@if (canSelectRecording(recording)) {
|
|
||||||
<mat-checkbox
|
|
||||||
[checked]="isRecordingSelected(recording)"
|
|
||||||
(change)="toggleRecordingSelection(recording)"
|
|
||||||
[disabled]="loading"
|
|
||||||
>
|
|
||||||
</mat-checkbox>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
}
|
|
||||||
|
|
||||||
<!-- Room Info Column -->
|
|
||||||
@if (showRoomInfo) {
|
|
||||||
<ng-container matColumnDef="roomInfo">
|
|
||||||
<th mat-header-cell *matHeaderCellDef class="room-header">Room</th>
|
|
||||||
<td mat-cell *matCellDef="let recording" class="room-cell">
|
|
||||||
<div class="room-info">
|
|
||||||
<span class="room-name">{{ recording.roomName }}</span>
|
|
||||||
<span class="room-id">{{ recording.roomId }}</span>
|
|
||||||
<!-- @if (recording.filename) {
|
|
||||||
<span class="filename">{{ recording.filename }}</span>
|
|
||||||
} -->
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
}
|
|
||||||
|
|
||||||
<!-- Status Column -->
|
|
||||||
<ng-container matColumnDef="status">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Status</th>
|
|
||||||
<td mat-cell *matCellDef="let recording">
|
|
||||||
<div class="status-badge" [style.color]="getStatusColor(recording.status)">
|
|
||||||
<mat-icon [style.color]="getStatusColor(recording.status)">
|
|
||||||
{{ getStatusIcon(recording.status) }}
|
|
||||||
</mat-icon>
|
|
||||||
<span class="status-label">{{ getStatusLabel(recording.status) }}</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<!-- Start Date Column -->
|
|
||||||
<ng-container matColumnDef="startDate">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Start Date</th>
|
|
||||||
<td mat-cell *matCellDef="let recording">
|
|
||||||
@if (recording.startDate) {
|
|
||||||
<div class="date-info">
|
|
||||||
<span class="date">{{ recording.startDate | date: 'mediumDate' }}</span>
|
|
||||||
<span class="time">{{ recording.startDate | date: 'shortTime' }}</span>
|
|
||||||
</div>
|
|
||||||
} @else {
|
|
||||||
<span class="no-data">-</span>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<!-- Duration Column -->
|
|
||||||
<ng-container matColumnDef="duration">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Duration</th>
|
|
||||||
<td mat-cell *matCellDef="let recording">
|
|
||||||
<span>{{ formatDuration(recording.duration) }}</span>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<!-- Size Column -->
|
|
||||||
<ng-container matColumnDef="size">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Size</th>
|
|
||||||
<td mat-cell *matCellDef="let recording">
|
|
||||||
<span>{{ formatFileSize(recording.size) }}</span>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<!-- Actions Column -->
|
|
||||||
<ng-container matColumnDef="actions">
|
|
||||||
<th mat-header-cell *matHeaderCellDef class="actions-header">Actions</th>
|
|
||||||
<td mat-cell *matCellDef="let recording" class="actions-cell">
|
|
||||||
<div class="action-buttons">
|
|
||||||
<!-- Play Button -->
|
|
||||||
@if (canPlayRecording(recording)) {
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
matTooltip="Play Recording"
|
|
||||||
(click)="playRecording(recording)"
|
|
||||||
[disabled]="loading"
|
|
||||||
id="play-recording-btn-{{ recording.recordingId }}"
|
|
||||||
>
|
|
||||||
<mat-icon>play_arrow</mat-icon>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
<!-- Download Button -->
|
|
||||||
@if (canDownloadRecording(recording)) {
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
matTooltip="Download Recording"
|
|
||||||
(click)="downloadRecording(recording)"
|
|
||||||
[disabled]="loading"
|
|
||||||
id="download-recording-btn-{{ recording.recordingId }}"
|
|
||||||
>
|
|
||||||
<mat-icon>download</mat-icon>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (isRecordingFailed(recording)) {
|
|
||||||
<button
|
|
||||||
class="delete-action"
|
|
||||||
mat-icon-button
|
|
||||||
matTooltip="Delete Recording"
|
|
||||||
(click)="deleteRecording(recording)"
|
|
||||||
[disabled]="loading"
|
|
||||||
id="delete-recording-btn-{{ recording.recordingId }}"
|
|
||||||
>
|
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
</button>
|
|
||||||
} @else {
|
|
||||||
<!-- More Actions Menu -->
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
[matMenuTriggerFor]="actionsMenu"
|
|
||||||
matTooltip="More Actions"
|
|
||||||
[disabled]="loading"
|
|
||||||
id="more-actions-btn-{{ recording.recordingId }}"
|
|
||||||
>
|
|
||||||
<mat-icon>more_vert</mat-icon>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<mat-menu #actionsMenu="matMenu">
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
(click)="shareRecordingLink(recording)"
|
|
||||||
id="share-recording-link-{{ recording.recordingId }}"
|
|
||||||
>
|
|
||||||
<mat-icon>share</mat-icon>
|
|
||||||
<span>Share link</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
@if (canDeleteRecording(recording)) {
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
<button
|
|
||||||
mat-menu-item
|
|
||||||
(click)="deleteRecording(recording)"
|
|
||||||
class="delete-action"
|
|
||||||
id="delete-recording-btn-{{ recording.recordingId }}"
|
|
||||||
>
|
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
<span>Delete recording</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</mat-menu>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
|
||||||
<tr
|
|
||||||
mat-row
|
|
||||||
*matRowDef="let row; columns: displayedColumns"
|
|
||||||
[class.selected-row]="isRecordingSelected(row)"
|
|
||||||
></tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Load More Section -->
|
|
||||||
@if (showLoadMore) {
|
|
||||||
<div class="load-more-container" id="load-more-container">
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
class="load-more-btn"
|
|
||||||
(click)="loadMoreRecordings()"
|
|
||||||
[disabled]="loading"
|
|
||||||
id="load-more-btn"
|
|
||||||
>
|
|
||||||
<mat-icon>expand_more</mat-icon>
|
|
||||||
<span>Load More Recordings</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
} @else if (recordings.length === 0 && showEmptyFilterMessage) {
|
||||||
} @else {
|
<!-- No recordings match the current filters -->
|
||||||
<!-- Empty State -->
|
<div class="no-recordings-state">
|
||||||
<div class="no-recordings-state">
|
<div class="empty-content">
|
||||||
<div class="empty-content">
|
<h3>No recordings match your search criteria and/or filters</h3>
|
||||||
<h3>No recordings yet</h3>
|
|
||||||
<p>Recordings from your meetings will appear here. Start a recording in any room to see them listed.</p>
|
|
||||||
<div class="getting-started-actions">
|
|
||||||
<button mat-button (click)="refresh.emit()" class="refresh-recordings-btn primary-button">
|
|
||||||
<mat-icon>refresh</mat-icon>
|
|
||||||
Refresh Recordings
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<!-- TODO: Show this when no recordings match the filters
|
|
||||||
@if (hasActiveFilters()) {
|
|
||||||
<h3>No recordings match your search criteria</h3>
|
|
||||||
<p>Try adjusting or clearing your filters to see more recordings.</p>
|
<p>Try adjusting or clearing your filters to see more recordings.</p>
|
||||||
<div class="getting-started-actions">
|
<div class="getting-started-actions">
|
||||||
<button mat-raised-button color="primary" (click)="clearFilters()" class="clear-filters-btn">
|
<button mat-button (click)="clearFilters()" class="clear-filters-btn primary-button">
|
||||||
<mat-icon>filter_alt_off</mat-icon>
|
<mat-icon>filter_alt_off</mat-icon>
|
||||||
Clear Filters
|
Clear Filters
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
} -->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
} @else {
|
||||||
|
<!-- Recordings Table -->
|
||||||
|
<div class="table-container">
|
||||||
|
<table mat-table [dataSource]="recordings" class="recordings-table">
|
||||||
|
<!-- Selection Column -->
|
||||||
|
@if (showSelection) {
|
||||||
|
<ng-container matColumnDef="select">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>
|
||||||
|
<mat-checkbox
|
||||||
|
[checked]="allSelected()"
|
||||||
|
[indeterminate]="someSelected()"
|
||||||
|
(change)="toggleAllSelection()"
|
||||||
|
[disabled]="loading"
|
||||||
|
>
|
||||||
|
</mat-checkbox>
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let recording">
|
||||||
|
@if (canSelectRecording(recording)) {
|
||||||
|
<mat-checkbox
|
||||||
|
[checked]="isRecordingSelected(recording)"
|
||||||
|
(change)="toggleRecordingSelection(recording)"
|
||||||
|
[disabled]="loading"
|
||||||
|
>
|
||||||
|
</mat-checkbox>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Room Info Column -->
|
||||||
|
@if (showRoomInfo) {
|
||||||
|
<ng-container matColumnDef="roomInfo">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="room-header">Room</th>
|
||||||
|
<td mat-cell *matCellDef="let recording" class="room-cell">
|
||||||
|
<div class="room-info">
|
||||||
|
<span class="room-name">{{ recording.roomName }}</span>
|
||||||
|
<span class="room-id">{{ recording.roomId }}</span>
|
||||||
|
<!-- @if (recording.filename) {
|
||||||
|
<span class="filename">{{ recording.filename }}</span>
|
||||||
|
} -->
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Status Column -->
|
||||||
|
<ng-container matColumnDef="status">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Status</th>
|
||||||
|
<td mat-cell *matCellDef="let recording">
|
||||||
|
<div class="status-badge" [style.color]="getStatusColor(recording.status)">
|
||||||
|
<mat-icon [style.color]="getStatusColor(recording.status)">
|
||||||
|
{{ getStatusIcon(recording.status) }}
|
||||||
|
</mat-icon>
|
||||||
|
<span class="status-label">{{ getStatusLabel(recording.status) }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Start Date Column -->
|
||||||
|
<ng-container matColumnDef="startDate">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Start Date</th>
|
||||||
|
<td mat-cell *matCellDef="let recording">
|
||||||
|
@if (recording.startDate) {
|
||||||
|
<div class="date-info">
|
||||||
|
<span class="date">{{ recording.startDate | date: 'mediumDate' }}</span>
|
||||||
|
<span class="time">{{ recording.startDate | date: 'shortTime' }}</span>
|
||||||
|
</div>
|
||||||
|
} @else {
|
||||||
|
<span class="no-data">-</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Duration Column -->
|
||||||
|
<ng-container matColumnDef="duration">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Duration</th>
|
||||||
|
<td mat-cell *matCellDef="let recording">
|
||||||
|
<span>{{ formatDuration(recording.duration) }}</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Size Column -->
|
||||||
|
<ng-container matColumnDef="size">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>Size</th>
|
||||||
|
<td mat-cell *matCellDef="let recording">
|
||||||
|
<span>{{ formatFileSize(recording.size) }}</span>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Actions Column -->
|
||||||
|
<ng-container matColumnDef="actions">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="actions-header">Actions</th>
|
||||||
|
<td mat-cell *matCellDef="let recording" class="actions-cell">
|
||||||
|
<div class="action-buttons">
|
||||||
|
<!-- Play Button -->
|
||||||
|
@if (canPlayRecording(recording)) {
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
matTooltip="Play Recording"
|
||||||
|
(click)="playRecording(recording)"
|
||||||
|
[disabled]="loading"
|
||||||
|
id="play-recording-btn-{{ recording.recordingId }}"
|
||||||
|
>
|
||||||
|
<mat-icon>play_arrow</mat-icon>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Download Button -->
|
||||||
|
@if (canDownloadRecording(recording)) {
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
matTooltip="Download Recording"
|
||||||
|
(click)="downloadRecording(recording)"
|
||||||
|
[disabled]="loading"
|
||||||
|
id="download-recording-btn-{{ recording.recordingId }}"
|
||||||
|
>
|
||||||
|
<mat-icon>download</mat-icon>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (isRecordingFailed(recording)) {
|
||||||
|
<button
|
||||||
|
class="delete-action"
|
||||||
|
mat-icon-button
|
||||||
|
matTooltip="Delete Recording"
|
||||||
|
(click)="deleteRecording(recording)"
|
||||||
|
[disabled]="loading"
|
||||||
|
id="delete-recording-btn-{{ recording.recordingId }}"
|
||||||
|
>
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
</button>
|
||||||
|
} @else {
|
||||||
|
<!-- More Actions Menu -->
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
[matMenuTriggerFor]="actionsMenu"
|
||||||
|
matTooltip="More Actions"
|
||||||
|
[disabled]="loading"
|
||||||
|
id="more-actions-btn-{{ recording.recordingId }}"
|
||||||
|
>
|
||||||
|
<mat-icon>more_vert</mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<mat-menu #actionsMenu="matMenu">
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
(click)="shareRecordingLink(recording)"
|
||||||
|
id="share-recording-link-{{ recording.recordingId }}"
|
||||||
|
>
|
||||||
|
<mat-icon>share</mat-icon>
|
||||||
|
<span>Share link</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
@if (canDeleteRecording(recording)) {
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
(click)="deleteRecording(recording)"
|
||||||
|
class="delete-action"
|
||||||
|
id="delete-recording-btn-{{ recording.recordingId }}"
|
||||||
|
>
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
<span>Delete recording</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</mat-menu>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr
|
||||||
|
mat-row
|
||||||
|
*matRowDef="let row; columns: displayedColumns"
|
||||||
|
[class.selected-row]="isRecordingSelected(row)"
|
||||||
|
></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Load More Section -->
|
||||||
|
@if (showLoadMore) {
|
||||||
|
<div class="load-more-container" id="load-more-container">
|
||||||
|
<button
|
||||||
|
mat-button
|
||||||
|
class="load-more-btn"
|
||||||
|
(click)="loadMoreRecordings()"
|
||||||
|
[disabled]="loading"
|
||||||
|
id="load-more-btn"
|
||||||
|
>
|
||||||
|
<mat-icon>expand_more</mat-icon>
|
||||||
|
<span>Load More Recordings</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,10 @@
|
|||||||
::ng-deep .refresh-btn {
|
::ng-deep .refresh-btn {
|
||||||
padding: var(--ov-meet-spacing-sm);
|
padding: var(--ov-meet-spacing-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::ng-deep .clear-btn {
|
||||||
|
padding: var(--ov-meet-spacing-sm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +156,10 @@
|
|||||||
.refresh-recordings-btn {
|
.refresh-recordings-btn {
|
||||||
@extend .refresh-btn;
|
@extend .refresh-btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.clear-filters-btn {
|
||||||
|
@extend .refresh-btn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -90,6 +90,7 @@ export class RecordingListsComponent implements OnInit, OnChanges {
|
|||||||
@Input() showRoomInfo = true;
|
@Input() showRoomInfo = true;
|
||||||
@Input() showLoadMore = false;
|
@Input() showLoadMore = false;
|
||||||
@Input() loading = false;
|
@Input() loading = false;
|
||||||
|
@Input() initialFilters: { nameFilter: string; statusFilter: string } = { nameFilter: '', statusFilter: '' };
|
||||||
|
|
||||||
// Host binding for styling when recordings are selected
|
// Host binding for styling when recordings are selected
|
||||||
@HostBinding('class.has-selections')
|
@HostBinding('class.has-selections')
|
||||||
@ -107,6 +108,8 @@ export class RecordingListsComponent implements OnInit, OnChanges {
|
|||||||
nameFilterControl = new FormControl('');
|
nameFilterControl = new FormControl('');
|
||||||
statusFilterControl = new FormControl('');
|
statusFilterControl = new FormControl('');
|
||||||
|
|
||||||
|
showEmptyFilterMessage = false; // Show message when no recordings match filters
|
||||||
|
|
||||||
// Selection state
|
// Selection state
|
||||||
selectedRecordings = signal<Set<string>>(new Set());
|
selectedRecordings = signal<Set<string>>(new Set());
|
||||||
allSelected = signal(false);
|
allSelected = signal(false);
|
||||||
@ -156,16 +159,28 @@ export class RecordingListsComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (changes['recordings']) {
|
if (changes['recordings']) {
|
||||||
|
// Update selected recordings based on current recordings
|
||||||
const validIds = new Set(this.recordings.map((r) => r.recordingId));
|
const validIds = new Set(this.recordings.map((r) => r.recordingId));
|
||||||
const filteredSelection = new Set([...this.selectedRecordings()].filter((id) => validIds.has(id)));
|
const filteredSelection = new Set([...this.selectedRecordings()].filter((id) => validIds.has(id)));
|
||||||
this.selectedRecordings.set(filteredSelection);
|
this.selectedRecordings.set(filteredSelection);
|
||||||
this.updateSelectionState();
|
this.updateSelectionState();
|
||||||
|
|
||||||
|
// Show message when no recordings match filters
|
||||||
|
if (this.recordings.length === 0 && this.hasActiveFilters()) {
|
||||||
|
this.showEmptyFilterMessage = true;
|
||||||
|
} else {
|
||||||
|
this.showEmptyFilterMessage = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== INITIALIZATION METHODS =====
|
// ===== INITIALIZATION METHODS =====
|
||||||
|
|
||||||
private setupFilters() {
|
private setupFilters() {
|
||||||
|
// Set up initial filter values
|
||||||
|
this.nameFilterControl.setValue(this.initialFilters.nameFilter);
|
||||||
|
this.statusFilterControl.setValue(this.initialFilters.statusFilter);
|
||||||
|
|
||||||
// Set up name filter with debounce
|
// Set up name filter with debounce
|
||||||
this.nameFilterControl.valueChanges.pipe(debounceTime(300), distinctUntilChanged()).subscribe((value) => {
|
this.nameFilterControl.valueChanges.pipe(debounceTime(300), distinctUntilChanged()).subscribe((value) => {
|
||||||
this.filterChange.emit({
|
this.filterChange.emit({
|
||||||
|
|||||||
@ -38,6 +38,7 @@
|
|||||||
[showFilters]="false"
|
[showFilters]="false"
|
||||||
[showSelection]="true"
|
[showSelection]="true"
|
||||||
[showLoadMore]="hasMoreRecordings"
|
[showLoadMore]="hasMoreRecordings"
|
||||||
|
[initialFilters]="initialFilters"
|
||||||
(recordingAction)="onRecordingAction($event)"
|
(recordingAction)="onRecordingAction($event)"
|
||||||
(loadMore)="loadMoreRecordings($event)"
|
(loadMore)="loadMoreRecordings($event)"
|
||||||
(refresh)="refreshRecordings($event)"
|
(refresh)="refreshRecordings($event)"
|
||||||
|
|||||||
@ -22,6 +22,11 @@ export class RecordingsComponent implements OnInit {
|
|||||||
showInitialLoader = false;
|
showInitialLoader = false;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
|
||||||
|
initialFilters = {
|
||||||
|
nameFilter: '',
|
||||||
|
statusFilter: ''
|
||||||
|
};
|
||||||
|
|
||||||
// Pagination
|
// Pagination
|
||||||
hasMoreRecordings = false;
|
hasMoreRecordings = false;
|
||||||
private nextPageToken?: string;
|
private nextPageToken?: string;
|
||||||
@ -45,7 +50,8 @@ export class RecordingsComponent implements OnInit {
|
|||||||
|
|
||||||
if (roomId) {
|
if (roomId) {
|
||||||
// If a specific room ID is provided, filter recordings by that room
|
// If a specific room ID is provided, filter recordings by that room
|
||||||
await this.loadRecordings({ nameFilter: roomId, statusFilter: '' });
|
this.initialFilters.nameFilter = roomId;
|
||||||
|
await this.loadRecordings(this.initialFilters);
|
||||||
} else {
|
} else {
|
||||||
// Load all recordings if no room ID is specified
|
// Load all recordings if no room ID is specified
|
||||||
await this.loadRecordings();
|
await this.loadRecordings();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user