diff --git a/apps/client/src/app/app-routing.module.ts b/apps/client/src/app/app-routing.module.ts index 46ad162ea..63eef7250 100644 --- a/apps/client/src/app/app-routing.module.ts +++ b/apps/client/src/app/app-routing.module.ts @@ -32,7 +32,7 @@ const routes: Routes = [ ) }, { - path: ghostfolioRoutes.adminControl, + path: internalRoutes.adminControl.path, loadChildren: () => import('./pages/admin/admin-page.module').then((m) => m.AdminPageModule) }, @@ -46,9 +46,10 @@ const routes: Routes = [ title: 'Ghostfolio API' }, { - path: ghostfolioRoutes.auth, + path: internalRoutes.auth.path, loadChildren: () => - import('./pages/auth/auth-page.module').then((m) => m.AuthPageModule) + import('./pages/auth/auth-page.module').then((m) => m.AuthPageModule), + title: internalRoutes.auth.title }, { path: publicRoutes.blog.path, @@ -61,7 +62,7 @@ const routes: Routes = [ import('./pages/demo/demo-page.component').then( (c) => c.GfDemoPageComponent ), - path: ghostfolioRoutes.demo + path: publicRoutes.demo.path }, { path: publicRoutes.faq.path, @@ -139,7 +140,7 @@ const routes: Routes = [ ) }, { - path: ghostfolioRoutes.start, + path: publicRoutes.start.path, loadChildren: () => import('./pages/landing/landing-page.module').then( (m) => m.LandingPageModule @@ -150,8 +151,8 @@ const routes: Routes = [ import('./pages/webauthn/webauthn-page.component').then( (c) => c.GfWebauthnPageComponent ), - path: ghostfolioRoutes.webauthn, - title: $localize`Sign in` + path: internalRoutes.webauthn.path, + title: internalRoutes.webauthn.title }, { path: internalRoutes.zen.path, diff --git a/apps/client/src/app/app.component.ts b/apps/client/src/app/app.component.ts index 7d2c51af9..72e8b84d8 100644 --- a/apps/client/src/app/app.component.ts +++ b/apps/client/src/app/app.component.ts @@ -202,7 +202,7 @@ export class AppComponent implements OnDestroy, OnInit { this.currentRoute === publicRoutes.faq.path || this.currentRoute === publicRoutes.resources.path || this.currentRoute === internalRoutes.account.path || - this.currentRoute === routes.adminControl || + this.currentRoute === internalRoutes.adminControl.path || this.currentRoute === internalRoutes.home.path || this.currentRoute === internalRoutes.portfolio.path || this.currentRoute === internalRoutes.zen.path) && @@ -216,7 +216,7 @@ export class AppComponent implements OnDestroy, OnInit { this.currentRoute === routes.public || this.currentRoute === publicRoutes.pricing.path || this.currentRoute === publicRoutes.register.path || - this.currentRoute === routes.start) && + this.currentRoute === publicRoutes.start.path) && this.deviceType !== 'mobile'; if (this.deviceType === 'mobile') { diff --git a/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts b/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts index 32ac71afa..d6589eda5 100644 --- a/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts +++ b/apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -13,7 +13,7 @@ import { } from '@ghostfolio/common/helper'; import { LineChartItem, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; -import { routes } from '@ghostfolio/common/routes/routes'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { ColorScheme } from '@ghostfolio/common/types'; import { @@ -64,10 +64,8 @@ export class BenchmarkComparatorComponent implements OnChanges, OnDestroy { public chart: Chart<'line'>; public hasPermissionToAccessAdminControl: boolean; - public routerLinkAdminControlMarketData = [ - '/' + routes.adminControl, - routes.marketData - ]; + public routerLinkAdminControlMarketData = + internalRoutes.adminControl.subRoutes.marketData.routerLink; public constructor() { Chart.register( diff --git a/apps/client/src/app/components/header/header.component.ts b/apps/client/src/app/components/header/header.component.ts index a79ec6786..0ab5e91f3 100644 --- a/apps/client/src/app/components/header/header.component.ts +++ b/apps/client/src/app/components/header/header.component.ts @@ -93,7 +93,7 @@ export class HeaderComponent implements OnChanges { public routerLinkAbout = publicRoutes.about.routerLink; public routerLinkAccount = internalRoutes.account.routerLink; public routerLinkAccounts = internalRoutes.accounts.routerLink; - public routerLinkAdminControl = ['/' + routes.adminControl]; + public routerLinkAdminControl = internalRoutes.adminControl.routerLink; public routerLinkFeatures = publicRoutes.features.routerLink; public routerLinkMarkets = publicRoutes.markets.routerLink; public routerLinkPortfolio = internalRoutes.portfolio.routerLink; diff --git a/apps/client/src/app/core/auth.guard.ts b/apps/client/src/app/core/auth.guard.ts index 4ddc0d229..ef6a8f4a7 100644 --- a/apps/client/src/app/core/auth.guard.ts +++ b/apps/client/src/app/core/auth.guard.ts @@ -21,7 +21,7 @@ export class AuthGuard { private static PUBLIC_PAGE_ROUTES = [ `/${publicRoutes.about.path}`, `/${publicRoutes.blog.path}`, - `/${routes.demo}`, + `/${publicRoutes.demo.path}`, `/${publicRoutes.faq.path}`, `/${publicRoutes.features.path}`, `/${publicRoutes.markets.path}`, @@ -52,7 +52,7 @@ export class AuthGuard { .pipe( catchError(() => { if (utmSource === 'ios') { - this.router.navigate(['/' + routes.demo]); + this.router.navigate(publicRoutes.demo.routerLink); resolve(false); } else if (utmSource === 'trusted-web-activity') { this.router.navigate(publicRoutes.register.routerLink); @@ -66,7 +66,7 @@ export class AuthGuard { resolve(true); return EMPTY; } else if (state.url !== '/start') { - this.router.navigate(['/' + routes.start]); + this.router.navigate(publicRoutes.start.routerLink); resolve(false); return EMPTY; } @@ -98,7 +98,7 @@ export class AuthGuard { this.router.navigate(internalRoutes.zen.routerLink); resolve(false); return; - } else if (state.url.startsWith(`/${routes.start}`)) { + } else if (state.url.startsWith(`/${publicRoutes.start.path}`)) { if (user.settings.viewMode === 'ZEN') { this.router.navigate(internalRoutes.zen.routerLink); } else { diff --git a/apps/client/src/app/core/http-response.interceptor.ts b/apps/client/src/app/core/http-response.interceptor.ts index 8fdc21e0d..c2eef4175 100644 --- a/apps/client/src/app/core/http-response.interceptor.ts +++ b/apps/client/src/app/core/http-response.interceptor.ts @@ -2,7 +2,7 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service'; import { InfoItem } from '@ghostfolio/common/interfaces'; -import { publicRoutes, routes } from '@ghostfolio/common/routes/routes'; +import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes'; import { HTTP_INTERCEPTORS, @@ -60,7 +60,9 @@ export class HttpResponseInterceptor implements HttpInterceptor { duration: ms('6 seconds') } ); - } else if (!error.url.includes('/auth')) { + } else if ( + !error.url.includes(internalRoutes.auth.routerLink.join('')) + ) { this.snackBarRef = this.snackBar.open( $localize`This action is not allowed.`, undefined, @@ -111,7 +113,7 @@ export class HttpResponseInterceptor implements HttpInterceptor { } else if (error.status === StatusCodes.UNAUTHORIZED) { if (!error.url.includes('/data-providers/ghostfolio/status')) { if (this.webAuthnService.isEnabled()) { - this.router.navigate(['/' + routes.webauthn]); + this.router.navigate(internalRoutes.webauthn.routerLink); } else { this.tokenStorageService.signOut(); } diff --git a/apps/client/src/app/pages/admin/admin-page-routing.module.ts b/apps/client/src/app/pages/admin/admin-page-routing.module.ts index 31c51dbab..efcb217af 100644 --- a/apps/client/src/app/pages/admin/admin-page-routing.module.ts +++ b/apps/client/src/app/pages/admin/admin-page-routing.module.ts @@ -4,7 +4,7 @@ import { AdminOverviewComponent } from '@ghostfolio/client/components/admin-over import { AdminSettingsComponent } from '@ghostfolio/client/components/admin-settings/admin-settings.component'; import { AdminUsersComponent } from '@ghostfolio/client/components/admin-users/admin-users.component'; import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; -import { routes as ghostfolioRoutes } from '@ghostfolio/common/routes/routes'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; @@ -18,27 +18,27 @@ const routes: Routes = [ { path: '', component: AdminOverviewComponent, - title: $localize`Admin Control` + title: internalRoutes.adminControl.title }, { - path: ghostfolioRoutes.jobs, + path: internalRoutes.adminControl.subRoutes.jobs.path, component: AdminJobsComponent, - title: $localize`Job Queue` + title: internalRoutes.adminControl.subRoutes.jobs.title }, { - path: ghostfolioRoutes.marketData, + path: internalRoutes.adminControl.subRoutes.marketData.path, component: AdminMarketDataComponent, - title: $localize`Market Data` + title: internalRoutes.adminControl.subRoutes.marketData.title }, { - path: ghostfolioRoutes.settings, + path: internalRoutes.adminControl.subRoutes.settings.path, component: AdminSettingsComponent, - title: $localize`Settings` + title: internalRoutes.adminControl.subRoutes.settings.title }, { - path: ghostfolioRoutes.users, + path: internalRoutes.adminControl.subRoutes.users.path, component: AdminUsersComponent, - title: $localize`Users` + title: internalRoutes.adminControl.subRoutes.users.title } ], component: AdminPageComponent, diff --git a/apps/client/src/app/pages/admin/admin-page.component.ts b/apps/client/src/app/pages/admin/admin-page.component.ts index 5c9f0e063..02aa8ba18 100644 --- a/apps/client/src/app/pages/admin/admin-page.component.ts +++ b/apps/client/src/app/pages/admin/admin-page.component.ts @@ -1,5 +1,5 @@ import { TabConfiguration } from '@ghostfolio/common/interfaces'; -import { routes } from '@ghostfolio/common/routes/routes'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { DeviceDetectorService } from 'ngx-device-detector'; @@ -27,27 +27,27 @@ export class AdminPageComponent implements OnDestroy, OnInit { { iconName: 'reader-outline', label: $localize`Overview`, - routerLink: ['/' + routes.adminControl] + routerLink: internalRoutes.adminControl.routerLink }, { iconName: 'settings-outline', - label: $localize`Settings`, - routerLink: ['/' + routes.adminControl, routes.settings] + label: internalRoutes.adminControl.subRoutes.settings.title, + routerLink: internalRoutes.adminControl.subRoutes.settings.routerLink }, { iconName: 'server-outline', - label: $localize`Market Data`, - routerLink: ['/' + routes.adminControl, routes.marketData] + label: internalRoutes.adminControl.subRoutes.marketData.title, + routerLink: internalRoutes.adminControl.subRoutes.marketData.routerLink }, { iconName: 'flash-outline', - label: $localize`Job Queue`, - routerLink: ['/' + routes.adminControl, routes.jobs] + label: internalRoutes.adminControl.subRoutes.jobs.title, + routerLink: internalRoutes.adminControl.subRoutes.jobs.routerLink }, { iconName: 'people-outline', - label: $localize`Users`, - routerLink: ['/' + routes.adminControl, routes.users] + label: internalRoutes.adminControl.subRoutes.users.title, + routerLink: internalRoutes.adminControl.subRoutes.users.routerLink } ]; } diff --git a/apps/client/src/app/pages/faq/saas/saas-page.component.ts b/apps/client/src/app/pages/faq/saas/saas-page.component.ts index e3fba4d21..f5063d765 100644 --- a/apps/client/src/app/pages/faq/saas/saas-page.component.ts +++ b/apps/client/src/app/pages/faq/saas/saas-page.component.ts @@ -1,10 +1,6 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { User } from '@ghostfolio/common/interfaces'; -import { - internalRoutes, - publicRoutes, - routes -} from '@ghostfolio/common/routes/routes'; +import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes'; import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core'; import { Subject, takeUntil } from 'rxjs'; @@ -19,10 +15,8 @@ import { Subject, takeUntil } from 'rxjs'; export class SaasPageComponent implements OnDestroy { public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${publicRoutes.pricing.path}`; public routerLinkAccount = internalRoutes.account.routerLink; - public routerLinkAccountMembership = [ - '/' + internalRoutes.account.path, - routes.membership - ]; + public routerLinkAccountMembership = + internalRoutes.account.subRoutes.membership.routerLink; public routerLinkMarkets = publicRoutes.markets.routerLink; public routerLinkRegister = publicRoutes.register.routerLink; public user: User; diff --git a/apps/client/src/app/pages/landing/landing-page.component.ts b/apps/client/src/app/pages/landing/landing-page.component.ts index 6212ce56c..0a965b8fa 100644 --- a/apps/client/src/app/pages/landing/landing-page.component.ts +++ b/apps/client/src/app/pages/landing/landing-page.component.ts @@ -1,7 +1,7 @@ import { DataService } from '@ghostfolio/client/services/data.service'; import { Statistics } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; -import { publicRoutes, routes } from '@ghostfolio/common/routes/routes'; +import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { format } from 'date-fns'; @@ -26,7 +26,7 @@ export class LandingPageComponent implements OnDestroy, OnInit { public hasPermissionForSubscription: boolean; public hasPermissionToCreateUser: boolean; public routerLinkAbout = publicRoutes.about.routerLink; - public routerLinkDemo = ['/' + routes.demo]; + public routerLinkDemo = publicRoutes.demo.routerLink; public routerLinkOpenStartup = publicRoutes.openStartup.routerLink; public routerLinkRegister = publicRoutes.register.routerLink; public statistics: Statistics; diff --git a/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts b/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts index a9c41b68d..2d40309c1 100644 --- a/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts +++ b/apps/client/src/app/pages/user-account/user-account-page-routing.module.ts @@ -2,7 +2,7 @@ import { UserAccountAccessComponent } from '@ghostfolio/client/components/user-a import { UserAccountMembershipComponent } from '@ghostfolio/client/components/user-account-membership/user-account-membership.component'; import { UserAccountSettingsComponent } from '@ghostfolio/client/components/user-account-settings/user-account-settings.component'; import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; -import { routes as ghostfolioRoutes } from '@ghostfolio/common/routes/routes'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; @@ -16,17 +16,17 @@ const routes: Routes = [ { path: '', component: UserAccountSettingsComponent, - title: $localize`Settings` + title: internalRoutes.userAccount.title }, { - path: ghostfolioRoutes.membership, + path: internalRoutes.userAccount.subRoutes.membership.path, component: UserAccountMembershipComponent, - title: $localize`Membership` + title: internalRoutes.userAccount.subRoutes.membership.title }, { - path: ghostfolioRoutes.access, + path: internalRoutes.userAccount.subRoutes.access.path, component: UserAccountAccessComponent, - title: $localize`Access` + title: internalRoutes.userAccount.subRoutes.access.title } ], component: UserAccountPageComponent, diff --git a/apps/client/src/app/pages/user-account/user-account-page.component.ts b/apps/client/src/app/pages/user-account/user-account-page.component.ts index 278812dc6..78783f400 100644 --- a/apps/client/src/app/pages/user-account/user-account-page.component.ts +++ b/apps/client/src/app/pages/user-account/user-account-page.component.ts @@ -1,6 +1,6 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; -import { internalRoutes, routes } from '@ghostfolio/common/routes/routes'; +import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { DeviceDetectorService } from 'ngx-device-detector'; @@ -39,17 +39,15 @@ export class UserAccountPageComponent implements OnDestroy, OnInit { }, { iconName: 'diamond-outline', - label: $localize`Membership`, - routerLink: [ - '/' + internalRoutes.account.path, - routes.membership - ], + label: internalRoutes.account.subRoutes.membership.title, + routerLink: + internalRoutes.account.subRoutes.membership.routerLink, showCondition: !!this.user?.subscription }, { iconName: 'key-outline', - label: $localize`Access`, - routerLink: ['/' + internalRoutes.account.path, routes.access] + label: internalRoutes.account.subRoutes.access.title, + routerLink: internalRoutes.account.subRoutes.access.routerLink } ]; diff --git a/libs/common/src/lib/routes/routes.ts b/libs/common/src/lib/routes/routes.ts index d993da7ed..6f6017623 100644 --- a/libs/common/src/lib/routes/routes.ts +++ b/libs/common/src/lib/routes/routes.ts @@ -3,22 +3,11 @@ import '@angular/localize/init'; import { IRoute } from './interfaces/interfaces'; export const routes = { - access: 'access', - adminControl: 'admin', api: 'api', - auth: 'auth', - demo: 'demo', i18n: 'i18n', - jobs: 'jobs', market: 'market', - marketData: 'market-data', - membership: 'membership', personalFinanceTools: 'personal-finance-tools', public: 'p', - settings: 'settings', - start: 'start', - users: 'users', - webauthn: 'webauthn', // Publicly accessible pages openSourceAlternativeTo: $localize`:kebab-case:open-source-alternative-to` @@ -28,13 +17,59 @@ export const internalRoutes: Record = { account: { path: 'account', routerLink: ['/account'], + subRoutes: { + access: { + path: 'access', + routerLink: ['/account', 'access'], + title: $localize`Access` + }, + membership: { + path: 'membership', + routerLink: ['/account', 'membership'], + title: $localize`Membership` + } + }, title: $localize`Settings` }, + adminControl: { + excludeFromAssistant: true, + path: 'admin', + routerLink: ['/admin'], + subRoutes: { + jobs: { + path: 'jobs', + routerLink: ['/admin', 'jobs'], + title: $localize`Job Queue` + }, + marketData: { + path: 'market-data', + routerLink: ['/admin', 'market-data'], + title: $localize`Market Data` + }, + settings: { + path: 'settings', + routerLink: ['/admin', 'settings'], + title: $localize`Settings` + }, + users: { + path: 'users', + routerLink: ['/admin', 'users'], + title: $localize`Users` + } + }, + title: $localize`Admin Control` + }, accounts: { path: 'accounts', routerLink: ['/accounts'], title: $localize`Accounts` }, + auth: { + excludeFromAssistant: true, + path: 'auth', + routerLink: ['/auth'], + title: $localize`Sign in` + }, home: { path: 'home', routerLink: ['/home'], @@ -89,6 +124,12 @@ export const internalRoutes: Record = { }, title: $localize`Portfolio` }, + webauthn: { + excludeFromAssistant: true, + path: 'webauthn', + routerLink: ['/webauthn'], + title: $localize`Sign in` + }, zen: { excludeFromAssistant: true, path: 'zen', @@ -154,6 +195,11 @@ export const publicRoutes = { routerLink: ['/blog'], title: $localize`Blog` }, + demo: { + path: 'demo', + routerLink: ['/demo'], + title: $localize`Live Demo` + }, faq: { path: $localize`:kebab-case:faq`, routerLink: ['/' + $localize`:kebab-case:faq`], @@ -229,5 +275,9 @@ export const publicRoutes = { } }, title: $localize`Resources` + }, + start: { + path: 'start', + routerLink: ['/start'] } };