frontend: enhance navigation and error handling
This commit is contained in:
parent
4053cfd572
commit
d2371120d8
@ -1,10 +1,11 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { ErrorReason } from '@lib/models/navigation.model';
|
||||
import { AuthMode, ParticipantRole } from '@lib/typings/ce';
|
||||
import { AuthService, ContextService, HttpService, SessionStorageService } from '../services';
|
||||
import { AuthService, ContextService, HttpService, NavigationService, SessionStorageService } from '../services';
|
||||
|
||||
export const checkUserAuthenticatedGuard: CanActivateFn = async (
|
||||
route: ActivatedRouteSnapshot,
|
||||
_route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
) => {
|
||||
const authService = inject(AuthService);
|
||||
@ -23,11 +24,29 @@ export const checkUserAuthenticatedGuard: CanActivateFn = async (
|
||||
return true;
|
||||
};
|
||||
|
||||
export const checkUserNotAuthenticatedGuard: CanActivateFn = async (
|
||||
_route: ActivatedRouteSnapshot,
|
||||
_state: RouterStateSnapshot
|
||||
) => {
|
||||
const authService = inject(AuthService);
|
||||
const router = inject(Router);
|
||||
|
||||
// Check if user is not authenticated
|
||||
const isAuthenticated = await authService.isUserAuthenticated();
|
||||
if (isAuthenticated) {
|
||||
// Redirect to the console page
|
||||
return router.createUrlTree(['console']);
|
||||
}
|
||||
|
||||
// Allow access to the requested page
|
||||
return true;
|
||||
};
|
||||
|
||||
export const checkParticipantRoleAndAuthGuard: CanActivateFn = async (
|
||||
_route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
) => {
|
||||
const router = inject(Router);
|
||||
const navigationService = inject(NavigationService);
|
||||
const authService = inject(AuthService);
|
||||
const contextService = inject(ContextService);
|
||||
const sessionStorageService = inject(SessionStorageService);
|
||||
@ -49,12 +68,12 @@ export const checkParticipantRoleAndAuthGuard: CanActivateFn = async (
|
||||
switch (error.status) {
|
||||
case 400:
|
||||
// Invalid secret
|
||||
return redirectToErrorPage(router, 'invalid-secret');
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.INVALID_ROOM_SECRET);
|
||||
case 404:
|
||||
// Room not found
|
||||
return redirectToErrorPage(router, 'invalid-room');
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.INVALID_ROOM);
|
||||
default:
|
||||
return redirectToErrorPage(router, 'internal-error');
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,34 +91,10 @@ export const checkParticipantRoleAndAuthGuard: CanActivateFn = async (
|
||||
const isAuthenticated = await authService.isUserAuthenticated();
|
||||
if (!isAuthenticated) {
|
||||
// Redirect to the login page with query param to redirect back to the room
|
||||
return router.createUrlTree(['login'], {
|
||||
queryParams: { redirectTo: state.url }
|
||||
});
|
||||
return navigationService.createRedirectionToLoginPage(state.url);
|
||||
}
|
||||
}
|
||||
|
||||
// Allow access to the room
|
||||
return true;
|
||||
};
|
||||
|
||||
export const checkUserNotAuthenticatedGuard: CanActivateFn = async (
|
||||
route: ActivatedRouteSnapshot,
|
||||
_state: RouterStateSnapshot
|
||||
) => {
|
||||
const authService = inject(AuthService);
|
||||
const router = inject(Router);
|
||||
|
||||
// Check if user is not authenticated
|
||||
const isAuthenticated = await authService.isUserAuthenticated();
|
||||
if (isAuthenticated) {
|
||||
// Redirect to the console page
|
||||
return router.createUrlTree(['console']);
|
||||
}
|
||||
|
||||
// Allow access to the requested page
|
||||
return true;
|
||||
};
|
||||
|
||||
const redirectToErrorPage = (router: Router, reason: string): UrlTree => {
|
||||
return router.createUrlTree(['error'], { queryParams: { reason } });
|
||||
};
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router';
|
||||
import { ContextService } from '../services';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn } from '@angular/router';
|
||||
import { ContextService, NavigationService } from '../services';
|
||||
import { ErrorReason } from '@lib/models/navigation.model';
|
||||
|
||||
export const extractRoomQueryParamsGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {
|
||||
const router = inject(Router);
|
||||
const navigationService = inject(NavigationService);
|
||||
const contextService = inject(ContextService);
|
||||
const { roomId, participantName, secret, leaveRedirectUrl, viewRecordings } = extractParams(route);
|
||||
|
||||
@ -11,24 +12,33 @@ export const extractRoomQueryParamsGuard: CanActivateFn = (route: ActivatedRoute
|
||||
contextService.setLeaveRedirectUrl(leaveRedirectUrl);
|
||||
}
|
||||
|
||||
if (!secret) {
|
||||
// If no secret is provided, redirect to the error page
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.MISSING_ROOM_SECRET);
|
||||
}
|
||||
|
||||
contextService.setRoomId(roomId);
|
||||
contextService.setParticipantName(participantName);
|
||||
contextService.setSecret(secret);
|
||||
|
||||
if (viewRecordings === 'true') {
|
||||
// Redirect to the room recordings page
|
||||
return router.createUrlTree([`room/${roomId}/recordings`], {
|
||||
queryParams: { secret }
|
||||
});
|
||||
return navigationService.createRedirectionToRecordingsPage(roomId, secret);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
export const extractRecordingQueryParamsGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {
|
||||
const navigationService = inject(NavigationService);
|
||||
const contextService = inject(ContextService);
|
||||
const { roomId, secret } = extractParams(route);
|
||||
|
||||
if (!secret) {
|
||||
// If no secret is provided, redirect to the error page
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.MISSING_ROOM_SECRET);
|
||||
}
|
||||
|
||||
contextService.setRoomId(roomId);
|
||||
contextService.setSecret(secret);
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { CanActivateFn, NavigationEnd } from '@angular/router';
|
||||
import { Router } from '@angular/router';
|
||||
import { ContextService, HttpService, SessionStorageService } from '../services';
|
||||
import { CanActivateFn, NavigationEnd, Router } from '@angular/router';
|
||||
import { filter, take } from 'rxjs';
|
||||
import { ContextService, NavigationService, SessionStorageService } from '../services';
|
||||
|
||||
/**
|
||||
* Guard that intercepts navigation to remove the 'secret' query parameter from the URL
|
||||
@ -12,10 +10,9 @@ import { filter, take } from 'rxjs';
|
||||
* enhance security.
|
||||
*/
|
||||
export const removeModeratorSecretGuard: CanActivateFn = (route, _state) => {
|
||||
const httpService = inject(HttpService);
|
||||
const contextService = inject(ContextService);
|
||||
const navigationService = inject(NavigationService);
|
||||
const router = inject(Router);
|
||||
const location: Location = inject(Location);
|
||||
const sessionStorageService = inject(SessionStorageService);
|
||||
|
||||
router.events
|
||||
@ -28,36 +25,12 @@ export const removeModeratorSecretGuard: CanActivateFn = (route, _state) => {
|
||||
const roomId = contextService.getRoomId();
|
||||
const storedSecret = sessionStorageService.getModeratorSecret(roomId);
|
||||
const moderatorSecret = storedSecret || contextService.getSecret();
|
||||
|
||||
// Store the moderator secret in session storage for the current room and remove it from the URL
|
||||
sessionStorageService.setModeratorSecret(roomId, moderatorSecret);
|
||||
|
||||
// Remove secret from URL
|
||||
const queryParams = { ...route.queryParams };
|
||||
delete queryParams['secret'];
|
||||
const urlTree = router.createUrlTree([], { queryParams });
|
||||
const newUrl = router.serializeUrl(urlTree);
|
||||
|
||||
location.replaceState(newUrl);
|
||||
navigationService.removeModeratorSecretFromUrl(route.queryParams);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const getUrlSecret = async (
|
||||
httpService: HttpService,
|
||||
roomId: string
|
||||
): Promise<{ moderatorSecret: string; publisherSecret: string }> => {
|
||||
const { moderatorRoomUrl, publisherRoomUrl } = await httpService.getRoom(roomId);
|
||||
|
||||
const extractSecret = (urlString: string, type: string): string => {
|
||||
const url = new URL(urlString);
|
||||
const secret = url.searchParams.get('secret');
|
||||
if (!secret) throw new Error(`${type} secret not found`);
|
||||
return secret;
|
||||
};
|
||||
|
||||
const publisherSecret = extractSecret(publisherRoomUrl, 'Publisher');
|
||||
const moderatorSecret = extractSecret(moderatorRoomUrl, 'Moderator');
|
||||
|
||||
return { publisherSecret, moderatorSecret };
|
||||
};
|
||||
|
||||
@ -1,13 +1,7 @@
|
||||
import { inject } from '@angular/core';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
Router,
|
||||
RouterStateSnapshot,
|
||||
CanActivateFn,
|
||||
UrlTree,
|
||||
RedirectCommand
|
||||
} from '@angular/router';
|
||||
import { ContextService, HttpService, SessionStorageService } from '../services';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot } from '@angular/router';
|
||||
import { ErrorReason } from '@lib/models/navigation.model';
|
||||
import { ContextService, HttpService, NavigationService, SessionStorageService } from '../services';
|
||||
|
||||
/**
|
||||
* Guard to validate the access to recordings.
|
||||
@ -18,7 +12,7 @@ export const validateRecordingAccessGuard: CanActivateFn = async (
|
||||
) => {
|
||||
const httpService = inject(HttpService);
|
||||
const contextService = inject(ContextService);
|
||||
const router = inject(Router);
|
||||
const navigationService = inject(NavigationService);
|
||||
const sessionStorageService = inject(SessionStorageService);
|
||||
|
||||
const roomId = contextService.getRoomId();
|
||||
@ -32,7 +26,7 @@ export const validateRecordingAccessGuard: CanActivateFn = async (
|
||||
|
||||
if (!contextService.canRetrieveRecordings()) {
|
||||
// If the user does not have permission to retrieve recordings, redirect to the error page
|
||||
return redirectToErrorPage(router, 'unauthorized-recording-access');
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.UNAUTHORIZED_RECORDING_ACCESS);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -41,19 +35,15 @@ export const validateRecordingAccessGuard: CanActivateFn = async (
|
||||
switch (error.status) {
|
||||
case 400:
|
||||
// Invalid secret
|
||||
return redirectToErrorPage(router, 'invalid-secret');
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.INVALID_RECORDING_SECRET);
|
||||
case 403:
|
||||
// Recording access is configured for admins only
|
||||
return redirectToErrorPage(router, 'recordings-admin-only-access');
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.RECORDINGS_ADMIN_ONLY_ACCESS);
|
||||
case 404:
|
||||
// There are no recordings in the room or the room does not exist
|
||||
return redirectToErrorPage(router, 'no-recordings');
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.NO_RECORDINGS);
|
||||
default:
|
||||
return redirectToErrorPage(router, 'internal-error');
|
||||
return navigationService.createRedirectionToErrorPage(ErrorReason.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const redirectToErrorPage = (router: Router, reason: string): UrlTree => {
|
||||
return router.createUrlTree(['error'], { queryParams: { reason } });
|
||||
};
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
export interface ErrorRedirectReason {
|
||||
'invalid-secret': string;
|
||||
'invalid-room': string;
|
||||
'internal-error': string;
|
||||
export const enum ErrorReason {
|
||||
MISSING_ROOM_SECRET = 'missing-room-secret',
|
||||
MISSING_RECORDING_SECRET = 'missing-recording-secret',
|
||||
INVALID_ROOM_SECRET = 'invalid-room-secret',
|
||||
INVALID_RECORDING_SECRET = 'invalid-recording-secret',
|
||||
INVALID_ROOM = 'invalid-room',
|
||||
INVALID_RECORDING = 'invalid-recording',
|
||||
NO_RECORDINGS = 'no-recordings',
|
||||
UNAUTHORIZED_RECORDING_ACCESS = 'unauthorized-recording-access',
|
||||
RECORDINGS_ADMIN_ONLY_ACCESS = 'recordings-admin-only-access',
|
||||
INTERNAL_ERROR = 'internal-error'
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ErrorReason } from '@lib/models/navigation.model';
|
||||
|
||||
@Component({
|
||||
selector: 'ov-error',
|
||||
@ -19,24 +20,40 @@ export class ErrorComponent implements OnInit {
|
||||
this.route.queryParams.subscribe((params) => {
|
||||
const reason = params['reason'];
|
||||
switch (reason) {
|
||||
case 'invalid-secret':
|
||||
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';
|
||||
break;
|
||||
case ErrorReason.MISSING_RECORDING_SECRET:
|
||||
this.errorName = 'Missing secret';
|
||||
this.message = 'You need to provide a secret to access the recording';
|
||||
break;
|
||||
case ErrorReason.INVALID_ROOM_SECRET:
|
||||
this.errorName = 'Invalid secret';
|
||||
this.message =
|
||||
'The secret provided to join the room is neither valid for moderators nor publishers';
|
||||
break;
|
||||
case 'invalid-room':
|
||||
case ErrorReason.INVALID_RECORDING_SECRET:
|
||||
this.errorName = 'Invalid secret';
|
||||
this.message = 'The secret provided to access the recording is invalid';
|
||||
break;
|
||||
case ErrorReason.INVALID_ROOM:
|
||||
this.errorName = 'Invalid room';
|
||||
this.message = 'The room you are trying to join does not exist or has been deleted';
|
||||
break;
|
||||
case 'no-recordings':
|
||||
case ErrorReason.INVALID_RECORDING:
|
||||
this.errorName = 'Invalid recording';
|
||||
this.message = 'The recording you are trying to access does not exist or has been deleted';
|
||||
break;
|
||||
case ErrorReason.NO_RECORDINGS:
|
||||
this.errorName = 'No recordings';
|
||||
this.message = 'There are no recordings in this room or the room does not exist';
|
||||
break;
|
||||
case 'unauthorized-recording-access':
|
||||
case ErrorReason.UNAUTHORIZED_RECORDING_ACCESS:
|
||||
this.errorName = 'Unauthorized recording access';
|
||||
this.message = 'You are not authorized to access the recordings in this room';
|
||||
break;
|
||||
case 'recordings-admin-only-access':
|
||||
case ErrorReason.RECORDINGS_ADMIN_ONLY_ACCESS:
|
||||
this.errorName = 'Unauthorized recording access';
|
||||
this.message = 'Recordings access is configured for admins only in this room';
|
||||
break;
|
||||
|
||||
@ -1,12 +1,19 @@
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { AsyncPipe } from '@angular/common';
|
||||
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ErrorReason } from '@lib/models/navigation.model';
|
||||
import {
|
||||
ApplicationFeatures,
|
||||
FeatureConfigurationService
|
||||
} from '@lib/services/feature-configuration/feature-configuration.service';
|
||||
import { NavigationService } from '@lib/services/navigation/navigation.service';
|
||||
import { ParticipantTokenService } from '@lib/services/participant-token/participant-token.service';
|
||||
import { RecordingManagerService } from '@lib/services/recording-manager/recording-manager.service';
|
||||
import { OpenViduMeetPermissions, ParticipantRole } from '@lib/typings/ce';
|
||||
import {
|
||||
ApiDirectiveModule,
|
||||
@ -17,6 +24,7 @@ import {
|
||||
RecordingStartRequestedEvent,
|
||||
RecordingStopRequestedEvent
|
||||
} from 'openvidu-components-angular';
|
||||
import { Observable } from 'rxjs';
|
||||
import { WebComponentEvent } from 'webcomponent/src/models/event.model';
|
||||
import { OutboundEventMessage } from 'webcomponent/src/models/message.type';
|
||||
import {
|
||||
@ -26,14 +34,6 @@ import {
|
||||
SessionStorageService,
|
||||
WebComponentManagerService
|
||||
} from '../../services';
|
||||
import { ParticipantTokenService } from '@lib/services/participant-token/participant-token.service';
|
||||
import { RecordingManagerService } from '@lib/services/recording-manager/recording-manager.service';
|
||||
import { NavigationService } from '@lib/services/navigation/navigation.service';
|
||||
import {
|
||||
ApplicationFeatures,
|
||||
FeatureConfigurationService
|
||||
} from '@lib/services/feature-configuration/feature-configuration.service';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-video-room',
|
||||
@ -155,7 +155,7 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
private async generateParticipantToken() {
|
||||
try {
|
||||
const { token, role, permissions } = await this.participantTokenService.generateToken(
|
||||
const { role, permissions } = await this.participantTokenService.generateToken(
|
||||
this.roomId,
|
||||
this.participantName,
|
||||
this.roomSecret
|
||||
@ -169,11 +169,11 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
||||
switch (error.status) {
|
||||
case 400:
|
||||
// Invalid secret
|
||||
await this.navigationService.redirectToErrorPage('invalid-secret');
|
||||
await this.navigationService.redirectToErrorPage(ErrorReason.INVALID_ROOM_SECRET);
|
||||
break;
|
||||
case 404:
|
||||
// Room not found
|
||||
await this.navigationService.redirectToErrorPage('invalid-room');
|
||||
await this.navigationService.redirectToErrorPage(ErrorReason.INVALID_ROOM);
|
||||
break;
|
||||
case 409:
|
||||
// Participant already exists.
|
||||
@ -181,7 +181,7 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
||||
this.participantForm.get('name')?.setErrors({ participantExists: true });
|
||||
throw new Error('Participant already exists in the room');
|
||||
default:
|
||||
await this.navigationService.redirectToErrorPage('internal-error');
|
||||
await this.navigationService.redirectToErrorPage(ErrorReason.INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,14 +202,14 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
// Replace secret and participant name in the URL query parameters
|
||||
this.navigationService.updateUrlQueryParams(this.route, {
|
||||
this.navigationService.updateUrlQueryParams(this.route.snapshot.queryParams, {
|
||||
secret: secretQueryParam,
|
||||
'participant-name': this.participantName
|
||||
});
|
||||
}
|
||||
|
||||
async goToRecordings() {
|
||||
await this.navigationService.goToRecordings(this.roomId, this.roomSecret);
|
||||
await this.navigationService.redirectToRecordingsPage(this.roomId, this.roomSecret);
|
||||
}
|
||||
|
||||
onParticipantConnected(event: ParticipantModel) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ErrorRedirectReason } from '@lib/models/navigation.model';
|
||||
import { ActivatedRoute, Params, Router, UrlTree } from '@angular/router';
|
||||
import { ErrorReason } from '@lib/models/navigation.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -32,7 +32,7 @@ export class NavigationService {
|
||||
/**
|
||||
* Redirects to error page with specific reason
|
||||
*/
|
||||
async redirectToErrorPage(reason: keyof ErrorRedirectReason): Promise<void> {
|
||||
async redirectToErrorPage(reason: ErrorReason): Promise<void> {
|
||||
try {
|
||||
await this.router.navigate(['error'], { queryParams: { reason } });
|
||||
} catch (error) {
|
||||
@ -40,12 +40,48 @@ export class NavigationService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URL tree for redirecting to error page
|
||||
*/
|
||||
createRedirectionToErrorPage(reason: ErrorReason): UrlTree {
|
||||
return this.router.createUrlTree(['error'], { queryParams: { reason } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URL tree for redirecting to login page with `redirectTo` query parameter
|
||||
*/
|
||||
createRedirectionToLoginPage(redirectTo: string): UrlTree {
|
||||
return this.router.createUrlTree(['login'], { queryParams: { redirectTo } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to recordings page
|
||||
*/
|
||||
async redirectToRecordingsPage(roomId: string, secret: string): Promise<void> {
|
||||
try {
|
||||
await this.router.navigate([`room/${roomId}/recordings`], {
|
||||
queryParams: { secret }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error navigating to recordings:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URL tree for redirecting to recordings page
|
||||
*/
|
||||
createRedirectionToRecordingsPage(roomId: string, secret: string): UrlTree {
|
||||
return this.router.createUrlTree([`room/${roomId}/recordings`], {
|
||||
queryParams: { secret }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates URL query parameters without navigation
|
||||
*/
|
||||
updateUrlQueryParams(route: ActivatedRoute, newParams: Record<string, any>): void {
|
||||
updateUrlQueryParams(oldParams: Params, newParams: Record<string, any>): void {
|
||||
const queryParams = {
|
||||
...route.snapshot.queryParams,
|
||||
...oldParams,
|
||||
...newParams
|
||||
};
|
||||
const urlTree = this.router.createUrlTree([], {
|
||||
@ -57,15 +93,12 @@ export class NavigationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to recordings page
|
||||
* Removes the 'secret' query parameter from the URL
|
||||
*/
|
||||
async goToRecordings(roomId: string, secret: string): Promise<void> {
|
||||
try {
|
||||
await this.router.navigate([`room/${roomId}/recordings`], {
|
||||
queryParams: { secret }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error navigating to recordings:', error);
|
||||
}
|
||||
removeModeratorSecretFromUrl(queryParams: Params): void {
|
||||
delete queryParams['secret'];
|
||||
const urlTree = this.router.createUrlTree([], { queryParams });
|
||||
const newUrl = this.router.serializeUrl(urlTree);
|
||||
this.location.replaceState(newUrl);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user