frontend: refactor room recordings page layout and enhance loading state styling
This commit is contained in:
parent
6ae98e452a
commit
3c629c8511
@ -1,55 +1,49 @@
|
|||||||
<div class="dashboard-container">
|
<div class="ov-page-container">
|
||||||
<mat-toolbar class="header">
|
<!-- Room Recordings Header -->
|
||||||
<span id="header-title">
|
<div class="recordings-page-header fade-in">
|
||||||
Recordings for room: <span id="room-id">{{ roomId }}</span>
|
<div class="recordings-header">
|
||||||
</span>
|
<mat-icon class="ov-recording-icon room-icon">video_library</mat-icon>
|
||||||
</mat-toolbar>
|
<div class="room-info">
|
||||||
|
<h1 class="room-title">
|
||||||
|
Recordings for room
|
||||||
|
<span class="room-id">
|
||||||
|
{{ roomId }}
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="dashboard-body">
|
<!-- Loading State -->
|
||||||
@if (isLoading) {
|
@if (isLoading && showLoadingSpinner) {
|
||||||
@if (showLoadingSpinner) {
|
<div class="recordings-loading-container fade-in">
|
||||||
<!-- Enhanced Loading State with delay -->
|
<div class="loading-card">
|
||||||
<div class="ov-page-loading">
|
<mat-icon class="ov-recording-icon loading-icon">video_library</mat-icon>
|
||||||
<div class="loading-content">
|
<h2 class="loading-title">Loading Recordings</h2>
|
||||||
<div class="loading-header">
|
<p class="loading-subtitle">Please wait while we fetch your recordings...</p>
|
||||||
<div class="loading-title">
|
<div class="loading-spinner-container">
|
||||||
<mat-icon class="ov-recording-icon loading-icon">video_library</mat-icon>
|
<mat-spinner diameter="48"></mat-spinner>
|
||||||
<h1>Loading Recordings</h1>
|
|
||||||
</div>
|
|
||||||
<p class="loading-subtitle">Please wait while we fetch your recordings...</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="loading-spinner-container">
|
|
||||||
<mat-spinner diameter="48"></mat-spinner>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
} @else {
|
|
||||||
<div class="ov-page-container ov-mb-xxl">
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="title">
|
|
||||||
<mat-icon class="ov-recording-icon">video_library</mat-icon>
|
|
||||||
<h1>Recordings</h1>
|
|
||||||
</div>
|
|
||||||
<p class="subtitle">
|
|
||||||
Manage recordings from room, play, download, and share them with others.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="page-content">
|
|
||||||
<ov-recording-lists
|
|
||||||
[recordings]="recordings()"
|
|
||||||
[canDeleteRecordings]="canDeleteRecordings"
|
|
||||||
[loading]="isLoading"
|
|
||||||
[showFilters]="false"
|
|
||||||
[showSelection]="true"
|
|
||||||
(recordingAction)="onRecordingAction($event)"
|
|
||||||
(refresh)="refreshRecordings()"
|
|
||||||
>
|
|
||||||
</ov-recording-lists>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
</div>
|
||||||
</div>
|
}
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
@if (!isLoading || recordings().length > 0) {
|
||||||
|
<div class="recordings-content fade-in-delayed">
|
||||||
|
<div class="section-content">
|
||||||
|
<ov-recording-lists
|
||||||
|
[recordings]="recordings()"
|
||||||
|
[canDeleteRecordings]="canDeleteRecordings"
|
||||||
|
[loading]="isLoading"
|
||||||
|
[showFilters]="false"
|
||||||
|
[showSelection]="true"
|
||||||
|
(recordingAction)="onRecordingAction($event)"
|
||||||
|
(refresh)="refreshRecordings()"
|
||||||
|
class="recordings-list"
|
||||||
|
>
|
||||||
|
</ov-recording-lists>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,26 +1,146 @@
|
|||||||
@import '../../../../../../src/assets/styles/design-tokens';
|
@import '../../../../../../src/assets/styles/design-tokens';
|
||||||
|
|
||||||
.dashboard-container {
|
// === ROOM RECORDINGS PAGE LAYOUT ===
|
||||||
height: 100%;
|
|
||||||
|
.recordings-page-header {
|
||||||
|
@include ov-container;
|
||||||
|
@include ov-page-content;
|
||||||
|
padding-top: var(--ov-meet-spacing-xxl);
|
||||||
|
background: var(--ov-meet-background-color);
|
||||||
|
gap: var(--ov-meet-spacing-xxl);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
// Room Header
|
||||||
height: 50px;
|
.recordings-header {
|
||||||
background-color: var(--ov-primary-action-color);
|
@include ov-flex-center;
|
||||||
color: var(--ov-text-primary-color);
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
gap: var(--ov-meet-spacing-md);
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.room-icon {
|
||||||
|
@include ov-icon(xl);
|
||||||
|
color: var(--ov-meet-icon-recordings);
|
||||||
|
margin-bottom: var(--ov-meet-spacing-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-info {
|
||||||
|
.room-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--ov-meet-font-size-xl);
|
||||||
|
font-weight: var(--ov-meet-font-weight-light);
|
||||||
|
color: var(--ov-meet-text-primary);
|
||||||
|
line-height: var(--ov-meet-line-height-tight);
|
||||||
|
|
||||||
|
.room-id {
|
||||||
|
font-weight: var(--ov-meet-font-weight-semibold);
|
||||||
|
color: var(--ov-meet-text-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#header-title {
|
// === CONTENT SECTIONS ===
|
||||||
font-weight: bold;
|
|
||||||
|
.recordings-content {
|
||||||
|
@include ov-container;
|
||||||
|
@include ov-page-content;
|
||||||
|
margin-top: var(--ov-meet-spacing-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
#room-id {
|
// === LOADING STATE ===
|
||||||
font-weight: normal;
|
|
||||||
font-style: italic;
|
.recordings-loading-container {
|
||||||
|
@include ov-container;
|
||||||
|
@include ov-flex-center;
|
||||||
|
min-height: 60vh;
|
||||||
|
padding: var(--ov-meet-spacing-xxl);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-body {
|
.loading-card {
|
||||||
background-color: var(--ov-secondary-action-color);
|
@include ov-card;
|
||||||
height: 100%;
|
@include ov-flex-center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--ov-meet-spacing-lg);
|
||||||
|
text-align: center;
|
||||||
|
max-width: 400px;
|
||||||
|
padding: var(--ov-meet-spacing-xxl);
|
||||||
|
|
||||||
|
.loading-icon {
|
||||||
|
@include ov-icon(xl);
|
||||||
|
color: var(--ov-meet-icon-recordings);
|
||||||
|
margin-bottom: var(--ov-meet-spacing-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--ov-meet-font-size-xl);
|
||||||
|
font-weight: var(--ov-meet-font-weight-medium);
|
||||||
|
color: var(--ov-meet-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-subtitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--ov-meet-font-size-md);
|
||||||
|
color: var(--ov-meet-text-secondary);
|
||||||
|
line-height: var(--ov-meet-line-height-relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-spinner-container {
|
||||||
|
margin-top: var(--ov-meet-spacing-lg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === RESPONSIVE DESIGN ===
|
||||||
|
|
||||||
|
@include ov-tablet-down {
|
||||||
|
.recordings-page-header {
|
||||||
|
padding-top: var(--ov-meet-spacing-lg);
|
||||||
|
gap: var(--ov-meet-spacing-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.recordings-header {
|
||||||
|
.room-icon {
|
||||||
|
@include ov-icon(lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-info {
|
||||||
|
.room-title {
|
||||||
|
font-size: var(--ov-meet-font-size-xxl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-subtitle {
|
||||||
|
font-size: var(--ov-meet-font-size-md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-card {
|
||||||
|
padding: var(--ov-meet-spacing-md);
|
||||||
|
|
||||||
|
.description-content .description-text {
|
||||||
|
font-size: var(--ov-meet-font-size-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include ov-mobile-down {
|
||||||
|
.recordings-page-header {
|
||||||
|
padding: var(--ov-meet-spacing-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-card {
|
||||||
|
padding: var(--ov-meet-spacing-lg);
|
||||||
|
|
||||||
|
.loading-icon {
|
||||||
|
@include ov-icon(lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-title {
|
||||||
|
font-size: var(--ov-meet-font-size-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-subtitle {
|
||||||
|
font-size: var(--ov-meet-font-size-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import { Component, OnInit, signal } from '@angular/core';
|
import { Component, OnInit, signal } from '@angular/core';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { RecordingListsComponent, RecordingTableAction } from '@lib/components';
|
import { RecordingListsComponent, RecordingTableAction } from '@lib/components';
|
||||||
import { NotificationService, RecordingManagerService } from '@lib/services';
|
import { NavigationService, NotificationService, RecordingManagerService } from '@lib/services';
|
||||||
import { MeetRecordingFilters, MeetRecordingInfo } from '@lib/typings/ce';
|
import { MeetRecordingFilters, MeetRecordingInfo } from '@lib/typings/ce';
|
||||||
import { ILogger, LoggerService } from 'openvidu-components-angular';
|
import { ILogger, LoggerService } from 'openvidu-components-angular';
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ import { ILogger, LoggerService } from 'openvidu-components-angular';
|
|||||||
templateUrl: './room-recordings.component.html',
|
templateUrl: './room-recordings.component.html',
|
||||||
styleUrls: ['./room-recordings.component.scss'],
|
styleUrls: ['./room-recordings.component.scss'],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [MatToolbarModule, RecordingListsComponent, MatIconModule, MatProgressSpinnerModule]
|
imports: [MatToolbarModule, MatButtonModule, RecordingListsComponent, MatIconModule, MatProgressSpinnerModule]
|
||||||
})
|
})
|
||||||
export class RoomRecordingsComponent implements OnInit {
|
export class RoomRecordingsComponent implements OnInit {
|
||||||
recordings = signal<MeetRecordingInfo[]>([]);
|
recordings = signal<MeetRecordingInfo[]>([]);
|
||||||
@ -33,6 +34,7 @@ export class RoomRecordingsComponent implements OnInit {
|
|||||||
protected loggerService: LoggerService,
|
protected loggerService: LoggerService,
|
||||||
protected recordingService: RecordingManagerService,
|
protected recordingService: RecordingManagerService,
|
||||||
protected notificationService: NotificationService,
|
protected notificationService: NotificationService,
|
||||||
|
protected navigationService: NavigationService,
|
||||||
protected route: ActivatedRoute
|
protected route: ActivatedRoute
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerService.get('OpenVidu Meet - RoomRecordingsComponent');
|
this.log = this.loggerService.get('OpenVidu Meet - RoomRecordingsComponent');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user