import { Location } from '@angular/common'; import { Injectable } from '@angular/core'; import { Params, Router, UrlTree } from '@angular/router'; import { ErrorReason } from '@lib/models'; import { AppDataService, SessionStorageService } from '@lib/services'; @Injectable({ providedIn: 'root' }) export class NavigationService { protected leaveRedirectUrl?: string; constructor( private router: Router, private location: Location, private sessionStorageService: SessionStorageService, private appDataService: AppDataService ) {} setLeaveRedirectUrl(leaveRedirectUrl: string): void { this.leaveRedirectUrl = leaveRedirectUrl; this.sessionStorageService.setRedirectUrl(leaveRedirectUrl); } getLeaveRedirectURL(): string | undefined { const storedRedirectUrl = this.sessionStorageService.getRedirectUrl(); if (!this.leaveRedirectUrl && storedRedirectUrl) { this.leaveRedirectUrl = storedRedirectUrl; } return this.leaveRedirectUrl; } /** * Navigates to a specific route * * @param route - The route to navigate to * @param queryParams - Optional query parameters to include in the navigation * @param replaceUrl - If true, replaces the current URL in the browser history */ async navigateTo(route: string, queryParams?: Params, replaceUrl: boolean = false): Promise { try { await this.router.navigate([route], { queryParams, replaceUrl }); } catch (error) { console.error('Error navigating to route:', error); } } /** * Redirects to internal or external URLs * * @param url - The URL to redirect to */ async redirectTo(url: string): Promise { const isExternalURL = /^https?:\/\//.test(url); if (isExternalURL) { console.log('Redirecting to external URL:', url); if (this.appDataService.isEmbeddedMode()) { // Change the top window location if in embedded mode window.top!.location.href = url; } else { window.location.href = url; } } else { console.log('Redirecting to internal route:', url); try { let urlTree = this.router.parseUrl(url); await this.router.navigateByUrl(urlTree, { replaceUrl: true }); } catch (error) { console.error('Error navigating to internal route:', error); } } } /** * Creates a URL tree for redirecting to a specific route * * @param route - The route to redirect to * @param queryParams - Optional query parameters to include in the URL * @returns A UrlTree representing the redirection */ createRedirectionTo(route: string, queryParams?: Params): UrlTree { return this.router.createUrlTree([route], { queryParams }); } /** * Creates a UrlTree for the error page with specific reason and optionally navigates to it. * * @param reason - The error reason to include as a query parameter * @param navigate - If true, navigates to the generated UrlTree * @returns The UrlTree for the error page */ async redirectToErrorPage(reason: ErrorReason, navigate = false): Promise { const urlTree = this.createRedirectionTo('error', { reason }); if (navigate) { try { await this.router.navigateByUrl(urlTree); } catch (error) { console.error('Error redirecting to error page:', error); } } return urlTree; } /** * Creates a UrlTree for the login page with a `redirectTo` query parameter and optionally navigates to it. * * @param redirectTo - The URL to redirect to after login * @param navigate - If true, navigates to the generated UrlTree * @returns The UrlTree for the login page */ async redirectToLoginPage(redirectTo?: string, navigate = false): Promise { const queryParams = redirectTo ? { redirectTo } : undefined; const urlTree = this.createRedirectionTo('login', queryParams); if (navigate) { try { await this.router.navigateByUrl(urlTree); } catch (error) { console.error('Error redirecting to login page:', error); } } return urlTree; } /** * Checks if the current URL contains a specific route * * @param route - The route to check against the current URL * @returns True if the current URL contains the route, false otherwise */ containsRoute(route: string): boolean { const currentUrl = this.router.url.split('?')[0]; // Remove query params for comparison return currentUrl.includes(route); } /** * Updates the query parameters in the URL by merging existing parameters with new ones. * * @param oldParams - The existing query parameters * @param newParams - The new query parameters to merge with the existing ones */ async updateQueryParamsFromUrl(oldParams: Params, newParams: Params): Promise { const queryParams = { ...oldParams, ...newParams }; await this.router.navigate([], { queryParams, replaceUrl: true, queryParamsHandling: 'merge' }); } /** * Removes a specific query parameter from the URL * * @param queryParams - The current query parameters * @param param - The parameter to remove */ async removeQueryParamFromUrl(queryParams: Params, param: string): Promise { const updatedParams = { ...queryParams }; delete updatedParams[param]; await this.router.navigate([], { queryParams: updatedParams, replaceUrl: true, queryParamsHandling: 'replace' }); } }