Browse Source

Merge branch 'main' of https://github.com/aleskrin/ghostfolio into improve-spanish

pull/4924/head
Alesky Zakarin 2 weeks ago
parent
commit
bd7801a967
  1. 15
      CHANGELOG.md
  2. 8
      DEVELOPMENT.md
  3. 6
      apps/api/src/app/app.module.ts
  4. 2
      apps/api/src/app/endpoints/ai/ai.service.ts
  5. 12
      apps/api/src/main.ts
  6. 43
      apps/client/src/app/app-routing.module.ts
  7. 54
      apps/client/src/app/app.component.ts
  8. 4
      apps/client/src/app/components/access-table/access-table.component.ts
  9. 4
      apps/client/src/app/components/admin-settings/admin-settings.component.ts
  10. 8
      apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts
  11. 13
      apps/client/src/app/components/header/header.component.html
  12. 25
      apps/client/src/app/components/header/header.component.ts
  13. 4
      apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts
  14. 4
      apps/client/src/app/components/user-account-membership/user-account-membership.component.ts
  15. 28
      apps/client/src/app/core/auth.guard.ts
  16. 10
      apps/client/src/app/core/http-response.interceptor.ts
  17. 14
      apps/client/src/app/pages/about/about-page-routing.module.ts
  18. 26
      apps/client/src/app/pages/about/about-page.component.ts
  19. 2
      apps/client/src/app/pages/about/about-page.html
  20. 3
      apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts
  21. 3
      apps/client/src/app/pages/about/license/license-page-routing.module.ts
  22. 3
      apps/client/src/app/pages/about/oss-friends/oss-friends-page-routing.module.ts
  23. 6
      apps/client/src/app/pages/about/overview/about-overview-page.component.ts
  24. 3
      apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts
  25. 3
      apps/client/src/app/pages/about/terms-of-service/terms-of-service-page-routing.module.ts
  26. 20
      apps/client/src/app/pages/admin/admin-page-routing.module.ts
  27. 20
      apps/client/src/app/pages/admin/admin-page.component.ts
  28. 2
      apps/client/src/app/pages/admin/admin-page.html
  29. 8
      apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts
  30. 8
      apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts
  31. 6
      apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts
  32. 4
      apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.component.ts
  33. 6
      apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts
  34. 8
      apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts
  35. 4
      apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.component.ts
  36. 6
      apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts
  37. 4
      apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.component.ts
  38. 4
      apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.component.ts
  39. 4
      apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.component.ts
  40. 6
      apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts
  41. 6
      apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts
  42. 4
      apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts
  43. 7
      apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts
  44. 11
      apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts
  45. 6
      apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts
  46. 6
      apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts
  47. 6
      apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts
  48. 6
      apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts
  49. 6
      apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts
  50. 3
      apps/client/src/app/pages/blog/blog-page-routing.module.ts
  51. 8
      apps/client/src/app/pages/faq/faq-page-routing.module.ts
  52. 8
      apps/client/src/app/pages/faq/faq-page.component.ts
  53. 2
      apps/client/src/app/pages/faq/faq-page.html
  54. 4
      apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts
  55. 3
      apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts
  56. 16
      apps/client/src/app/pages/faq/saas/saas-page.component.ts
  57. 3
      apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts
  58. 4
      apps/client/src/app/pages/faq/self-hosting/self-hosting-page.component.ts
  59. 4
      apps/client/src/app/pages/features/features-page.component.ts
  60. 9
      apps/client/src/app/pages/home/home-page-routing.module.ts
  61. 14
      apps/client/src/app/pages/home/home-page.component.ts
  62. 2
      apps/client/src/app/pages/home/home-page.html
  63. 6
      apps/client/src/app/pages/landing/landing-page.component.ts
  64. 3
      apps/client/src/app/pages/markets/markets-page-routing.module.ts
  65. 12
      apps/client/src/app/pages/portfolio/portfolio-page.component.ts
  66. 2
      apps/client/src/app/pages/portfolio/portfolio-page.html
  67. 8
      apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.component.ts
  68. 4
      apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts
  69. 8
      apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts
  70. 4
      apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts
  71. 4
      apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts
  72. 2
      apps/client/src/app/pages/resources/overview/resources-overview.component.html
  73. 18
      apps/client/src/app/pages/resources/overview/resources-overview.component.ts
  74. 8
      apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts
  75. 12
      apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts
  76. 4
      apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html
  77. 10
      apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
  78. 16
      apps/client/src/app/pages/resources/resources-page-routing.module.ts
  79. 21
      apps/client/src/app/pages/resources/resources-page.component.ts
  80. 2
      apps/client/src/app/pages/resources/resources-page.html
  81. 12
      apps/client/src/app/pages/user-account/user-account-page-routing.module.ts
  82. 13
      apps/client/src/app/pages/user-account/user-account-page.component.ts
  83. 2
      apps/client/src/app/pages/user-account/user-account-page.html
  84. 4
      apps/client/src/app/pages/zen/zen-page.component.ts
  85. 2
      apps/client/src/app/pages/zen/zen-page.html
  86. 530
      apps/client/src/locales/messages.ca.xlf
  87. 526
      apps/client/src/locales/messages.de.xlf
  88. 526
      apps/client/src/locales/messages.es.xlf
  89. 526
      apps/client/src/locales/messages.fr.xlf
  90. 526
      apps/client/src/locales/messages.it.xlf
  91. 526
      apps/client/src/locales/messages.nl.xlf
  92. 526
      apps/client/src/locales/messages.pl.xlf
  93. 552
      apps/client/src/locales/messages.pt.xlf
  94. 526
      apps/client/src/locales/messages.tr.xlf
  95. 530
      apps/client/src/locales/messages.uk.xlf
  96. 522
      apps/client/src/locales/messages.xlf
  97. 550
      apps/client/src/locales/messages.zh.xlf
  98. 2
      libs/common/src/lib/interfaces/tab-configuration.interface.ts
  99. 243
      libs/common/src/lib/routes/routes.ts
  100. 5
      libs/ui/src/lib/account-balances/account-balances.component.ts

15
CHANGELOG.md

@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Changed
- Adapted the options of the date range selector in the assistant dynamically based on the user’s first activity
- Migrated the `@ghostfolio/ui/assistant` component to control flow
- Migrated the `@ghostfolio/ui/value` component to control flow
- Improved the language localization for Chinese (`zh`)
- Improved the language localization for Portuguese (`pt`)
## 2.171.0 - 2025-06-15
### Added
- Added the current holdings as default options of the symbol search in the create or update activity dialog
@ -31,6 +41,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the language localization for Turkish (`tr`)
- Upgraded the _Stripe_ dependencies
### Fixed
- Fixed a date offset issue with account balances
- Fixed missing `/.well-known/assetlinks.json` for TWA
## 2.170.0 - 2025-06-11
### Added

8
DEVELOPMENT.md

@ -30,7 +30,13 @@ Run `npm run start:server`
### Start Client
Run `npm run start:client` and open https://localhost:4200/en in your browser
#### English (Default)
Run `npm run start:client` and open https://localhost:4200/en in your browser.
#### Other Languages
To start the client in a different language, such as German (`de`), adapt the `start:client` script in the `package.json` file by changing `--configuration=development-en` to `--configuration=development-de`. Then, run `npm run start:client` and open https://localhost:4200/de in your browser.
### Start _Storybook_

6
apps/api/src/app/app.module.ts

@ -103,7 +103,7 @@ import { UserModule } from './user/user.module';
RedisCacheModule,
ScheduleModule.forRoot(),
ServeStaticModule.forRoot({
exclude: ['/api/*wildcard', '/sitemap.xml'],
exclude: ['/.well-known/*wildcard', '/api/*wildcard', '/sitemap.xml'],
rootPath: join(__dirname, '..', 'client'),
serveStaticOptions: {
setHeaders: (res) => {
@ -126,6 +126,10 @@ import { UserModule } from './user/user.module';
}
}
}),
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'client', '.well-known'),
serveRoot: '/.well-known'
}),
SitemapModule,
SubscriptionModule,
SymbolModule,

2
apps/api/src/app/endpoints/ai/ai.service.ts

@ -30,7 +30,7 @@ export class AiService {
});
const holdingsTable = [
'| Name | Symbol | Currency | Asset Class | Asset Sub Class | Allocation in Percentage |',
'| Name | Symbol | Currency | Asset Class | Asset Sub Class | Allocation in Percentage |',
'| --- | --- | --- | --- | --- | --- |',
...Object.values(holdings)
.sort((a, b) => {

12
apps/api/src/main.ts

@ -1,7 +1,8 @@
import {
DEFAULT_HOST,
DEFAULT_PORT,
STORYBOOK_PATH
STORYBOOK_PATH,
SUPPORTED_LANGUAGE_CODES
} from '@ghostfolio/common/config';
import {
@ -43,7 +44,14 @@ async function bootstrap() {
defaultVersion: '1',
type: VersioningType.URI
});
app.setGlobalPrefix('api', { exclude: ['sitemap.xml'] });
app.setGlobalPrefix('api', {
exclude: [
'sitemap.xml',
...SUPPORTED_LANGUAGE_CODES.map((languageCode) => {
return `/${languageCode}/*wildcard`;
})
]
});
app.useGlobalPipes(
new ValidationPipe({
forbidNonWhitelisted: true,

43
apps/client/src/app/app-routing.module.ts

@ -1,10 +1,6 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { PageTitleStrategy } from '@ghostfolio/client/services/page-title.strategy';
import {
publicRoutes,
routes as ghostfolioRoutes,
internalRoutes
} from '@ghostfolio/common/routes/routes';
import { publicRoutes, internalRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes, TitleStrategy } from '@angular/router';
@ -13,7 +9,7 @@ import { ModulePreloadService } from './core/module-preload.service';
const routes: Routes = [
{
path: ghostfolioRoutes.about,
path: publicRoutes.about.path,
loadChildren: () =>
import('./pages/about/about-page.module').then((m) => m.AboutPageModule)
},
@ -32,7 +28,7 @@ const routes: Routes = [
)
},
{
path: ghostfolioRoutes.adminControl,
path: internalRoutes.adminControl.path,
loadChildren: () =>
import('./pages/admin/admin-page.module').then((m) => m.AdminPageModule)
},
@ -42,16 +38,17 @@ const routes: Routes = [
import('./pages/api/api-page.component').then(
(c) => c.GfApiPageComponent
),
path: ghostfolioRoutes.api,
title: 'Ghostfolio API'
path: internalRoutes.api.path,
title: internalRoutes.api.title
},
{
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: ghostfolioRoutes.blog,
path: publicRoutes.blog.path,
loadChildren: () =>
import('./pages/blog/blog-page.module').then((m) => m.BlogPageModule)
},
@ -61,10 +58,10 @@ const routes: Routes = [
import('./pages/demo/demo-page.component').then(
(c) => c.GfDemoPageComponent
),
path: ghostfolioRoutes.demo
path: publicRoutes.demo.path
},
{
path: ghostfolioRoutes.faq,
path: publicRoutes.faq.path,
loadChildren: () =>
import('./pages/faq/faq-page.module').then((m) => m.FaqPageModule)
},
@ -88,11 +85,11 @@ const routes: Routes = [
import('./pages/i18n/i18n-page.component').then(
(c) => c.GfI18nPageComponent
),
path: ghostfolioRoutes.i18n,
title: $localize`Internationalization`
path: internalRoutes.i18n.path,
title: internalRoutes.i18n.title
},
{
path: ghostfolioRoutes.markets,
path: publicRoutes.markets.path,
loadChildren: () =>
import('./pages/markets/markets-page.module').then(
(m) => m.MarketsPageModule
@ -111,14 +108,14 @@ const routes: Routes = [
)
},
{
path: ghostfolioRoutes.pricing,
path: publicRoutes.pricing.path,
loadChildren: () =>
import('./pages/pricing/pricing-page.module').then(
(m) => m.PricingPageModule
)
},
{
path: ghostfolioRoutes.public,
path: publicRoutes.public.path,
loadChildren: () =>
import('./pages/public/public-page.module').then(
(m) => m.PublicPageModule
@ -132,14 +129,14 @@ const routes: Routes = [
)
},
{
path: ghostfolioRoutes.resources,
path: publicRoutes.resources.path,
loadChildren: () =>
import('./pages/resources/resources-page.module').then(
(m) => m.ResourcesPageModule
)
},
{
path: ghostfolioRoutes.start,
path: publicRoutes.start.path,
loadChildren: () =>
import('./pages/landing/landing-page.module').then(
(m) => m.LandingPageModule
@ -150,8 +147,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,

54
apps/client/src/app/app.component.ts

@ -3,11 +3,7 @@ import { HoldingDetailDialogParams } from '@ghostfolio/client/components/holding
import { getCssVariable } from '@ghostfolio/common/helper';
import { InfoItem, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import {
internalRoutes,
publicRoutes,
routes
} from '@ghostfolio/common/routes/routes';
import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes';
import { ColorScheme } from '@ghostfolio/common/types';
import { DOCUMENT } from '@angular/common';
@ -67,25 +63,23 @@ export class AppComponent implements OnDestroy, OnInit {
public hasTabs = false;
public info: InfoItem;
public pageTitle: string;
public routerLinkAbout = ['/' + routes.about];
public routerLinkAboutChangelog = ['/' + routes.about, routes.changelog];
public routerLinkAboutLicense = ['/' + routes.about, routes.license];
public routerLinkAboutPrivacyPolicy = [
'/' + routes.about,
routes.privacyPolicy
];
public routerLinkAboutTermsOfService = [
'/' + routes.about,
routes.termsOfService
];
public routerLinkBlog = ['/' + routes.blog];
public routerLinkFaq = ['/' + routes.faq];
public routerLinkAbout = publicRoutes.about.routerLink;
public routerLinkAboutChangelog =
publicRoutes.about.subRoutes.changelog.routerLink;
public routerLinkAboutLicense =
publicRoutes.about.subRoutes.license.routerLink;
public routerLinkAboutPrivacyPolicy =
publicRoutes.about.subRoutes.privacyPolicy.routerLink;
public routerLinkAboutTermsOfService =
publicRoutes.about.subRoutes.termsOfService.routerLink;
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFaq = publicRoutes.faq.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkMarkets = ['/' + routes.markets];
public routerLinkMarkets = publicRoutes.markets.routerLink;
public routerLinkOpenStartup = publicRoutes.openStartup.routerLink;
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkPricing = publicRoutes.pricing.routerLink;
public routerLinkRegister = publicRoutes.register.routerLink;
public routerLinkResources = ['/' + routes.resources];
public routerLinkResources = publicRoutes.resources.routerLink;
public showFooter = false;
public user: User;
@ -200,25 +194,25 @@ export class AppComponent implements OnDestroy, OnInit {
}
this.hasTabs =
(this.currentRoute === routes.about ||
this.currentRoute === routes.faq ||
this.currentRoute === routes.resources ||
(this.currentRoute === publicRoutes.about.path ||
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) &&
this.deviceType !== 'mobile';
this.showFooter =
(this.currentRoute === routes.blog ||
(this.currentRoute === publicRoutes.blog.path ||
this.currentRoute === publicRoutes.features.path ||
this.currentRoute === routes.markets ||
this.currentRoute === publicRoutes.markets.path ||
this.currentRoute === publicRoutes.openStartup.path ||
this.currentRoute === routes.public ||
this.currentRoute === routes.pricing ||
this.currentRoute === publicRoutes.public.path ||
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') {

4
apps/client/src/app/components/access-table/access-table.component.ts

@ -1,7 +1,7 @@
import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type';
import { NotificationService } from '@ghostfolio/client/core/notification/notification.service';
import { Access, User } from '@ghostfolio/common/interfaces';
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Clipboard } from '@angular/cdk/clipboard';
import {
@ -55,7 +55,7 @@ export class AccessTableComponent implements OnChanges {
public getPublicUrl(aId: string): string {
const languageCode = this.user.settings.language;
return `${this.baseUrl}/${languageCode}/${routes.public}/${aId}`;
return `${this.baseUrl}/${languageCode}/${publicRoutes.public.path}/${aId}`;
}
public onCopyUrlToClipboard(aId: string): void {

4
apps/client/src/app/components/admin-settings/admin-settings.component.ts

@ -10,7 +10,7 @@ import {
DataProviderInfo,
User
} from '@ghostfolio/common/interfaces';
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import {
ChangeDetectionStrategy,
@ -72,7 +72,7 @@ export class AdminSettingsComponent implements OnDestroy, OnInit {
const languageCode = this.user.settings.language;
this.pricingUrl = `https://ghostfol.io/${languageCode}/${routes.pricing}`;
this.pricingUrl = `https://ghostfol.io/${languageCode}/${publicRoutes.pricing.path}`;
this.changeDetectorRef.markForCheck();
}

8
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(

13
apps/client/src/app/components/header/header.component.html

@ -65,8 +65,10 @@
i18n
mat-flat-button
[ngClass]="{
'font-weight-bold': currentRoute === routes.adminControl,
'text-decoration-underline': currentRoute === routes.adminControl
'font-weight-bold':
currentRoute === internalRoutes.adminControl.path,
'text-decoration-underline':
currentRoute === internalRoutes.adminControl.path
}"
[routerLink]="routerLinkAdminControl"
>Admin Control</a
@ -268,7 +270,9 @@
<a
i18n
mat-menu-item
[ngClass]="{ 'font-weight-bold': currentRoute === routes.account }"
[ngClass]="{
'font-weight-bold': currentRoute === internalRoutes.account.path
}"
[routerLink]="routerLinkAccount"
>My Ghostfolio</a
>
@ -278,7 +282,8 @@
i18n
mat-menu-item
[ngClass]="{
'font-weight-bold': currentRoute === routes.adminControl
'font-weight-bold':
currentRoute === internalRoutes.adminControl.path
}"
[routerLink]="routerLinkAdminControl"
>Admin Control</a

25
apps/client/src/app/components/header/header.component.ts

@ -12,11 +12,7 @@ import { TokenStorageService } from '@ghostfolio/client/services/token-storage.s
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { Filter, InfoItem, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import {
internalRoutes,
publicRoutes,
routes
} from '@ghostfolio/common/routes/routes';
import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes';
import { DateRange } from '@ghostfolio/common/types';
import { GfAssistantComponent } from '@ghostfolio/ui/assistant/assistant.component';
@ -85,22 +81,21 @@ export class HeaderComponent implements OnChanges {
public impersonationId: string;
public internalRoutes = internalRoutes;
public isMenuOpen: boolean;
public routeAbout = routes.about;
public routeAbout = publicRoutes.about.path;
public routeFeatures = publicRoutes.features.path;
public routeMarkets = routes.markets;
public routePricing = routes.pricing;
public routeResources = routes.resources;
public routerLinkAbout = ['/' + routes.about];
public routeMarkets = publicRoutes.markets.path;
public routePricing = publicRoutes.pricing.path;
public routeResources = publicRoutes.resources.path;
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 = ['/' + routes.markets];
public routerLinkMarkets = publicRoutes.markets.routerLink;
public routerLinkPortfolio = internalRoutes.portfolio.routerLink;
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkPricing = publicRoutes.pricing.routerLink;
public routerLinkRegister = publicRoutes.register.routerLink;
public routerLinkResources = ['/' + routes.resources];
public routes = routes;
public routerLinkResources = publicRoutes.resources.routerLink;
private unsubscribeSubject = new Subject<void>();

4
apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import {
ChangeDetectionStrategy,
@ -28,7 +28,7 @@ export class SubscriptionInterstitialDialog implements OnInit {
public remainingSkipButtonDelay =
SubscriptionInterstitialDialog.SKIP_BUTTON_DELAY_IN_SECONDS;
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkPricing = publicRoutes.pricing.routerLink;
public variantIndex: number;
private unsubscribeSubject = new Subject<void>();

4
apps/client/src/app/components/user-account-membership/user-account-membership.component.ts

@ -5,7 +5,7 @@ import { UserService } from '@ghostfolio/client/services/user/user.service';
import { getDateFormatString } from '@ghostfolio/common/helper';
import { User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import {
ChangeDetectionStrategy,
@ -37,7 +37,7 @@ export class UserAccountMembershipComponent implements OnDestroy {
public hasPermissionToUpdateUserSettings: boolean;
public price: number;
public priceId: string;
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkPricing = publicRoutes.pricing.routerLink;
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;

28
apps/client/src/app/core/auth.guard.ts

@ -1,11 +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 {
internalRoutes,
publicRoutes,
routes
} from '@ghostfolio/common/routes/routes';
import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes';
import { Injectable } from '@angular/core';
import {
@ -19,17 +15,17 @@ import { catchError } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class AuthGuard {
private static PUBLIC_PAGE_ROUTES = [
`/${routes.about}`,
`/${routes.blog}`,
`/${routes.demo}`,
`/${routes.faq}`,
`/${publicRoutes.about.path}`,
`/${publicRoutes.blog.path}`,
`/${publicRoutes.demo.path}`,
`/${publicRoutes.faq.path}`,
`/${publicRoutes.features.path}`,
`/${routes.markets}`,
`/${publicRoutes.markets.path}`,
`/${publicRoutes.openStartup.path}`,
`/${routes.pricing}`,
`/${routes.public}`,
`/${publicRoutes.pricing.path}`,
`/${publicRoutes.public.path}`,
`/${publicRoutes.register.path}`,
`/${routes.resources}`
`/${publicRoutes.resources.path}`
];
public constructor(
@ -52,7 +48,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 +62,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 +94,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 {

10
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 { 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,
@ -75,7 +77,7 @@ export class HttpResponseInterceptor implements HttpInterceptor {
});
this.snackBarRef.onAction().subscribe(() => {
this.router.navigate(['/' + routes.pricing]);
this.router.navigate(publicRoutes.pricing.routerLink);
});
}
} else if (error.status === StatusCodes.INTERNAL_SERVER_ERROR) {
@ -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();
}

14
apps/client/src/app/pages/about/about-page-routing.module.ts

@ -1,5 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { routes as ghostfolioRoutes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -18,35 +18,35 @@ const routes: Routes = [
)
},
{
path: ghostfolioRoutes.changelog,
path: publicRoutes.about.subRoutes.changelog.path,
loadChildren: () =>
import('./changelog/changelog-page.module').then(
(m) => m.ChangelogPageModule
)
},
{
path: ghostfolioRoutes.license,
path: publicRoutes.about.subRoutes.license.path,
loadChildren: () =>
import('./license/license-page.module').then(
(m) => m.LicensePageModule
)
},
{
path: ghostfolioRoutes.ossFriends,
path: publicRoutes.about.subRoutes.ossFriends.path,
loadChildren: () =>
import('./oss-friends/oss-friends-page.module').then(
(m) => m.OpenSourceSoftwareFriendsPageModule
)
},
{
path: ghostfolioRoutes.privacyPolicy,
path: publicRoutes.about.subRoutes.privacyPolicy.path,
loadChildren: () =>
import('./privacy-policy/privacy-policy-page.module').then(
(m) => m.PrivacyPolicyPageModule
)
},
{
path: ghostfolioRoutes.termsOfService,
path: publicRoutes.about.subRoutes.termsOfService.path,
loadChildren: () =>
import('./terms-of-service/terms-of-service-page.module').then(
(m) => m.TermsOfServicePageModule
@ -55,7 +55,7 @@ const routes: Routes = [
],
component: AboutPageComponent,
path: '',
title: $localize`About`
title: publicRoutes.about.title
}
];

26
apps/client/src/app/pages/about/about-page.component.ts

@ -2,7 +2,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 { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -43,18 +43,18 @@ export class AboutPageComponent implements OnDestroy, OnInit {
this.tabs = [
{
iconName: 'information-circle-outline',
label: $localize`About`,
path: ['/' + routes.about]
label: publicRoutes.about.title,
routerLink: publicRoutes.about.routerLink
},
{
iconName: 'sparkles-outline',
label: $localize`Changelog`,
path: ['/' + routes.about, routes.changelog]
label: publicRoutes.about.subRoutes.changelog.title,
routerLink: publicRoutes.about.subRoutes.changelog.routerLink
},
{
iconName: 'ribbon-outline',
label: $localize`License`,
path: ['/' + routes.about, routes.license],
label: publicRoutes.about.subRoutes.license.title,
routerLink: publicRoutes.about.subRoutes.license.routerLink,
showCondition: !this.hasPermissionForSubscription
}
];
@ -62,15 +62,15 @@ export class AboutPageComponent implements OnDestroy, OnInit {
if (state?.user) {
this.tabs.push({
iconName: 'shield-checkmark-outline',
label: $localize`Privacy Policy`,
path: ['/' + routes.about, routes.privacyPolicy],
label: publicRoutes.about.subRoutes.privacyPolicy.title,
routerLink: publicRoutes.about.subRoutes.privacyPolicy.routerLink,
showCondition: this.hasPermissionForSubscription
});
this.tabs.push({
iconName: 'document-text-outline',
label: $localize`Terms of Service`,
path: ['/' + routes.about, routes.termsOfService],
label: publicRoutes.about.subRoutes.termsOfService.title,
routerLink: publicRoutes.about.subRoutes.termsOfService.routerLink,
showCondition: this.hasPermissionForSubscription
});
@ -81,8 +81,8 @@ export class AboutPageComponent implements OnDestroy, OnInit {
this.tabs.push({
iconName: 'happy-outline',
label: 'OSS Friends',
path: ['/' + routes.about, routes.ossFriends]
label: publicRoutes.about.subRoutes.ossFriends.title,
routerLink: publicRoutes.about.subRoutes.ossFriends.routerLink
});
});
}

2
apps/client/src/app/pages/about/about-page.html

@ -16,7 +16,7 @@
mat-tab-link
routerLinkActive
[active]="rla.isActive"
[routerLink]="tab.path"
[routerLink]="tab.routerLink"
[routerLinkActiveOptions]="{ exact: true }"
>
<ion-icon

3
apps/client/src/app/pages/about/changelog/changelog-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: ChangelogPageComponent,
path: '',
title: $localize`Changelog`
title: publicRoutes.about.subRoutes.changelog.title
}
];

3
apps/client/src/app/pages/about/license/license-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: LicensePageComponent,
path: '',
title: $localize`License`
title: publicRoutes.about.subRoutes.license.title
}
];

3
apps/client/src/app/pages/about/oss-friends/oss-friends-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: OpenSourceSoftwareFriendsPageComponent,
path: '',
title: 'OSS Friends'
title: publicRoutes.about.subRoutes.ossFriends.title
}
];

6
apps/client/src/app/pages/about/overview/about-overview-page.component.ts

@ -2,7 +2,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 { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
@ -18,8 +18,8 @@ export class AboutOverviewPageComponent implements OnDestroy, OnInit {
public hasPermissionForStatistics: boolean;
public hasPermissionForSubscription: boolean;
public isLoggedIn: boolean;
public routerLinkBlog = ['/' + routes.blog];
public routerLinkFaq = ['/' + routes.faq];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFaq = publicRoutes.faq.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkOpenStartup = publicRoutes.openStartup.routerLink;
public user: User;

3
apps/client/src/app/pages/about/privacy-policy/privacy-policy-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: PrivacyPolicyPageComponent,
path: '',
title: $localize`Privacy Policy`
title: publicRoutes.about.subRoutes.privacyPolicy.title
}
];

3
apps/client/src/app/pages/about/terms-of-service/terms-of-service-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: TermsOfServicePageComponent,
path: '',
title: $localize`Terms of Service`
title: publicRoutes.about.subRoutes.termsOfService.title
}
];

20
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,

20
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`,
path: ['/' + routes.adminControl]
routerLink: internalRoutes.adminControl.routerLink
},
{
iconName: 'settings-outline',
label: $localize`Settings`,
path: ['/' + routes.adminControl, routes.settings]
label: internalRoutes.adminControl.subRoutes.settings.title,
routerLink: internalRoutes.adminControl.subRoutes.settings.routerLink
},
{
iconName: 'server-outline',
label: $localize`Market Data`,
path: ['/' + routes.adminControl, routes.marketData]
label: internalRoutes.adminControl.subRoutes.marketData.title,
routerLink: internalRoutes.adminControl.subRoutes.marketData.routerLink
},
{
iconName: 'flash-outline',
label: $localize`Job Queue`,
path: ['/' + routes.adminControl, routes.jobs]
label: internalRoutes.adminControl.subRoutes.jobs.title,
routerLink: internalRoutes.adminControl.subRoutes.jobs.routerLink
},
{
iconName: 'people-outline',
label: $localize`Users`,
path: ['/' + routes.adminControl, routes.users]
label: internalRoutes.adminControl.subRoutes.users.title,
routerLink: internalRoutes.adminControl.subRoutes.users.routerLink
}
];
}

2
apps/client/src/app/pages/admin/admin-page.html

@ -16,7 +16,7 @@
mat-tab-link
routerLinkActive
[active]="rla.isActive"
[routerLink]="tab.path"
[routerLink]="tab.routerLink"
[routerLinkActiveOptions]="{ exact: true }"
>
<ion-icon

8
apps/client/src/app/pages/blog/2021/07/hallo-ghostfolio/hallo-ghostfolio-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,7 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './hallo-ghostfolio-page.html'
})
export class HalloGhostfolioPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkResources = ['/' + routes.resources];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkPricing = publicRoutes.pricing.routerLink;
public routerLinkResources = publicRoutes.resources.routerLink;
}

8
apps/client/src/app/pages/blog/2021/07/hello-ghostfolio/hello-ghostfolio-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,7 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './hello-ghostfolio-page.html'
})
export class HelloGhostfolioPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkResources = ['/' + routes.resources];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkPricing = publicRoutes.pricing.routerLink;
public routerLinkResources = publicRoutes.resources.routerLink;
}

6
apps/client/src/app/pages/blog/2022/01/first-months-in-open-source/first-months-in-open-source-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './first-months-in-open-source-page.html'
})
export class FirstMonthsInOpenSourcePageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkPricing = publicRoutes.pricing.routerLink;
}

4
apps/client/src/app/pages/blog/2022/07/ghostfolio-meets-internet-identity/ghostfolio-meets-internet-identity-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './ghostfolio-meets-internet-identity-page.html'
})
export class GhostfolioMeetsInternetIdentityPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
}

6
apps/client/src/app/pages/blog/2022/07/how-do-i-get-my-finances-in-order/how-do-i-get-my-finances-in-order-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './how-do-i-get-my-finances-in-order-page.html'
})
export class HowDoIGetMyFinancesInOrderPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkResources = ['/' + routes.resources];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkResources = publicRoutes.resources.routerLink;
}

8
apps/client/src/app/pages/blog/2022/08/500-stars-on-github/500-stars-on-github-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,7 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './500-stars-on-github-page.html'
})
export class FiveHundredStarsOnGitHubPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkMarkets = ['/' + routes.markets];
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkMarkets = publicRoutes.markets.routerLink;
public routerLinkPricing = publicRoutes.pricing.routerLink;
}

4
apps/client/src/app/pages/blog/2022/10/hacktoberfest-2022/hacktoberfest-2022-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './hacktoberfest-2022-page.html'
})
export class Hacktoberfest2022PageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
}

6
apps/client/src/app/pages/blog/2022/11/black-friday-2022/black-friday-2022-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { Component } from '@angular/core';
@ -12,7 +12,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './black-friday-2022-page.html'
})
export class BlackFriday2022PageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkPricing = publicRoutes.pricing.routerLink;
}

4
apps/client/src/app/pages/blog/2022/12/the-importance-of-tracking-your-personal-finances/the-importance-of-tracking-your-personal-finances-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './the-importance-of-tracking-your-personal-finances-page.html'
})
export class TheImportanceOfTrackingYourPersonalFinancesPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
}

4
apps/client/src/app/pages/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt/ghostfolio-auf-sackgeld-vorgestellt-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './ghostfolio-auf-sackgeld-vorgestellt-page.html'
})
export class GhostfolioAufSackgeldVorgestelltPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
}

4
apps/client/src/app/pages/blog/2023/02/ghostfolio-meets-umbrel/ghostfolio-meets-umbrel-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,5 +11,5 @@ import { RouterModule } from '@angular/router';
templateUrl: './ghostfolio-meets-umbrel-page.html'
})
export class GhostfolioMeetsUmbrelPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
}

6
apps/client/src/app/pages/blog/2023/03/1000-stars-on-github/1000-stars-on-github-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,7 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './1000-stars-on-github-page.html'
})
export class ThousandStarsOnGitHubPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkPricing = publicRoutes.pricing.routerLink;
}

6
apps/client/src/app/pages/blog/2023/05/unlock-your-financial-potential-with-ghostfolio/unlock-your-financial-potential-with-ghostfolio-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,7 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './unlock-your-financial-potential-with-ghostfolio-page.html'
})
export class UnlockYourFinancialPotentialWithGhostfolioPageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkResources = ['/' + routes.resources];
public routerLinkResources = publicRoutes.resources.routerLink;
}

4
apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,6 +11,6 @@ import { RouterModule } from '@angular/router';
templateUrl: './exploring-the-path-to-fire-page.html'
})
export class ExploringThePathToFirePageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
}

7
apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,6 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './ghostfolio-joins-oss-friends-page.html'
})
export class GhostfolioJoinsOssFriendsPageComponent {
public routerLinkAboutOssFriends = ['/' + routes.about, routes.ossFriends];
public routerLinkBlog = ['/' + routes.blog];
public routerLinkAboutOssFriends =
publicRoutes.about.subRoutes.ossFriends.routerLink;
public routerLinkBlog = publicRoutes.blog.routerLink;
}

11
apps/client/src/app/pages/blog/2023/09/ghostfolio-2/ghostfolio-2-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,9 +11,10 @@ import { RouterModule } from '@angular/router';
templateUrl: './ghostfolio-2-page.html'
})
export class Ghostfolio2PageComponent {
public routerLinkAbout = ['/' + routes.about];
public routerLinkAboutChangelog = ['/' + routes.about, routes.changelog];
public routerLinkBlog = ['/' + routes.blog];
public routerLinkAbout = publicRoutes.about.routerLink;
public routerLinkAboutChangelog =
publicRoutes.about.subRoutes.changelog.routerLink;
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkMarkets = ['/' + routes.markets];
public routerLinkMarkets = publicRoutes.markets.routerLink;
}

6
apps/client/src/app/pages/blog/2023/09/hacktoberfest-2023/hacktoberfest-2023-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,7 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './hacktoberfest-2023-page.html'
})
export class Hacktoberfest2023PageComponent {
public routerLinkAbout = ['/' + routes.about];
public routerLinkBlog = ['/' + routes.blog];
public routerLinkAbout = publicRoutes.about.routerLink;
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkOpenStartup = publicRoutes.openStartup.routerLink;
}

6
apps/client/src/app/pages/blog/2023/11/black-week-2023/black-week-2023-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { Component } from '@angular/core';
@ -12,7 +12,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './black-week-2023-page.html'
})
export class BlackWeek2023PageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkPricing = publicRoutes.pricing.routerLink;
}

6
apps/client/src/app/pages/blog/2023/11/hacktoberfest-2023-debriefing/hacktoberfest-2023-debriefing-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,7 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './hacktoberfest-2023-debriefing-page.html'
})
export class Hacktoberfest2023DebriefingPageComponent {
public routerLinkAbout = ['/' + routes.about];
public routerLinkBlog = ['/' + routes.blog];
public routerLinkAbout = publicRoutes.about.routerLink;
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
}

6
apps/client/src/app/pages/blog/2024/09/hacktoberfest-2024/hacktoberfest-2024-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@ -11,7 +11,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './hacktoberfest-2024-page.html'
})
export class Hacktoberfest2024PageComponent {
public routerLinkAbout = ['/' + routes.about];
public routerLinkBlog = ['/' + routes.blog];
public routerLinkAbout = publicRoutes.about.routerLink;
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkOpenStartup = publicRoutes.openStartup.routerLink;
}

6
apps/client/src/app/pages/blog/2024/11/black-weeks-2024/black-weeks-2024-page.component.ts

@ -1,4 +1,4 @@
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { Component } from '@angular/core';
@ -12,7 +12,7 @@ import { RouterModule } from '@angular/router';
templateUrl: './black-weeks-2024-page.html'
})
export class BlackWeeks2024PageComponent {
public routerLinkBlog = ['/' + routes.blog];
public routerLinkBlog = publicRoutes.blog.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkPricing = ['/' + routes.pricing];
public routerLinkPricing = publicRoutes.pricing.routerLink;
}

3
apps/client/src/app/pages/blog/blog-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: BlogPageComponent,
path: '',
title: $localize`Blog`
title: publicRoutes.blog.title
},
{
canActivate: [AuthGuard],

8
apps/client/src/app/pages/faq/faq-page-routing.module.ts

@ -1,5 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { routes as ghostfolioRoutes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -18,12 +18,12 @@ const routes: Routes = [
)
},
{
path: ghostfolioRoutes.saas,
path: publicRoutes.faq.subRoutes.saas.path,
loadChildren: () =>
import('./saas/saas-page.module').then((m) => m.SaasPageModule)
},
{
path: ghostfolioRoutes.selfHosting,
path: publicRoutes.faq.subRoutes.selfHosting.path,
loadChildren: () =>
import('./self-hosting/self-hosting-page.module').then(
(m) => m.SelfHostingPageModule
@ -32,7 +32,7 @@ const routes: Routes = [
],
component: FaqPageComponent,
path: '',
title: $localize`Frequently Asked Questions (FAQ)`
title: publicRoutes.faq.title
}
];

8
apps/client/src/app/pages/faq/faq-page.component.ts

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

2
apps/client/src/app/pages/faq/faq-page.html

@ -16,7 +16,7 @@
mat-tab-link
routerLinkActive
[active]="rla.isActive"
[routerLink]="tab.path"
[routerLink]="tab.routerLink"
[routerLinkActiveOptions]="{ exact: true }"
>
<ion-icon

4
apps/client/src/app/pages/faq/overview/faq-overview-page.component.ts

@ -1,6 +1,6 @@
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { User } from '@ghostfolio/common/interfaces';
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
@ -13,7 +13,7 @@ import { Subject, takeUntil } from 'rxjs';
standalone: false
})
export class FaqOverviewPageComponent implements OnDestroy {
public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${routes.pricing}`;
public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${publicRoutes.pricing.path}`;
public routerLinkFeatures = publicRoutes.features.routerLink;
public user: User;

3
apps/client/src/app/pages/faq/saas/saas-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: SaasPageComponent,
path: '',
title: $localize`Cloud` + ' (SaaS) – ' + $localize`FAQ`
title: `${publicRoutes.faq.subRoutes.saas.title} - ${publicRoutes.faq.title}`
}
];

16
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';
@ -17,13 +13,11 @@ import { Subject, takeUntil } from 'rxjs';
standalone: false
})
export class SaasPageComponent implements OnDestroy {
public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${routes.pricing}`;
public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${publicRoutes.pricing.path}`;
public routerLinkAccount = internalRoutes.account.routerLink;
public routerLinkAccountMembership = [
'/' + internalRoutes.account.path,
routes.membership
];
public routerLinkMarkets = ['/' + routes.markets];
public routerLinkAccountMembership =
internalRoutes.account.subRoutes.membership.routerLink;
public routerLinkMarkets = publicRoutes.markets.routerLink;
public routerLinkRegister = publicRoutes.register.routerLink;
public user: User;

3
apps/client/src/app/pages/faq/self-hosting/self-hosting-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: SelfHostingPageComponent,
path: '',
title: $localize`Self-Hosting` + ' – ' + $localize`FAQ`
title: `${publicRoutes.faq.subRoutes.selfHosting.title} - ${publicRoutes.faq.title}`
}
];

4
apps/client/src/app/pages/faq/self-hosting/self-hosting-page.component.ts

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

4
apps/client/src/app/pages/features/features-page.component.ts

@ -2,7 +2,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 { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';
@ -27,7 +27,7 @@ export class GfFeaturesPageComponent implements OnDestroy {
public hasPermissionForSubscription: boolean;
public info: InfoItem;
public routerLinkRegister = publicRoutes.register.routerLink;
public routerLinkResources = ['/' + routes.resources];
public routerLinkResources = publicRoutes.resources.routerLink;
public user: User;
private unsubscribeSubject = new Subject<void>();

9
apps/client/src/app/pages/home/home-page-routing.module.ts

@ -4,10 +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 {
routes as ghostfolioRoutes,
internalRoutes
} from '@ghostfolio/common/routes/routes';
import { internalRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -33,9 +30,9 @@ const routes: Routes = [
title: internalRoutes.home.subRoutes.summary.title
},
{
path: ghostfolioRoutes.market,
path: internalRoutes.home.subRoutes.markets.path,
component: HomeMarketComponent,
title: $localize`Markets`
title: internalRoutes.home.subRoutes.markets.title
},
{
path: internalRoutes.home.subRoutes.watchlist.path,

14
apps/client/src/app/pages/home/home-page.component.ts

@ -1,7 +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 { 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';
@ -37,27 +37,27 @@ export class HomePageComponent implements OnDestroy, OnInit {
{
iconName: 'analytics-outline',
label: internalRoutes.home.title,
path: internalRoutes.home.routerLink
routerLink: internalRoutes.home.routerLink
},
{
iconName: 'wallet-outline',
label: internalRoutes.home.subRoutes.holdings.title,
path: internalRoutes.home.subRoutes.holdings.routerLink
routerLink: internalRoutes.home.subRoutes.holdings.routerLink
},
{
iconName: 'reader-outline',
label: internalRoutes.home.subRoutes.summary.title,
path: internalRoutes.home.subRoutes.summary.routerLink
routerLink: internalRoutes.home.subRoutes.summary.routerLink
},
{
iconName: 'bookmark-outline',
label: internalRoutes.home.subRoutes.watchlist.title,
path: internalRoutes.home.subRoutes.watchlist.routerLink
routerLink: internalRoutes.home.subRoutes.watchlist.routerLink
},
{
iconName: 'newspaper-outline',
label: $localize`Markets`,
path: ['/' + internalRoutes.home.path, routes.market]
label: internalRoutes.home.subRoutes.markets.title,
routerLink: internalRoutes.home.subRoutes.markets.routerLink
}
];

2
apps/client/src/app/pages/home/home-page.html

@ -16,7 +16,7 @@
mat-tab-link
routerLinkActive
[active]="rla.isActive"
[routerLink]="tab.path"
[routerLink]="tab.routerLink"
[routerLinkActiveOptions]="{ exact: true }"
>
<ion-icon

6
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';
@ -25,8 +25,8 @@ export class LandingPageComponent implements OnDestroy, OnInit {
public hasPermissionForStatistics: boolean;
public hasPermissionForSubscription: boolean;
public hasPermissionToCreateUser: boolean;
public routerLinkAbout = ['/' + routes.about];
public routerLinkDemo = ['/' + routes.demo];
public routerLinkAbout = publicRoutes.about.routerLink;
public routerLinkDemo = publicRoutes.demo.routerLink;
public routerLinkOpenStartup = publicRoutes.openStartup.routerLink;
public routerLinkRegister = publicRoutes.register.routerLink;
public statistics: Statistics;

3
apps/client/src/app/pages/markets/markets-page-routing.module.ts

@ -1,4 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -10,7 +11,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: MarketsPageComponent,
path: '',
title: $localize`Markets`
title: publicRoutes.markets.title
}
];

12
apps/client/src/app/pages/portfolio/portfolio-page.component.ts

@ -34,27 +34,29 @@ export class PortfolioPageComponent implements OnDestroy, OnInit {
{
iconName: 'analytics-outline',
label: internalRoutes.portfolio.subRoutes.analysis.title,
path: internalRoutes.portfolio.routerLink
routerLink: internalRoutes.portfolio.routerLink
},
{
iconName: 'swap-vertical-outline',
label: internalRoutes.portfolio.subRoutes.activities.title,
path: internalRoutes.portfolio.subRoutes.activities.routerLink
routerLink:
internalRoutes.portfolio.subRoutes.activities.routerLink
},
{
iconName: 'pie-chart-outline',
label: internalRoutes.portfolio.subRoutes.allocations.title,
path: internalRoutes.portfolio.subRoutes.allocations.routerLink
routerLink:
internalRoutes.portfolio.subRoutes.allocations.routerLink
},
{
iconName: 'calculator-outline',
label: internalRoutes.portfolio.subRoutes.fire.title,
path: internalRoutes.portfolio.subRoutes.fire.routerLink
routerLink: internalRoutes.portfolio.subRoutes.fire.routerLink
},
{
iconName: 'scan-outline',
label: internalRoutes.portfolio.subRoutes.xRay.title,
path: internalRoutes.portfolio.subRoutes.xRay.routerLink
routerLink: internalRoutes.portfolio.subRoutes.xRay.routerLink
}
];
this.user = state.user;

2
apps/client/src/app/pages/portfolio/portfolio-page.html

@ -16,7 +16,7 @@
mat-tab-link
routerLinkActive
[active]="rla.isActive"
[routerLink]="tab.path"
[routerLink]="tab.routerLink"
[routerLinkActiveOptions]="{ exact: true }"
>
<ion-icon

8
apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.component.ts

@ -1,5 +1,5 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import {
ChangeDetectionStrategy,
@ -30,10 +30,8 @@ export class ShowAccessTokenDialog {
public isCreateAccountButtonDisabled = true;
public isDisclaimerChecked = false;
public role: string;
public routerLinkAboutTermsOfService = [
'/' + routes.about,
routes.termsOfService
];
public routerLinkAboutTermsOfService =
publicRoutes.about.subRoutes.termsOfService.routerLink;
private unsubscribeSubject = new Subject<void>();

4
apps/client/src/app/pages/resources/glossary/resources-glossary-routing.module.ts

@ -1,3 +1,5 @@
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -7,7 +9,7 @@ const routes: Routes = [
{
component: ResourcesGlossaryPageComponent,
path: '',
title: $localize`Glossary`
title: publicRoutes.resources.subRoutes.glossary.title
}
];

8
apps/client/src/app/pages/resources/glossary/resources-glossary.component.ts

@ -1,7 +1,7 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { InfoItem } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component, OnInit } from '@angular/core';
@ -14,10 +14,8 @@ import { Component, OnInit } from '@angular/core';
export class ResourcesGlossaryPageComponent implements OnInit {
public hasPermissionForSubscription: boolean;
public info: InfoItem;
public routerLinkResourcesPersonalFinanceTools = [
'/' + routes.resources,
routes.personalFinanceTools
];
public routerLinkResourcesPersonalFinanceTools =
publicRoutes.resources.subRoutes.personalFinanceTools.routerLink;
public constructor(private dataService: DataService) {
this.info = this.dataService.fetchInfo();

4
apps/client/src/app/pages/resources/guides/resources-guides-routing.module.ts

@ -1,3 +1,5 @@
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -7,7 +9,7 @@ const routes: Routes = [
{
component: ResourcesGuidesComponent,
path: '',
title: $localize`Guides`
title: publicRoutes.resources.subRoutes.guides.title
}
];

4
apps/client/src/app/pages/resources/markets/resources-markets-routing.module.ts

@ -1,3 +1,5 @@
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -7,7 +9,7 @@ const routes: Routes = [
{
component: ResourcesMarketsComponent,
path: '',
title: $localize`Markets`
title: publicRoutes.resources.subRoutes.markets.title
}
];

2
apps/client/src/app/pages/resources/overview/resources-overview.component.html

@ -7,7 +7,7 @@
<div class="mb-4">
<h3 class="h5 mt-0">{{ item.title }}</h3>
<p class="mb-1">{{ item.description }}</p>
<a [routerLink]="item.link">Explore {{ item.title }} →</a>
<a [routerLink]="item.routerLink">Explore {{ item.title }} →</a>
</div>
}
</div>

18
apps/client/src/app/pages/resources/overview/resources-overview.component.ts

@ -1,4 +1,4 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component } from '@angular/core';
@ -11,28 +11,28 @@ import { Component } from '@angular/core';
export class ResourcesOverviewComponent {
public overviewItems = [
{
title: 'Frequently Asked Questions (FAQ)',
description:
'Find quick answers to commonly asked questions about Ghostfolio in our Frequently Asked Questions (FAQ) section.',
link: ['/' + routes.faq]
routerLink: publicRoutes.faq.routerLink,
title: publicRoutes.faq.title
},
{
title: 'Guides',
description:
'Explore our guides to help you get started with investing and managing your finances.',
link: ['/' + routes.resources, routes.guides]
routerLink: publicRoutes.resources.subRoutes.guides.routerLink,
title: publicRoutes.resources.subRoutes.guides.title
},
{
title: 'Markets',
description:
'Access various market resources and tools to stay informed about financial markets.',
link: ['/' + routes.resources, routes.markets]
routerLink: publicRoutes.resources.subRoutes.markets.routerLink,
title: publicRoutes.resources.subRoutes.markets.title
},
{
title: 'Glossary',
description:
'Learn key financial terms and concepts in our comprehensive glossary.',
link: ['/' + routes.resources, routes.glossary]
routerLink: publicRoutes.resources.subRoutes.glossary.routerLink,
title: publicRoutes.resources.subRoutes.glossary.title
}
];
}

8
apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page-routing.module.ts

@ -1,6 +1,6 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { routes as ghostfolioRoutes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -12,7 +12,7 @@ const routes: Routes = [
canActivate: [AuthGuard],
component: PersonalFinanceToolsPageComponent,
path: '',
title: $localize`Personal Finance Tools`
title: publicRoutes.resources.subRoutes.personalFinanceTools.title
},
...personalFinanceTools.map(({ alias, key, name }) => {
return {
@ -24,8 +24,8 @@ const routes: Routes = [
return GfProductPageComponent;
}
),
path: `${ghostfolioRoutes.openSourceAlternativeTo}-${alias ?? key}`,
title: $localize`Open Source Alternative to ${name}`
path: `${publicRoutes.resources.subRoutes.personalFinanceTools.subRoutes.product.path}-${alias ?? key}`,
title: `${publicRoutes.resources.subRoutes.personalFinanceTools.subRoutes.product.title} ${name}`
};
})
];

12
apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts

@ -1,5 +1,5 @@
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
@ -12,12 +12,16 @@ import { Subject } from 'rxjs';
standalone: false
})
export class PersonalFinanceToolsPageComponent implements OnDestroy {
public pathAlternativeTo = routes.openSourceAlternativeTo + '-';
public pathResources = '/' + routes.resources;
public pathAlternativeTo =
publicRoutes.resources.subRoutes.personalFinanceTools.subRoutes.product
.path + '-';
public pathResources = publicRoutes.resources.path;
public pathPersonalFinanceTools =
publicRoutes.resources.subRoutes.personalFinanceTools.path;
public personalFinanceTools = personalFinanceTools.sort((a, b) => {
return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
});
public routerLinkAbout = ['/' + routes.about];
public routerLinkAbout = publicRoutes.about.routerLink;
private unsubscribeSubject = new Subject<void>();

4
apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.html

@ -32,8 +32,8 @@
personalFinanceTool.name
}} - {{ personalFinanceTool.slogan }}"
[routerLink]="[
pathResources,
'personal-finance-tools',
'/' + pathResources,
pathPersonalFinanceTools,
pathAlternativeTo +
(personalFinanceTool.alias ?? personalFinanceTool.key)
]"

10
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts

@ -1,7 +1,7 @@
import { DataService } from '@ghostfolio/client/services/data.service';
import { Product } from '@ghostfolio/common/interfaces';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { publicRoutes, routes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { translate } from '@ghostfolio/ui/i18n';
import { Component, OnInit } from '@angular/core';
@ -20,12 +20,10 @@ export class GfProductPageComponent implements OnInit {
public price: number;
public product1: Product;
public product2: Product;
public routerLinkAbout = ['/' + routes.about];
public routerLinkAbout = publicRoutes.about.routerLink;
public routerLinkFeatures = publicRoutes.features.routerLink;
public routerLinkResourcesPersonalFinanceTools = [
'/' + routes.resources,
routes.personalFinanceTools
];
public routerLinkResourcesPersonalFinanceTools =
publicRoutes.resources.subRoutes.personalFinanceTools.routerLink;
public tags: string[];
public constructor(

16
apps/client/src/app/pages/resources/resources-page-routing.module.ts

@ -1,5 +1,5 @@
import { AuthGuard } from '@ghostfolio/client/core/auth.guard';
import { routes as ghostfolioRoutes } from '@ghostfolio/common/routes/routes';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
@ -19,36 +19,36 @@ const routes: Routes = [
)
},
{
path: ghostfolioRoutes.glossary,
path: publicRoutes.resources.subRoutes.glossary.path,
loadChildren: () =>
import('./glossary/resources-glossary.module').then(
(m) => m.ResourcesGlossaryPageModule
)
},
{
path: ghostfolioRoutes.guides,
path: publicRoutes.resources.subRoutes.guides.path,
loadChildren: () =>
import('./guides/resources-guides.module').then(
(m) => m.ResourcesGuidesModule
)
},
{
path: ghostfolioRoutes.markets,
path: publicRoutes.resources.subRoutes.markets.path,
loadChildren: () =>
import('./markets/resources-markets.module').then(
(m) => m.ResourcesMarketsModule
)
},
...[ghostfolioRoutes.personalFinanceTools].map((path) => ({
path,
{
path: publicRoutes.resources.subRoutes.personalFinanceTools.path,
loadChildren: () =>
import(
'./personal-finance-tools/personal-finance-tools-page.module'
).then((m) => m.PersonalFinanceToolsPageModule)
}))
}
],
path: '',
title: $localize`Resources`
title: publicRoutes.resources.title
}
];

21
apps/client/src/app/pages/resources/resources-page.component.ts

@ -1,4 +1,5 @@
import { routes } from '@ghostfolio/common/routes/routes';
import { TabConfiguration } from '@ghostfolio/common/interfaces';
import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { Component, OnInit } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -13,26 +14,26 @@ import { Subject } from 'rxjs';
})
export class ResourcesPageComponent implements OnInit {
public deviceType: string;
public tabs = [
public tabs: TabConfiguration[] = [
{
path: '.',
iconName: 'reader-outline',
label: $localize`Overview`,
iconName: 'reader-outline'
routerLink: publicRoutes.resources.routerLink
},
{
path: routes.guides,
label: $localize`Guides`,
iconName: 'book-outline'
iconName: 'book-outline',
routerLink: publicRoutes.resources.subRoutes.guides.routerLink
},
{
path: routes.markets,
iconName: 'newspaper-outline',
label: $localize`Markets`,
iconName: 'newspaper-outline'
routerLink: publicRoutes.resources.subRoutes.markets.routerLink
},
{
path: routes.glossary,
iconName: 'library-outline',
label: $localize`Glossary`,
iconName: 'library-outline'
routerLink: publicRoutes.resources.subRoutes.glossary.routerLink
}
];

2
apps/client/src/app/pages/resources/resources-page.html

@ -16,7 +16,7 @@
mat-tab-link
routerLinkActive
[active]="rla.isActive"
[routerLink]="tab.path"
[routerLink]="tab.routerLink"
[routerLinkActiveOptions]="{ exact: true }"
>
<ion-icon

12
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,

13
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';
@ -35,18 +35,19 @@ export class UserAccountPageComponent implements OnDestroy, OnInit {
{
iconName: 'settings-outline',
label: internalRoutes.account.title,
path: internalRoutes.account.routerLink
routerLink: internalRoutes.account.routerLink
},
{
iconName: 'diamond-outline',
label: $localize`Membership`,
path: ['/' + 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`,
path: ['/' + internalRoutes.account.path, routes.access]
label: internalRoutes.account.subRoutes.access.title,
routerLink: internalRoutes.account.subRoutes.access.routerLink
}
];

2
apps/client/src/app/pages/user-account/user-account-page.html

@ -16,7 +16,7 @@
mat-tab-link
routerLinkActive
[active]="rla.isActive"
[routerLink]="tab.path"
[routerLink]="tab.routerLink"
[routerLinkActiveOptions]="{ exact: true }"
>
<ion-icon

4
apps/client/src/app/pages/zen/zen-page.component.ts

@ -34,12 +34,12 @@ export class ZenPageComponent implements OnDestroy, OnInit {
{
iconName: 'analytics-outline',
label: internalRoutes.zen.title,
path: internalRoutes.zen.routerLink
routerLink: internalRoutes.zen.routerLink
},
{
iconName: 'wallet-outline',
label: internalRoutes.zen.subRoutes.holdings.title,
path: internalRoutes.zen.subRoutes.holdings.routerLink
routerLink: internalRoutes.zen.subRoutes.holdings.routerLink
}
];
this.user = state.user;

2
apps/client/src/app/pages/zen/zen-page.html

@ -16,7 +16,7 @@
mat-tab-link
routerLinkActive
[active]="rla.isActive"
[routerLink]="tab.path"
[routerLink]="tab.routerLink"
[routerLinkActiveOptions]="{ exact: true }"
>
<ion-icon

530
apps/client/src/locales/messages.ca.xlf

File diff suppressed because it is too large

526
apps/client/src/locales/messages.de.xlf

File diff suppressed because it is too large

526
apps/client/src/locales/messages.es.xlf

File diff suppressed because it is too large

526
apps/client/src/locales/messages.fr.xlf

File diff suppressed because it is too large

526
apps/client/src/locales/messages.it.xlf

File diff suppressed because it is too large

526
apps/client/src/locales/messages.nl.xlf

File diff suppressed because it is too large

526
apps/client/src/locales/messages.pl.xlf

File diff suppressed because it is too large

552
apps/client/src/locales/messages.pt.xlf

File diff suppressed because it is too large

526
apps/client/src/locales/messages.tr.xlf

File diff suppressed because it is too large

530
apps/client/src/locales/messages.uk.xlf

File diff suppressed because it is too large

522
apps/client/src/locales/messages.xlf

File diff suppressed because it is too large

550
apps/client/src/locales/messages.zh.xlf

File diff suppressed because it is too large

2
libs/common/src/lib/interfaces/tab-configuration.interface.ts

@ -1,6 +1,6 @@
export interface TabConfiguration {
iconName: string;
label: string;
path: string[];
routerLink: string[];
showCondition?: boolean;
}

243
libs/common/src/lib/routes/routes.ts

@ -2,54 +2,69 @@ 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',
saas: 'saas',
settings: 'settings',
start: 'start',
users: 'users',
webauthn: 'webauthn',
// Publicly accessible pages
about: $localize`:kebab-case:about`,
blog: 'blog',
changelog: $localize`:kebab-case:changelog`,
faq: $localize`:kebab-case:faq`,
glossary: $localize`:kebab-case:glossary`,
guides: $localize`:kebab-case:guides`,
license: $localize`:kebab-case:license`,
markets: $localize`:kebab-case:markets`,
openSourceAlternativeTo: $localize`:kebab-case:open-source-alternative-to`,
ossFriends: 'oss-friends',
pricing: $localize`:kebab-case:pricing`,
privacyPolicy: $localize`:kebab-case:privacy-policy`,
resources: $localize`:kebab-case:resources`,
selfHosting: $localize`:kebab-case:self-hosting`,
termsOfService: $localize`:kebab-case:terms-of-service`
};
export const internalRoutes: Record<string, IRoute> = {
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`
},
api: {
excludeFromAssistant: true,
path: 'api',
routerLink: ['/api'],
title: 'Ghostfolio API'
},
auth: {
excludeFromAssistant: true,
path: 'auth',
routerLink: ['/auth'],
title: $localize`Sign in`
},
home: {
path: 'home',
routerLink: ['/home'],
@ -59,6 +74,11 @@ export const internalRoutes: Record<string, IRoute> = {
routerLink: ['/home', 'holdings'],
title: $localize`Holdings`
},
markets: {
path: 'markets',
routerLink: ['/home', 'markets'],
title: $localize`Markets`
},
summary: {
path: 'summary',
routerLink: ['/home', 'summary'],
@ -72,6 +92,12 @@ export const internalRoutes: Record<string, IRoute> = {
},
title: $localize`Overview`
},
i18n: {
excludeFromAssistant: true,
path: 'i18n',
routerLink: ['/i18n'],
title: $localize`Internationalization`
},
portfolio: {
path: 'portfolio',
routerLink: ['/portfolio'],
@ -104,6 +130,12 @@ export const internalRoutes: Record<string, IRoute> = {
},
title: $localize`Portfolio`
},
webauthn: {
excludeFromAssistant: true,
path: 'webauthn',
routerLink: ['/webauthn'],
title: $localize`Sign in`
},
zen: {
excludeFromAssistant: true,
path: 'zen',
@ -120,19 +152,156 @@ export const internalRoutes: Record<string, IRoute> = {
};
export const publicRoutes = {
about: {
path: $localize`:kebab-case:about`,
routerLink: ['/' + $localize`:kebab-case:about`],
subRoutes: {
changelog: {
path: $localize`:kebab-case:changelog`,
routerLink: [
'/' + $localize`:kebab-case:about`,
$localize`:kebab-case:changelog`
],
title: $localize`Changelog`
},
license: {
path: $localize`:kebab-case:license`,
routerLink: [
'/' + $localize`:kebab-case:about`,
$localize`:kebab-case:license`
],
title: $localize`License`
},
ossFriends: {
path: 'oss-friends',
routerLink: ['/' + $localize`:kebab-case:about`, 'oss-friends'],
title: 'OSS Friends'
},
privacyPolicy: {
path: $localize`:kebab-case:privacy-policy`,
routerLink: [
'/' + $localize`:kebab-case:about`,
$localize`:kebab-case:privacy-policy`
],
title: $localize`Privacy Policy`
},
termsOfService: {
path: $localize`:kebab-case:terms-of-service`,
routerLink: [
'/' + $localize`:kebab-case:about`,
$localize`:kebab-case:terms-of-service`
],
title: $localize`Terms of Service`
}
},
title: $localize`About`
},
blog: {
path: 'blog',
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`],
subRoutes: {
saas: {
path: 'saas',
routerLink: ['/' + $localize`:kebab-case:faq`, 'saas'],
title: $localize`Cloud` + ' (SaaS)'
},
selfHosting: {
path: $localize`:kebab-case:self-hosting`,
routerLink: [
'/' + $localize`:kebab-case:faq`,
$localize`:kebab-case:self-hosting`
],
title: $localize`Self-Hosting`
}
},
title: $localize`Frequently Asked Questions (FAQ)`
},
features: {
path: $localize`:kebab-case:features`,
routerLink: ['/' + $localize`:kebab-case:features`],
title: $localize`Features`
},
markets: {
path: $localize`:kebab-case:markets`,
routerLink: ['/' + $localize`:kebab-case:markets`],
title: $localize`Markets`
},
openStartup: {
path: 'open',
routerLink: ['/open'],
title: 'Open Startup'
},
pricing: {
path: $localize`:kebab-case:pricing`,
routerLink: ['/' + $localize`:kebab-case:pricing`],
title: $localize`Pricing`
},
public: {
path: 'p',
routerLink: ['/p']
},
register: {
path: $localize`:kebab-case:register`,
routerLink: ['/' + $localize`:kebab-case:register`],
title: $localize`Registration`
},
resources: {
path: $localize`:kebab-case:resources`,
routerLink: ['/' + $localize`:kebab-case:resources`],
subRoutes: {
glossary: {
path: $localize`:kebab-case:glossary`,
routerLink: [
'/' + $localize`:kebab-case:resources`,
$localize`:kebab-case:glossary`
],
title: $localize`Glossary`
},
guides: {
path: $localize`:kebab-case:guides`,
routerLink: [
'/' + $localize`:kebab-case:resources`,
$localize`:kebab-case:guides`
],
title: $localize`Guides`
},
markets: {
path: $localize`:kebab-case:markets`,
routerLink: [
'/' + $localize`:kebab-case:resources`,
$localize`:kebab-case:markets`
],
title: $localize`Markets`
},
personalFinanceTools: {
path: 'personal-finance-tools',
routerLink: [
'/' + $localize`:kebab-case:resources`,
'personal-finance-tools'
],
subRoutes: {
product: {
path: $localize`:kebab-case:open-source-alternative-to`,
title: $localize`Open Source Alternative to`
}
},
title: $localize`Personal Finance Tools`
}
},
title: $localize`Resources`
},
start: {
path: 'start',
routerLink: ['/start']
}
};

5
libs/ui/src/lib/account-balances/account-balances.component.ts

@ -2,7 +2,7 @@ import { CreateAccountBalanceDto } from '@ghostfolio/api/app/account-balance/cre
import { ConfirmationDialogType } from '@ghostfolio/client/core/notification/confirmation-dialog/confirmation-dialog.type';
import { NotificationService } from '@ghostfolio/client/core/notification/notification.service';
import { validateObjectForForm } from '@ghostfolio/client/util/form.util';
import { getLocale } from '@ghostfolio/common/helper';
import { DATE_FORMAT, getLocale } from '@ghostfolio/common/helper';
import { AccountBalancesResponse } from '@ghostfolio/common/interfaces';
import {
@ -31,6 +31,7 @@ import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { format } from 'date-fns';
import { get } from 'lodash';
import { Subject } from 'rxjs';
@ -114,7 +115,7 @@ export class GfAccountBalancesComponent
const accountBalance: CreateAccountBalanceDto = {
accountId: this.accountId,
balance: this.accountBalanceForm.get('balance').value,
date: this.accountBalanceForm.get('date').value.toISOString()
date: format(this.accountBalanceForm.get('date').value, DATE_FORMAT)
};
try {

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save