Bugfix/fix page navigation (#4711)

* Fix page navigation and use paths references
This commit is contained in:
Kenrick Tandrian 2025-05-23 21:54:09 +07:00 committed by GitHub
parent ba6503636e
commit 4bffb3107d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
72 changed files with 1962 additions and 6636 deletions

View File

@ -1,6 +1,6 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { paths } from '@ghostfolio/client/core/paths';
import { PageTitleStrategy } from '@ghostfolio/client/services/page-title.strategy';
import { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes, TitleStrategy } from '@angular/router';
@ -14,21 +14,21 @@ const routes: Routes = [
import('./pages/about/about-page.module').then((m) => m.AboutPageModule)
},
{
path: 'account',
path: paths.account,
loadChildren: () =>
import('./pages/user-account/user-account-page.module').then(
(m) => m.UserAccountPageModule
)
},
{
path: 'accounts',
path: paths.accounts,
loadChildren: () =>
import('./pages/accounts/accounts-page.module').then(
(m) => m.AccountsPageModule
)
},
{
path: 'admin',
path: paths.admin,
loadChildren: () =>
import('./pages/admin/admin-page.module').then((m) => m.AdminPageModule)
},
@ -38,16 +38,16 @@ const routes: Routes = [
import('./pages/api/api-page.component').then(
(c) => c.GfApiPageComponent
),
path: 'api',
path: paths.api,
title: 'Ghostfolio API'
},
{
path: 'auth',
path: paths.auth,
loadChildren: () =>
import('./pages/auth/auth-page.module').then((m) => m.AuthPageModule)
},
{
path: 'blog',
path: paths.blog,
loadChildren: () =>
import('./pages/blog/blog-page.module').then((m) => m.BlogPageModule)
},
@ -57,7 +57,7 @@ const routes: Routes = [
import('./pages/demo/demo-page.component').then(
(c) => c.GfDemoPageComponent
),
path: 'demo'
path: paths.demo
},
{
path: paths.faq,
@ -74,7 +74,7 @@ const routes: Routes = [
title: $localize`Features`
},
{
path: 'home',
path: paths.home,
loadChildren: () =>
import('./pages/home/home-page.module').then((m) => m.HomePageModule)
},
@ -84,7 +84,7 @@ const routes: Routes = [
import('./pages/i18n/i18n-page.component').then(
(c) => c.GfI18nPageComponent
),
path: 'i18n',
path: paths.i18n,
title: $localize`Internationalization`
},
{
@ -95,19 +95,12 @@ const routes: Routes = [
)
},
{
path: 'open',
path: paths.open,
loadChildren: () =>
import('./pages/open/open-page.module').then((m) => m.OpenPageModule)
},
{
path: 'p',
loadChildren: () =>
import('./pages/public/public-page.module').then(
(m) => m.PublicPageModule
)
},
{
path: 'portfolio',
path: paths.portfolio,
loadChildren: () =>
import('./pages/portfolio/portfolio-page.module').then(
(m) => m.PortfolioPageModule
@ -120,6 +113,13 @@ const routes: Routes = [
(m) => m.PricingPageModule
)
},
{
path: paths.public,
loadChildren: () =>
import('./pages/public/public-page.module').then(
(m) => m.PublicPageModule
)
},
{
path: paths.register,
loadChildren: () =>
@ -135,7 +135,7 @@ const routes: Routes = [
)
},
{
path: 'start',
path: paths.start,
loadChildren: () =>
import('./pages/landing/landing-page.module').then(
(m) => m.LandingPageModule
@ -146,11 +146,11 @@ const routes: Routes = [
import('./pages/webauthn/webauthn-page.component').then(
(c) => c.GfWebauthnPageComponent
),
path: 'webauthn',
path: paths.webauthn,
title: $localize`Sign in`
},
{
path: 'zen',
path: paths.zen,
loadChildren: () =>
import('./pages/zen/zen-page.module').then((m) => m.ZenPageModule)
},

View File

@ -2,6 +2,7 @@ import { GfHoldingDetailDialogComponent } from '@ghostfolio/client/components/ho
import { HoldingDetailDialogParams } from '@ghostfolio/client/components/holding-detail-dialog/interfaces/interfaces';
import { getCssVariable } from '@ghostfolio/common/helper';
import { InfoItem, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { ColorScheme } from '@ghostfolio/common/types';
@ -62,29 +63,23 @@ export class AppComponent implements OnDestroy, OnInit {
public hasTabs = false;
public info: InfoItem;
public pageTitle: string;
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkAboutChangelog = [
'/' + $localize`:snake-case:about`,
'changelog'
];
public routerLinkAboutLicense = [
'/' + $localize`:snake-case:about`,
$localize`:snake-case:license`
];
public routerLinkAbout = ['/' + paths.about];
public routerLinkAboutChangelog = ['/' + paths.about, paths.changelog];
public routerLinkAboutLicense = ['/' + paths.about, paths.license];
public routerLinkAboutPrivacyPolicy = [
'/' + $localize`:snake-case:about`,
$localize`:snake-case:privacy-policy`
'/' + paths.about,
paths.privacyPolicy
];
public routerLinkAboutTermsOfService = [
'/' + $localize`:snake-case:about`,
$localize`:snake-case:terms-of-service`
'/' + paths.about,
paths.termsOfService
];
public routerLinkFaq = ['/' + $localize`:snake-case:faq`];
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkMarkets = ['/' + $localize`:snake-case:markets`];
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkRegister = ['/' + $localize`:snake-case:register`];
public routerLinkResources = ['/' + $localize`:snake-case:resources`];
public routerLinkFaq = ['/' + paths.faq];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkMarkets = ['/' + paths.markets];
public routerLinkPricing = ['/' + paths.pricing];
public routerLinkRegister = ['/' + paths.register];
public routerLinkResources = ['/' + paths.resources];
public showFooter = false;
public user: User;

View File

@ -2,6 +2,7 @@ import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/con
import { NotificationService } from '@ghostfolio/client/core/notification/notification.service';
import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config';
import { Access, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { Clipboard } from '@angular/cdk/clipboard';
import {
@ -55,7 +56,7 @@ export class AccessTableComponent implements OnChanges {
public getPublicUrl(aId: string): string {
const languageCode = this.user?.settings?.language ?? DEFAULT_LANGUAGE_CODE;
return `${this.baseUrl}/${languageCode}/p/${aId}`;
return `${this.baseUrl}/${languageCode}/${paths.public}/${aId}`;
}
public onCopyUrlToClipboard(aId: string): void {

View File

@ -9,6 +9,7 @@ import {
PortfolioPosition,
User
} from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { OrderWithAccount } from '@ghostfolio/common/types';
@ -92,7 +93,7 @@ export class AccountDetailDialog implements OnDestroy, OnInit {
}
public onCloneActivity(aActivity: Activity) {
this.router.navigate(['/portfolio', 'activities'], {
this.router.navigate(['/' + paths.portfolio, paths.activities], {
queryParams: { activityId: aActivity.id, createDialog: true }
});
@ -151,7 +152,7 @@ export class AccountDetailDialog implements OnDestroy, OnInit {
}
public onUpdateActivity(aActivity: Activity) {
this.router.navigate(['/portfolio', 'activities'], {
this.router.navigate(['/' + paths.portfolio, paths.activities], {
queryParams: { activityId: aActivity.id, editDialog: true }
});

View File

@ -13,6 +13,7 @@ import {
DataProviderInfo,
User
} from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import {
ChangeDetectionStrategy,
@ -75,9 +76,7 @@ export class AdminSettingsComponent implements OnDestroy, OnInit {
const languageCode =
this.user?.settings?.language ?? DEFAULT_LANGUAGE_CODE;
this.pricingUrl =
`https://ghostfol.io/${languageCode}/` +
$localize`:snake-case:pricing`;
this.pricingUrl = `https://ghostfol.io/${languageCode}/${paths.pricing}`;
this.changeDetectorRef.markForCheck();
}

View File

@ -11,6 +11,7 @@ import {
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { Filter, InfoItem, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { DateRange } from '@ghostfolio/common/types';
import { GfAssistantComponent } from '@ghostfolio/ui/assistant/assistant.component';
@ -79,17 +80,17 @@ export class HeaderComponent implements OnChanges {
public hasPermissionToCreateUser: boolean;
public impersonationId: string;
public isMenuOpen: boolean;
public routeAbout = $localize`:snake-case:about`;
public routeFeatures = $localize`:snake-case:features`;
public routeMarkets = $localize`:snake-case:markets`;
public routePricing = $localize`:snake-case:pricing`;
public routeResources = $localize`:snake-case:resources`;
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkMarkets = ['/' + $localize`:snake-case:markets`];
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkRegister = ['/' + $localize`:snake-case:register`];
public routerLinkResources = ['/' + $localize`:snake-case:resources`];
public routeAbout = paths.about;
public routeFeatures = paths.features;
public routeMarkets = paths.markets;
public routePricing = paths.pricing;
public routeResources = paths.resources;
public routerLinkAbout = ['/' + paths.about];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkMarkets = ['/' + paths.markets];
public routerLinkPricing = ['/' + paths.pricing];
public routerLinkRegister = ['/' + paths.register];
public routerLinkResources = ['/' + paths.resources];
private unsubscribeSubject = new Subject<void>();

View File

@ -13,6 +13,7 @@ import {
LineChartItem,
User
} from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table';
import { GfDataProviderCreditsComponent } from '@ghostfolio/ui/data-provider-credits';
@ -468,7 +469,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
}
public onCloneActivity(aActivity: Activity) {
this.router.navigate(['/portfolio', 'activities'], {
this.router.navigate(['/' + paths.portfolio, paths.activities], {
queryParams: { activityId: aActivity.id, createDialog: true }
});
@ -510,7 +511,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
}
public onUpdateActivity(aActivity: Activity) {
this.router.navigate(['/portfolio', 'activities'], {
this.router.navigate(['/' + paths.portfolio, paths.activities], {
queryParams: { activityId: aActivity.id, editDialog: true }
});

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
@ -26,7 +28,7 @@ export class SubscriptionInterstitialDialog implements OnInit {
public remainingSkipButtonDelay =
SubscriptionInterstitialDialog.SKIP_BUTTON_DELAY_IN_SECONDS;
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkPricing = ['/' + paths.pricing];
public variantIndex: number;
private unsubscribeSubject = new Subject<void>();

View File

@ -4,6 +4,7 @@ import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { getDateFormatString } from '@ghostfolio/common/helper';
import { User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import {
@ -36,7 +37,7 @@ export class UserAccountMembershipComponent implements OnDestroy {
public hasPermissionToUpdateUserSettings: boolean;
public price: number;
public priceId: string;
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkPricing = ['/' + paths.pricing];
public trySubscriptionMail =
'mailto:hi@ghostfol.io?Subject=Ghostfolio Premium Trial&body=Hello%0D%0DI am interested in Ghostfolio Premium. Can you please send me a coupon code to try it for some time?%0D%0DKind regards';
public user: User;

View File

@ -1,6 +1,7 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { SettingsStorageService } from '@ghostfolio/client/services/settings-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { paths } from '@ghostfolio/common/paths';
import { Injectable } from '@angular/core';
import {
@ -11,20 +12,18 @@ import {
import { EMPTY } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { paths } from './paths';
@Injectable({ providedIn: 'root' })
export class AuthGuard {
private static PUBLIC_PAGE_ROUTES = [
`/${paths.about}`,
'/blog',
'/demo',
`/${paths.blog}`,
`/${paths.demo}`,
`/${paths.faq}`,
`/${paths.features}`,
`/${paths.markets}`,
'/open',
'/p',
`/${paths.open}`,
`/${paths.pricing}`,
`/${paths.public}`,
`/${paths.register}`,
`/${paths.resources}`
];
@ -49,21 +48,21 @@ export class AuthGuard {
.pipe(
catchError(() => {
if (utmSource === 'ios') {
this.router.navigate(['/demo']);
this.router.navigate(['/' + paths.demo]);
resolve(false);
} else if (utmSource === 'trusted-web-activity') {
this.router.navigate(['/' + $localize`register`]);
this.router.navigate(['/' + paths.register]);
resolve(false);
} else if (
AuthGuard.PUBLIC_PAGE_ROUTES.filter((publicPageRoute) => {
const [, url] = state.url.split('/');
AuthGuard.PUBLIC_PAGE_ROUTES.some((publicPageRoute) => {
const [, url] = decodeURIComponent(state.url).split('/');
return `/${url}` === publicPageRoute;
})?.length > 0
})
) {
resolve(true);
return EMPTY;
} else if (state.url !== '/start') {
this.router.navigate(['/start']);
this.router.navigate(['/' + paths.start]);
resolve(false);
return EMPTY;
}
@ -89,26 +88,26 @@ export class AuthGuard {
resolve(true);
return;
} else if (
state.url.startsWith('/home') &&
state.url.startsWith(`/${paths.home}`) &&
user.settings.viewMode === 'ZEN'
) {
this.router.navigate(['/zen']);
this.router.navigate(['/' + paths.zen]);
resolve(false);
return;
} else if (state.url.startsWith('/start')) {
} else if (state.url.startsWith(`/${paths.start}`)) {
if (user.settings.viewMode === 'ZEN') {
this.router.navigate(['/zen']);
this.router.navigate(['/' + paths.zen]);
} else {
this.router.navigate(['/home']);
this.router.navigate(['/' + paths.home]);
}
resolve(false);
return;
} else if (
state.url.startsWith('/zen') &&
state.url.startsWith(`/${paths.zen}`) &&
user.settings.viewMode === 'DEFAULT'
) {
this.router.navigate(['/home']);
this.router.navigate(['/' + paths.home]);
resolve(false);
return;
}

View File

@ -2,6 +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 { paths } from '@ghostfolio/common/paths';
import {
HTTP_INTERCEPTORS,
@ -74,7 +75,7 @@ export class HttpResponseInterceptor implements HttpInterceptor {
});
this.snackBarRef.onAction().subscribe(() => {
this.router.navigate(['/' + $localize`pricing`]);
this.router.navigate(['/' + paths.pricing]);
});
}
} else if (error.status === StatusCodes.INTERNAL_SERVER_ERROR) {
@ -110,7 +111,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(['/webauthn']);
this.router.navigate(['/' + paths.webauthn]);
} else {
this.tokenStorageService.signOut();
}

View File

@ -1,12 +0,0 @@
export const paths = {
about: $localize`about`,
faq: $localize`faq`,
features: $localize`features`,
license: $localize`license`,
markets: $localize`markets`,
pricing: $localize`pricing`,
privacyPolicy: $localize`privacy-policy`,
register: $localize`register`,
resources: $localize`resources`,
termsOfService: $localize`terms-of-service`
};

View File

@ -1,5 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { paths } from '@ghostfolio/client/core/paths';
import { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -18,7 +18,7 @@ const routes: Routes = [
)
},
{
path: 'changelog',
path: paths.changelog,
loadChildren: () =>
import('./changelog/changelog-page.module').then(
(m) => m.ChangelogPageModule
@ -32,7 +32,7 @@ const routes: Routes = [
)
},
{
path: 'oss-friends',
path: paths.ossFriends,
loadChildren: () =>
import('./oss-friends/oss-friends-page.module').then(
(m) => m.OpenSourceSoftwareFriendsPageModule

View File

@ -1,6 +1,7 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { TabConfiguration, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
@ -43,17 +44,17 @@ export class AboutPageComponent implements OnDestroy, OnInit {
{
iconName: 'information-circle-outline',
label: $localize`About`,
path: ['/' + $localize`about`]
path: ['/' + paths.about]
},
{
iconName: 'sparkles-outline',
label: $localize`Changelog`,
path: ['/' + $localize`about`, 'changelog']
path: ['/' + paths.about, paths.changelog]
},
{
iconName: 'ribbon-outline',
label: $localize`License`,
path: ['/' + $localize`about`, $localize`license`],
path: ['/' + paths.about, paths.license],
showCondition: !this.hasPermissionForSubscription
}
];
@ -62,14 +63,14 @@ export class AboutPageComponent implements OnDestroy, OnInit {
this.tabs.push({
iconName: 'shield-checkmark-outline',
label: $localize`Privacy Policy`,
path: ['/' + $localize`about`, $localize`privacy-policy`],
path: ['/' + paths.about, paths.privacyPolicy],
showCondition: this.hasPermissionForSubscription
});
this.tabs.push({
iconName: 'document-text-outline',
label: $localize`Terms of Service`,
path: ['/' + $localize`about`, $localize`terms-of-service`],
path: ['/' + paths.about, paths.termsOfService],
showCondition: this.hasPermissionForSubscription
});
@ -81,7 +82,7 @@ export class AboutPageComponent implements OnDestroy, OnInit {
this.tabs.push({
iconName: 'happy-outline',
label: 'OSS Friends',
path: ['/' + $localize`about`, 'oss-friends']
path: ['/' + paths.about, paths.ossFriends]
});
});
}

View File

@ -1,6 +1,7 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
@ -17,8 +18,8 @@ export class AboutOverviewPageComponent implements OnDestroy, OnInit {
public hasPermissionForStatistics: boolean;
public hasPermissionForSubscription: boolean;
public isLoggedIn: boolean;
public routerLinkFaq = ['/' + $localize`:snake-case:faq`];
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkFaq = ['/' + paths.faq];
public routerLinkFeatures = ['/' + paths.features];
public user: User;
private unsubscribeSubject = new Subject<void>();

View File

@ -4,6 +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 { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -20,22 +21,22 @@ const routes: Routes = [
title: $localize`Admin Control`
},
{
path: 'jobs',
path: paths.jobs,
component: AdminJobsComponent,
title: $localize`Job Queue`
},
{
path: 'market-data',
path: paths.marketData,
component: AdminMarketDataComponent,
title: $localize`Market Data`
},
{
path: 'settings',
path: paths.settings,
component: AdminSettingsComponent,
title: $localize`Settings`
},
{
path: 'users',
path: paths.users,
component: AdminUsersComponent,
title: $localize`Users`
}

View File

@ -1,4 +1,5 @@
import { TabConfiguration } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -26,27 +27,27 @@ export class AdminPageComponent implements OnDestroy, OnInit {
{
iconName: 'reader-outline',
label: $localize`Overview`,
path: ['/admin']
path: ['/' + paths.admin]
},
{
iconName: 'settings-outline',
label: $localize`Settings`,
path: ['/admin', 'settings']
path: ['/' + paths.admin, paths.settings]
},
{
iconName: 'server-outline',
label: $localize`Market Data`,
path: ['/admin', 'market-data']
path: ['/' + paths.admin, paths.marketData]
},
{
iconName: 'flash-outline',
label: $localize`Job Queue`,
path: ['/admin', 'jobs']
path: ['/' + paths.admin, paths.jobs]
},
{
iconName: 'people-outline',
label: $localize`Users`,
path: ['/admin', 'users']
path: ['/' + paths.admin, paths.users]
}
];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './hallo-ghostfolio-page.html'
})
export class HalloGhostfolioPageComponent {
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkResources = ['/' + $localize`:snake-case:resources`];
public routerLinkPricing = ['/' + paths.pricing];
public routerLinkResources = ['/' + paths.resources];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './hello-ghostfolio-page.html'
})
export class HelloGhostfolioPageComponent {
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkResources = ['/' + $localize`:snake-case:resources`];
public routerLinkPricing = ['/' + paths.pricing];
public routerLinkResources = ['/' + paths.resources];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './first-months-in-open-source-page.html'
})
export class FirstMonthsInOpenSourcePageComponent {
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkPricing = ['/' + paths.pricing];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './how-do-i-get-my-finances-in-order-page.html'
})
export class HowDoIGetMyFinancesInOrderPageComponent {
public routerLinkResources = ['/' + $localize`:snake-case:resources`];
public routerLinkResources = ['/' + paths.resources];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './500-stars-on-github-page.html'
})
export class FiveHundredStarsOnGitHubPageComponent {
public routerLinkMarkets = ['/' + $localize`:snake-case:markets`];
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkMarkets = ['/' + paths.markets];
public routerLinkPricing = ['/' + paths.pricing];
}

View File

@ -1,3 +1,4 @@
import { paths } from '@ghostfolio/common/paths';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { Component } from '@angular/core';
@ -11,6 +12,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './black-friday-2022-page.html'
})
export class BlackFriday2022PageComponent {
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkPricing = ['/' + paths.pricing];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './1000-stars-on-github-page.html'
})
export class ThousandStarsOnGitHubPageComponent {
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkPricing = ['/' + paths.pricing];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './unlock-your-financial-potential-with-ghostfolio-page.html'
})
export class UnlockYourFinancialPotentialWithGhostfolioPageComponent {
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkResources = ['/' + $localize`:snake-case:resources`];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkResources = ['/' + paths.resources];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './exploring-the-path-to-fire-page.html'
})
export class ExploringThePathToFirePageComponent {
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkFeatures = ['/' + paths.features];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,8 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './ghostfolio-joins-oss-friends-page.html'
})
export class GhostfolioJoinsOssFriendsPageComponent {
public routerLinkAboutOssFriends = [
'/' + $localize`:snake-case:about`,
'oss-friends'
];
public routerLinkAboutOssFriends = ['/' + paths.about, paths.ossFriends];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,11 +11,8 @@ import { RouterModule } from '@angular/router';
templateUrl: './ghostfolio-2-page.html'
})
export class Ghostfolio2PageComponent {
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkAboutChangelog = [
'/' + $localize`:snake-case:about`,
'changelog'
];
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkMarkets = ['/' + $localize`:snake-case:markets`];
public routerLinkAbout = ['/' + paths.about];
public routerLinkAboutChangelog = ['/' + paths.about, paths.changelog];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkMarkets = ['/' + paths.markets];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './hacktoberfest-2023-page.html'
})
export class Hacktoberfest2023PageComponent {
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkAbout = ['/' + paths.about];
}

View File

@ -1,3 +1,4 @@
import { paths } from '@ghostfolio/common/paths';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { Component } from '@angular/core';
@ -11,6 +12,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './black-week-2023-page.html'
})
export class BlackWeek2023PageComponent {
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkPricing = ['/' + paths.pricing];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './hacktoberfest-2023-debriefing-page.html'
})
export class Hacktoberfest2023DebriefingPageComponent {
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkAbout = ['/' + paths.about];
public routerLinkFeatures = ['/' + paths.features];
}

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { RouterModule } from '@angular/router';
@ -9,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './hacktoberfest-2024-page.html'
})
export class Hacktoberfest2024PageComponent {
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkAbout = ['/' + paths.about];
}

View File

@ -1,3 +1,4 @@
import { paths } from '@ghostfolio/common/paths';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { Component } from '@angular/core';
@ -11,6 +12,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './black-weeks-2024-page.html'
})
export class BlackWeeks2024PageComponent {
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkPricing = ['/' + paths.pricing];
}

View File

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -17,12 +18,12 @@ const routes: Routes = [
)
},
{
path: 'saas',
path: paths.saas,
loadChildren: () =>
import('./saas/saas-page.module').then((m) => m.SaasPageModule)
},
{
path: 'self-hosting',
path: paths.selfHosting,
loadChildren: () =>
import('./self-hosting/self-hosting-page.module').then(
(m) => m.SelfHostingPageModule

View File

@ -1,5 +1,6 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { TabConfiguration } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { Component, OnDestroy, OnInit } from '@angular/core';
@ -35,18 +36,18 @@ export class FaqPageComponent implements OnDestroy, OnInit {
{
iconName: 'reader-outline',
label: $localize`General`,
path: ['/' + $localize`faq`]
path: ['/' + paths.faq]
},
{
iconName: 'cloudy-outline',
label: $localize`Cloud` + ' (SaaS)',
path: ['/' + $localize`faq`, 'saas'],
path: ['/' + paths.faq, paths.saas],
showCondition: this.hasPermissionForSubscription
},
{
iconName: 'server-outline',
label: $localize`Self-Hosting`,
path: ['/' + $localize`faq`, $localize`self-hosting`]
path: ['/' + paths.faq, paths.selfHosting]
}
];
}

View File

@ -1,5 +1,6 @@
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
@ -12,10 +13,8 @@ import { Subject, takeUntil } from 'rxjs';
standalone: false
})
export class FaqOverviewPageComponent implements OnDestroy {
public pricingUrl =
`https://ghostfol.io/${document.documentElement.lang}/` +
$localize`:snake-case:pricing`;
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${paths.pricing}`;
public routerLinkFeatures = ['/' + paths.features];
public user: User;
private unsubscribeSubject = new Subject<void>();

View File

@ -1,5 +1,6 @@
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
@ -12,11 +13,9 @@ import { Subject, takeUntil } from 'rxjs';
standalone: false
})
export class SaasPageComponent implements OnDestroy {
public pricingUrl =
`https://ghostfol.io/${document.documentElement.lang}/` +
$localize`:snake-case:pricing`;
public routerLinkMarkets = ['/' + $localize`:snake-case:markets`];
public routerLinkRegister = ['/' + $localize`:snake-case:register`];
public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${paths.pricing}`;
public routerLinkMarkets = ['/' + paths.markets];
public routerLinkRegister = ['/' + paths.register];
public user: User;
private unsubscribeSubject = new Subject<void>();

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
@ -9,9 +11,7 @@ import { Subject } from 'rxjs';
standalone: false
})
export class SelfHostingPageComponent implements OnDestroy {
public pricingUrl =
`https://ghostfol.io/${document.documentElement.lang}/` +
$localize`:snake-case:pricing`;
public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${paths.pricing}`;
private unsubscribeSubject = new Subject<void>();

View File

@ -1,6 +1,7 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { InfoItem, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
@ -25,8 +26,8 @@ import { Subject, takeUntil } from 'rxjs';
export class GfFeaturesPageComponent implements OnDestroy {
public hasPermissionForSubscription: boolean;
public info: InfoItem;
public routerLinkRegister = ['/' + $localize`:snake-case:register`];
public routerLinkResources = ['/' + $localize`:snake-case:resources`];
public routerLinkRegister = ['/' + paths.register];
public routerLinkResources = ['/' + paths.resources];
public user: User;
private unsubscribeSubject = new Subject<void>();

View File

@ -4,6 +4,7 @@ import { HomeOverviewComponent } from '@ghostfolio/client/components/home-overvi
import { HomeSummaryComponent } from '@ghostfolio/client/components/home-summary/home-summary.component';
import { HomeWatchlistComponent } from '@ghostfolio/client/components/home-watchlist/home-watchlist.component';
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -19,27 +20,22 @@ const routes: Routes = [
component: HomeOverviewComponent
},
{
path: 'holdings',
path: paths.holdings,
component: HomeHoldingsComponent,
title: $localize`Holdings`
},
{
path: 'holdings',
component: HomeHoldingsComponent,
title: $localize`Holdings`
},
{
path: 'summary',
path: paths.summary,
component: HomeSummaryComponent,
title: $localize`Summary`
},
{
path: 'market',
path: paths.market,
component: HomeMarketComponent,
title: $localize`Markets`
},
{
path: 'watchlist',
path: paths.watchlist,
component: HomeWatchlistComponent,
title: $localize`Watchlist`
}

View File

@ -1,6 +1,7 @@
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { TabConfiguration, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -36,27 +37,27 @@ export class HomePageComponent implements OnDestroy, OnInit {
{
iconName: 'analytics-outline',
label: $localize`Overview`,
path: ['/home']
path: ['/' + paths.home]
},
{
iconName: 'wallet-outline',
label: $localize`Holdings`,
path: ['/home', 'holdings']
path: ['/' + paths.home, paths.holdings]
},
{
iconName: 'reader-outline',
label: $localize`Summary`,
path: ['/home', 'summary']
path: ['/' + paths.home, paths.summary]
},
{
iconName: 'bookmark-outline',
label: $localize`Watchlist`,
path: ['/home', 'watchlist']
path: ['/' + paths.home, paths.watchlist]
},
{
iconName: 'newspaper-outline',
label: $localize`Markets`,
path: ['/home', 'market']
path: ['/' + paths.home, paths.market]
}
];

View File

@ -1,5 +1,6 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { Statistics } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { Component, OnDestroy, OnInit } from '@angular/core';
@ -24,8 +25,8 @@ export class LandingPageComponent implements OnDestroy, OnInit {
public hasPermissionForStatistics: boolean;
public hasPermissionForSubscription: boolean;
public hasPermissionToCreateUser: boolean;
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkRegister = ['/' + $localize`:snake-case:register`];
public routerLinkAbout = ['/' + paths.about];
public routerLinkRegister = ['/' + paths.register];
public statistics: Statistics;
public testimonials = [
{

View File

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -17,26 +18,26 @@ const routes: Routes = [
)
},
{
path: 'activities',
path: paths.activities,
loadChildren: () =>
import('./activities/activities-page.module').then(
(m) => m.ActivitiesPageModule
)
},
{
path: 'allocations',
path: paths.allocations,
loadChildren: () =>
import('./allocations/allocations-page.module').then(
(m) => m.AllocationsPageModule
)
},
{
path: 'fire',
path: paths.fire,
loadChildren: () =>
import('./fire/fire-page.module').then((m) => m.FirePageModule)
},
{
path: 'x-ray',
path: paths.xRay,
loadChildren: () =>
import('./x-ray/x-ray-page.module').then((m) => m.XRayPageModule)
}

View File

@ -1,5 +1,6 @@
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { TabConfiguration, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -33,27 +34,27 @@ export class PortfolioPageComponent implements OnDestroy, OnInit {
{
iconName: 'analytics-outline',
label: $localize`Analysis`,
path: ['/portfolio']
path: ['/' + paths.portfolio]
},
{
iconName: 'swap-vertical-outline',
label: $localize`Activities`,
path: ['/portfolio', 'activities']
path: ['/' + paths.portfolio, paths.activities]
},
{
iconName: 'pie-chart-outline',
label: $localize`Allocations`,
path: ['/portfolio', 'allocations']
path: ['/' + paths.portfolio, paths.allocations]
},
{
iconName: 'calculator-outline',
label: 'FIRE ',
path: ['/portfolio', 'fire']
path: ['/' + paths.portfolio, paths.fire]
},
{
iconName: 'scan-outline',
label: 'X-ray',
path: ['/portfolio', 'x-ray']
path: ['/' + paths.portfolio, paths.xRay]
}
];
this.user = state.user;

View File

@ -2,6 +2,7 @@ import { NotificationService } from '@ghostfolio/client/core/notification/notifi
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { translate } from '@ghostfolio/ui/i18n';
@ -40,8 +41,8 @@ export class PricingPageComponent implements OnDestroy, OnInit {
public professionalDataProviderTooltipPremium = translate(
'PROFESSIONAL_DATA_PROVIDER_TOOLTIP_PREMIUM'
);
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkRegister = ['/' + $localize`:snake-case:register`];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkRegister = ['/' + paths.register];
public user: User;
private unsubscribeSubject = new Subject<void>();

View File

@ -1,4 +1,5 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { paths } from '@ghostfolio/common/paths';
import {
ChangeDetectionStrategy,
@ -30,8 +31,8 @@ export class ShowAccessTokenDialog {
public isDisclaimerChecked = false;
public role: string;
public routerLinkAboutTermsOfService = [
'/' + $localize`:snake-case:about`,
$localize`:snake-case:terms-of-service`
'/' + paths.about,
paths.termsOfService
];
private unsubscribeSubject = new Subject<void>();

View File

@ -1,5 +1,6 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { InfoItem } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { Component, OnInit } from '@angular/core';
@ -14,8 +15,8 @@ export class ResourcesGlossaryPageComponent implements OnInit {
public hasPermissionForSubscription: boolean;
public info: InfoItem;
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`:snake-case:resources`,
'personal-finance-tools'
'/' + paths.resources,
paths.personalFinanceTools
];
public constructor(private dataService: DataService) {

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component } from '@angular/core';
@Component({
@ -12,34 +14,25 @@ export class ResourcesOverviewComponent {
title: 'Frequently Asked Questions (FAQ)',
description:
'Find quick answers to commonly asked questions about Ghostfolio in our Frequently Asked Questions (FAQ) section.',
link: ['/' + $localize`:snake-case:faq`]
link: ['/' + paths.faq]
},
{
title: 'Guides',
description:
'Explore our guides to help you get started with investing and managing your finances.',
link: [
'/' + $localize`:snake-case:resources`,
$localize`:snake-case:guides`
]
link: ['/' + paths.resources, paths.guides]
},
{
title: 'Markets',
description:
'Access various market resources and tools to stay informed about financial markets.',
link: [
'/' + $localize`:snake-case:resources`,
$localize`:snake-case:markets`
]
link: ['/' + paths.resources, paths.markets]
},
{
title: 'Glossary',
description:
'Learn key financial terms and concepts in our comprehensive glossary.',
link: [
'/' + $localize`:snake-case:resources`,
$localize`:snake-case:glossary`
]
link: ['/' + paths.resources, paths.glossary]
}
];
}

View File

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { paths } from '@ghostfolio/common/paths';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { NgModule } from '@angular/core';
@ -23,7 +24,7 @@ const routes: Routes = [
return GfProductPageComponent;
}
),
path: $localize`open-source-alternative-to` + `-${alias ?? key}`,
path: `${paths.openSourceAlternativeTo}-${alias ?? key}`,
title: $localize`Open Source Alternative to ${name}`
};
})

View File

@ -1,3 +1,4 @@
import { paths } from '@ghostfolio/common/paths';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { Component, OnDestroy } from '@angular/core';
@ -11,12 +12,12 @@ import { Subject } from 'rxjs';
standalone: false
})
export class PersonalFinanceToolsPageComponent implements OnDestroy {
public pathAlternativeTo = $localize`open-source-alternative-to` + '-';
public pathResources = '/' + $localize`resources`;
public pathAlternativeTo = paths.openSourceAlternativeTo + '-';
public pathResources = '/' + paths.resources;
public personalFinanceTools = personalFinanceTools.sort((a, b) => {
return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
});
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkAbout = ['/' + paths.about];
private unsubscribeSubject = new Subject<void>();

View File

@ -1,5 +1,6 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { Product } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { translate } from '@ghostfolio/ui/i18n';
@ -19,11 +20,11 @@ export class GfProductPageComponent implements OnInit {
public price: number;
public product1: Product;
public product2: Product;
public routerLinkAbout = ['/' + $localize`:snake-case:about`];
public routerLinkFeatures = ['/' + $localize`:snake-case:features`];
public routerLinkAbout = ['/' + paths.about];
public routerLinkFeatures = ['/' + paths.features];
public routerLinkResourcesPersonalFinanceTools = [
'/' + $localize`:snake-case:resources`,
'personal-finance-tools'
'/' + paths.resources,
paths.personalFinanceTools
];
public tags: string[];

View File

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -18,27 +19,27 @@ const routes: Routes = [
)
},
{
path: $localize`:snake-case:glossary`,
path: paths.glossary,
loadChildren: () =>
import('./glossary/resources-glossary.module').then(
(m) => m.ResourcesGlossaryPageModule
)
},
{
path: $localize`:snake-case:guides`,
path: paths.guides,
loadChildren: () =>
import('./guides/resources-guides.module').then(
(m) => m.ResourcesGuidesModule
)
},
{
path: $localize`:snake-case:markets`,
path: paths.markets,
loadChildren: () =>
import('./markets/resources-markets.module').then(
(m) => m.ResourcesMarketsModule
)
},
...['personal-finance-tools'].map((path) => ({
...[paths.personalFinanceTools].map((path) => ({
path,
loadChildren: () =>
import(

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { Component, OnInit } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
@ -18,17 +20,17 @@ export class ResourcesPageComponent implements OnInit {
iconName: 'reader-outline'
},
{
path: 'guides',
path: paths.guides,
label: $localize`Guides`,
iconName: 'book-outline'
},
{
path: 'markets',
path: paths.markets,
label: $localize`Markets`,
iconName: 'newspaper-outline'
},
{
path: 'glossary',
path: paths.glossary,
label: $localize`Glossary`,
iconName: 'library-outline'
}

View File

@ -2,6 +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 { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -18,12 +19,12 @@ const routes: Routes = [
title: $localize`Settings`
},
{
path: 'membership',
path: paths.membership,
component: UserAccountMembershipComponent,
title: $localize`Membership`
},
{
path: 'access',
path: paths.access,
component: UserAccountAccessComponent,
title: $localize`Access`
}

View File

@ -1,5 +1,6 @@
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { TabConfiguration, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -34,18 +35,18 @@ export class UserAccountPageComponent implements OnDestroy, OnInit {
{
iconName: 'settings-outline',
label: $localize`Settings`,
path: ['/account']
path: ['/' + paths.account]
},
{
iconName: 'diamond-outline',
label: $localize`Membership`,
path: ['/account/membership'],
path: ['/' + paths.account, paths.membership],
showCondition: !!this.user?.subscription
},
{
iconName: 'key-outline',
label: $localize`Access`,
path: ['/account', 'access']
path: ['/' + paths.account, paths.access]
}
];

View File

@ -1,6 +1,7 @@
import { HomeHoldingsComponent } from '@ghostfolio/client/components/home-holdings/home-holdings.component';
import { HomeOverviewComponent } from '@ghostfolio/client/components/home-overview/home-overview.component';
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { paths } from '@ghostfolio/common/paths';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -12,7 +13,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
children: [
{ path: '', component: HomeOverviewComponent },
{ path: 'holdings', component: HomeHoldingsComponent }
{ path: paths.holdings, component: HomeHoldingsComponent }
],
component: ZenPageComponent,
path: '',

View File

@ -1,5 +1,6 @@
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { TabConfiguration, User } from '@ghostfolio/common/interfaces';
import { paths } from '@ghostfolio/common/paths';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -33,12 +34,12 @@ export class ZenPageComponent implements OnDestroy, OnInit {
{
iconName: 'analytics-outline',
label: $localize`Overview`,
path: ['/zen']
path: ['/' + paths.zen]
},
{
iconName: 'wallet-outline',
label: $localize`Holdings`,
path: ['/zen', 'holdings']
path: ['/' + paths.zen, paths.holdings]
}
];
this.user = state.user;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
import '@angular/localize/init';
export const paths = {
access: 'access',
account: 'account',
accounts: 'accounts',
activities: 'activities',
admin: 'admin',
allocations: 'allocations',
api: 'api',
auth: 'auth',
blog: 'blog',
demo: 'demo',
fire: 'fire',
holdings: 'holdings',
home: 'home',
i18n: 'i18n',
jobs: 'jobs',
market: 'market',
marketData: 'market-data',
membership: 'membership',
open: 'open',
personalFinanceTools: 'personal-finance-tools',
portfolio: 'portfolio',
public: 'p',
saas: 'saas',
settings: 'settings',
start: 'start',
summary: 'summary',
users: 'users',
watchlist: 'watchlist',
webauthn: 'webauthn',
xRay: 'x-ray',
zen: 'zen',
// Localized paths (public-facing pages)
about: $localize`:snake-case:about`,
changelog: $localize`:snake-case:changelog`,
faq: $localize`:snake-case:faq`,
features: $localize`:snake-case:features`,
glossary: $localize`:snake-case:glossary`,
guides: $localize`:snake-case:guides`,
license: $localize`:snake-case:license`,
markets: $localize`:snake-case:markets`,
openSourceAlternativeTo: $localize`:snake-case:open-source-alternative-to`,
ossFriends: $localize`:snake-case:oss-friends`,
pricing: $localize`:snake-case:pricing`,
privacyPolicy: $localize`:snake-case:privacy-policy`,
register: $localize`:snake-case:register`,
resources: $localize`:snake-case:resources`,
selfHosting: $localize`:snake-case:self-hosting`,
termsOfService: $localize`:snake-case:terms-of-service`
};

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { CommonModule } from '@angular/common';
import {
CUSTOM_ELEMENTS_SCHEMA,
@ -27,7 +29,7 @@ export class GfMembershipCardComponent {
@Output() generateApiKeyClicked = new EventEmitter<void>();
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkPricing = ['/' + paths.pricing];
public onGenerateApiKey(event: MouseEvent) {
event.preventDefault();

View File

@ -1,3 +1,5 @@
import { paths } from '@ghostfolio/common/paths';
import { CommonModule } from '@angular/common';
import {
CUSTOM_ELEMENTS_SCHEMA,
@ -18,5 +20,5 @@ import { RouterModule } from '@angular/router';
export class GfPremiumIndicatorComponent {
@Input() enableLink = true;
public routerLinkPricing = ['/' + $localize`:snake-case:pricing`];
public routerLinkPricing = ['/' + paths.pricing];
}