Browse Source

Merge branch 'main' into Task/upgrade-class-validator-to-version-0.14.3

pull/6091/head
Thomas Kaul 1 month ago
committed by GitHub
parent
commit
93bc731c55
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 16
      CHANGELOG.md
  2. 3
      apps/api/src/app/subscription/subscription.service.ts
  3. 2
      apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts
  4. 1
      apps/api/tsconfig.app.json
  5. 1
      apps/api/tsconfig.spec.json
  6. 1
      apps/client/project.json
  7. 2
      apps/client/src/app/components/access-table/access-table.component.ts
  8. 2
      apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
  9. 3
      apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.ts
  10. 3
      apps/client/src/app/components/footer/footer.component.ts
  11. 2
      apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts
  12. 2
      apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts
  13. 20
      apps/client/src/app/components/user-account-membership/user-account-membership.component.ts
  14. 2
      apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts
  15. 3
      apps/client/src/app/pages/blog/blog-page.component.ts
  16. 3
      apps/client/src/app/pages/markets/markets-page.component.ts
  17. 3
      apps/client/src/app/pages/open/open-page.component.ts
  18. 24
      apps/client/src/app/pages/pricing/pricing-page.component.ts
  19. 2
      apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.component.ts
  20. 3
      apps/client/src/app/pages/zen/zen-page.component.ts
  21. 15
      apps/client/src/main.ts
  22. 1
      apps/client/tsconfig.app.json
  23. 2
      apps/client/tsconfig.json
  24. 3
      apps/client/tsconfig.spec.json
  25. 3
      libs/common/src/lib/interfaces/info-item.interface.ts
  26. 3
      libs/common/src/lib/interfaces/responses/create-stripe-checkout-session-response.interface.ts
  27. 2
      libs/common/src/lib/routes/routes.ts
  28. 6
      libs/common/tsconfig.json
  29. 3
      libs/common/tsconfig.spec.json
  30. 2
      libs/ui/src/lib/logo-carousel/logo-carousel.component.ts
  31. 3
      libs/ui/tsconfig.json
  32. 2
      libs/ui/tsconfig.lib.json
  33. 3
      libs/ui/tsconfig.spec.json
  34. 4821
      package-lock.json
  35. 80
      package.json
  36. 3
      tsconfig.base.json

16
CHANGELOG.md

@ -7,21 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
### Changed
- Upgraded `class-validator` from version `0.14.2` to `0.14.3`
## 2.225.0 - 2025-12-31
### Added ### Added
- Added a new endpoint to get all platforms (`GET api/v1/platforms`) - Added a new endpoint to get all platforms (`GET api/v1/platforms`)
- Added the session url to the endpoint response of the _Stripe_ checkout
### Changed ### Changed
- Improved the routing of the user detail dialog in the users section of the admin control panel - Improved the routing of the user detail dialog in the users section of the admin control panel
- Lifted the asset profile identifier editing restriction for `MANUAL` data sources in the asset profile details dialog of the admin control panel - Lifted the asset profile identifier editing restriction for `MANUAL` data sources in the asset profile details dialog of the admin control panel
- Deprecated the public _Stripe_ key
- Improved the language localization for German (`de`) - Improved the language localization for German (`de`)
- Upgraded `angular` from version `20.2.4` to `20.3.9` - Upgraded `angular` from version `20.2.4` to `20.3.9`
- Upgraded `class-validator` from version `0.14.2` to `0.14.3` - Upgraded `class-validator` from version `0.14.2` to `0.14.3`
- Eliminated `ngx-stripe`
- Upgraded `angular` from version `20.2.4` to `21.0.6`
- Upgraded `marked` from version `15.0.4` to `17.0.1`
- Upgraded `ngx-device-detector` from version `10.1.0` to `11.0.0`
- Upgraded `ng-extract-i18n-merge` from `3.1.0` to `3.2.1` - Upgraded `ng-extract-i18n-merge` from `3.1.0` to `3.2.1`
- Upgraded `Nx` from version `21.5.1` to `22.1.3` - Upgraded `ngx-markdown` from version `20.0.0` to `21.0.1`
- Upgraded `Nx` from version `21.5.1` to `22.3.3`
- Upgraded `shx` from version `0.3.4` to `0.4.0` - Upgraded `shx` from version `0.3.4` to `0.4.0`
- Upgraded `storybook` from version `9.1.5` to `10.1.10` - Upgraded `storybook` from version `9.1.5` to `10.1.10`
- Upgraded `zone.js` from version `0.15.1` to `0.16.0`
### Fixed ### Fixed

3
apps/api/src/app/subscription/subscription.service.ts

@ -100,7 +100,8 @@ export class SubscriptionService {
); );
return { return {
sessionId: session.id sessionId: session.id,
sessionUrl: session.url
}; };
} }

2
apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts

@ -18,7 +18,7 @@ import {
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { DataSource, SymbolProfile } from '@prisma/client'; import { DataSource, SymbolProfile } from '@prisma/client';
import * as Alphavantage from 'alphavantage'; import Alphavantage from 'alphavantage';
import { format, isAfter, isBefore, parse } from 'date-fns'; import { format, isAfter, isBefore, parse } from 'date-fns';
import { AlphaVantageHistoricalResponse } from './interfaces/interfaces'; import { AlphaVantageHistoricalResponse } from './interfaces/interfaces';

1
apps/api/tsconfig.app.json

@ -4,6 +4,7 @@
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"types": ["node"], "types": ["node"],
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"moduleResolution": "node10",
"target": "es2021", "target": "es2021",
"module": "commonjs" "module": "commonjs"
}, },

1
apps/api/tsconfig.spec.json

@ -3,6 +3,7 @@
"compilerOptions": { "compilerOptions": {
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node10",
"types": ["jest", "node"] "types": ["jest", "node"]
}, },
"include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts", "jest.config.ts"] "include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts", "jest.config.ts"]

1
apps/client/project.json

@ -75,7 +75,6 @@
"ngswConfigPath": "apps/client/ngsw-config.json", "ngswConfigPath": "apps/client/ngsw-config.json",
"optimization": false, "optimization": false,
"polyfills": "apps/client/src/polyfills.ts", "polyfills": "apps/client/src/polyfills.ts",
"scripts": ["node_modules/marked/marked.min.js"],
"serviceWorker": true, "serviceWorker": true,
"sourceMap": true, "sourceMap": true,
"styles": [ "styles": [

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

@ -4,7 +4,6 @@ import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { NotificationService } from '@ghostfolio/ui/notifications'; import { NotificationService } from '@ghostfolio/ui/notifications';
import { Clipboard, ClipboardModule } from '@angular/cdk/clipboard'; import { Clipboard, ClipboardModule } from '@angular/cdk/clipboard';
import { CommonModule } from '@angular/common';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
@ -36,7 +35,6 @@ import ms from 'ms';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ imports: [
ClipboardModule, ClipboardModule,
CommonModule,
IonIcon, IonIcon,
MatButtonModule, MatButtonModule,
MatMenuModule, MatMenuModule,

2
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts

@ -29,7 +29,6 @@ import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplet
import { GfValueComponent } from '@ghostfolio/ui/value'; import { GfValueComponent } from '@ghostfolio/ui/value';
import { TextFieldModule } from '@angular/cdk/text-field'; import { TextFieldModule } from '@angular/cdk/text-field';
import { CommonModule } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http'; import { HttpErrorResponse } from '@angular/common/http';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
@ -95,7 +94,6 @@ import { AssetProfileDialogParams } from './interfaces/interfaces';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'd-flex flex-column h-100' }, host: { class: 'd-flex flex-column h-100' },
imports: [ imports: [
CommonModule,
FormsModule, FormsModule,
GfCurrencySelectorComponent, GfCurrencySelectorComponent,
GfEntityLogoComponent, GfEntityLogoComponent,

3
apps/client/src/app/components/fear-and-greed-index/fear-and-greed-index.component.ts

@ -1,7 +1,6 @@
import { resolveFearAndGreedIndex } from '@ghostfolio/common/helper'; import { resolveFearAndGreedIndex } from '@ghostfolio/common/helper';
import { translate } from '@ghostfolio/ui/i18n'; import { translate } from '@ghostfolio/ui/i18n';
import { CommonModule } from '@angular/common';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
@ -12,7 +11,7 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, NgxSkeletonLoaderModule], imports: [NgxSkeletonLoaderModule],
selector: 'gf-fear-and-greed-index', selector: 'gf-fear-and-greed-index',
styleUrls: ['./fear-and-greed-index.component.scss'], styleUrls: ['./fear-and-greed-index.component.scss'],
templateUrl: './fear-and-greed-index.component.html' templateUrl: './fear-and-greed-index.component.html'

3
apps/client/src/app/components/footer/footer.component.ts

@ -3,7 +3,6 @@ import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { GfLogoComponent } from '@ghostfolio/ui/logo'; import { GfLogoComponent } from '@ghostfolio/ui/logo';
import { CommonModule } from '@angular/common';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
@ -18,7 +17,7 @@ import { openOutline } from 'ionicons/icons';
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, GfLogoComponent, IonIcon, RouterModule], imports: [GfLogoComponent, IonIcon, RouterModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-footer', selector: 'gf-footer',
styleUrls: ['./footer.component.scss'], styleUrls: ['./footer.component.scss'],

2
apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts

@ -4,7 +4,6 @@ import {
} from '@ghostfolio/client/services/settings-storage.service'; } from '@ghostfolio/client/services/settings-storage.service';
import { GfDialogHeaderComponent } from '@ghostfolio/ui/dialog-header'; import { GfDialogHeaderComponent } from '@ghostfolio/ui/dialog-header';
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@ -28,7 +27,6 @@ import { LoginWithAccessTokenDialogParams } from './interfaces/interfaces';
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ imports: [
CommonModule,
GfDialogHeaderComponent, GfDialogHeaderComponent,
IonIcon, IonIcon,
MatButtonModule, MatButtonModule,

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

@ -2,7 +2,6 @@ import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { GfMembershipCardComponent } from '@ghostfolio/ui/membership-card'; import { GfMembershipCardComponent } from '@ghostfolio/ui/membership-card';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { CommonModule } from '@angular/common';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
@ -31,7 +30,6 @@ import { SubscriptionInterstitialDialogParams } from './interfaces/interfaces';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'd-flex flex-column flex-grow-1 h-100' }, host: { class: 'd-flex flex-column flex-grow-1 h-100' },
imports: [ imports: [
CommonModule,
GfMembershipCardComponent, GfMembershipCardComponent,
GfPremiumIndicatorComponent, GfPremiumIndicatorComponent,
IonIcon, IonIcon,

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

@ -21,9 +21,8 @@ import { MatCardModule } from '@angular/material/card';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import ms, { StringValue } from 'ms'; import ms, { StringValue } from 'ms';
import { StripeService } from 'ngx-stripe';
import { EMPTY, Subject } from 'rxjs'; import { EMPTY, Subject } from 'rxjs';
import { catchError, switchMap, takeUntil } from 'rxjs/operators'; import { catchError, takeUntil } from 'rxjs/operators';
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
@ -62,7 +61,6 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
private dataService: DataService, private dataService: DataService,
private notificationService: NotificationService, private notificationService: NotificationService,
private snackBar: MatSnackBar, private snackBar: MatSnackBar,
private stripeService: StripeService,
private userService: UserService private userService: UserService
) { ) {
const { baseCurrency, globalPermissions } = this.dataService.fetchInfo(); const { baseCurrency, globalPermissions } = this.dataService.fetchInfo();
@ -113,23 +111,17 @@ export class GfUserAccountMembershipComponent implements OnDestroy {
priceId: this.priceId priceId: this.priceId
}) })
.pipe( .pipe(
catchError((error) => { catchError((error: Error) => {
this.notificationService.alert({ this.notificationService.alert({
title: error.message title: error.message
}); });
throw error; return EMPTY;
}), }),
switchMap(({ sessionId }) => { takeUntil(this.unsubscribeSubject)
return this.stripeService.redirectToCheckout({ sessionId });
})
) )
.subscribe((result) => { .subscribe(({ sessionUrl }) => {
if (result.error) { window.location.href = sessionUrl;
this.notificationService.alert({
title: result.error.message
});
}
}); });
} }

2
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts

@ -4,7 +4,6 @@ import { GfDialogFooterComponent } from '@ghostfolio/ui/dialog-footer';
import { GfDialogHeaderComponent } from '@ghostfolio/ui/dialog-header'; import { GfDialogHeaderComponent } from '@ghostfolio/ui/dialog-header';
import { GfValueComponent } from '@ghostfolio/ui/value'; import { GfValueComponent } from '@ghostfolio/ui/value';
import { CommonModule } from '@angular/common';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
@ -26,7 +25,6 @@ import { UserDetailDialogParams } from './interfaces/interfaces';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'd-flex flex-column h-100' }, host: { class: 'd-flex flex-column h-100' },
imports: [ imports: [
CommonModule,
GfDialogFooterComponent, GfDialogFooterComponent,
GfDialogHeaderComponent, GfDialogHeaderComponent,
GfValueComponent, GfValueComponent,

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

@ -1,7 +1,6 @@
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { CommonModule } from '@angular/common';
import { Component, CUSTOM_ELEMENTS_SCHEMA, OnDestroy } from '@angular/core'; import { Component, CUSTOM_ELEMENTS_SCHEMA, OnDestroy } from '@angular/core';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
@ -12,7 +11,7 @@ import { Subject } from 'rxjs';
@Component({ @Component({
host: { class: 'page' }, host: { class: 'page' },
imports: [CommonModule, IonIcon, MatCardModule, RouterModule], imports: [IonIcon, MatCardModule, RouterModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-blog-page', selector: 'gf-blog-page',
styleUrls: ['./blog-page.scss'], styleUrls: ['./blog-page.scss'],

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

@ -1,12 +1,11 @@
import { GfHomeMarketComponent } from '@ghostfolio/client/components/home-market/home-market.component'; import { GfHomeMarketComponent } from '@ghostfolio/client/components/home-market/home-market.component';
import { CommonModule } from '@angular/common';
import { Component, OnDestroy } from '@angular/core'; import { Component, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@Component({ @Component({
host: { class: 'page' }, host: { class: 'page' },
imports: [CommonModule, GfHomeMarketComponent], imports: [GfHomeMarketComponent],
selector: 'gf-markets-page', selector: 'gf-markets-page',
styleUrls: ['./markets-page.scss'], styleUrls: ['./markets-page.scss'],
templateUrl: './markets-page.html' templateUrl: './markets-page.html'

3
apps/client/src/app/pages/open/open-page.component.ts

@ -3,7 +3,6 @@ import { UserService } from '@ghostfolio/client/services/user/user.service';
import { Statistics, User } from '@ghostfolio/common/interfaces'; import { Statistics, User } from '@ghostfolio/common/interfaces';
import { GfValueComponent } from '@ghostfolio/ui/value'; import { GfValueComponent } from '@ghostfolio/ui/value';
import { CommonModule } from '@angular/common';
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
@ -16,7 +15,7 @@ import { Subject, takeUntil } from 'rxjs';
@Component({ @Component({
host: { class: 'page' }, host: { class: 'page' },
imports: [CommonModule, GfValueComponent, MatCardModule], imports: [GfValueComponent, MatCardModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA], schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-open-page', selector: 'gf-open-page',
styleUrls: ['./open-page.scss'], styleUrls: ['./open-page.scss'],

24
apps/client/src/app/pages/pricing/pricing-page.component.ts

@ -27,9 +27,8 @@ import {
informationCircleOutline informationCircleOutline
} from 'ionicons/icons'; } from 'ionicons/icons';
import { StringValue } from 'ms'; import { StringValue } from 'ms';
import { StripeService } from 'ngx-stripe'; import { EMPTY, Subject } from 'rxjs';
import { Subject } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators';
import { catchError, switchMap, takeUntil } from 'rxjs/operators';
@Component({ @Component({
host: { class: 'page' }, host: { class: 'page' },
@ -98,7 +97,6 @@ export class GfPricingPageComponent implements OnDestroy, OnInit {
private changeDetectorRef: ChangeDetectorRef, private changeDetectorRef: ChangeDetectorRef,
private dataService: DataService, private dataService: DataService,
private notificationService: NotificationService, private notificationService: NotificationService,
private stripeService: StripeService,
private userService: UserService private userService: UserService
) { ) {
addIcons({ addIcons({
@ -155,23 +153,17 @@ export class GfPricingPageComponent implements OnDestroy, OnInit {
priceId: this.priceId priceId: this.priceId
}) })
.pipe( .pipe(
switchMap(({ sessionId }) => { catchError((error: Error) => {
return this.stripeService.redirectToCheckout({ sessionId });
}),
catchError((error) => {
this.notificationService.alert({ this.notificationService.alert({
title: error.message title: error.message
}); });
throw error; return EMPTY;
}) }),
takeUntil(this.unsubscribeSubject)
) )
.subscribe((result) => { .subscribe(({ sessionUrl }) => {
if (result.error) { window.location.href = sessionUrl;
this.notificationService.alert({
title: result.error.message
});
}
}); });
} }

2
apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.component.ts

@ -3,7 +3,6 @@ import { publicRoutes } from '@ghostfolio/common/routes/routes';
import { ClipboardModule } from '@angular/cdk/clipboard'; import { ClipboardModule } from '@angular/cdk/clipboard';
import { TextFieldModule } from '@angular/cdk/text-field'; import { TextFieldModule } from '@angular/cdk/text-field';
import { CommonModule } from '@angular/common';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
@ -36,7 +35,6 @@ import { UserAccountRegistrationDialogParams } from './interfaces/interfaces';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ imports: [
ClipboardModule, ClipboardModule,
CommonModule,
FormsModule, FormsModule,
IonIcon, IonIcon,
MatButtonModule, MatButtonModule,

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

@ -2,7 +2,6 @@ import { UserService } from '@ghostfolio/client/services/user/user.service';
import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces';
import { internalRoutes } from '@ghostfolio/common/routes/routes'; import { internalRoutes } from '@ghostfolio/common/routes/routes';
import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { MatTabsModule } from '@angular/material/tabs'; import { MatTabsModule } from '@angular/material/tabs';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
@ -15,7 +14,7 @@ import { takeUntil } from 'rxjs/operators';
@Component({ @Component({
host: { class: 'page has-tabs' }, host: { class: 'page has-tabs' },
imports: [CommonModule, IonIcon, MatTabsModule, RouterModule], imports: [IonIcon, MatTabsModule, RouterModule],
selector: 'gf-zen-page', selector: 'gf-zen-page',
styleUrls: ['./zen-page.scss'], styleUrls: ['./zen-page.scss'],
templateUrl: './zen-page.html' templateUrl: './zen-page.html'

15
apps/client/src/main.ts

@ -7,7 +7,11 @@ import {
provideHttpClient, provideHttpClient,
withInterceptorsFromDi withInterceptorsFromDi
} from '@angular/common/http'; } from '@angular/common/http';
import { enableProdMode, importProvidersFrom } from '@angular/core'; import {
enableProdMode,
importProvidersFrom,
provideZoneChangeDetection
} from '@angular/core';
import { import {
DateAdapter, DateAdapter,
MAT_DATE_FORMATS, MAT_DATE_FORMATS,
@ -23,7 +27,6 @@ import { ServiceWorkerModule } from '@angular/service-worker';
import { provideIonicAngular } from '@ionic/angular/standalone'; import { provideIonicAngular } from '@ionic/angular/standalone';
import { provideMarkdown } from 'ngx-markdown'; import { provideMarkdown } from 'ngx-markdown';
import { provideNgxSkeletonLoader } from 'ngx-skeleton-loader'; import { provideNgxSkeletonLoader } from 'ngx-skeleton-loader';
import { NgxStripeModule, STRIPE_PUBLISHABLE_KEY } from 'ngx-stripe';
import { CustomDateAdapter } from './app/adapter/custom-date-adapter'; import { CustomDateAdapter } from './app/adapter/custom-date-adapter';
import { DateFormats } from './app/adapter/date-formats'; import { DateFormats } from './app/adapter/date-formats';
@ -50,8 +53,6 @@ import { environment } from './environments/environment';
(window as any).info = info; (window as any).info = info;
environment.stripePublicKey = info.stripePublicKey;
if (environment.production) { if (environment.production) {
enableProdMode(); enableProdMode();
} }
@ -65,7 +66,6 @@ import { environment } from './environments/environment';
MatNativeDateModule, MatNativeDateModule,
MatSnackBarModule, MatSnackBarModule,
MatTooltipModule, MatTooltipModule,
NgxStripeModule.forRoot(environment.stripePublicKey),
RouterModule.forRoot(routes, { RouterModule.forRoot(routes, {
anchorScrolling: 'enabled', anchorScrolling: 'enabled',
preloadingStrategy: ModulePreloadService, preloadingStrategy: ModulePreloadService,
@ -83,6 +83,7 @@ import { environment } from './environments/environment';
provideIonicAngular(), provideIonicAngular(),
provideMarkdown(), provideMarkdown(),
provideNgxSkeletonLoader(), provideNgxSkeletonLoader(),
provideZoneChangeDetection(),
{ {
deps: [LanguageService, MAT_DATE_LOCALE, Platform], deps: [LanguageService, MAT_DATE_LOCALE, Platform],
provide: DateAdapter, provide: DateAdapter,
@ -92,10 +93,6 @@ import { environment } from './environments/environment';
provide: MAT_DATE_FORMATS, provide: MAT_DATE_FORMATS,
useValue: DateFormats useValue: DateFormats
}, },
{
provide: STRIPE_PUBLISHABLE_KEY,
useFactory: () => environment.stripePublicKey
},
{ {
provide: TitleStrategy, provide: TitleStrategy,
useClass: PageTitleStrategy useClass: PageTitleStrategy

1
apps/client/tsconfig.app.json

@ -1,7 +1,6 @@
{ {
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"moduleResolution": "bundler",
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"types": ["node"], "types": ["node"],
"typeRoots": ["../../node_modules/@types"], "typeRoots": ["../../node_modules/@types"],

2
apps/client/tsconfig.json

@ -20,6 +20,8 @@
"strictTemplates": false "strictTemplates": false
}, },
"compilerOptions": { "compilerOptions": {
"lib": ["dom", "es2022"],
"module": "preserve",
"target": "es2020" "target": "es2020"
} }
} }

3
apps/client/tsconfig.spec.json

@ -2,7 +2,8 @@
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"module": "commonjs", "module": "preserve",
"isolatedModules": true,
"types": ["jest", "node"], "types": ["jest", "node"],
"target": "es2016" "target": "es2016"
}, },

3
libs/common/src/lib/interfaces/info-item.interface.ts

@ -18,6 +18,9 @@ export interface InfoItem {
platforms: Platform[]; platforms: Platform[];
statistics: Statistics; statistics: Statistics;
/** @deprecated */
stripePublicKey?: string; stripePublicKey?: string;
subscriptionOffer?: SubscriptionOffer; subscriptionOffer?: SubscriptionOffer;
} }

3
libs/common/src/lib/interfaces/responses/create-stripe-checkout-session-response.interface.ts

@ -1,3 +1,6 @@
export interface CreateStripeCheckoutSessionResponse { export interface CreateStripeCheckoutSessionResponse {
/** @deprecated */
sessionId: string; sessionId: string;
sessionUrl: string;
} }

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

@ -5,7 +5,7 @@ import { InternalRoute } from './interfaces/internal-route.interface';
import { PublicRoute } from './interfaces/public-route.interface'; import { PublicRoute } from './interfaces/public-route.interface';
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
import('@angular/localize/init'); import('@angular/localize');
} else { } else {
(global as any).$localize = ( (global as any).$localize = (
messageParts: TemplateStringsArray, messageParts: TemplateStringsArray,

6
libs/common/tsconfig.json

@ -9,5 +9,9 @@
{ {
"path": "./tsconfig.spec.json" "path": "./tsconfig.spec.json"
} }
] ],
"compilerOptions": {
"module": "preserve",
"lib": ["dom", "es2022"]
}
} }

3
libs/common/tsconfig.spec.json

@ -2,7 +2,8 @@
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"module": "commonjs", "module": "preserve",
"isolatedModules": true,
"types": ["jest", "node"] "types": ["jest", "node"]
}, },
"include": [ "include": [

2
libs/ui/src/lib/logo-carousel/logo-carousel.component.ts

@ -1,11 +1,9 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ChangeDetectionStrategy, Component } from '@angular/core';
import { LogoItem } from './interfaces/interfaces'; import { LogoItem } from './interfaces/interfaces';
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule],
selector: 'gf-logo-carousel', selector: 'gf-logo-carousel',
styleUrls: ['./logo-carousel.component.scss'], styleUrls: ['./logo-carousel.component.scss'],
templateUrl: './logo-carousel.component.html' templateUrl: './logo-carousel.component.html'

3
libs/ui/tsconfig.json

@ -14,7 +14,8 @@
} }
], ],
"compilerOptions": { "compilerOptions": {
"moduleResolution": "bundler", "lib": ["dom", "es2022"],
"module": "preserve",
"target": "es2020", "target": "es2020",
// TODO: Remove once solved in tsconfig.base.json // TODO: Remove once solved in tsconfig.base.json
"strict": false, "strict": false,

2
libs/ui/tsconfig.lib.json

@ -7,7 +7,7 @@
"declarationMap": true, "declarationMap": true,
"inlineSources": true, "inlineSources": true,
"types": [], "types": [],
"lib": ["dom", "es2018"] "lib": ["dom", "es2022"]
}, },
"exclude": [ "exclude": [
"src/test-setup.ts", "src/test-setup.ts",

3
libs/ui/tsconfig.spec.json

@ -2,7 +2,8 @@
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"module": "commonjs", "module": "preserve",
"isolatedModules": true,
"types": ["jest", "node"], "types": ["jest", "node"],
"target": "es2016" "target": "es2016"
}, },

4821
package-lock.json

File diff suppressed because it is too large

80
package.json

@ -1,6 +1,6 @@
{ {
"name": "ghostfolio", "name": "ghostfolio",
"version": "2.224.2", "version": "2.225.0",
"homepage": "https://ghostfol.io", "homepage": "https://ghostfol.io",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio", "repository": "https://github.com/ghostfolio/ghostfolio",
@ -54,17 +54,17 @@
"workspace-generator": "nx workspace-generator" "workspace-generator": "nx workspace-generator"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "20.3.9", "@angular/animations": "21.0.6",
"@angular/cdk": "20.2.9", "@angular/cdk": "21.0.5",
"@angular/common": "20.3.9", "@angular/common": "21.0.6",
"@angular/compiler": "20.3.9", "@angular/compiler": "21.0.6",
"@angular/core": "20.3.9", "@angular/core": "21.0.6",
"@angular/forms": "20.3.9", "@angular/forms": "21.0.6",
"@angular/material": "20.2.9", "@angular/material": "21.0.5",
"@angular/platform-browser": "20.3.9", "@angular/platform-browser": "21.0.6",
"@angular/platform-browser-dynamic": "20.3.9", "@angular/platform-browser-dynamic": "21.0.6",
"@angular/router": "20.3.9", "@angular/router": "21.0.6",
"@angular/service-worker": "20.3.9", "@angular/service-worker": "21.0.6",
"@codewithdan/observable-store": "2.2.15", "@codewithdan/observable-store": "2.2.15",
"@date-fns/utc": "2.1.0", "@date-fns/utc": "2.1.0",
"@internationalized/number": "3.6.5", "@internationalized/number": "3.6.5",
@ -85,7 +85,6 @@
"@prisma/client": "6.19.0", "@prisma/client": "6.19.0",
"@simplewebauthn/browser": "13.1.0", "@simplewebauthn/browser": "13.1.0",
"@simplewebauthn/server": "13.1.1", "@simplewebauthn/server": "13.1.1",
"@stripe/stripe-js": "7.9.0",
"ai": "4.3.16", "ai": "4.3.16",
"alphavantage": "2.2.0", "alphavantage": "2.2.0",
"big.js": "7.0.1", "big.js": "7.0.1",
@ -114,13 +113,12 @@
"ionicons": "8.0.13", "ionicons": "8.0.13",
"jsonpath": "1.1.1", "jsonpath": "1.1.1",
"lodash": "4.17.21", "lodash": "4.17.21",
"marked": "15.0.4", "marked": "17.0.1",
"ms": "3.0.0-canary.1", "ms": "3.0.0-canary.1",
"ng-extract-i18n-merge": "3.2.1", "ng-extract-i18n-merge": "3.2.1",
"ngx-device-detector": "10.1.0", "ngx-device-detector": "11.0.0",
"ngx-markdown": "20.0.0", "ngx-markdown": "21.0.1",
"ngx-skeleton-loader": "11.3.0", "ngx-skeleton-loader": "11.3.0",
"ngx-stripe": "20.7.0",
"open-color": "1.9.1", "open-color": "1.9.1",
"papaparse": "5.3.1", "papaparse": "5.3.1",
"passport": "0.7.0", "passport": "0.7.0",
@ -135,35 +133,35 @@
"tablemark": "4.1.0", "tablemark": "4.1.0",
"twitter-api-v2": "1.27.0", "twitter-api-v2": "1.27.0",
"yahoo-finance2": "3.10.2", "yahoo-finance2": "3.10.2",
"zone.js": "0.15.1" "zone.js": "0.16.0"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "20.3.9", "@angular-devkit/build-angular": "21.0.4",
"@angular-devkit/core": "20.3.9", "@angular-devkit/core": "21.0.4",
"@angular-devkit/schematics": "20.3.9", "@angular-devkit/schematics": "21.0.4",
"@angular-eslint/eslint-plugin": "20.7.0", "@angular-eslint/eslint-plugin": "21.1.0",
"@angular-eslint/eslint-plugin-template": "20.7.0", "@angular-eslint/eslint-plugin-template": "21.1.0",
"@angular-eslint/template-parser": "20.7.0", "@angular-eslint/template-parser": "21.1.0",
"@angular/cli": "20.3.9", "@angular/cli": "21.0.4",
"@angular/compiler-cli": "20.3.9", "@angular/compiler-cli": "21.0.6",
"@angular/language-service": "20.3.9", "@angular/language-service": "21.0.6",
"@angular/localize": "20.3.9", "@angular/localize": "21.0.6",
"@angular/pwa": "20.3.9", "@angular/pwa": "21.0.4",
"@eslint/eslintrc": "3.3.1", "@eslint/eslintrc": "3.3.1",
"@eslint/js": "9.35.0", "@eslint/js": "9.35.0",
"@nestjs/schematics": "11.0.9", "@nestjs/schematics": "11.0.9",
"@nestjs/testing": "11.1.8", "@nestjs/testing": "11.1.8",
"@nx/angular": "22.1.3", "@nx/angular": "22.3.3",
"@nx/eslint-plugin": "22.1.3", "@nx/eslint-plugin": "22.3.3",
"@nx/jest": "22.1.3", "@nx/jest": "22.3.3",
"@nx/js": "22.1.3", "@nx/js": "22.3.3",
"@nx/module-federation": "22.1.3", "@nx/module-federation": "22.3.3",
"@nx/nest": "22.1.3", "@nx/nest": "22.3.3",
"@nx/node": "22.1.3", "@nx/node": "22.3.3",
"@nx/storybook": "22.1.3", "@nx/storybook": "22.3.3",
"@nx/web": "22.1.3", "@nx/web": "22.3.3",
"@nx/workspace": "22.1.3", "@nx/workspace": "22.3.3",
"@schematics/angular": "20.3.9", "@schematics/angular": "21.0.4",
"@storybook/addon-docs": "10.1.10", "@storybook/addon-docs": "10.1.10",
"@storybook/angular": "10.1.10", "@storybook/angular": "10.1.10",
"@trivago/prettier-plugin-sort-imports": "5.2.2", "@trivago/prettier-plugin-sort-imports": "5.2.2",
@ -185,7 +183,7 @@
"jest": "30.2.0", "jest": "30.2.0",
"jest-environment-jsdom": "30.2.0", "jest-environment-jsdom": "30.2.0",
"jest-preset-angular": "16.0.0", "jest-preset-angular": "16.0.0",
"nx": "22.1.3", "nx": "22.3.3",
"prettier": "3.7.4", "prettier": "3.7.4",
"prettier-plugin-organize-attributes": "1.0.0", "prettier-plugin-organize-attributes": "1.0.0",
"prisma": "6.19.0", "prisma": "6.19.0",

3
tsconfig.base.json

@ -4,8 +4,9 @@
"rootDir": ".", "rootDir": ".",
"sourceMap": true, "sourceMap": true,
"declaration": false, "declaration": false,
"moduleResolution": "node", "moduleResolution": "bundler",
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"esModuleInterop": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"importHelpers": true, "importHelpers": true,
"target": "es2015", "target": "es2015",

Loading…
Cancel
Save