frontend: refactor ErrorComponent to improve error handling and back navigation logic
This commit is contained in:
parent
bf0ccf9c39
commit
621064b251
@ -1,4 +1,4 @@
|
|||||||
export const enum ErrorReason {
|
export enum ErrorReason {
|
||||||
MISSING_ROOM_SECRET = 'missing-room-secret',
|
MISSING_ROOM_SECRET = 'missing-room-secret',
|
||||||
MISSING_RECORDING_SECRET = 'missing-recording-secret',
|
MISSING_RECORDING_SECRET = 'missing-recording-secret',
|
||||||
INVALID_ROOM_SECRET = 'invalid-room-secret',
|
INVALID_ROOM_SECRET = 'invalid-room-secret',
|
||||||
|
|||||||
@ -11,11 +11,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="error-actions">
|
<div class="error-actions">
|
||||||
@if (isAdmin) {
|
@if (showBackButton) {
|
||||||
<div class="fade-in-delayed-more">
|
<div class="fade-in-delayed-more">
|
||||||
<button mat-button (click)="goToConsole()">
|
<button mat-button (click)="goBack()">
|
||||||
<mat-icon>arrow_back</mat-icon>
|
<mat-icon>arrow_back</mat-icon>
|
||||||
<span>Back to Console</span>
|
<span>{{ backButtonText }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { ErrorReason } from '@lib/models';
|
import { ErrorReason } from '@lib/models';
|
||||||
import { AuthService, NavigationService } from '@lib/services';
|
import { AppDataService, AuthService, NavigationService, WebComponentManagerService } from '@lib/services';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ov-error',
|
selector: 'ov-error',
|
||||||
@ -17,67 +17,125 @@ export class ErrorComponent implements OnInit {
|
|||||||
errorName = 'Error';
|
errorName = 'Error';
|
||||||
message = '';
|
message = '';
|
||||||
|
|
||||||
|
showBackButton = true;
|
||||||
|
backButtonText = 'Back';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
protected authService: AuthService,
|
protected authService: AuthService,
|
||||||
protected navService: NavigationService
|
protected navService: NavigationService,
|
||||||
|
protected appDataService: AppDataService,
|
||||||
|
protected wcManagerService: WebComponentManagerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit() {
|
||||||
this.route.queryParams.subscribe((params) => {
|
this.setErrorReason();
|
||||||
const reason = params['reason'];
|
this.setBackButtonText();
|
||||||
switch (reason) {
|
}
|
||||||
case ErrorReason.MISSING_ROOM_SECRET:
|
|
||||||
this.errorName = 'Missing secret';
|
/**
|
||||||
this.message = 'You need to provide a secret to join the room as a moderator or publisher';
|
* Retrieves the error reason from URL query parameters
|
||||||
break;
|
*/
|
||||||
case ErrorReason.MISSING_RECORDING_SECRET:
|
private setErrorReason() {
|
||||||
this.errorName = 'Missing secret';
|
const reason = this.route.snapshot.queryParams['reason'];
|
||||||
this.message = 'You need to provide a secret to access the recording';
|
if (reason) {
|
||||||
break;
|
const { title, message } = this.mapReasonToNameAndMessage(reason);
|
||||||
case ErrorReason.INVALID_ROOM_SECRET:
|
this.errorName = title;
|
||||||
this.errorName = 'Invalid secret';
|
this.message = message;
|
||||||
this.message =
|
}
|
||||||
'The secret provided to join the room is neither valid for moderators nor publishers';
|
}
|
||||||
break;
|
|
||||||
case ErrorReason.INVALID_RECORDING_SECRET:
|
/**
|
||||||
this.errorName = 'Invalid secret';
|
* Maps technical error reasons to user-friendly names and messages
|
||||||
this.message = 'The secret provided to access the recording is invalid';
|
*/
|
||||||
break;
|
private mapReasonToNameAndMessage(reason: string): { title: string; message: string } {
|
||||||
case ErrorReason.INVALID_ROOM:
|
const reasonMap: { [key in ErrorReason]: { title: string; message: string } } = {
|
||||||
this.errorName = 'Invalid room';
|
[ErrorReason.MISSING_ROOM_SECRET]: {
|
||||||
this.message = 'The room you are trying to join does not exist or has been deleted';
|
title: 'Missing secret',
|
||||||
break;
|
message: 'You need to provide a secret to join the room as a moderator or publisher'
|
||||||
case ErrorReason.INVALID_RECORDING:
|
},
|
||||||
this.errorName = 'Invalid recording';
|
[ErrorReason.MISSING_RECORDING_SECRET]: {
|
||||||
this.message = 'The recording you are trying to access does not exist or has been deleted';
|
title: 'Missing secret',
|
||||||
break;
|
message: 'You need to provide a secret to access the recording'
|
||||||
case ErrorReason.NO_RECORDINGS:
|
},
|
||||||
this.errorName = 'No recordings';
|
[ErrorReason.INVALID_ROOM_SECRET]: {
|
||||||
this.message = 'There are no recordings in this room or the room does not exist';
|
title: 'Invalid secret',
|
||||||
break;
|
message: 'The secret provided to join the room is neither valid for moderators nor publishers'
|
||||||
case ErrorReason.UNAUTHORIZED_RECORDING_ACCESS:
|
},
|
||||||
this.errorName = 'Unauthorized recording access';
|
[ErrorReason.INVALID_RECORDING_SECRET]: {
|
||||||
this.message = 'You are not authorized to access the recordings in this room';
|
title: 'Invalid secret',
|
||||||
break;
|
message: 'The secret provided to access the recording is invalid'
|
||||||
case ErrorReason.RECORDINGS_ADMIN_ONLY_ACCESS:
|
},
|
||||||
this.errorName = 'Unauthorized recording access';
|
[ErrorReason.INVALID_ROOM]: {
|
||||||
this.message = 'Recordings access is configured for admins only in this room';
|
title: 'Invalid room',
|
||||||
break;
|
message: 'The room you are trying to join does not exist or has been deleted'
|
||||||
default:
|
},
|
||||||
this.errorName = 'Internal error';
|
[ErrorReason.INVALID_RECORDING]: {
|
||||||
this.message = 'Something went wrong...';
|
title: 'Invalid recording',
|
||||||
break;
|
message: 'The recording you are trying to access does not exist or has been deleted'
|
||||||
|
},
|
||||||
|
[ErrorReason.NO_RECORDINGS]: {
|
||||||
|
title: 'No recordings',
|
||||||
|
message: 'There are no recordings in this room or the room does not exist'
|
||||||
|
},
|
||||||
|
[ErrorReason.UNAUTHORIZED_RECORDING_ACCESS]: {
|
||||||
|
title: 'Unauthorized recording access',
|
||||||
|
message: 'You are not authorized to access the recordings in this room'
|
||||||
|
},
|
||||||
|
[ErrorReason.RECORDINGS_ADMIN_ONLY_ACCESS]: {
|
||||||
|
title: 'Unauthorized recording access',
|
||||||
|
message: 'Recordings access is configured for admins only in this room'
|
||||||
|
},
|
||||||
|
[ErrorReason.INTERNAL_ERROR]: {
|
||||||
|
title: 'Internal error',
|
||||||
|
message: 'An unexpected error occurred, please try again later'
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const normalizedReason = Object.values(ErrorReason).find((enumValue) => enumValue === reason) as
|
||||||
|
| ErrorReason
|
||||||
|
| undefined;
|
||||||
|
return reasonMap[normalizedReason ?? ErrorReason.INTERNAL_ERROR];
|
||||||
}
|
}
|
||||||
|
|
||||||
get isAdmin(): boolean {
|
/**
|
||||||
return this.authService.isAdmin();
|
* Sets the back button text based on the application mode and user role
|
||||||
|
*/
|
||||||
|
async setBackButtonText() {
|
||||||
|
const isStandaloneMode = this.appDataService.isStandaloneMode();
|
||||||
|
const redirection = this.navService.getLeaveRedirectURL();
|
||||||
|
const isAdmin = await this.authService.isAdmin();
|
||||||
|
|
||||||
|
if (isStandaloneMode && !redirection && !isAdmin) {
|
||||||
|
// If in standalone mode, no redirection URL and not an admin, hide the back button
|
||||||
|
this.showBackButton = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.showBackButton = true;
|
||||||
|
this.backButtonText = isStandaloneMode && !redirection && isAdmin ? 'Back to Console' : 'Back';
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToConsole(): Promise<void> {
|
/**
|
||||||
|
* Handles the back button click event and navigates accordingly
|
||||||
|
* If in embedded mode, it closes the WebComponentManagerService
|
||||||
|
* If in standalone mode, it navigates to the redirect URL or to the admin console
|
||||||
|
*/
|
||||||
|
async goBack() {
|
||||||
|
if (this.appDataService.isEmbeddedMode()) {
|
||||||
|
this.wcManagerService.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standalone mode handling
|
||||||
|
const redirectTo = this.navService.getLeaveRedirectURL();
|
||||||
|
if (redirectTo) {
|
||||||
|
// Navigate to the specified redirect URL
|
||||||
|
await this.navService.redirectTo(redirectTo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Navigate to the admin console
|
// Navigate to the admin console
|
||||||
await this.navService.redirectTo('/overview', false);
|
await this.navService.navigateTo('/overview', undefined, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user