frontend: Revamp video room access UI with new design and navigation features
This commit is contained in:
parent
a3560ee845
commit
0cf5eba604
@ -1,13 +1,31 @@
|
|||||||
@if (!showRoom) {
|
@if (!showRoom) {
|
||||||
<div class="form-container">
|
<div class="ov-page-container">
|
||||||
<div class="card-wrapper">
|
<div class="room-access-container fade-in">
|
||||||
<mat-card class="form-card">
|
<!-- Header Section -->
|
||||||
<h2 class="form-title">
|
<div class="room-header">
|
||||||
Access room <strong>{{ roomId }}</strong>
|
<mat-icon class="ov-room-icon room-icon">video_chat</mat-icon>
|
||||||
</h2>
|
<div class="room-info">
|
||||||
<form [formGroup]="participantForm" (ngSubmit)="submitAccessRoom()">
|
<h1 class="room-title">{{ roomId }}</h1>
|
||||||
<mat-form-field appearance="outline" class="full-width">
|
<p class="room-subtitle">Choose how you want to proceed</p>
|
||||||
<mat-label>Name</mat-label>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Action Cards Grid -->
|
||||||
|
<div class="action-cards-grid">
|
||||||
|
<!-- Join Room Card -->
|
||||||
|
<mat-card class="action-card primary-card fade-in">
|
||||||
|
<mat-card-header class="card-header">
|
||||||
|
<mat-icon class="ov-room-icon card-icon">meeting_room</mat-icon>
|
||||||
|
<div class="card-title-group">
|
||||||
|
<mat-card-title>Join Meeting</mat-card-title>
|
||||||
|
<mat-card-subtitle>Enter the room and start connecting</mat-card-subtitle>
|
||||||
|
</div>
|
||||||
|
</mat-card-header>
|
||||||
|
|
||||||
|
<mat-card-content class="card-content">
|
||||||
|
<form [formGroup]="participantForm" (ngSubmit)="submitAccessRoom()" class="join-form">
|
||||||
|
<mat-form-field appearance="outline" class="name-field">
|
||||||
|
<mat-label>Your display name</mat-label>
|
||||||
<input
|
<input
|
||||||
id="participant-name-input"
|
id="participant-name-input"
|
||||||
matInput
|
matInput
|
||||||
@ -15,6 +33,7 @@
|
|||||||
formControlName="name"
|
formControlName="name"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
<mat-icon matSuffix class="ov-action-icon">person</mat-icon>
|
||||||
@if (participantForm.get('name')?.hasError('minlength')) {
|
@if (participantForm.get('name')?.hasError('minlength')) {
|
||||||
<mat-error> The name must be at least <strong>4 characters</strong> </mat-error>
|
<mat-error> The name must be at least <strong>4 characters</strong> </mat-error>
|
||||||
}
|
}
|
||||||
@ -32,22 +51,56 @@
|
|||||||
mat-raised-button
|
mat-raised-button
|
||||||
color="primary"
|
color="primary"
|
||||||
id="participant-name-submit"
|
id="participant-name-submit"
|
||||||
class="full-width"
|
type="submit"
|
||||||
|
class="join-button"
|
||||||
[disabled]="participantForm.invalid"
|
[disabled]="participantForm.invalid"
|
||||||
>
|
>
|
||||||
Continue to room
|
<span>Join Meeting</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<mat-card class="recordings-card">
|
<!-- View Recordings Card -->
|
||||||
<div class="recordings-content">
|
@if (showRecordingCard) {
|
||||||
<h3>View recordings</h3>
|
<mat-card class="action-card secondary-card fade-in-delayed">
|
||||||
<button id="view-recordings-btn" mat-stroked-button color="accent" (click)="goToRecordings()">
|
<mat-card-header class="card-header">
|
||||||
Go to recordings
|
<mat-icon class="ov-recording-icon card-icon">video_library</mat-icon>
|
||||||
|
<div class="card-title-group">
|
||||||
|
<mat-card-title>View Recordings</mat-card-title>
|
||||||
|
<mat-card-subtitle>Browse and manage past recordings</mat-card-subtitle>
|
||||||
|
</div>
|
||||||
|
</mat-card-header>
|
||||||
|
|
||||||
|
<mat-card-content class="card-content">
|
||||||
|
<div class="recordings-info">
|
||||||
|
<p class="recordings-description">
|
||||||
|
Access previously recorded meetings from this room. You can watch, download, or
|
||||||
|
manage existing recordings.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
id="view-recordings-btn"
|
||||||
|
mat-stroked-button
|
||||||
|
color="accent"
|
||||||
|
(click)="goToRecordings()"
|
||||||
|
class="recordings-button"
|
||||||
|
>
|
||||||
|
<span>Browse Recordings</span>
|
||||||
|
</button>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Actions -->
|
||||||
|
<div class="quick-actions fade-in-delayed-more">
|
||||||
|
<button mat-button class="quick-action-button" (click)="goBack()">
|
||||||
|
<mat-icon>arrow_back</mat-icon>
|
||||||
|
<span>Back to Rooms</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</mat-card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
|
|||||||
@ -1,81 +1,264 @@
|
|||||||
.form-container {
|
@import '../../../../../../src/assets/styles/design-tokens';
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100vh;
|
|
||||||
background-color: var(--ov-meet-surface-background);
|
|
||||||
padding: 20px;
|
|
||||||
|
|
||||||
.card-wrapper {
|
// Room Access Container - Main layout using design tokens
|
||||||
display: flex;
|
.room-access-container {
|
||||||
gap: 40px;
|
@include ov-container;
|
||||||
flex-wrap: wrap;
|
@include ov-page-content;
|
||||||
justify-content: center;
|
min-height: 100vh;
|
||||||
align-items: flex-start;
|
padding-top: var(--ov-meet-spacing-xxl);
|
||||||
|
background: var(--ov-meet-background-color);
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Room Header - Clean title section
|
||||||
|
.room-header {
|
||||||
|
@include ov-flex-center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--ov-meet-spacing-md);
|
||||||
|
margin-bottom: var(--ov-meet-spacing-xxl);
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.room-icon {
|
||||||
|
@include ov-icon(xl);
|
||||||
|
color: var(--ov-meet-icon-rooms);
|
||||||
|
margin-bottom: var(--ov-meet-spacing-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-card {
|
.room-info {
|
||||||
width: 400px;
|
.room-title {
|
||||||
padding: 20px;
|
margin: 0;
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
font-size: var(--ov-meet-font-size-hero);
|
||||||
border-radius: var(--ov-meet-surface-radius);
|
font-weight: var(--ov-meet-font-weight-light);
|
||||||
background-color: var(--ov-meet-surface-primary);
|
color: var(--ov-meet-text-primary);
|
||||||
|
line-height: var(--ov-meet-line-height-tight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-subtitle {
|
||||||
|
margin: var(--ov-meet-spacing-xs) 0 0 0;
|
||||||
|
font-size: var(--ov-meet-font-size-lg);
|
||||||
|
color: var(--ov-meet-text-secondary);
|
||||||
|
line-height: var(--ov-meet-line-height-normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action Cards Grid - Responsive layout
|
||||||
|
.action-cards-grid {
|
||||||
|
@include ov-grid-responsive(320px);
|
||||||
|
gap: var(--ov-meet-spacing-xl);
|
||||||
|
margin-bottom: var(--ov-meet-spacing-xxl);
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
// When there's only one card, limit its width to maintain visual consistency
|
||||||
|
&:has(.action-card:only-child) {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.action-card {
|
||||||
|
max-width: 400px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include ov-tablet-down {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: var(--ov-meet-spacing-lg);
|
||||||
|
|
||||||
|
// On tablets and mobile, single cards should use full width
|
||||||
|
&:has(.action-card:only-child) {
|
||||||
|
.action-card {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action Card Base - Consistent card styling
|
||||||
|
.action-card {
|
||||||
|
@include ov-card;
|
||||||
|
@include ov-hover-lift(-4px);
|
||||||
|
@include ov-theme-transition;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
// Card Header
|
||||||
|
.card-header {
|
||||||
|
padding: var(--ov-meet-spacing-lg);
|
||||||
|
border-bottom: 1px solid var(--ov-meet-border-color-light);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--ov-meet-spacing-md);
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.card-icon {
|
||||||
|
@include ov-icon(lg);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title-group {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.mat-mdc-card-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--ov-meet-font-size-xl);
|
||||||
|
font-weight: var(--ov-meet-font-weight-semibold);
|
||||||
|
color: var(--ov-meet-text-primary);
|
||||||
|
line-height: var(--ov-meet-line-height-tight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-card-subtitle {
|
||||||
|
margin: var(--ov-meet-spacing-xs) 0 0 0;
|
||||||
|
font-size: var(--ov-meet-font-size-sm);
|
||||||
|
color: var(--ov-meet-text-secondary);
|
||||||
|
line-height: var(--ov-meet-line-height-normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Card Content
|
||||||
|
.card-content {
|
||||||
|
padding: var(--ov-meet-spacing-lg);
|
||||||
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.recordings-card {
|
// Primary Card - Join meeting styling
|
||||||
padding: 16px;
|
.primary-card {
|
||||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
|
.card-header {
|
||||||
border-radius: var(--ov-meet-surface-radius);
|
background: linear-gradient(135deg, var(--ov-meet-surface-color) 0%, var(--ov-meet-color-primary-light) 180%);
|
||||||
background-color: var(--ov-meet-surface-primary);
|
color: var(--ov-meet-text-on-primary);
|
||||||
width: fit-content;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.recordings-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-title {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
color: var(--ov-meet-text-primary);
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-width {
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
height: 56px;
|
|
||||||
border-radius: var(--ov-meet-surface-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
button:not([disabled]) {
|
|
||||||
background-color: var(--ov-meet-color-accent);
|
|
||||||
color: var(--ov-meet-text-on-accent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Secondary Card - Recordings styling
|
||||||
|
.secondary-card {
|
||||||
|
.card-header {
|
||||||
|
background: linear-gradient(135deg, var(--ov-meet-surface-color) 0%, var(--ov-meet-color-accent) 180%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join Form - Form styling
|
||||||
|
.join-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--ov-meet-spacing-lg);
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.name-field {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.mat-mdc-form-field-icon-suffix {
|
||||||
|
color: var(--ov-meet-text-hint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.join-button {
|
||||||
|
@include ov-button-base;
|
||||||
|
height: 56px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: var(--ov-meet-spacing-sm);
|
||||||
|
margin-top: auto;
|
||||||
|
background-color: var(--ov-meet-color-secondary);
|
||||||
|
color: var(--ov-meet-text-on-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recordings Info - Content for recordings card
|
||||||
|
.recordings-info {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--ov-meet-spacing-lg);
|
||||||
|
|
||||||
|
.recordings-description {
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--ov-meet-font-size-md);
|
||||||
|
color: var(--ov-meet-text-secondary);
|
||||||
|
line-height: var(--ov-meet-line-height-relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.recordings-button {
|
||||||
|
@include ov-button-base;
|
||||||
|
height: 56px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: var(--ov-meet-spacing-sm);
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quick Actions - Footer actions
|
||||||
|
.quick-actions {
|
||||||
|
@include ov-flex-center;
|
||||||
|
margin-top: var(--ov-meet-spacing-xl);
|
||||||
|
|
||||||
|
.quick-action-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--ov-meet-spacing-sm);
|
||||||
|
color: var(--ov-meet-text-secondary);
|
||||||
|
@include ov-theme-transition;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--ov-meet-text-primary);
|
||||||
|
background-color: var(--ov-meet-surface-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsive adjustments
|
||||||
|
@include ov-mobile-down {
|
||||||
|
.room-access-container {
|
||||||
|
padding: var(--ov-meet-spacing-lg);
|
||||||
|
padding-top: var(--ov-meet-spacing-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-header {
|
||||||
|
margin-bottom: var(--ov-meet-spacing-xl);
|
||||||
|
|
||||||
|
.room-info .room-title {
|
||||||
|
font-size: var(--ov-meet-font-size-xxl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-card {
|
||||||
|
min-height: auto;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
padding: var(--ov-meet-spacing-md);
|
||||||
|
|
||||||
|
.card-title-group {
|
||||||
|
.mat-mdc-card-title {
|
||||||
|
font-size: var(--ov-meet-font-size-lg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-content {
|
||||||
|
padding: var(--ov-meet-spacing-md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom leave button styling (existing functionality)
|
||||||
::ng-deep {
|
::ng-deep {
|
||||||
#media-buttons-container .custom-leave-btn > button {
|
#media-buttons-container .custom-leave-btn > button {
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--ov-error-color) !important;
|
background-color: var(--ov-meet-color-error) !important;
|
||||||
}
|
}
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: var(--ov-error-color) !important;
|
background-color: var(--ov-meet-color-error) !important;
|
||||||
color: var(--ov-secondary-action-color);
|
color: var(--ov-meet-text-on-primary);
|
||||||
border-radius: var(--ov-leave-button-radius) !important;
|
border-radius: var(--ov-meet-radius-sm) !important;
|
||||||
width: 65px !important;
|
width: 65px !important;
|
||||||
margin: 0px !important;
|
margin: 0px !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
|||||||
name: new FormControl('', [Validators.required, Validators.minLength(4)])
|
name: new FormControl('', [Validators.required, Validators.minLength(4)])
|
||||||
});
|
});
|
||||||
showRoom = false;
|
showRoom = false;
|
||||||
|
showRecordingCard = false;
|
||||||
roomId = '';
|
roomId = '';
|
||||||
roomSecret = '';
|
roomSecret = '';
|
||||||
participantName = '';
|
participantName = '';
|
||||||
@ -90,6 +90,14 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
|||||||
this.roomId = this.roomService.getRoomId();
|
this.roomId = this.roomService.getRoomId();
|
||||||
this.roomSecret = this.roomService.getRoomSecret();
|
this.roomSecret = this.roomService.getRoomSecret();
|
||||||
|
|
||||||
|
const { recordings } = await this.recManagerService.listRecordings({
|
||||||
|
maxItems: 1,
|
||||||
|
roomId: this.roomId,
|
||||||
|
fields: 'recordingId'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.showRecordingCard = recordings.length > 0;
|
||||||
|
|
||||||
await this.initializeParticipantName();
|
await this.initializeParticipantName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,6 +232,14 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async goBack() {
|
||||||
|
try {
|
||||||
|
await this.navigationService.navigateTo('rooms');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error navigating back to rooms:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onParticipantConnected(event: ParticipantModel) {
|
onParticipantConnected(event: ParticipantModel) {
|
||||||
const message: WebComponentOutboundEventMessage = {
|
const message: WebComponentOutboundEventMessage = {
|
||||||
event: WebComponentEvent.JOIN,
|
event: WebComponentEvent.JOIN,
|
||||||
|
|||||||
@ -7,6 +7,8 @@
|
|||||||
--ov-meet-color-primary: #1976d2;
|
--ov-meet-color-primary: #1976d2;
|
||||||
--ov-meet-color-primary-light: #42a5f5;
|
--ov-meet-color-primary-light: #42a5f5;
|
||||||
--ov-meet-color-primary-dark: #1565c0;
|
--ov-meet-color-primary-dark: #1565c0;
|
||||||
|
--ov-meet-color-secondary: #585858;
|
||||||
|
--ov-meet-color-secondary-light: #b0a7a8;
|
||||||
--ov-meet-color-accent: #7b1fa2;
|
--ov-meet-color-accent: #7b1fa2;
|
||||||
--ov-meet-color-accent-light: #9c27b0;
|
--ov-meet-color-accent-light: #9c27b0;
|
||||||
--ov-meet-color-accent-dark: #6a1b9a;
|
--ov-meet-color-accent-dark: #6a1b9a;
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
--ov-meet-text-hint: #9e9e9e;
|
--ov-meet-text-hint: #9e9e9e;
|
||||||
--ov-meet-text-disabled: #bdbdbd;
|
--ov-meet-text-disabled: #bdbdbd;
|
||||||
--ov-meet-text-on-primary: #ffffff;
|
--ov-meet-text-on-primary: #ffffff;
|
||||||
|
--ov-meet-text-on-secondary: #ffffff;
|
||||||
--ov-meet-text-on-accent: #ffffff;
|
--ov-meet-text-on-accent: #ffffff;
|
||||||
--ov-meet-text-on-surface: #212121;
|
--ov-meet-text-on-surface: #212121;
|
||||||
--ov-meet-text-on-background: #212121;
|
--ov-meet-text-on-background: #212121;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user