From 02a61b373ceebec54e7228e3e34f60a69f366083 Mon Sep 17 00:00:00 2001 From: slegarraga <64795732+slegarraga@users.noreply.github.com> Date: Sun, 1 Mar 2026 11:37:33 -0300 Subject: [PATCH 001/138] Task/eliminate OnDestroy lifecycle hook from register page (#6433) * Eliminate OnDestroy lifecycle hook --- .../pages/register/register-page.component.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/apps/client/src/app/pages/register/register-page.component.ts b/apps/client/src/app/pages/register/register-page.component.ts index 21b26944e..3678f0249 100644 --- a/apps/client/src/app/pages/register/register-page.component.ts +++ b/apps/client/src/app/pages/register/register-page.component.ts @@ -7,15 +7,14 @@ import { DataService } from '@ghostfolio/ui/services'; import { Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { Router, RouterModule } from '@angular/router'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; import { UserAccountRegistrationDialogParams } from './user-account-registration-dialog/interfaces/interfaces'; import { GfUserAccountRegistrationDialogComponent } from './user-account-registration-dialog/user-account-registration-dialog.component'; @@ -28,7 +27,7 @@ import { GfUserAccountRegistrationDialogComponent } from './user-account-registr styleUrls: ['./register-page.scss'], templateUrl: './register-page.html' }) -export class GfRegisterPageComponent implements OnDestroy, OnInit { +export class GfRegisterPageComponent implements OnInit { public deviceType: string; public hasPermissionForAuthGoogle: boolean; public hasPermissionForAuthToken: boolean; @@ -37,10 +36,9 @@ export class GfRegisterPageComponent implements OnDestroy, OnInit { public historicalDataItems: LineChartItem[]; public info: InfoItem; - private unsubscribeSubject = new Subject(); - public constructor( private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private dialog: MatDialog, private router: Router, @@ -93,7 +91,7 @@ export class GfRegisterPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((authToken) => { if (authToken) { this.tokenStorageService.saveToken(authToken, true); @@ -102,9 +100,4 @@ export class GfRegisterPageComponent implements OnDestroy, OnInit { } }); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 41de73fe41b6dfa835acbfff42ca992824be95b6 Mon Sep 17 00:00:00 2001 From: slegarraga <64795732+slegarraga@users.noreply.github.com> Date: Sun, 1 Mar 2026 12:06:26 -0300 Subject: [PATCH 002/138] Task/eliminate OnDestroy lifecycle hook from features page (#6431) * Eliminate OnDestroy lifecycle hook --- .../pages/features/features-page.component.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/apps/client/src/app/pages/features/features-page.component.ts b/apps/client/src/app/pages/features/features-page.component.ts index b9eb91fe2..cef90f2e5 100644 --- a/apps/client/src/app/pages/features/features-page.component.ts +++ b/apps/client/src/app/pages/features/features-page.component.ts @@ -5,11 +5,11 @@ import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { DataService } from '@ghostfolio/ui/services'; -import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core'; +import { ChangeDetectorRef, Component, DestroyRef } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { RouterModule } from '@angular/router'; -import { Subject, takeUntil } from 'rxjs'; @Component({ host: { class: 'page' }, @@ -23,7 +23,7 @@ import { Subject, takeUntil } from 'rxjs'; styleUrls: ['./features-page.scss'], templateUrl: './features-page.html' }) -export class GfFeaturesPageComponent implements OnDestroy { +export class GfFeaturesPageComponent { public hasPermissionForSubscription: boolean; public hasPermissionToCreateUser: boolean; public info: InfoItem; @@ -31,11 +31,10 @@ export class GfFeaturesPageComponent implements OnDestroy { public routerLinkResources = publicRoutes.resources.routerLink; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private userService: UserService ) { this.info = this.dataService.fetchInfo(); @@ -43,7 +42,7 @@ export class GfFeaturesPageComponent implements OnDestroy { public ngOnInit() { this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -62,9 +61,4 @@ export class GfFeaturesPageComponent implements OnDestroy { permissions.createUserAccount ); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 8c83742d9c741db13e63fea943129eef43bb01a8 Mon Sep 17 00:00:00 2001 From: slegarraga <64795732+slegarraga@users.noreply.github.com> Date: Sun, 1 Mar 2026 12:07:50 -0300 Subject: [PATCH 003/138] Task/eliminate OnDestroy lifecycle hook from webauthn page (#6429) * Eliminate OnDestroy lifecycle hook --- .../pages/webauthn/webauthn-page.component.ts | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/apps/client/src/app/pages/webauthn/webauthn-page.component.ts b/apps/client/src/app/pages/webauthn/webauthn-page.component.ts index 74631eeca..8e7e58fd1 100644 --- a/apps/client/src/app/pages/webauthn/webauthn-page.component.ts +++ b/apps/client/src/app/pages/webauthn/webauthn-page.component.ts @@ -2,12 +2,16 @@ import { TokenStorageService } from '@ghostfolio/client/services/token-storage.s import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service'; import { GfLogoComponent } from '@ghostfolio/ui/logo'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + DestroyRef, + OnInit +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { Router } from '@angular/router'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'page' }, @@ -16,13 +20,12 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./webauthn-page.scss'], templateUrl: './webauthn-page.html' }) -export class GfWebauthnPageComponent implements OnDestroy, OnInit { +export class GfWebauthnPageComponent implements OnInit { public hasError = false; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, + private destroyRef: DestroyRef, private router: Router, private tokenStorageService: TokenStorageService, private webAuthnService: WebAuthnService @@ -35,7 +38,7 @@ export class GfWebauthnPageComponent implements OnDestroy, OnInit { public deregisterDevice() { this.webAuthnService .deregister() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.router.navigate(['/']); }); @@ -46,7 +49,7 @@ export class GfWebauthnPageComponent implements OnDestroy, OnInit { this.webAuthnService .login() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe( ({ authToken }) => { this.tokenStorageService.saveToken(authToken, false); @@ -59,9 +62,4 @@ export class GfWebauthnPageComponent implements OnDestroy, OnInit { } ); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 412b37956ae26298556c1c0573d9da1033c82c34 Mon Sep 17 00:00:00 2001 From: slegarraga <64795732+slegarraga@users.noreply.github.com> Date: Sun, 1 Mar 2026 12:09:23 -0300 Subject: [PATCH 004/138] Task/eliminate OnDestroy lifecycle hook from portfolio page (#6430) * Eliminate OnDestroy lifecycle hook --- .../portfolio/portfolio-page.component.ts | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts index 387e3fd0f..eb4935127 100644 --- a/apps/client/src/app/pages/portfolio/portfolio-page.component.ts +++ b/apps/client/src/app/pages/portfolio/portfolio-page.component.ts @@ -2,7 +2,13 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + DestroyRef, + OnInit +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatTabsModule } from '@angular/material/tabs'; import { RouterModule } from '@angular/router'; import { addIcons } from 'ionicons'; @@ -14,8 +20,6 @@ import { swapVerticalOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'page has-tabs' }, @@ -24,20 +28,19 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./portfolio-page.scss'], templateUrl: './portfolio-page.html' }) -export class PortfolioPageComponent implements OnDestroy, OnInit { +export class PortfolioPageComponent implements OnInit { public deviceType: string; public tabs: TabConfiguration[] = []; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private userService: UserService ) { this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.tabs = [ @@ -87,9 +90,4 @@ export class PortfolioPageComponent implements OnDestroy, OnInit { public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 28bf3dff079326ad190f9ecccf3487c02584c512 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 1 Mar 2026 17:17:18 +0100 Subject: [PATCH 005/138] Task/remove unused OnDestroy hook in privacy policy page component (#6381) * Remove unused OnDestroy hook --- .../privacy-policy/privacy-policy-page.component.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.component.ts b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.component.ts index 78881cd2c..50e4e3e2f 100644 --- a/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.component.ts +++ b/apps/client/src/app/pages/about/privacy-policy/privacy-policy-page.component.ts @@ -1,6 +1,5 @@ -import { Component, OnDestroy } from '@angular/core'; +import { Component } from '@angular/core'; import { MarkdownModule } from 'ngx-markdown'; -import { Subject } from 'rxjs'; @Component({ imports: [MarkdownModule], @@ -8,11 +7,4 @@ import { Subject } from 'rxjs'; styleUrls: ['./privacy-policy-page.scss'], templateUrl: './privacy-policy-page.html' }) -export class GfPrivacyPolicyPageComponent implements OnDestroy { - private unsubscribeSubject = new Subject(); - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } -} +export class GfPrivacyPolicyPageComponent {} From f3f655591149286b9e724b95a76188fbba8ac6ff Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 1 Mar 2026 17:17:53 +0100 Subject: [PATCH 006/138] Task/remove unused OnDestroy hook in blog page component (#6382) * Remove unused OnDestroy hook --- .../client/src/app/pages/blog/blog-page.component.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/client/src/app/pages/blog/blog-page.component.ts b/apps/client/src/app/pages/blog/blog-page.component.ts index 8a379a7e4..7f2c56d2d 100644 --- a/apps/client/src/app/pages/blog/blog-page.component.ts +++ b/apps/client/src/app/pages/blog/blog-page.component.ts @@ -1,13 +1,12 @@ import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { DataService } from '@ghostfolio/ui/services'; -import { Component, CUSTOM_ELEMENTS_SCHEMA, OnDestroy } from '@angular/core'; +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { MatCardModule } from '@angular/material/card'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { chevronForwardOutline } from 'ionicons/icons'; -import { Subject } from 'rxjs'; @Component({ host: { class: 'page' }, @@ -17,11 +16,9 @@ import { Subject } from 'rxjs'; styleUrls: ['./blog-page.scss'], templateUrl: './blog-page.html' }) -export class GfBlogPageComponent implements OnDestroy { +export class GfBlogPageComponent { public hasPermissionForSubscription: boolean; - private unsubscribeSubject = new Subject(); - public constructor(private dataService: DataService) { const info = this.dataService.fetchInfo(); @@ -32,9 +29,4 @@ export class GfBlogPageComponent implements OnDestroy { addIcons({ chevronForwardOutline }); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 1ffe64e8066067da6366cd896de69ba5535b80d1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 1 Mar 2026 18:00:26 +0100 Subject: [PATCH 007/138] Task/upgrade Nx to version 22.5.3 (#6444) * Upgrade Nx to version 22.5.3 * Update changelog --- CHANGELOG.md | 6 + package-lock.json | 665 ++++++++++++++++++++++++---------------------- package.json | 22 +- 3 files changed, 370 insertions(+), 323 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e34823b31..d7ebb665c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Upgraded `Nx` from version `22.4.5` to `22.5.3` + ## 2.245.0 - 2026-03-01 ### Changed diff --git a/package-lock.json b/package-lock.json index f7371da13..52b460666 100644 --- a/package-lock.json +++ b/package-lock.json @@ -108,16 +108,16 @@ "@eslint/js": "9.35.0", "@nestjs/schematics": "11.0.9", "@nestjs/testing": "11.1.14", - "@nx/angular": "22.4.5", - "@nx/eslint-plugin": "22.4.5", - "@nx/jest": "22.4.5", - "@nx/js": "22.4.5", - "@nx/module-federation": "22.4.5", - "@nx/nest": "22.4.5", - "@nx/node": "22.4.5", - "@nx/storybook": "22.4.5", - "@nx/web": "22.4.5", - "@nx/workspace": "22.4.5", + "@nx/angular": "22.5.3", + "@nx/eslint-plugin": "22.5.3", + "@nx/jest": "22.5.3", + "@nx/js": "22.5.3", + "@nx/module-federation": "22.5.3", + "@nx/nest": "22.5.3", + "@nx/node": "22.5.3", + "@nx/storybook": "22.5.3", + "@nx/web": "22.5.3", + "@nx/workspace": "22.5.3", "@schematics/angular": "21.1.1", "@storybook/addon-docs": "10.1.10", "@storybook/angular": "10.1.10", @@ -142,7 +142,7 @@ "jest": "30.2.0", "jest-environment-jsdom": "30.2.0", "jest-preset-angular": "16.0.0", - "nx": "22.4.5", + "nx": "22.5.3", "prettier": "3.8.1", "prettier-plugin-organize-attributes": "1.0.0", "prisma": "6.19.0", @@ -6672,15 +6672,15 @@ } }, "node_modules/@module-federation/node": { - "version": "2.7.31", - "resolved": "https://registry.npmjs.org/@module-federation/node/-/node-2.7.31.tgz", - "integrity": "sha512-NSa0PFDKDLxmtfmCVHW9RhtfD9mcNOrp1d+cjVEoxb5x8dDI4jQTi1o3nsa9ettxs3bVtWhAUEQUNQBQ6ZA+Hw==", + "version": "2.7.32", + "resolved": "https://registry.npmjs.org/@module-federation/node/-/node-2.7.32.tgz", + "integrity": "sha512-hUj5v2GGwpNzl2gaJS4AyzCYRzJBhN8875A+ucKF9tq3jaQb5zpy3izYMISqqbN2q9a7jz3nEUgwAh3pjri+rQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/enhanced": "2.0.0", - "@module-federation/runtime": "2.0.0", - "@module-federation/sdk": "2.0.0", + "@module-federation/enhanced": "2.0.1", + "@module-federation/runtime": "2.0.1", + "@module-federation/sdk": "2.0.1", "btoa": "1.2.1", "encoding": "^0.1.13", "node-fetch": "2.7.0" @@ -6695,26 +6695,26 @@ } }, "node_modules/@module-federation/node/node_modules/@module-federation/bridge-react-webpack-plugin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-2.0.0.tgz", - "integrity": "sha512-AVT/rZK6RHva6ZTYfsyQ8oP4xYNTws3OzqKW/YxWaLXwQ3oG9ZbF7fKl4jIKoMKuuy2L9MGVXS4CYPZy0s8fXg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-2.0.1.tgz", + "integrity": "sha512-D7LMW5EMAJShOMR1aZDAJ6s+MdsYDHaQyJADLQ3LaY0sne/BkVqkPikUwcO1IwOwKbXjYsDlQVOEvk9wZVRFhA==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/sdk": "2.0.0", + "@module-federation/sdk": "2.0.1", "@types/semver": "7.5.8", "semver": "7.6.3" } }, "node_modules/@module-federation/node/node_modules/@module-federation/cli": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/cli/-/cli-2.0.0.tgz", - "integrity": "sha512-IWGWbdgoeNcuA5jzqPr6pLTN1hovMQh9A1lgJp5fAvKfICfFXKq7K8nwMAQrWD6iEKApIenI0madk1Dg2PU3pw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/cli/-/cli-2.0.1.tgz", + "integrity": "sha512-2SL5Y8iODNX10y9T3CBLhHjSXo4afnA1BK82m4sNfZebuVO+o34bxewqwod9xfWq9xhTZmOSFZ+n+lgTKRv+CQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/dts-plugin": "2.0.0", - "@module-federation/sdk": "2.0.0", + "@module-federation/dts-plugin": "2.0.1", + "@module-federation/sdk": "2.0.1", "chalk": "3.0.0", "commander": "11.1.0", "jiti": "2.4.2" @@ -6727,14 +6727,14 @@ } }, "node_modules/@module-federation/node/node_modules/@module-federation/data-prefetch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/data-prefetch/-/data-prefetch-2.0.0.tgz", - "integrity": "sha512-KPyZoqNrb5WgFY2owYnMaO2Mg2DYD6KXLVI7GPguj7Z/4pPKEC+SUjWU2FuSfTeyE6ZIi0iFGdwerxzlQ6nfmw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/data-prefetch/-/data-prefetch-2.0.1.tgz", + "integrity": "sha512-Kq0P1OABGt6QAvs6TaE/zY9Ut9Y/oJFrzoSF3eWaCYbUAr2KD2SpTyMsPz4ssBzjeKXTgimugh6tHHd6mpCBIQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "2.0.0", - "@module-federation/sdk": "2.0.0", + "@module-federation/runtime": "2.0.1", + "@module-federation/sdk": "2.0.1", "fs-extra": "9.1.0" }, "peerDependencies": { @@ -6751,16 +6751,16 @@ } }, "node_modules/@module-federation/node/node_modules/@module-federation/dts-plugin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-2.0.0.tgz", - "integrity": "sha512-YyYMgLNARKdf3FLihnIzzUTgafHrqzR9YnKPmrfuCm2Jit+USqFT4QO58hcb0F5KSEyjB2ARPz9RM4XAVZhzMg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-2.0.1.tgz", + "integrity": "sha512-PLneTsf1fQS5/RTBedtLAAmCPRdMfIlhfJkOa8QH3WDJaQsqm8Wb3r2cTUBf2aNj/bP3aH/y6Hs9JFB/4x0l5g==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/error-codes": "2.0.0", - "@module-federation/managers": "2.0.0", - "@module-federation/sdk": "2.0.0", - "@module-federation/third-party-dts-extractor": "2.0.0", + "@module-federation/error-codes": "2.0.1", + "@module-federation/managers": "2.0.1", + "@module-federation/sdk": "2.0.1", + "@module-federation/third-party-dts-extractor": "2.0.1", "adm-zip": "^0.5.10", "ansi-colors": "^4.1.3", "axios": "^1.12.0", @@ -6785,23 +6785,23 @@ } }, "node_modules/@module-federation/node/node_modules/@module-federation/enhanced": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-2.0.0.tgz", - "integrity": "sha512-xeVrGvypYMvN8gJulbro3j1t8+aS1f9xjj4quwAAqgJF0Nz8bt7sXUYJyjUHPmC2UZsShZ0GnPHJNtI8/2GYjA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "2.0.0", - "@module-federation/cli": "2.0.0", - "@module-federation/data-prefetch": "2.0.0", - "@module-federation/dts-plugin": "2.0.0", - "@module-federation/error-codes": "2.0.0", - "@module-federation/inject-external-runtime-core-plugin": "2.0.0", - "@module-federation/managers": "2.0.0", - "@module-federation/manifest": "2.0.0", - "@module-federation/rspack": "2.0.0", - "@module-federation/runtime-tools": "2.0.0", - "@module-federation/sdk": "2.0.0", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-2.0.1.tgz", + "integrity": "sha512-EZIARQ/8ScoTP6PV8+E4SsmMYWK4ErrikZJ0G/FX8wvK8mCtdoKatFtvDN9++P6Nl78kN9zHYgAV4AHKdBVjfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/bridge-react-webpack-plugin": "2.0.1", + "@module-federation/cli": "2.0.1", + "@module-federation/data-prefetch": "2.0.1", + "@module-federation/dts-plugin": "2.0.1", + "@module-federation/error-codes": "2.0.1", + "@module-federation/inject-external-runtime-core-plugin": "2.0.1", + "@module-federation/managers": "2.0.1", + "@module-federation/manifest": "2.0.1", + "@module-federation/rspack": "2.0.1", + "@module-federation/runtime-tools": "2.0.1", + "@module-federation/sdk": "2.0.1", "btoa": "^1.2.1", "schema-utils": "^4.3.0", "upath": "2.0.1" @@ -6827,62 +6827,62 @@ } }, "node_modules/@module-federation/node/node_modules/@module-federation/error-codes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-2.0.0.tgz", - "integrity": "sha512-9oE+hXuPv2zej7AxJ5hOgeRqlPs98meooV2FiutTfftLAyy2N6+Kwmmz5NR9d9t91weJj8N0cSHFoyenNHKTVg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-2.0.1.tgz", + "integrity": "sha512-2bJF/ft+qL9L6Zvq2t/G9/f/0wFL73cM8/NJ04uyYz9BjIgvx28K5qu8/6+IwgEEKATG7vOhBBVj6wH3S+5ASA==", "dev": true, "license": "MIT" }, "node_modules/@module-federation/node/node_modules/@module-federation/inject-external-runtime-core-plugin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/inject-external-runtime-core-plugin/-/inject-external-runtime-core-plugin-2.0.0.tgz", - "integrity": "sha512-aZ6f4UU7KM5zBnHf3xsb2guqsfaEd6IlmuldbpED3JPk4ITwZk0DbvxRMr4prde7cfj8RH0nKMz2kmMncp+lIQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/inject-external-runtime-core-plugin/-/inject-external-runtime-core-plugin-2.0.1.tgz", + "integrity": "sha512-oAA7G+4GCHM+WRYfscR/x4GwCyM9CEqfdD9/x2L6y8mtLWK9anRLKTocsI759AvzXsbT1m3EQ5ki1O6wlwDu3g==", "dev": true, "license": "MIT", "peerDependencies": { - "@module-federation/runtime-tools": "2.0.0" + "@module-federation/runtime-tools": "2.0.1" } }, "node_modules/@module-federation/node/node_modules/@module-federation/managers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-2.0.0.tgz", - "integrity": "sha512-ZmkRIujH+T3xvkmy04TNvviFH8xFOrNeKCLb4tlH4ifU/kLfjTu+PYO/KAEIsgtmrDnd52zTf22dg3ok85OAHA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-2.0.1.tgz", + "integrity": "sha512-KR01lSlcYRQ9C6hW2a8CQQtAE0LvfTLgtV/6ZNUTagw8sRfeDln+ggrZsYilKu9zl0i8RPDgpv/kS60o4lcxCQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/sdk": "2.0.0", + "@module-federation/sdk": "2.0.1", "find-pkg": "2.0.0", "fs-extra": "9.1.0" } }, "node_modules/@module-federation/node/node_modules/@module-federation/manifest": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-2.0.0.tgz", - "integrity": "sha512-AXwYyGiDJdfP9MteKyIdJrLwG5tp4qKaq0uOPiWHilYN3/21G0DM7f30HgJqgx3WSTFSh7hcq0a3V3EZHH/9TA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-2.0.1.tgz", + "integrity": "sha512-p8nYGjHWp17MsYdW/Vv0ogBDiTTsI1PHWPQbvVIqLQXDqwiesaRSRR1zziECXQoEL8lV5Bs+uSkcaJGhea9P+A==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/dts-plugin": "2.0.0", - "@module-federation/managers": "2.0.0", - "@module-federation/sdk": "2.0.0", + "@module-federation/dts-plugin": "2.0.1", + "@module-federation/managers": "2.0.1", + "@module-federation/sdk": "2.0.1", "chalk": "3.0.0", "find-pkg": "2.0.0" } }, "node_modules/@module-federation/node/node_modules/@module-federation/rspack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-2.0.0.tgz", - "integrity": "sha512-1kziarKrPRM+rJax/AaMEZTwu7ORGed2xSxfdoP9GEbAFEGyNliadvw4kB6PqAfLad3PI4lQMX2vGMLI1KoyVQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-2.0.1.tgz", + "integrity": "sha512-SAlNE8iclFmzrKtx3/C2GivXYx6nPzx4MgQV01QG/a4LpnLbwlxzdZu3rqQ2swp4NNWT/t/GT7Y+7gfhyVa7mg==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "2.0.0", - "@module-federation/dts-plugin": "2.0.0", - "@module-federation/inject-external-runtime-core-plugin": "2.0.0", - "@module-federation/managers": "2.0.0", - "@module-federation/manifest": "2.0.0", - "@module-federation/runtime-tools": "2.0.0", - "@module-federation/sdk": "2.0.0", + "@module-federation/bridge-react-webpack-plugin": "2.0.1", + "@module-federation/dts-plugin": "2.0.1", + "@module-federation/inject-external-runtime-core-plugin": "2.0.1", + "@module-federation/managers": "2.0.1", + "@module-federation/manifest": "2.0.1", + "@module-federation/runtime-tools": "2.0.1", + "@module-federation/sdk": "2.0.1", "btoa": "1.2.1" }, "peerDependencies": { @@ -6900,50 +6900,50 @@ } }, "node_modules/@module-federation/node/node_modules/@module-federation/runtime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-2.0.0.tgz", - "integrity": "sha512-vPxQrmQNq3Z1T+1fkHEvFwTdJq9wuCLvdp/lpu9k2Oy7QP/Pj6QoQ/S7J5MCIAoRwj8Wj3z3ma21/DyHwLGvzA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-2.0.1.tgz", + "integrity": "sha512-UQ72P5Oo40dS6vdhHetwTtIsbGciEr+bjoYvDgh1WLPfFlTYd8zo9cLfqaf3juuPfV3cMVARAVPmh16lQYpUGA==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/error-codes": "2.0.0", - "@module-federation/runtime-core": "2.0.0", - "@module-federation/sdk": "2.0.0" + "@module-federation/error-codes": "2.0.1", + "@module-federation/runtime-core": "2.0.1", + "@module-federation/sdk": "2.0.1" } }, "node_modules/@module-federation/node/node_modules/@module-federation/runtime-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-2.0.0.tgz", - "integrity": "sha512-UhIGUs7Mg+TwMI2lgaLnj4UehpoyXbR7HDb2+vLikgBulPmFtodeWfsxCgENEwKsIY1vS0lOun15lNOn1vo3Xg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-2.0.1.tgz", + "integrity": "sha512-gOuCPSHoQGUGwlxfSTMInFX+QvLxdEWegGGMiLdU5vqbXuva4E9M+kXBBO7/0MkcBPMmVs0wOJGm0XOLeV2f1Q==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/error-codes": "2.0.0", - "@module-federation/sdk": "2.0.0" + "@module-federation/error-codes": "2.0.1", + "@module-federation/sdk": "2.0.1" } }, "node_modules/@module-federation/node/node_modules/@module-federation/runtime-tools": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-2.0.0.tgz", - "integrity": "sha512-eMDQN4hYpwvUnCNMjfQdtPVzYaO2DdauemHVc4HnyibgqijRzBwJh9bI2ph4R1xfYEm18+QmTrfXrRlaK2Xizw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-2.0.1.tgz", + "integrity": "sha512-AStdwBtsGB3jIfDg9oP+KyVPsimdaeHsP855gqCxDp1hi2+GKjlZWZx9ThkS8NytVSXSUysxqoUL1ivDoKgcCQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "2.0.0", - "@module-federation/webpack-bundler-runtime": "2.0.0" + "@module-federation/runtime": "2.0.1", + "@module-federation/webpack-bundler-runtime": "2.0.1" } }, "node_modules/@module-federation/node/node_modules/@module-federation/sdk": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-2.0.0.tgz", - "integrity": "sha512-JYd1wTulsaoLT7HTk2oXL5y5797Z+H4mzxuUEKnSJo7R34RZSqehsqPSND7n0HT/1nf7uyn0Rb4qBfR3BVvdHQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-2.0.1.tgz", + "integrity": "sha512-32PwudojGjog51cwpTali7D6ud82oVgsyvOx9JjAzhvXBX96YI4mRsursuWcthDxmigJP9ZvUTXDuRUEDh1OQA==", "dev": true, "license": "MIT" }, "node_modules/@module-federation/node/node_modules/@module-federation/third-party-dts-extractor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-2.0.0.tgz", - "integrity": "sha512-B99+Wkbd2xIodVTjNCeFtFC89Uh2/AtYkSESlz4+6Cec42wyqrGxyfYm4qRY0LhJI+YmZXLk/RTm85m15eBKKg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-2.0.1.tgz", + "integrity": "sha512-neKSr6FNUeGRh+YR57l/QZUzPytJXuJx+babF7j5iGJG3FP+kfizr6QD0hgVis5KEoXMVbQ8yyvG0slERizeyw==", "dev": true, "license": "MIT", "dependencies": { @@ -6953,14 +6953,14 @@ } }, "node_modules/@module-federation/node/node_modules/@module-federation/webpack-bundler-runtime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-2.0.0.tgz", - "integrity": "sha512-XxiFR/A1G1fa9hTyylWNbs6yEU2hC7FqHAArFptD4U9qp/xyoLgqbK4M8LwltOAyAM8hRofcMdSyiRKVlWqAfQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-2.0.1.tgz", + "integrity": "sha512-u1NId3SF4lHDTmD2CHFEszulmXmIq1TGw9JYvnLx5rKJL7xt3aNxcb1GvkaYbRNVBXhSMjJ75E5LsQlZzyBx9A==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "2.0.0", - "@module-federation/sdk": "2.0.0" + "@module-federation/runtime": "2.0.1", + "@module-federation/sdk": "2.0.1" } }, "node_modules/@module-federation/node/node_modules/jiti": { @@ -8282,20 +8282,20 @@ } }, "node_modules/@nx/angular": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/angular/-/angular-22.4.5.tgz", - "integrity": "sha512-mwffAG7qhElwtWCEIaH7bTJuE3foaFBa3LWReqNc9HkIZmka0BDHRReg3wyhfSGq4ZQlYXK5sQS2uDJd+Qj97Q==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/angular/-/angular-22.5.3.tgz", + "integrity": "sha512-Z5vNcPl95CsTnRhDszWZ0ort22dEtMxdqJFkVzdNwolhfiLm1eKP2Rc8q9MnUdrZMeTqDKnCckG2qs12FZrIkw==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", - "@nx/eslint": "22.4.5", - "@nx/js": "22.4.5", - "@nx/module-federation": "22.4.5", - "@nx/rspack": "22.4.5", - "@nx/web": "22.4.5", - "@nx/webpack": "22.4.5", - "@nx/workspace": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/eslint": "22.5.3", + "@nx/js": "22.5.3", + "@nx/module-federation": "22.5.3", + "@nx/rspack": "22.5.3", + "@nx/web": "22.5.3", + "@nx/webpack": "22.5.3", + "@nx/workspace": "22.5.3", "@phenomnomnominal/tsquery": "~6.1.4", "@typescript-eslint/type-utils": "^8.0.0", "enquirer": "~2.3.6", @@ -8343,15 +8343,15 @@ } }, "node_modules/@nx/cypress": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-22.4.5.tgz", - "integrity": "sha512-FAGLQa7dnMW5Z93bS5isw9WgVNapCOgRFgxl9sA1ePstte3Vh0ajRpvVjVoeVHyA3qg6aQbE41ctErOdq/p5bg==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-22.5.3.tgz", + "integrity": "sha512-0jIYOhU1sFv5w2NYmyxIdpT4pC7QvUphrM4QLyUk8nEfO5gwfmON7JLNbtDveX+FeGpjy1zDjoBdd2OBzqUEcA==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", - "@nx/eslint": "22.4.5", - "@nx/js": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/eslint": "22.5.3", + "@nx/js": "22.5.3", "@phenomnomnominal/tsquery": "~6.1.4", "detect-port": "^1.5.1", "semver": "^7.6.3", @@ -8368,16 +8368,16 @@ } }, "node_modules/@nx/devkit": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-22.4.5.tgz", - "integrity": "sha512-mw5G6k/XTkL675eVIcFpyZdfdIc3wQMSSGWzfA6tQGmANDYc/NFGeZR9wDqXDceHXnYKoRO6g6GhKTOHUCW23Q==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-22.5.3.tgz", + "integrity": "sha512-zhRNTFsi4pbwg7L/zhBHtTOSevlgwm1iKlhPlQWoOv2PR6b+3JvjL8o4P1MbkIkut3Lsn+oTuJJ1LUPlr5vprg==", "dev": true, "license": "MIT", "dependencies": { "@zkochan/js-yaml": "0.0.7", "ejs": "^3.1.7", "enquirer": "~2.3.6", - "minimatch": "10.1.1", + "minimatch": "10.2.1", "semver": "^7.6.3", "tslib": "^2.3.0", "yargs-parser": "21.1.1" @@ -8386,14 +8386,37 @@ "nx": ">= 21 <= 23 || ^22.0.0-0" } }, + "node_modules/@nx/devkit/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@nx/devkit/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/@nx/devkit/node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" }, "engines": { "node": "20 || >=22" @@ -8403,33 +8426,33 @@ } }, "node_modules/@nx/docker": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/docker/-/docker-22.4.5.tgz", - "integrity": "sha512-ZgBjd/HCgqkulYJwUH+xQvgsoupVD+2leiFmK5lFjb6IDny/W1uB3EVL5BZxrz8ftMoqiq+AP6Ubiaj99V4hzQ==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/docker/-/docker-22.5.3.tgz", + "integrity": "sha512-4BO1hAyun2MM15w1oldUZtCvZEZlDXOCeEkimVij9znk6t4FUBnH7v87Uj4w5dhJAWB7yJFgQbF5w1fZbhRXfw==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", + "@nx/devkit": "22.5.3", "enquirer": "~2.3.6", "tslib": "^2.3.0" } }, "node_modules/@nx/eslint": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-22.4.5.tgz", - "integrity": "sha512-/N/kG86gqagDziC7Ij/WwAnjjXx55E1Jbpp3kkau3Ncj+wjPoLqCebpg6aW83VJQ7a4SUU0BO3U5bkqQZPGBXQ==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-22.5.3.tgz", + "integrity": "sha512-XJKpwnSJRCat+81sUDdJWWvKz3vKo/3X9oHMGDzTYx3mexCgKgpmHBuRVgnZ9n2IVDx8S5ye4ICc9qiY6oHWIA==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", - "@nx/js": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/js": "22.5.3", "semver": "^7.6.3", "tslib": "^2.3.0", "typescript": "~5.9.2" }, "peerDependencies": { "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" + "eslint": "^8.0.0 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { "@zkochan/js-yaml": { @@ -8438,14 +8461,14 @@ } }, "node_modules/@nx/eslint-plugin": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-22.4.5.tgz", - "integrity": "sha512-Kb3owVrbhRkJAjqEDsgDs8eSlI2/uEFOS35a8Z1drHIpMF6Zt9OHQf6bKELeXzG3fC2AGM3pyunauhbJ/ZmqMw==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-22.5.3.tgz", + "integrity": "sha512-dFz3nSUOV+VLc+ZQxWncKINhych6h5oEfInWp1+5WkeUBW5/x77IsM3Hpq1JrjAK6dqXjmzTsFnoU8c5Cf1Q4w==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", - "@nx/js": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/js": "22.5.3", "@phenomnomnominal/tsquery": "~6.1.4", "@typescript-eslint/type-utils": "^8.0.0", "@typescript-eslint/utils": "^8.0.0", @@ -8497,22 +8520,22 @@ } }, "node_modules/@nx/jest": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-22.4.5.tgz", - "integrity": "sha512-qlEJc0Jbp8E14g7+piHH8DXsAm6C3w1CLuvtE57+LFMhM2zbBDiQ8oeXBdFPEHLCfpbSK/4yCSEmkUj1Yyrs2A==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-22.5.3.tgz", + "integrity": "sha512-4yaGlApTR09zdz4fC4Ep0aENcaon5rDRDOUnEJblU67ik35jds9mczHq2rBMJO4Cnjj1pM9acm08Vb0Wg+9cuQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/reporters": "^30.0.2", "@jest/test-result": "^30.0.2", - "@nx/devkit": "22.4.5", - "@nx/js": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/js": "22.5.3", "@phenomnomnominal/tsquery": "~6.1.4", "identity-obj-proxy": "3.0.0", "jest-config": "^30.0.2", "jest-resolve": "^30.0.2", "jest-util": "^30.0.2", - "minimatch": "10.1.1", + "minimatch": "10.2.1", "picocolors": "^1.1.0", "resolve.exports": "2.0.3", "semver": "^7.6.3", @@ -8520,14 +8543,37 @@ "yargs-parser": "21.1.1" } }, + "node_modules/@nx/jest/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@nx/jest/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/@nx/jest/node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" }, "engines": { "node": "20 || >=22" @@ -8537,9 +8583,9 @@ } }, "node_modules/@nx/js": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-22.4.5.tgz", - "integrity": "sha512-t8972z2uF6X5i4FFmTlnvSwwxfHkk87zBpKQK0yMH5CzOENViVFNbiPnbvCIJcGNrgVUSALL3f2ngwKcTZObmA==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-22.5.3.tgz", + "integrity": "sha512-gglQYL6GeSH0mt6NpEFTXMFFFePU3B7TEyZq7LLUYZDH5y65izgNpdSAuEqYR7xHLtahVnesDlhPw3rtRiwMwA==", "dev": true, "license": "MIT", "dependencies": { @@ -8550,8 +8596,8 @@ "@babel/preset-env": "^7.23.2", "@babel/preset-typescript": "^7.22.5", "@babel/runtime": "^7.22.6", - "@nx/devkit": "22.4.5", - "@nx/workspace": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/workspace": "22.5.3", "@zkochan/js-yaml": "0.0.7", "babel-plugin-const-enum": "^1.0.1", "babel-plugin-macros": "^3.1.0", @@ -8625,18 +8671,18 @@ } }, "node_modules/@nx/module-federation": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/module-federation/-/module-federation-22.4.5.tgz", - "integrity": "sha512-aNO595Xk0B4av9tpAaePF0jjDooAiXN34xEpFleSCmf8y31371JfkI8WMSnIZLa5ehyk1U+oMxHyYtt7v0RFWw==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/module-federation/-/module-federation-22.5.3.tgz", + "integrity": "sha512-dKRkT/ULV+nXr7O25YMDwQu/4nxl27AcHJfOmVBVKquXrtrBu/d6dbypfFDMyr5pXqR5gb2euEw0mGVMyHLTiA==", "dev": true, "license": "MIT", "dependencies": { "@module-federation/enhanced": "^0.21.2", "@module-federation/node": "^2.7.21", "@module-federation/sdk": "^0.21.2", - "@nx/devkit": "22.4.5", - "@nx/js": "22.4.5", - "@nx/web": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/js": "22.5.3", + "@nx/web": "22.5.3", "@rspack/core": "1.6.8", "express": "^4.21.2", "http-proxy-middleware": "^3.0.5", @@ -8947,41 +8993,41 @@ } }, "node_modules/@nx/nest": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nest/-/nest-22.4.5.tgz", - "integrity": "sha512-cFufm3cPuy7Cj10D8BB2Y+Vo1w/1ihQGeduXprC0gs719dI5zvyG8bVOYJ+m87HHdFVQ8ckIVVifO6T7ujWgFw==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nest/-/nest-22.5.3.tgz", + "integrity": "sha512-DShcD4HdaABg9L7/qgLVgZj0LLSaaYa7Rrj8zquMGGZXrxozCTKzn/7vWrN7Am9hY4wEwaXTXwauHAFoIj9C9A==", "dev": true, "license": "MIT", "dependencies": { "@nestjs/schematics": "^11.0.0", - "@nx/devkit": "22.4.5", - "@nx/eslint": "22.4.5", - "@nx/js": "22.4.5", - "@nx/node": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/eslint": "22.5.3", + "@nx/js": "22.5.3", + "@nx/node": "22.5.3", "tslib": "^2.3.0" } }, "node_modules/@nx/node": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/node/-/node-22.4.5.tgz", - "integrity": "sha512-ZYN3uIeUs0jKPX9Io75DkISMo5ha15djVLPNFhsh6qgQkL7+mqXGeW3QiEso16XZqbl0Iw2Ye5msrBO6UShFkQ==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/node/-/node-22.5.3.tgz", + "integrity": "sha512-szdpsyRUzXBhMIiEk+zI3XPP/e0U1wNmIzkvgCS1e+ejsA1jq0EF5sppkdwJEQVAb6O5hiCPKED+1sSo4TR4/A==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", - "@nx/docker": "22.4.5", - "@nx/eslint": "22.4.5", - "@nx/jest": "22.4.5", - "@nx/js": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/docker": "22.5.3", + "@nx/eslint": "22.5.3", + "@nx/jest": "22.5.3", + "@nx/js": "22.5.3", "kill-port": "^1.6.1", "tcp-port-used": "^1.0.2", "tslib": "^2.3.0" } }, "node_modules/@nx/nx-darwin-arm64": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.4.5.tgz", - "integrity": "sha512-zdRHZv1AMvzgp+5g2VZNXXuqk0/n1wOFksOeZ6BRyKg6hC2YkjGyn5xle/UK668MDAwe9KKm4jizvztK/LlPuA==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.5.3.tgz", + "integrity": "sha512-cKXBq5bJanXp8uv6+wPvx/G4q4oFpOxMSPGaeFOVhbul2QHGGq+XMcSo+D8aYJCsk1YnbyAnnQ8r8RH/kTK5Mw==", "cpu": [ "arm64" ], @@ -8993,9 +9039,9 @@ ] }, "node_modules/@nx/nx-darwin-x64": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.4.5.tgz", - "integrity": "sha512-1NVWaSgpa8yawi2UILX4NE9UcMuNzAAGh95JSV2yJovRfKxFQgQSB6hj0gpJu+TLLVCroTqy4woSQ2a0SPodeQ==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.5.3.tgz", + "integrity": "sha512-mToS41o8I+8CfxYVRMTISkgT7I1cnazgwMf7U9DoLqKOwOZzj9WD3NmsWc1h69QNJPltbeRPS8y/wnhu7RHzRA==", "cpu": [ "x64" ], @@ -9007,9 +9053,9 @@ ] }, "node_modules/@nx/nx-freebsd-x64": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.4.5.tgz", - "integrity": "sha512-baaLz53wr/HsVfSJ7ZgIFCPAb/OtP7yPPasb3eIu65oVhSswGfgvz9+YINhuInUgW7x7STmRnhGeR8pj6iqFqw==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.5.3.tgz", + "integrity": "sha512-CAWysdFSZVbTfdjNXojd9TgXbZiK9i0k3njROeV+jORsDWw4Eth3PDmK94Wk916b3n2hS0UjyI6RZaMy2GEqzA==", "cpu": [ "x64" ], @@ -9021,9 +9067,9 @@ ] }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.4.5.tgz", - "integrity": "sha512-wRBPv/l39tz+sQjZUH4hygCsd/DoUXUbDYkR6lnNXWHAVyPUh48/27JozM8hD3o/G3O2Vd8PFQasIXtvy2GS0Q==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.5.3.tgz", + "integrity": "sha512-PRjPrijQQbdrvYwNuA3xQ3VXEQ4zfhnPjy+S2ZlQZqhFI4mlP22xfhOH1bQ7pIfzCNC2f/J9UMNYOrq/bEFjBg==", "cpu": [ "arm" ], @@ -9035,9 +9081,9 @@ ] }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.4.5.tgz", - "integrity": "sha512-6B/yCFiqjvV2Bkz6MKUtfFWjwtiF53DN07K1BFksMpQef+h2yE1IrGaG/OCl6VaVl4VRzQgLOluqP96M1yhDgg==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.5.3.tgz", + "integrity": "sha512-dmDBio/5z4Zch2VlRMdgBPm53d8xwq1l7xLj1dFMKjfE7ByfPukjPM7ZEYBiPckfiQfJBRh6HKDN7uEkA/y8CQ==", "cpu": [ "arm64" ], @@ -9049,9 +9095,9 @@ ] }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.4.5.tgz", - "integrity": "sha512-n0v60vRYn7BDHWB588snPZntLO2XC8/pvLd+QunneM2VGEPf51n5llX5U3AwTt/ybaZHWhbuHv0sJBIbT4I0GA==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.5.3.tgz", + "integrity": "sha512-E81ET/MnnKfuLhKiovF5ueJirHOMjhC1eK0MDM2Do9wdPyusZzfGSVFQ9DOHtg7L37dAE95NNd1lCVO8gJ96vg==", "cpu": [ "arm64" ], @@ -9063,9 +9109,9 @@ ] }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.4.5.tgz", - "integrity": "sha512-zT7nb1PRE3NcW/HFnbgKJ9ZPtCOeVDpbJ5J4ZhHj36ZAUWZVXFEIPq9VTIZFy5+0pioLUIClQQY7OUfwnV/Zig==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.5.3.tgz", + "integrity": "sha512-AgXCsPCzC0sAu2VRclMjs7LrvPQfqS3sFiehlXWTbNHQitPZLuAmQGb2l4T8lbMOs0Xn3EIrg6BF6/ntTTp6Xg==", "cpu": [ "x64" ], @@ -9077,9 +9123,9 @@ ] }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.4.5.tgz", - "integrity": "sha512-r8Rls5BS7lGQbUNX1Z1S370XrOacOU1bQ/dxY8i7qahFQKnMwpFo0W8odhgzjk+vrC/WLf9jOgz5/JPzehQBIw==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.5.3.tgz", + "integrity": "sha512-sKs4bFQRu8Btxf5rMYKPsRVNxkQ2ey8sqoCyhJj8fwJF05DayK2ErJAR/rhtBK0c1NV7kQiKJA8nWBV3jnCdsg==", "cpu": [ "x64" ], @@ -9091,9 +9137,9 @@ ] }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.4.5.tgz", - "integrity": "sha512-Lv81LTnG6sSvBOq2vDSeyfzpF9X0cTGlJdzJOJzPZXCZGFhTV1ig9TdLiij/GM2JwV4Kvq5Co6YzA5dxtGUphQ==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.5.3.tgz", + "integrity": "sha512-KOCQLakSO5vl4D6et9qPytOAmkgq2IIuhI8A/g0xbD1LqrIlRPa+bdkZqOGpODYAk3NyKAk7hWHsqfXKHwwX6w==", "cpu": [ "arm64" ], @@ -9105,9 +9151,9 @@ ] }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.4.5.tgz", - "integrity": "sha512-52RfBcq9PXt76soCAZAJcNmCYrdsg6BvhBmjf0IFTMZ8IaeqZ9ktxAy1TZf/gCkOaM3ly4htbYMStiZ4MHX7Eg==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.5.3.tgz", + "integrity": "sha512-a6ZB2La82RIHcz4nrt3H6RZaOa+xkC2IPzhU9hMo2gbkLdIxn8wyof8uGA0frncmIVHuLc3nFAhpBOgf4j6tMA==", "cpu": [ "x64" ], @@ -9119,16 +9165,16 @@ ] }, "node_modules/@nx/rspack": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/rspack/-/rspack-22.4.5.tgz", - "integrity": "sha512-pqaJ713Jv82abDGisArEtKprAO0DuGxp7zddwpYW04J4Y8YmRAQFA3KriMPqjWTXuV3l4kpaqU7FtZ/3Xn1ShA==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/rspack/-/rspack-22.5.3.tgz", + "integrity": "sha512-2T5dkoC08FJGF8ZMiJDaKN6giXAljV0+LK7q5GJpSEUm+wtjZ/DRVoWSnlf8Dj/e0/cLb2GMElVcfjyDDDeV9w==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", - "@nx/js": "22.4.5", - "@nx/module-federation": "22.4.5", - "@nx/web": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/js": "22.5.3", + "@nx/module-federation": "22.5.3", + "@nx/web": "22.5.3", "@phenomnomnominal/tsquery": "~6.1.4", "@rspack/core": "1.6.8", "@rspack/dev-server": "^1.1.4", @@ -9550,16 +9596,16 @@ } }, "node_modules/@nx/storybook": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/storybook/-/storybook-22.4.5.tgz", - "integrity": "sha512-cxJDYpfpYcK0iuiJMHk6InLXXNLedj8VlOkRtcnZKuwDlC8quMSOuHKrdvBOjeOLV4C390/94BlzkToUZSey6g==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/storybook/-/storybook-22.5.3.tgz", + "integrity": "sha512-eP7cpRKnC1oYlOjSZU07Kf8BV8hNRPPXRib7BVdwwIUZ2v4K/b/cje2WCG729q4gk8fyoV8o7JNVgM+QGT8kBQ==", "dev": true, "license": "MIT", "dependencies": { - "@nx/cypress": "22.4.5", - "@nx/devkit": "22.4.5", - "@nx/eslint": "22.4.5", - "@nx/js": "22.4.5", + "@nx/cypress": "22.5.3", + "@nx/devkit": "22.5.3", + "@nx/eslint": "22.5.3", + "@nx/js": "22.5.3", "@phenomnomnominal/tsquery": "~6.1.4", "semver": "^7.6.3", "tslib": "^2.3.0" @@ -9569,14 +9615,14 @@ } }, "node_modules/@nx/web": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/web/-/web-22.4.5.tgz", - "integrity": "sha512-VXXkONZS7DEDDKUE8EUCiV7XhC+HmotExPKznU6NquoFpBZqvWCfC0rt/gKk2uIxJGu8qoISqtIIHFc6iO65RA==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/web/-/web-22.5.3.tgz", + "integrity": "sha512-Z7FYN5e9HIJAuJV0MU8jHaoEv9vgiLbpe1bbWPItfzIy02kWtSiS/aGZcLa34LDuWBfBaJVHZqFVp7OOPU26ew==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", - "@nx/js": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/js": "22.5.3", "detect-port": "^1.5.1", "http-server": "^14.1.0", "picocolors": "^1.1.0", @@ -9584,15 +9630,15 @@ } }, "node_modules/@nx/webpack": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-22.4.5.tgz", - "integrity": "sha512-3NZnJwkP1ztPc4Inz0g04rWf78P3U2np/kg3nKNf2I6kowWpcJakQCsWLufBzP48ooUtE3iPDVQoFIo3SgWqDg==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-22.5.3.tgz", + "integrity": "sha512-fEWvmynjxAfdyCH00Z3oaEedv/wKZAdHl8kz7UEiOJ7eKdGbbJIK0RuobXC1r2e2ERZ35vDrOiPYdruyfi35Jg==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.23.2", - "@nx/devkit": "22.4.5", - "@nx/js": "22.4.5", + "@nx/devkit": "22.5.3", + "@nx/js": "22.5.3", "@phenomnomnominal/tsquery": "~6.1.4", "ajv": "^8.12.0", "autoprefixer": "^10.4.9", @@ -9801,17 +9847,17 @@ } }, "node_modules/@nx/workspace": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-22.4.5.tgz", - "integrity": "sha512-QGapABrqBnRpEWbnd5UpbVCBzsYD+RlC1lWShXPpCM+dosR3qkGb+pSmxeSCsKbNVtCwYyyuRW+PvlF5Q5sU9A==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-22.5.3.tgz", + "integrity": "sha512-pioGwlt5zKB9PhX36I5KAeSml19Mq+g2KyQ9mh3F+3Lvft2JM4nIMELBaUfwPicPAOwNmrsx806IXO67Q4UHxQ==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "22.4.5", + "@nx/devkit": "22.5.3", "@zkochan/js-yaml": "0.0.7", "chalk": "^4.1.0", "enquirer": "~2.3.6", - "nx": "22.4.5", + "nx": "22.5.3", "picomatch": "4.0.2", "semver": "^7.6.3", "tslib": "^2.3.0", @@ -11651,9 +11697,9 @@ "license": "MIT" }, "node_modules/@rspack/plugin-react-refresh": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@rspack/plugin-react-refresh/-/plugin-react-refresh-1.6.0.tgz", - "integrity": "sha512-OO53gkrte/Ty4iRXxxM6lkwPGxsSsupFKdrPFnjwFIYrPvFLjeolAl5cTx+FzO5hYygJiGnw7iEKTmD+ptxqDA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@rspack/plugin-react-refresh/-/plugin-react-refresh-1.6.1.tgz", + "integrity": "sha512-eqqW5645VG3CzGzFgNg5HqNdHVXY+567PGjtDhhrM8t67caxmsSzRmT5qfoEIfBcGgFkH9vEg7kzXwmCYQdQDw==", "dev": true, "license": "MIT", "dependencies": { @@ -15017,14 +15063,14 @@ } }, "node_modules/axios": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.4.tgz", - "integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==", + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", "dev": true, "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, @@ -20394,9 +20440,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", @@ -20482,9 +20528,9 @@ } }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -26663,9 +26709,9 @@ "license": "MIT" }, "node_modules/nx": { - "version": "22.4.5", - "resolved": "https://registry.npmjs.org/nx/-/nx-22.4.5.tgz", - "integrity": "sha512-l68kzhnemXXGCDS9/W8eccZ7Bzse9pw1oJ466pzDM89MbA6hEaOQ0p+eDXZI++iWl0T+lYJ56EDhO23syKzt9g==", + "version": "22.5.3", + "resolved": "https://registry.npmjs.org/nx/-/nx-22.5.3.tgz", + "integrity": "sha512-IaEPqdgaFBIr0Bfmnt6WAcX3t660sOuDXQ71lpoS8GgpD8cqX1LIW2ZyzEAdOvCP1iD6HCZehpofcVvaaL1GNQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -26675,12 +26721,12 @@ "@yarnpkg/parsers": "3.0.2", "@zkochan/js-yaml": "0.0.7", "axios": "^1.12.0", - "chalk": "^4.1.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", "cliui": "^8.0.1", "dotenv": "~16.4.5", "dotenv-expand": "~11.0.6", + "ejs": "^3.1.7", "enquirer": "~2.3.6", "figures": "3.2.0", "flat": "^5.0.2", @@ -26689,11 +26735,12 @@ "jest-diff": "^30.0.2", "jsonc-parser": "3.2.0", "lines-and-columns": "2.0.3", - "minimatch": "10.1.1", + "minimatch": "10.2.1", "node-machine-id": "1.1.12", "npm-run-path": "^4.0.1", "open": "^8.4.0", "ora": "5.3.0", + "picocolors": "^1.1.0", "resolve.exports": "2.0.3", "semver": "^7.6.3", "string-width": "^4.2.3", @@ -26711,20 +26758,20 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "22.4.5", - "@nx/nx-darwin-x64": "22.4.5", - "@nx/nx-freebsd-x64": "22.4.5", - "@nx/nx-linux-arm-gnueabihf": "22.4.5", - "@nx/nx-linux-arm64-gnu": "22.4.5", - "@nx/nx-linux-arm64-musl": "22.4.5", - "@nx/nx-linux-x64-gnu": "22.4.5", - "@nx/nx-linux-x64-musl": "22.4.5", - "@nx/nx-win32-arm64-msvc": "22.4.5", - "@nx/nx-win32-x64-msvc": "22.4.5" + "@nx/nx-darwin-arm64": "22.5.3", + "@nx/nx-darwin-x64": "22.5.3", + "@nx/nx-freebsd-x64": "22.5.3", + "@nx/nx-linux-arm-gnueabihf": "22.5.3", + "@nx/nx-linux-arm64-gnu": "22.5.3", + "@nx/nx-linux-arm64-musl": "22.5.3", + "@nx/nx-linux-x64-gnu": "22.5.3", + "@nx/nx-linux-x64-musl": "22.5.3", + "@nx/nx-win32-arm64-msvc": "22.5.3", + "@nx/nx-win32-x64-msvc": "22.5.3" }, "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" + "@swc-node/register": "^1.11.1", + "@swc/core": "^1.15.8" }, "peerDependenciesMeta": { "@swc-node/register": { @@ -26757,6 +26804,29 @@ "tslib": "^2.4.0" } }, + "node_modules/nx/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nx/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/nx/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -26870,13 +26940,13 @@ "license": "MIT" }, "node_modules/nx/node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" }, "engines": { "node": "20 || >=22" @@ -32997,18 +33067,15 @@ } }, "node_modules/ts-checker-rspack-plugin": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/ts-checker-rspack-plugin/-/ts-checker-rspack-plugin-1.2.6.tgz", - "integrity": "sha512-aAJIfoNr2cPu8G6mqp/oPoNlUT/LgNoqt2n3SsbxWG0TwQogbjsYsr2f/fdsufUDoGDu8Jolmpf3L4PmIH/cEg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-checker-rspack-plugin/-/ts-checker-rspack-plugin-1.3.0.tgz", + "integrity": "sha512-89oK/BtApjdid1j9CGjPGiYry+EZBhsnTAM481/8ipgr/y2IOgCbW1HPnan+fs5FnzlpUgf9dWGNZ4Ayw3Bd8A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", "@rspack/lite-tapable": "^1.1.0", "chokidar": "^3.6.0", - "is-glob": "^4.0.3", - "memfs": "^4.51.1", - "minimatch": "^9.0.5", + "memfs": "^4.56.10", "picocolors": "^1.1.1" }, "peerDependencies": { @@ -33021,16 +33088,6 @@ } } }, - "node_modules/ts-checker-rspack-plugin/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/ts-checker-rspack-plugin/node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -33099,22 +33156,6 @@ "tslib": "2" } }, - "node_modules/ts-checker-rspack-plugin/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ts-checker-rspack-plugin/node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", diff --git a/package.json b/package.json index 794a09ea7..8871e8acc 100644 --- a/package.json +++ b/package.json @@ -153,16 +153,16 @@ "@eslint/js": "9.35.0", "@nestjs/schematics": "11.0.9", "@nestjs/testing": "11.1.14", - "@nx/angular": "22.4.5", - "@nx/eslint-plugin": "22.4.5", - "@nx/jest": "22.4.5", - "@nx/js": "22.4.5", - "@nx/module-federation": "22.4.5", - "@nx/nest": "22.4.5", - "@nx/node": "22.4.5", - "@nx/storybook": "22.4.5", - "@nx/web": "22.4.5", - "@nx/workspace": "22.4.5", + "@nx/angular": "22.5.3", + "@nx/eslint-plugin": "22.5.3", + "@nx/jest": "22.5.3", + "@nx/js": "22.5.3", + "@nx/module-federation": "22.5.3", + "@nx/nest": "22.5.3", + "@nx/node": "22.5.3", + "@nx/storybook": "22.5.3", + "@nx/web": "22.5.3", + "@nx/workspace": "22.5.3", "@schematics/angular": "21.1.1", "@storybook/addon-docs": "10.1.10", "@storybook/angular": "10.1.10", @@ -187,7 +187,7 @@ "jest": "30.2.0", "jest-environment-jsdom": "30.2.0", "jest-preset-angular": "16.0.0", - "nx": "22.4.5", + "nx": "22.5.3", "prettier": "3.8.1", "prettier-plugin-organize-attributes": "1.0.0", "prisma": "6.19.0", From 2cc36d002f87c19051f4dfed925bc4785eb3740d Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 1 Mar 2026 20:27:13 +0100 Subject: [PATCH 008/138] Task/restructure sponsors section in README.md (#6412) * Restructure sponsors section --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3be15e49f..44212b607 100644 --- a/README.md +++ b/README.md @@ -313,10 +313,12 @@ Ghostfolio is **100% free** and **open source**. We encourage and support an act Not sure what to work on? We have [some ideas](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22%20no%3Aassignee), even for [newcomers](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22%20no%3Aassignee). Please join the Ghostfolio [Slack](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) channel or post to [@ghostfolio\_](https://x.com/ghostfolio_) on _X_. We would love to hear from you. -If you like to support this project, become a [**Sponsor**](https://github.com/sponsors/ghostfolio), get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio). - ## Sponsors +If you like to support this project, get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing), become a [**Sponsor**](https://github.com/sponsors/ghostfolio) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio). + +
+
TestMu AI Logo From 8b187c96b567edce6b0fa1763cca032206bc7686 Mon Sep 17 00:00:00 2001 From: DmytroSkachko Date: Mon, 2 Mar 2026 12:13:24 +0100 Subject: [PATCH 009/138] Task/eliminate OnDestroy hook from ZEN page (#6452) * Eliminate OnDestroy hook --- .../src/app/pages/zen/zen-page.component.ts | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/client/src/app/pages/zen/zen-page.component.ts b/apps/client/src/app/pages/zen/zen-page.component.ts index 280f33c25..633f15885 100644 --- a/apps/client/src/app/pages/zen/zen-page.component.ts +++ b/apps/client/src/app/pages/zen/zen-page.component.ts @@ -2,15 +2,19 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { TabConfiguration, User } from '@ghostfolio/common/interfaces'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + DestroyRef, + OnInit +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatTabsModule } from '@angular/material/tabs'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { albumsOutline, analyticsOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'page has-tabs' }, @@ -19,20 +23,19 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./zen-page.scss'], templateUrl: './zen-page.html' }) -export class GfZenPageComponent implements OnDestroy, OnInit { +export class GfZenPageComponent implements OnInit { public deviceType: string; public tabs: TabConfiguration[] = []; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private userService: UserService ) { this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.tabs = [ @@ -59,9 +62,4 @@ export class GfZenPageComponent implements OnDestroy, OnInit { public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From cbf43340af06b1288ab2f36ab73800a7237678a9 Mon Sep 17 00:00:00 2001 From: Parth Sharma <99757071+pswitchy@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:01:44 +0530 Subject: [PATCH 010/138] Task/eliminate OnDestroy lifecycle hook from user account page (#6461) * Eliminate OnDestroy lifecycle hook --- .../user-account/user-account-page.component.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/apps/client/src/app/pages/user-account/user-account-page.component.ts b/apps/client/src/app/pages/user-account/user-account-page.component.ts index 7341660f2..24c150408 100644 --- a/apps/client/src/app/pages/user-account/user-account-page.component.ts +++ b/apps/client/src/app/pages/user-account/user-account-page.component.ts @@ -6,16 +6,16 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatTabsModule } from '@angular/material/tabs'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { diamondOutline, keyOutline, settingsOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject, takeUntil } from 'rxjs'; @Component({ host: { class: 'page has-tabs' }, @@ -25,20 +25,19 @@ import { Subject, takeUntil } from 'rxjs'; styleUrls: ['./user-account-page.scss'], templateUrl: './user-account-page.html' }) -export class GfUserAccountPageComponent implements OnDestroy, OnInit { +export class GfUserAccountPageComponent implements OnInit { public deviceType: string; public tabs: TabConfiguration[] = []; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private userService: UserService ) { this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -73,9 +72,4 @@ export class GfUserAccountPageComponent implements OnDestroy, OnInit { public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From c9924e030aa9df55ca9920d4f202c02059733e09 Mon Sep 17 00:00:00 2001 From: Parth Sharma <99757071+pswitchy@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:28:03 +0530 Subject: [PATCH 011/138] Task/eliminate OnDestroy lifecycle hook from home page (#6462) * Eliminate OnDestroy lifecycle hook --- .../src/app/pages/home/home-page.component.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/apps/client/src/app/pages/home/home-page.component.ts b/apps/client/src/app/pages/home/home-page.component.ts index fd860ced5..5130c8166 100644 --- a/apps/client/src/app/pages/home/home-page.component.ts +++ b/apps/client/src/app/pages/home/home-page.component.ts @@ -8,9 +8,10 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatTabsModule } from '@angular/material/tabs'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; @@ -23,8 +24,6 @@ import { readerOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'page has-tabs' }, @@ -34,22 +33,21 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./home-page.scss'], templateUrl: './home-page.html' }) -export class GfHomePageComponent implements OnDestroy, OnInit { +export class GfHomePageComponent implements OnInit { public deviceType: string; public hasImpersonationId: boolean; public tabs: TabConfiguration[] = []; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, private userService: UserService ) { this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -110,14 +108,9 @@ export class GfHomePageComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From e273bfcbea492901b330e8a18d3ddeab9d4359c6 Mon Sep 17 00:00:00 2001 From: Parth Sharma <99757071+pswitchy@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:48:41 +0530 Subject: [PATCH 012/138] Task/eliminate OnDestroy lifecycle hook from allocations page (#6463) * Eliminate OnDestroy lifecycle hook --- .../allocations/allocations-page.component.ts | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index 70fa09eb1..a98adc438 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -22,7 +22,13 @@ import { GfValueComponent } from '@ghostfolio/ui/value'; import { GfWorldMapChartComponent } from '@ghostfolio/ui/world-map-chart'; import { NgClass } from '@angular/common'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + DestroyRef, + OnInit +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatCardModule } from '@angular/material/card'; import { MatDialog } from '@angular/material/dialog'; import { MatProgressBarModule } from '@angular/material/progress-bar'; @@ -36,8 +42,6 @@ import { } from '@prisma/client'; import { isNumber } from 'lodash'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ imports: [ @@ -54,7 +58,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./allocations-page.scss'], templateUrl: './allocations-page.html' }) -export class GfAllocationsPageComponent implements OnDestroy, OnInit { +export class GfAllocationsPageComponent implements OnInit { public accounts: { [id: string]: Pick & { id: string; @@ -119,11 +123,10 @@ export class GfAllocationsPageComponent implements OnDestroy, OnInit { public user: User; public worldMapChartFormat: string; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private dialog: MatDialog, private impersonationStorageService: ImpersonationStorageService, @@ -132,7 +135,7 @@ export class GfAllocationsPageComponent implements OnDestroy, OnInit { private userService: UserService ) { this.route.queryParams - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((params) => { if (params['accountId'] && params['accountDetailDialog']) { this.openAccountDetailDialog(params['accountId']); @@ -145,13 +148,13 @@ export class GfAllocationsPageComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -166,7 +169,7 @@ export class GfAllocationsPageComponent implements OnDestroy, OnInit { this.initialize(); this.fetchPortfolioDetails() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((portfolioDetails) => { this.initialize(); @@ -202,11 +205,6 @@ export class GfAllocationsPageComponent implements OnDestroy, OnInit { } } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private extractEtfProvider({ assetSubClass, name @@ -578,7 +576,7 @@ export class GfAllocationsPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.router.navigate(['.'], { relativeTo: this.route }); }); From 9fb02dac0ebe8093dbe5dbd8cedf48c11535148b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:29:12 +0100 Subject: [PATCH 013/138] Task/remove unused OnDestroy hook in personal finance tools page (#6443) * Remove unused OnDestroy hook --- .../personal-finance-tools-page.component.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts index c4cfd184e..bb4ae3889 100644 --- a/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts +++ b/apps/client/src/app/pages/resources/personal-finance-tools/personal-finance-tools-page.component.ts @@ -1,13 +1,12 @@ import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools'; import { publicRoutes } from '@ghostfolio/common/routes/routes'; -import { Component, OnDestroy } from '@angular/core'; +import { Component } from '@angular/core'; import { MatCardModule } from '@angular/material/card'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { chevronForwardOutline } from 'ionicons/icons'; -import { Subject } from 'rxjs'; @Component({ host: { class: 'page' }, @@ -16,7 +15,7 @@ import { Subject } from 'rxjs'; styleUrls: ['./personal-finance-tools-page.scss'], templateUrl: './personal-finance-tools-page.html' }) -export class PersonalFinanceToolsPageComponent implements OnDestroy { +export class PersonalFinanceToolsPageComponent { public pathAlternativeTo = publicRoutes.resources.subRoutes.personalFinanceTools.subRoutes.product .path + '-'; @@ -28,14 +27,7 @@ export class PersonalFinanceToolsPageComponent implements OnDestroy { }); public routerLinkAbout = publicRoutes.about.routerLink; - private unsubscribeSubject = new Subject(); - public constructor() { addIcons({ chevronForwardOutline }); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 55952d3cc81eea937265b492c120515320b50096 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:30:50 +0100 Subject: [PATCH 014/138] Task/remove unused OnDestroy hook in i18n page component (#6441) * Remove unused OnDestroy hook --- apps/client/src/app/pages/i18n/i18n-page.component.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/apps/client/src/app/pages/i18n/i18n-page.component.ts b/apps/client/src/app/pages/i18n/i18n-page.component.ts index 19ecd222e..76d123914 100644 --- a/apps/client/src/app/pages/i18n/i18n-page.component.ts +++ b/apps/client/src/app/pages/i18n/i18n-page.component.ts @@ -1,5 +1,4 @@ import { Component } from '@angular/core'; -import { Subject } from 'rxjs'; @Component({ host: { class: 'page' }, @@ -8,11 +7,4 @@ import { Subject } from 'rxjs'; styleUrls: ['./i18n-page.scss'], templateUrl: './i18n-page.html' }) -export class GfI18nPageComponent { - private unsubscribeSubject = new Subject(); - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } -} +export class GfI18nPageComponent {} From f8ca87fadb8260aaff55d650feffde6451f6a393 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:31:33 +0100 Subject: [PATCH 015/138] Task/remove unused OnDestroy hook in self-hosting FAQ page component (#6436) * Remove unused OnDestroy hook --- .../faq/self-hosting/self-hosting-page.component.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.component.ts b/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.component.ts index ed1d74395..f2468c7d4 100644 --- a/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.component.ts +++ b/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.component.ts @@ -1,10 +1,9 @@ import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; -import { CUSTOM_ELEMENTS_SCHEMA, Component, OnDestroy } from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core'; import { MatCardModule } from '@angular/material/card'; import { RouterModule } from '@angular/router'; -import { Subject } from 'rxjs'; @Component({ host: { class: 'page' }, @@ -14,13 +13,6 @@ import { Subject } from 'rxjs'; styleUrls: ['./self-hosting-page.scss'], templateUrl: './self-hosting-page.html' }) -export class GfSelfHostingPageComponent implements OnDestroy { +export class GfSelfHostingPageComponent { public pricingUrl = `https://ghostfol.io/${document.documentElement.lang}/${publicRoutes.pricing.path}`; - - private unsubscribeSubject = new Subject(); - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 794c8f8016f20e0e71518437aa527e8a12f2f058 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:32:12 +0100 Subject: [PATCH 016/138] Task/remove unused OnDestroy hook in FAQ page component (#6437) * Remove unused OnDestroy hook --- .../src/app/pages/faq/faq-page.component.ts | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/apps/client/src/app/pages/faq/faq-page.component.ts b/apps/client/src/app/pages/faq/faq-page.component.ts index caf4217ca..83171254a 100644 --- a/apps/client/src/app/pages/faq/faq-page.component.ts +++ b/apps/client/src/app/pages/faq/faq-page.component.ts @@ -3,19 +3,13 @@ import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { publicRoutes } from '@ghostfolio/common/routes/routes'; import { DataService } from '@ghostfolio/ui/services'; -import { - CUSTOM_ELEMENTS_SCHEMA, - Component, - OnDestroy, - OnInit -} from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, Component, OnInit } from '@angular/core'; import { MatTabsModule } from '@angular/material/tabs'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { cloudyOutline, readerOutline, serverOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; @Component({ host: { class: 'page has-tabs' }, @@ -25,13 +19,11 @@ import { Subject } from 'rxjs'; styleUrls: ['./faq-page.scss'], templateUrl: './faq-page.html' }) -export class GfFaqPageComponent implements OnDestroy, OnInit { +export class GfFaqPageComponent implements OnInit { public deviceType: string; public hasPermissionForSubscription: boolean; public tabs: TabConfiguration[] = []; - private unsubscribeSubject = new Subject(); - public constructor( private dataService: DataService, private deviceService: DeviceDetectorService @@ -68,9 +60,4 @@ export class GfFaqPageComponent implements OnDestroy, OnInit { public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From a5d1f5988cd2f3c535244d6d4a28691a5267cb6e Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:32:39 +0100 Subject: [PATCH 017/138] Task/remove unused OnDestroy hook in terms of service page component (#6440) * Remove unused OnDestroy hook --- .../terms-of-service-page.component.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.component.ts b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.component.ts index dbf07ef19..7899f0187 100644 --- a/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.component.ts +++ b/apps/client/src/app/pages/about/terms-of-service/terms-of-service-page.component.ts @@ -1,6 +1,5 @@ -import { Component, OnDestroy } from '@angular/core'; +import { Component } from '@angular/core'; import { MarkdownModule } from 'ngx-markdown'; -import { Subject } from 'rxjs'; @Component({ imports: [MarkdownModule], @@ -8,11 +7,4 @@ import { Subject } from 'rxjs'; styleUrls: ['./terms-of-service-page.scss'], templateUrl: './terms-of-service-page.html' }) -export class GfTermsOfServicePageComponent implements OnDestroy { - private unsubscribeSubject = new Subject(); - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } -} +export class GfTermsOfServicePageComponent {} From 1de4d053e5782b2af37763d5babc5ac535d7b4bf Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:33:06 +0100 Subject: [PATCH 018/138] Task/remove unused OnDestroy hook in transfer balance dialog component (#6438) * Remove unused OnDestroy hook --- .../transfer-balance-dialog.component.ts | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.component.ts b/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.component.ts index 85d2e60bf..34a66b156 100644 --- a/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.component.ts +++ b/apps/client/src/app/pages/accounts/transfer-balance/transfer-balance-dialog.component.ts @@ -1,12 +1,7 @@ import { TransferBalanceDto } from '@ghostfolio/common/dtos'; import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; -import { - ChangeDetectionStrategy, - Component, - Inject, - OnDestroy -} from '@angular/core'; +import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; import { AbstractControl, FormBuilder, @@ -25,7 +20,6 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { Account } from '@prisma/client'; -import { Subject } from 'rxjs'; import { TransferBalanceDialogParams } from './interfaces/interfaces'; @@ -45,13 +39,11 @@ import { TransferBalanceDialogParams } from './interfaces/interfaces'; styleUrls: ['./transfer-balance-dialog.scss'], templateUrl: 'transfer-balance-dialog.html' }) -export class GfTransferBalanceDialogComponent implements OnDestroy { +export class GfTransferBalanceDialogComponent { public accounts: Account[] = []; public currency: string; public transferBalanceForm: FormGroup; - private unsubscribeSubject = new Subject(); - public constructor( @Inject(MAT_DIALOG_DATA) public data: TransferBalanceDialogParams, public dialogRef: MatDialogRef, @@ -93,11 +85,6 @@ export class GfTransferBalanceDialogComponent implements OnDestroy { this.dialogRef.close({ account }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private compareAccounts(control: AbstractControl): ValidationErrors { const accountFrom = control.get('fromAccount'); const accountTo = control.get('toAccount'); From ab07fba16b28b46848aae821482b1780cdf91a51 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:33:43 +0100 Subject: [PATCH 019/138] Task/remove unused OnDestroy hook in create or update account dialog component (#6439) * Remove unused OnDestroy hook --- ...reate-or-update-account-dialog.component.ts | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts index f4c68e70f..6cdd18251 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts @@ -5,12 +5,7 @@ import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; import { DataService } from '@ghostfolio/ui/services'; import { CommonModule, NgClass } from '@angular/common'; -import { - ChangeDetectionStrategy, - Component, - Inject, - OnDestroy -} from '@angular/core'; +import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; import { AbstractControl, FormBuilder, @@ -30,7 +25,7 @@ import { import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { Platform } from '@prisma/client'; -import { Observable, Subject } from 'rxjs'; +import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces'; @@ -55,14 +50,12 @@ import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces'; styleUrls: ['./create-or-update-account-dialog.scss'], templateUrl: 'create-or-update-account-dialog.html' }) -export class GfCreateOrUpdateAccountDialogComponent implements OnDestroy { +export class GfCreateOrUpdateAccountDialogComponent { public accountForm: FormGroup; public currencies: string[] = []; public filteredPlatforms: Observable; public platforms: Platform[] = []; - private unsubscribeSubject = new Subject(); - public constructor( @Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateAccountDialogParams, private dataService: DataService, @@ -170,11 +163,6 @@ export class GfCreateOrUpdateAccountDialogComponent implements OnDestroy { } } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private autocompleteObjectValidator(): ValidatorFn { return (control: AbstractControl) => { if (control.value && typeof control.value === 'string') { From 9bd4fe53cec45b4599dde796ecee1403a99c16a5 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 20:06:26 +0100 Subject: [PATCH 020/138] Task/extend personal finance tools 20260302 (#6464) * Extend personal finance tools --- libs/common/src/lib/personal-finance-tools.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/libs/common/src/lib/personal-finance-tools.ts b/libs/common/src/lib/personal-finance-tools.ts index 6d0a85fb2..063b4254c 100644 --- a/libs/common/src/lib/personal-finance-tools.ts +++ b/libs/common/src/lib/personal-finance-tools.ts @@ -33,6 +33,15 @@ export const personalFinanceTools: Product[] = [ origin: 'Switzerland', slogan: 'Simplicity for Complex Wealth' }, + { + founded: 2018, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'altruist', + name: 'Altruist', + origin: 'United States', + slogan: 'The wealth platform built for independent advisors' + }, { founded: 2023, hasFreePlan: false, @@ -116,6 +125,17 @@ export const personalFinanceTools: Product[] = [ origin: 'Switzerland', slogan: 'Schweizer Budget App für einfache & smarte Budgetplanung' }, + { + founded: 2015, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'boldin', + name: 'Boldin', + note: 'Originally named as NewRetirement', + origin: 'United States', + pricingPerYear: '$144', + slogan: 'Take control with retirement planning tools that begin with you' + }, { key: 'budgetpulse', name: 'BudgetPulse', @@ -841,6 +861,16 @@ export const personalFinanceTools: Product[] = [ pricingPerYear: '$108', slogan: 'Build Financial Plans You Love.' }, + { + founded: 2022, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'prostocktracker', + name: 'Pro Stock Tracker', + origin: 'United Kingdom', + pricingPerYear: '$60', + slogan: 'The stock portfolio tracker built for long-term investors' + }, { founded: 2015, hasSelfHostingAbility: false, @@ -1014,6 +1044,16 @@ export const personalFinanceTools: Product[] = [ regions: ['Austria', 'Germany', 'Switzerland'], slogan: 'Dein Vermögen immer im Blick' }, + { + founded: 2025, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'turbobulls', + name: 'Turbobulls', + origin: 'Romania', + pricingPerYear: '€39.99', + slogan: 'Your complete financial dashboard. Actually private.' + }, { hasFreePlan: true, hasSelfHostingAbility: false, From 8e47e198fa9218c123fc37cfb7a60f466affe93a Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 2 Mar 2026 20:06:53 +0100 Subject: [PATCH 021/138] Task/remove deprecated committed funds from summary of portfolio details (#6442) * Remove deprecated committedFunds * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/portfolio/portfolio.controller.ts | 1 - apps/api/src/app/portfolio/portfolio.service.ts | 3 --- apps/api/src/helper/object.helper.spec.ts | 2 -- libs/common/src/lib/interfaces/portfolio-summary.interface.ts | 4 ---- 5 files changed, 1 insertion(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7ebb665c..ddcb68ad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Removed the deprecated `committedFunds` from the summary of the portfolio details endpoint - Upgraded `Nx` from version `22.4.5` to `22.5.3` ## 2.245.0 - 2026-03-01 diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 5ed3c0009..67b5229c1 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -187,7 +187,6 @@ export class PortfolioController { portfolioSummary = nullifyValuesInObject(summary, [ 'cash', - 'committedFunds', 'currentNetWorth', 'currentValueInBaseCurrency', 'dividendInBaseCurrency', diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 17bd01ce4..26d16bf75 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1914,8 +1914,6 @@ export class PortfolioService { .plus(emergencyFundHoldingsValueInBaseCurrency) .toNumber(); - const committedFunds = new Big(totalBuy).minus(totalSell); - const totalOfExcludedActivities = this.getSumOfActivityType({ userCurrency, activities: excludedActivities, @@ -1979,7 +1977,6 @@ export class PortfolioService { activityCount: activities.filter(({ type }) => { return ['BUY', 'SELL'].includes(type); }).length, - committedFunds: committedFunds.toNumber(), currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(), dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), emergencyFund: { diff --git a/apps/api/src/helper/object.helper.spec.ts b/apps/api/src/helper/object.helper.spec.ts index eed261f3e..ba8760c70 100644 --- a/apps/api/src/helper/object.helper.spec.ts +++ b/apps/api/src/helper/object.helper.spec.ts @@ -1540,7 +1540,6 @@ describe('redactAttributes', () => { netPerformanceWithCurrencyEffect: null, totalBuy: null, totalSell: null, - committedFunds: null, currentValueInBaseCurrency: null, dividendInBaseCurrency: null, emergencyFund: null, @@ -3017,7 +3016,6 @@ describe('redactAttributes', () => { netPerformanceWithCurrencyEffect: null, totalBuy: null, totalSell: null, - committedFunds: null, currentValueInBaseCurrency: null, dividendInBaseCurrency: null, emergencyFund: null, diff --git a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts index 79fbf8707..8db6b39bb 100644 --- a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts @@ -6,10 +6,6 @@ export interface PortfolioSummary extends PortfolioPerformance { annualizedPerformancePercent: number; annualizedPerformancePercentWithCurrencyEffect: number; cash: number; - - /** @deprecated use totalInvestmentValueWithCurrencyEffect instead */ - committedFunds: number; - dateOfFirstActivity: Date; dividendInBaseCurrency: number; emergencyFund: { From 27b1e74d2350a0227b93ed639ee625b559fe735c Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:33:19 +0100 Subject: [PATCH 022/138] Bugfix/disabled buttons in assistant component (#6471) * Fix signal accessors * Update changelog --- CHANGELOG.md | 4 ++++ libs/ui/src/lib/assistant/assistant.html | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddcb68ad8..18055ec4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed the deprecated `committedFunds` from the summary of the portfolio details endpoint - Upgraded `Nx` from version `22.4.5` to `22.5.3` +### Fixed + +- Fixed an issue where the apply and reset filter buttons remained disabled in the assistant + ## 2.245.0 - 2026-03-01 ### Changed diff --git a/libs/ui/src/lib/assistant/assistant.html b/libs/ui/src/lib/assistant/assistant.html index 7e19833a9..79e2f31a1 100644 --- a/libs/ui/src/lib/assistant/assistant.html +++ b/libs/ui/src/lib/assistant/assistant.html @@ -197,7 +197,7 @@ mat-button type="button" [disabled]=" - !portfolioFilterForm.hasFilters() || portfolioFilterForm.disabled + !portfolioFilterForm.hasFilters() || portfolioFilterForm.disabled() " (click)="onResetFilters()" > @@ -210,7 +210,7 @@ type="button" [disabled]=" !portfolioFilterForm.filterForm.dirty || - portfolioFilterForm.disabled + portfolioFilterForm.disabled() " (click)="onApplyFilters()" > From 0883c7c5bf74282cad926c99d011c75b6894550d Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:35:26 +0100 Subject: [PATCH 023/138] Release 2.246.0 (#6472) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18055ec4b..b5575e543 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.246.0 - 2026-03-03 ### Changed diff --git a/package-lock.json b/package-lock.json index 52b460666..87e61400d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.245.0", + "version": "2.246.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.245.0", + "version": "2.246.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 8871e8acc..f3e74f28e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.245.0", + "version": "2.246.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From f92bb665e413729ffe83a3ccc068ef5061be45cc Mon Sep 17 00:00:00 2001 From: Lucas Macedo <83371481+lmaced0@users.noreply.github.com> Date: Wed, 4 Mar 2026 00:27:45 -0700 Subject: [PATCH 024/138] Task/upgrade yahoo-finance2 to version 3.13.1 (#6475) * Upgrade yahoo-finance2 to version 3.13.1 * Update changelog --- CHANGELOG.md | 6 ++++++ package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5575e543..25f00db9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Upgraded `yahoo-finance2` from version `3.13.0` to `3.13.1` + ## 2.246.0 - 2026-03-03 ### Changed diff --git a/package-lock.json b/package-lock.json index 87e61400d..370325602 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,7 +89,7 @@ "svgmap": "2.14.0", "tablemark": "4.1.0", "twitter-api-v2": "1.29.0", - "yahoo-finance2": "3.13.0", + "yahoo-finance2": "3.13.1", "zone.js": "0.16.0" }, "devDependencies": { @@ -35476,9 +35476,9 @@ } }, "node_modules/yahoo-finance2": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/yahoo-finance2/-/yahoo-finance2-3.13.0.tgz", - "integrity": "sha512-czBj2q/MD68YEsB7aXNnGhJvWxYZn01O5r/i7VYiQV2m2sWwhca6tKgjwf/LT7zHHEVxhKNiGLB46glLnmq9Ag==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/yahoo-finance2/-/yahoo-finance2-3.13.1.tgz", + "integrity": "sha512-kn3unY2OflG1NbeONedWxFDzq5QDyMYYAnr6VjRIOsMv5Q7ZXZZYFM8OadNZrOev4ikQjbYcMLLjogpVaez/vQ==", "license": "MIT", "dependencies": { "@deno/shim-deno": "~0.18.0", diff --git a/package.json b/package.json index f3e74f28e..f3397832e 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "svgmap": "2.14.0", "tablemark": "4.1.0", "twitter-api-v2": "1.29.0", - "yahoo-finance2": "3.13.0", + "yahoo-finance2": "3.13.1", "zone.js": "0.16.0" }, "devDependencies": { From 2bd8463cafff181b3d82bc4c82fe714028d34c91 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:43:43 +0100 Subject: [PATCH 025/138] Task/upgrade yahoo-finance2 to version 3.13.2 (#6477) * Upgrade yahoo-finance2 to version 3.13.2 * Update changelog --- CHANGELOG.md | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25f00db9d..6d5fa1836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Upgraded `yahoo-finance2` from version `3.13.0` to `3.13.1` +- Upgraded `yahoo-finance2` from version `3.13.0` to `3.13.2` ## 2.246.0 - 2026-03-03 diff --git a/package-lock.json b/package-lock.json index 370325602..2744da2c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,7 +89,7 @@ "svgmap": "2.14.0", "tablemark": "4.1.0", "twitter-api-v2": "1.29.0", - "yahoo-finance2": "3.13.1", + "yahoo-finance2": "3.13.2", "zone.js": "0.16.0" }, "devDependencies": { @@ -35476,9 +35476,9 @@ } }, "node_modules/yahoo-finance2": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/yahoo-finance2/-/yahoo-finance2-3.13.1.tgz", - "integrity": "sha512-kn3unY2OflG1NbeONedWxFDzq5QDyMYYAnr6VjRIOsMv5Q7ZXZZYFM8OadNZrOev4ikQjbYcMLLjogpVaez/vQ==", + "version": "3.13.2", + "resolved": "https://registry.npmjs.org/yahoo-finance2/-/yahoo-finance2-3.13.2.tgz", + "integrity": "sha512-aAOJEjuLClfDxVPRKxjcwFoyzMr8BE/svgUqr5IjnQR+kppYbKO92Wl3SbAGz5DRghy6FiUfqi5FBDSBA/e2jg==", "license": "MIT", "dependencies": { "@deno/shim-deno": "~0.18.0", diff --git a/package.json b/package.json index f3397832e..536f7fe80 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "svgmap": "2.14.0", "tablemark": "4.1.0", "twitter-api-v2": "1.29.0", - "yahoo-finance2": "3.13.1", + "yahoo-finance2": "3.13.2", "zone.js": "0.16.0" }, "devDependencies": { From 53d9fd42d8d34bd5b5c00a0a3665ea2de8cd6366 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:46:04 +0100 Subject: [PATCH 026/138] Release 2.247.0 (#6478) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d5fa1836..37ff3cf87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.247.0 - 2026-03-04 ### Changed diff --git a/package-lock.json b/package-lock.json index 2744da2c3..8dbc7866a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.246.0", + "version": "2.247.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.246.0", + "version": "2.247.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 536f7fe80..628de4a9d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.246.0", + "version": "2.247.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From 945450f3e00b498a609a8879e0f90f00bc008207 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 4 Mar 2026 19:39:29 +0100 Subject: [PATCH 027/138] Task/upgrade jsonpath to version 1.2.1 (#6465) * Upgrade jsonpath to version 1.2.1 * Update changelog --- CHANGELOG.md | 6 ++ package-lock.json | 160 +++++++++++++++------------------------------- package.json | 2 +- 3 files changed, 58 insertions(+), 110 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37ff3cf87..f536f143b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Upgraded `jsonpath` from version `1.1.1` to `1.2.1` + ## 2.247.0 - 2026-03-04 ### Changed diff --git a/package-lock.json b/package-lock.json index 8dbc7866a..8fb2f8bb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,7 +68,7 @@ "helmet": "7.0.0", "http-status-codes": "2.3.0", "ionicons": "8.0.13", - "jsonpath": "1.1.1", + "jsonpath": "1.2.1", "lodash": "4.17.23", "marked": "17.0.2", "ms": "3.0.0-canary.1", @@ -18320,6 +18320,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, "license": "MIT" }, "node_modules/deepmerge": { @@ -19280,6 +19281,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/eslint": { "version": "9.35.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", @@ -19713,7 +19745,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -20061,6 +20092,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, "license": "MIT" }, "node_modules/fast-redact": { @@ -24594,20 +24626,20 @@ "license": "MIT" }, "node_modules/jsonpath": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", - "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.2.1.tgz", + "integrity": "sha512-Jl6Jhk0jG+kP3yk59SSeGq7LFPR4JQz1DU0K+kXTysUhMostbhU3qh5mjTuf0PqFcXpAT7kvmMt9WxV10NyIgQ==", "license": "MIT", "dependencies": { - "esprima": "1.2.2", - "static-eval": "2.0.2", - "underscore": "1.12.1" + "esprima": "1.2.5", + "static-eval": "2.1.1", + "underscore": "1.13.6" } }, "node_modules/jsonpath/node_modules/esprima": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", - "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha512-S9VbPDU0adFErpDai3qDkjq8+G05ONtKzcyNrPKg/ZKa+tf879nX2KexNU95b31UoTJjRLInNBHHHjFPoCd7lQ==", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -31771,103 +31803,12 @@ "license": "MIT" }, "node_modules/static-eval": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", - "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", - "license": "MIT", - "dependencies": { - "escodegen": "^1.8.1" - } - }, - "node_modules/static-eval/node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/static-eval/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/static-eval/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/static-eval/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/static-eval/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/static-eval/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-eval/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.1.tgz", + "integrity": "sha512-MgWpQ/ZjGieSVB3eOJVs4OA2LT/q1vx98KPCTTQPzq/aLr0YUXTsgryTXr4SLfR0ZfUUCiedM9n/ABeDIyy4mA==", "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" + "escodegen": "^2.1.0" } }, "node_modules/statuses": { @@ -33721,9 +33662,9 @@ } }, "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "license": "MIT" }, "node_modules/undici": { @@ -35326,6 +35267,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" diff --git a/package.json b/package.json index 628de4a9d..0e2c3ccc1 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "helmet": "7.0.0", "http-status-codes": "2.3.0", "ionicons": "8.0.13", - "jsonpath": "1.1.1", + "jsonpath": "1.2.1", "lodash": "4.17.23", "marked": "17.0.2", "ms": "3.0.0-canary.1", From 86d4d6ed649f99e3e5b307d6f15590feead134eb Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 5 Mar 2026 22:29:11 +0100 Subject: [PATCH 028/138] Task/implement OnModuleInit interface in TwitterBotService (#6447) * Implement OnModuleInit interface --- apps/api/src/services/twitter-bot/twitter-bot.service.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/api/src/services/twitter-bot/twitter-bot.service.ts b/apps/api/src/services/twitter-bot/twitter-bot.service.ts index ee951820d..b424f7198 100644 --- a/apps/api/src/services/twitter-bot/twitter-bot.service.ts +++ b/apps/api/src/services/twitter-bot/twitter-bot.service.ts @@ -10,19 +10,21 @@ import { resolveMarketCondition } from '@ghostfolio/common/helper'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; import { isWeekend } from 'date-fns'; import { TwitterApi, TwitterApiReadWrite } from 'twitter-api-v2'; @Injectable() -export class TwitterBotService { +export class TwitterBotService implements OnModuleInit { private twitterClient: TwitterApiReadWrite; public constructor( private readonly benchmarkService: BenchmarkService, private readonly configurationService: ConfigurationService, private readonly symbolService: SymbolService - ) { + ) {} + + public onModuleInit() { this.twitterClient = new TwitterApi({ accessSecret: this.configurationService.get( 'TWITTER_ACCESS_TOKEN_SECRET' From 3d07f69e176d4f87996fc682f6e4a26add6c0ea5 Mon Sep 17 00:00:00 2001 From: DmytroSkachko Date: Thu, 5 Mar 2026 22:45:14 +0100 Subject: [PATCH 029/138] Task/reuse value component in tag component of Admin Control panel (#6467) * Reuse value component * Update changelog --- CHANGELOG.md | 1 + .../components/admin-settings/admin-settings.component.html | 2 +- .../components/admin-settings/admin-settings.component.ts | 2 +- .../src/app/components/admin-tag/admin-tag.component.html | 6 +++++- .../src/app/components/admin-tag/admin-tag.component.ts | 6 ++++++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f536f143b..0aa2e9459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Reused the value component in the tag management of the admin control panel - Upgraded `jsonpath` from version `1.1.1` to `1.2.1` ## 2.247.0 - 2026-03-04 diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.html b/apps/client/src/app/components/admin-settings/admin-settings.component.html index af64f034b..571e45afa 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.html +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -199,7 +199,7 @@

Tags

- +
diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.ts b/apps/client/src/app/components/admin-settings/admin-settings.component.ts index 446221058..219fd2847 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.ts +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.ts @@ -74,9 +74,9 @@ export class GfAdminSettingsComponent implements OnDestroy, OnInit { public isGhostfolioApiKeyValid: boolean; public isLoading = false; public pricingUrl: string; + public user: User; private unsubscribeSubject = new Subject(); - private user: User; public constructor( private adminService: AdminService, diff --git a/apps/client/src/app/components/admin-tag/admin-tag.component.html b/apps/client/src/app/components/admin-tag/admin-tag.component.html index 98919abd8..463a817ff 100644 --- a/apps/client/src/app/components/admin-tag/admin-tag.component.html +++ b/apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -45,7 +45,11 @@ Activities - {{ element.activityCount }} + diff --git a/apps/client/src/app/components/admin-tag/admin-tag.component.ts b/apps/client/src/app/components/admin-tag/admin-tag.component.ts index ca7950291..0b64a4ca1 100644 --- a/apps/client/src/app/components/admin-tag/admin-tag.component.ts +++ b/apps/client/src/app/components/admin-tag/admin-tag.component.ts @@ -1,13 +1,16 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { CreateTagDto, UpdateTagDto } from '@ghostfolio/common/dtos'; import { ConfirmationDialogType } from '@ghostfolio/common/enums'; +import { getLocale } from '@ghostfolio/common/helper'; import { NotificationService } from '@ghostfolio/ui/notifications'; import { DataService } from '@ghostfolio/ui/services'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + Input, OnDestroy, OnInit, ViewChild @@ -36,6 +39,7 @@ import { CreateOrUpdateTagDialogParams } from './create-or-update-tag-dialog/int @Component({ changeDetection: ChangeDetectionStrategy.OnPush, imports: [ + GfValueComponent, IonIcon, MatButtonModule, MatMenuModule, @@ -48,6 +52,8 @@ import { CreateOrUpdateTagDialogParams } from './create-or-update-tag-dialog/int templateUrl: './admin-tag.component.html' }) export class GfAdminTagComponent implements OnDestroy, OnInit { + @Input() locale = getLocale(); + @ViewChild(MatSort) sort: MatSort; public dataSource = new MatTableDataSource(); From 3c886f134d73be38abdf5aeb55977d17fc1db9cf Mon Sep 17 00:00:00 2001 From: Winn Cook <111204176+WinnCook@users.noreply.github.com> Date: Fri, 6 Mar 2026 00:18:07 -0700 Subject: [PATCH 030/138] Task/reuse value component in platform component of Admin Control panel (#6470) * Reuse value component * Update changelog --------- Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> --- CHANGELOG.md | 1 + .../components/admin-platform/admin-platform.component.html | 6 +++++- .../components/admin-platform/admin-platform.component.ts | 6 ++++++ .../components/admin-settings/admin-settings.component.html | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa2e9459..0ce9598e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Reused the value component in the platform management of the admin control panel - Reused the value component in the tag management of the admin control panel - Upgraded `jsonpath` from version `1.1.1` to `1.2.1` diff --git a/apps/client/src/app/components/admin-platform/admin-platform.component.html b/apps/client/src/app/components/admin-platform/admin-platform.component.html index 367827878..7370a19ae 100644 --- a/apps/client/src/app/components/admin-platform/admin-platform.component.html +++ b/apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -52,7 +52,11 @@ Accounts - {{ element.accountCount }} + diff --git a/apps/client/src/app/components/admin-platform/admin-platform.component.ts b/apps/client/src/app/components/admin-platform/admin-platform.component.ts index 02a2eed64..2a04f86cc 100644 --- a/apps/client/src/app/components/admin-platform/admin-platform.component.ts +++ b/apps/client/src/app/components/admin-platform/admin-platform.component.ts @@ -1,14 +1,17 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { CreatePlatformDto, UpdatePlatformDto } from '@ghostfolio/common/dtos'; import { ConfirmationDialogType } from '@ghostfolio/common/enums'; +import { getLocale } from '@ghostfolio/common/helper'; import { GfEntityLogoComponent } from '@ghostfolio/ui/entity-logo'; import { NotificationService } from '@ghostfolio/ui/notifications'; import { AdminService, DataService } from '@ghostfolio/ui/services'; +import { GfValueComponent } from '@ghostfolio/ui/value'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + Input, OnDestroy, OnInit, ViewChild @@ -38,6 +41,7 @@ import { CreateOrUpdatePlatformDialogParams } from './create-or-update-platform- changeDetection: ChangeDetectionStrategy.OnPush, imports: [ GfEntityLogoComponent, + GfValueComponent, IonIcon, MatButtonModule, MatMenuModule, @@ -50,6 +54,8 @@ import { CreateOrUpdatePlatformDialogParams } from './create-or-update-platform- templateUrl: './admin-platform.component.html' }) export class GfAdminPlatformComponent implements OnDestroy, OnInit { + @Input() locale = getLocale(); + @ViewChild(MatSort) sort: MatSort; public dataSource = new MatTableDataSource(); diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.html b/apps/client/src/app/components/admin-settings/admin-settings.component.html index 571e45afa..41a9992c9 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.html +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -193,7 +193,7 @@

Platforms

- +
From a1283e40f50a86dc2a4975d03b1d8e55ec44a2cd Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 7 Mar 2026 08:53:11 +0100 Subject: [PATCH 031/138] Task/upgrade @types/passport-google-oauth20 to version 2.0.17 (#6325) * Upgrade @types/passport-google-oauth20 to version 2.0.17 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8fb2f8bb1..0ea9bbdce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -130,7 +130,7 @@ "@types/lodash": "4.17.23", "@types/node": "22.15.17", "@types/papaparse": "5.3.7", - "@types/passport-google-oauth20": "2.0.16", + "@types/passport-google-oauth20": "2.0.17", "@types/passport-openidconnect": "0.1.3", "@typescript-eslint/eslint-plugin": "8.43.0", "@typescript-eslint/parser": "8.43.0", @@ -13304,9 +13304,9 @@ } }, "node_modules/@types/passport-google-oauth20": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz", - "integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.17.tgz", + "integrity": "sha512-MHNOd2l7gOTCn3iS+wInPQMiukliAUvMpODO3VlXxOiwNEMSyzV7UNvAdqxSN872o8OXx1SqPDVT6tLW74AtqQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 0e2c3ccc1..47c9e9ade 100644 --- a/package.json +++ b/package.json @@ -175,7 +175,7 @@ "@types/lodash": "4.17.23", "@types/node": "22.15.17", "@types/papaparse": "5.3.7", - "@types/passport-google-oauth20": "2.0.16", + "@types/passport-google-oauth20": "2.0.17", "@types/passport-openidconnect": "0.1.3", "@typescript-eslint/eslint-plugin": "8.43.0", "@typescript-eslint/parser": "8.43.0", From b7d976d2ff5c8fbf1972d9b6eaaa309acd2ae51c Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 7 Mar 2026 08:58:59 +0100 Subject: [PATCH 032/138] Task/add asset profile to portfolio position interface (#6473) * Add asset profile * Update changelog --- CHANGELOG.md | 2 + .../app/endpoints/public/public.controller.ts | 1 + .../src/app/portfolio/portfolio.service.ts | 31 ++++ ...orm-data-source-in-response.interceptor.ts | 1 + .../portfolio-position.interface.ts | 45 +++++ .../public-portfolio-response.interface.ts | 15 ++ libs/ui/src/lib/mocks/holdings.ts | 155 ++++++++++++++++-- 7 files changed, 240 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ce9598e3..b2b2eb1ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Included asset profile data in the endpoint `GET api/v1/portfolio/holdings` +- Included asset profile data in the holdings of the public page - Reused the value component in the platform management of the admin control panel - Reused the value component in the tag management of the admin control panel - Upgraded `jsonpath` from version `1.1.1` to `1.2.1` diff --git a/apps/api/src/app/endpoints/public/public.controller.ts b/apps/api/src/app/endpoints/public/public.controller.ts index b4ecd37ba..a1b2b7864 100644 --- a/apps/api/src/app/endpoints/public/public.controller.ts +++ b/apps/api/src/app/endpoints/public/public.controller.ts @@ -167,6 +167,7 @@ export class PublicController { allocationInPercentage: portfolioPosition.valueInBaseCurrency / totalValue, assetClass: hasDetails ? portfolioPosition.assetClass : undefined, + assetProfile: hasDetails ? portfolioPosition.assetProfile : undefined, countries: hasDetails ? portfolioPosition.countries : [], currency: hasDetails ? portfolioPosition.currency : undefined, dataSource: portfolioPosition.dataSource, diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 26d16bf75..1bfad8395 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -623,6 +623,27 @@ export class PortfolioService { ? 0 : valueInBaseCurrency.div(filteredValueInBaseCurrency).toNumber(), assetClass: assetProfile.assetClass, + assetProfile: { + assetClass: assetProfile.assetClass, + assetSubClass: assetProfile.assetSubClass, + countries: assetProfile.countries, + dataSource: assetProfile.dataSource, + holdings: assetProfile.holdings.map( + ({ allocationInPercentage, name }) => { + return { + allocationInPercentage, + name, + valueInBaseCurrency: valueInBaseCurrency + .mul(allocationInPercentage) + .toNumber() + }; + } + ), + name: assetProfile.name, + sectors: assetProfile.sectors, + symbol: assetProfile.symbol, + url: assetProfile.url + }, assetSubClass: assetProfile.assetSubClass, countries: assetProfile.countries, dataSource: assetProfile.dataSource, @@ -1672,6 +1693,16 @@ export class PortfolioService { allocationInPercentage: 0, assetClass: AssetClass.LIQUIDITY, assetSubClass: AssetSubClass.CASH, + assetProfile: { + assetClass: AssetClass.LIQUIDITY, + assetSubClass: AssetSubClass.CASH, + countries: [], + dataSource: undefined, + holdings: [], + name: currency, + sectors: [], + symbol: currency + }, countries: [], dataSource: undefined, dateOfFirstActivity: undefined, diff --git a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts index 3cccd6efa..57643f76c 100644 --- a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts +++ b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts @@ -68,6 +68,7 @@ export class TransformDataSourceInResponseInterceptor< 'errors[*].dataSource', 'fearAndGreedIndex.CRYPTOCURRENCIES.dataSource', 'fearAndGreedIndex.STOCKS.dataSource', + 'holdings[*].assetProfile.dataSource', 'holdings[*].dataSource', 'items[*].dataSource', 'SymbolProfile.dataSource', diff --git a/libs/common/src/lib/interfaces/portfolio-position.interface.ts b/libs/common/src/lib/interfaces/portfolio-position.interface.ts index 620cc00e9..742e63d7a 100644 --- a/libs/common/src/lib/interfaces/portfolio-position.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-position.interface.ts @@ -3,19 +3,50 @@ import { Market, MarketAdvanced } from '@ghostfolio/common/types'; import { AssetClass, AssetSubClass, DataSource, Tag } from '@prisma/client'; import { Country } from './country.interface'; +import { EnhancedSymbolProfile } from './enhanced-symbol-profile.interface'; import { Holding } from './holding.interface'; import { Sector } from './sector.interface'; export interface PortfolioPosition { activitiesCount: number; allocationInPercentage: number; + + /** @deprecated */ assetClass?: AssetClass; + + /** @deprecated */ assetClassLabel?: string; + + assetProfile: Pick< + EnhancedSymbolProfile, + | 'assetClass' + | 'assetSubClass' + | 'countries' + | 'dataSource' + | 'holdings' + | 'name' + | 'sectors' + | 'symbol' + | 'url' + > & { + assetClassLabel?: string; + assetSubClassLabel?: string; + }; + + /** @deprecated */ assetSubClass?: AssetSubClass; + + /** @deprecated */ assetSubClassLabel?: string; + + /** @deprecated */ countries: Country[]; + currency: string; + + /** @deprecated */ dataSource: DataSource; + dateOfFirstActivity: Date; dividend: number; exchange?: string; @@ -23,24 +54,38 @@ export interface PortfolioPosition { grossPerformancePercent: number; grossPerformancePercentWithCurrencyEffect: number; grossPerformanceWithCurrencyEffect: number; + + /** @deprecated */ holdings: Holding[]; + investment: number; marketChange?: number; marketChangePercent?: number; marketPrice: number; markets?: { [key in Market]: number }; marketsAdvanced?: { [key in MarketAdvanced]: number }; + + /** @deprecated */ name: string; + netPerformance: number; netPerformancePercent: number; netPerformancePercentWithCurrencyEffect: number; netPerformanceWithCurrencyEffect: number; quantity: number; + + /** @deprecated */ sectors: Sector[]; + + /** @deprecated */ symbol: string; + tags?: Tag[]; type?: string; + + /** @deprecated */ url?: string; + valueInBaseCurrency?: number; valueInPercentage?: number; } diff --git a/libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts b/libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts index 4a087ad16..eae14cec6 100644 --- a/libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts +++ b/libs/common/src/lib/interfaces/responses/public-portfolio-response.interface.ts @@ -14,16 +14,31 @@ export interface PublicPortfolioResponse extends PublicPortfolioResponseV1 { [symbol: string]: Pick< PortfolioPosition, | 'allocationInPercentage' + + /** @deprecated */ | 'assetClass' + | 'assetProfile' + + /** @deprecated */ | 'countries' | 'currency' + + /** @deprecated */ | 'dataSource' | 'dateOfFirstActivity' | 'markets' + + /** @deprecated */ | 'name' | 'netPerformancePercentWithCurrencyEffect' + + /** @deprecated */ | 'sectors' + + /** @deprecated */ | 'symbol' + + /** @deprecated */ | 'url' | 'valueInBaseCurrency' | 'valueInPercentage' diff --git a/libs/ui/src/lib/mocks/holdings.ts b/libs/ui/src/lib/mocks/holdings.ts index 5ab3e89eb..f426593c1 100644 --- a/libs/ui/src/lib/mocks/holdings.ts +++ b/libs/ui/src/lib/mocks/holdings.ts @@ -6,14 +6,35 @@ export const holdings: PortfolioPosition[] = [ allocationInPercentage: 0.042990776363386086, assetClass: 'EQUITY', assetClassLabel: 'Equity', + assetProfile: { + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [ + { + code: 'US', + continent: 'North America', + name: 'United States', + weight: 1 + } + ], + dataSource: 'YAHOO', + holdings: [], + sectors: [ + { + name: 'Technology', + weight: 1 + } + ], + symbol: 'AAPL' + }, assetSubClass: 'STOCK', assetSubClassLabel: 'Stock', countries: [ { code: 'US', - weight: 1, continent: 'North America', - name: 'United States' + name: 'United States', + weight: 1 } ], currency: 'USD', @@ -49,14 +70,35 @@ export const holdings: PortfolioPosition[] = [ allocationInPercentage: 0.02377401948293552, assetClass: 'EQUITY', assetClassLabel: 'Equity', + assetProfile: { + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [ + { + code: 'DE', + continent: 'Europe', + name: 'Germany', + weight: 1 + } + ], + dataSource: 'YAHOO', + holdings: [], + sectors: [ + { + name: 'Financial Services', + weight: 1 + } + ], + symbol: 'ALV.DE' + }, assetSubClass: 'STOCK', assetSubClassLabel: 'Stock', countries: [ { code: 'DE', - weight: 1, continent: 'Europe', - name: 'Germany' + name: 'Germany', + weight: 1 } ], currency: 'EUR', @@ -92,14 +134,35 @@ export const holdings: PortfolioPosition[] = [ allocationInPercentage: 0.08038536990007467, assetClass: 'EQUITY', assetClassLabel: 'Equity', + assetProfile: { + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [ + { + code: 'US', + continent: 'North America', + name: 'United States', + weight: 1 + } + ], + dataSource: 'YAHOO', + holdings: [], + sectors: [ + { + name: 'Consumer Discretionary', + weight: 1 + } + ], + symbol: 'AMZN' + }, assetSubClass: 'STOCK', assetSubClassLabel: 'Stock', countries: [ { code: 'US', - weight: 1, continent: 'North America', - name: 'United States' + name: 'United States', + weight: 1 } ], currency: 'USD', @@ -135,6 +198,15 @@ export const holdings: PortfolioPosition[] = [ allocationInPercentage: 0.19216416482928922, assetClass: 'LIQUIDITY', assetClassLabel: 'Liquidity', + assetProfile: { + assetClass: 'LIQUIDITY', + assetSubClass: 'CASH', + countries: [], + dataSource: 'COINGECKO', + holdings: [], + sectors: [], + symbol: 'bitcoin' + }, assetSubClass: 'CRYPTOCURRENCY', assetSubClassLabel: 'Cryptocurrency', countries: [], @@ -166,14 +238,35 @@ export const holdings: PortfolioPosition[] = [ allocationInPercentage: 0.04307127421937313, assetClass: 'EQUITY', assetClassLabel: 'Equity', + assetProfile: { + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [ + { + code: 'US', + continent: 'North America', + name: 'United States', + weight: 1 + } + ], + dataSource: 'YAHOO', + holdings: [], + sectors: [ + { + name: 'Technology', + weight: 1 + } + ], + symbol: 'MSFT' + }, assetSubClass: 'STOCK', assetSubClassLabel: 'Stock', countries: [ { code: 'US', - weight: 1, continent: 'North America', - name: 'United States' + name: 'United States', + weight: 1 } ], currency: 'USD', @@ -209,14 +302,35 @@ export const holdings: PortfolioPosition[] = [ allocationInPercentage: 0.18762679306394897, assetClass: 'EQUITY', assetClassLabel: 'Equity', + assetProfile: { + assetClass: 'EQUITY', + assetSubClass: 'STOCK', + countries: [ + { + code: 'US', + continent: 'North America', + name: 'United States', + weight: 1 + } + ], + dataSource: 'YAHOO', + holdings: [], + sectors: [ + { + name: 'Consumer Discretionary', + weight: 1 + } + ], + symbol: 'TSLA' + }, assetSubClass: 'STOCK', assetSubClassLabel: 'Stock', countries: [ { code: 'US', - weight: 1, continent: 'North America', - name: 'United States' + name: 'United States', + weight: 1 } ], currency: 'USD', @@ -252,6 +366,27 @@ export const holdings: PortfolioPosition[] = [ allocationInPercentage: 0.053051250766657634, assetClass: 'EQUITY', assetClassLabel: 'Equity', + assetProfile: { + assetClass: 'EQUITY', + assetSubClass: 'ETF', + countries: [ + { + code: 'US', + continent: 'North America', + name: 'United States', + weight: 1 + } + ], + dataSource: 'YAHOO', + holdings: [], + sectors: [ + { + name: 'Equity', + weight: 1 + } + ], + symbol: 'VTI' + }, assetSubClass: 'ETF', assetSubClassLabel: 'ETF', countries: [ From 9fe38e02f36bd1b2ea8e15e7bd0de7f02629a3dd Mon Sep 17 00:00:00 2001 From: David Requeno <108202767+DavidReque@users.noreply.github.com> Date: Sat, 7 Mar 2026 02:03:31 -0600 Subject: [PATCH 033/138] Feature/enable column sorting in data provider table (#6476) * Enable column sorting * Update changelog --- CHANGELOG.md | 4 ++++ .../admin-settings.component.html | 23 ++++++++++++++++--- .../admin-settings.component.ts | 10 +++++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2b2eb1ca..9a837052a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added support for column sorting to the data providers management of the admin control panel + ### Changed - Included asset profile data in the endpoint `GET api/v1/portfolio/holdings` diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.html b/apps/client/src/app/components/admin-settings/admin-settings.component.html index 41a9992c9..76af96c4e 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.html +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -40,9 +40,21 @@ } - +
- + -} @else if (benchmarks?.length === 0) { +} @else if (benchmarks()?.length === 0) {
No data available
diff --git a/libs/ui/src/lib/benchmark/benchmark.component.ts b/libs/ui/src/lib/benchmark/benchmark.component.ts index adef1f41b..5dbc4648b 100644 --- a/libs/ui/src/lib/benchmark/benchmark.component.ts +++ b/libs/ui/src/lib/benchmark/benchmark.component.ts @@ -16,13 +16,15 @@ import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, - EventEmitter, - Input, - OnChanges, - OnDestroy, - Output, - ViewChild + DestroyRef, + computed, + effect, + inject, + input, + output, + viewChild } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { MatMenuModule } from '@angular/material/menu'; @@ -34,7 +36,6 @@ import { addIcons } from 'ionicons'; import { ellipsisHorizontal, trashOutline } from 'ionicons/icons'; import { isNumber } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Subject, takeUntil } from 'rxjs'; import { translate } from '../i18n'; import { GfTrendIndicatorComponent } from '../trend-indicator/trend-indicator.component'; @@ -61,41 +62,58 @@ import { BenchmarkDetailDialogParams } from './benchmark-detail-dialog/interface styleUrls: ['./benchmark.component.scss'], templateUrl: './benchmark.component.html' }) -export class GfBenchmarkComponent implements OnChanges, OnDestroy { - @Input() benchmarks: Benchmark[]; - @Input() deviceType: string; - @Input() hasPermissionToDeleteItem: boolean; - @Input() locale = getLocale(); - @Input() showSymbol = true; - @Input() user: User; - - @Output() itemDeleted = new EventEmitter(); - - @ViewChild(MatSort) sort: MatSort; - - public dataSource = new MatTableDataSource([]); - public displayedColumns = [ - 'name', - 'date', - 'change', - 'marketCondition', - 'actions' - ]; - public isLoading = true; - public isNumber = isNumber; - public resolveMarketCondition = resolveMarketCondition; - public translate = translate; - - private unsubscribeSubject = new Subject(); - - public constructor( - private dialog: MatDialog, - private notificationService: NotificationService, - private route: ActivatedRoute, - private router: Router - ) { +export class GfBenchmarkComponent { + public readonly benchmarks = input.required(); + public readonly deviceType = input.required(); + public readonly hasPermissionToDeleteItem = input(); + public readonly locale = input(getLocale()); + public readonly showSymbol = input(true); + public readonly user = input(); + + public readonly itemDeleted = output(); + + protected readonly sort = viewChild(MatSort); + + protected readonly dataSource = new MatTableDataSource([]); + protected readonly displayedColumns = computed(() => { + return [ + 'name', + ...(this.user()?.settings?.isExperimentalFeatures + ? ['trend50d', 'trend200d'] + : []), + 'date', + 'change', + 'marketCondition', + 'actions' + ]; + }); + protected isLoading = true; + protected readonly isNumber = isNumber; + protected readonly resolveMarketCondition = resolveMarketCondition; + protected readonly translate = translate; + + private readonly destroyRef = inject(DestroyRef); + private readonly dialog = inject(MatDialog); + private readonly notificationService = inject(NotificationService); + private readonly route = inject(ActivatedRoute); + private readonly router = inject(Router); + + public constructor() { + effect(() => { + const benchmarks = this.benchmarks(); + + if (benchmarks) { + this.dataSource.data = benchmarks; + this.dataSource.sortingDataAccessor = getLowercase; + + this.dataSource.sort = this.sort() ?? null; + + this.isLoading = false; + } + }); + this.route.queryParams - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((params) => { if ( params['benchmarkDetailDialog'] && @@ -112,30 +130,7 @@ export class GfBenchmarkComponent implements OnChanges, OnDestroy { addIcons({ ellipsisHorizontal, trashOutline }); } - public ngOnChanges() { - if (this.benchmarks) { - this.dataSource.data = this.benchmarks; - this.dataSource.sortingDataAccessor = getLowercase; - - this.dataSource.sort = this.sort; - - this.isLoading = false; - } - - if (this.user?.settings?.isExperimentalFeatures) { - this.displayedColumns = [ - 'name', - 'trend50d', - 'trend200d', - 'date', - 'change', - 'marketCondition', - 'actions' - ]; - } - } - - public onDeleteItem({ dataSource, symbol }: AssetProfileIdentifier) { + protected onDeleteItem({ dataSource, symbol }: AssetProfileIdentifier) { this.notificationService.confirm({ confirmFn: () => { this.itemDeleted.emit({ dataSource, symbol }); @@ -145,17 +140,15 @@ export class GfBenchmarkComponent implements OnChanges, OnDestroy { }); } - public onOpenBenchmarkDialog({ dataSource, symbol }: AssetProfileIdentifier) { + protected onOpenBenchmarkDialog({ + dataSource, + symbol + }: AssetProfileIdentifier) { this.router.navigate([], { queryParams: { dataSource, symbol, benchmarkDetailDialog: true } }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private openBenchmarkDetailDialog({ dataSource, symbol @@ -167,17 +160,17 @@ export class GfBenchmarkComponent implements OnChanges, OnDestroy { data: { dataSource, symbol, - colorScheme: this.user?.settings?.colorScheme, - deviceType: this.deviceType, - locale: this.locale + colorScheme: this.user()?.settings?.colorScheme, + deviceType: this.deviceType(), + locale: this.locale() }, - height: this.deviceType === 'mobile' ? '98vh' : undefined, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' + height: this.deviceType() === 'mobile' ? '98vh' : undefined, + width: this.deviceType() === 'mobile' ? '100vw' : '50rem' }); dialogRef .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.router.navigate(['.'], { relativeTo: this.route }); }); From 9310466c7ab957e4e44b818c8e11db1c22c1806b Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:11:23 +0700 Subject: [PATCH 070/138] Task/improve type safety of holdings table component (#6556) * Improve type safety --- .../holdings-table.component.html | 4 ++-- .../holdings-table.component.ts | 21 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libs/ui/src/lib/holdings-table/holdings-table.component.html b/libs/ui/src/lib/holdings-table/holdings-table.component.html index 250eff578..3bb387ae4 100644 --- a/libs/ui/src/lib/holdings-table/holdings-table.component.html +++ b/libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -193,7 +193,7 @@
+ Name @@ -102,7 +114,12 @@ - + Asset Profiles diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.ts b/apps/client/src/app/components/admin-settings/admin-settings.component.ts index 219fd2847..b8cd3409d 100644 --- a/apps/client/src/app/components/admin-settings/admin-settings.component.ts +++ b/apps/client/src/app/components/admin-settings/admin-settings.component.ts @@ -23,17 +23,20 @@ import { ChangeDetectorRef, Component, OnDestroy, - OnInit + OnInit, + ViewChild } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatMenuModule } from '@angular/material/menu'; import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatSort, MatSortModule } from '@angular/material/sort'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { ellipsisHorizontal, trashOutline } from 'ionicons/icons'; +import { get } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { catchError, filter, of, Subject, takeUntil } from 'rxjs'; @@ -52,6 +55,7 @@ import { catchError, filter, of, Subject, takeUntil } from 'rxjs'; MatCardModule, MatMenuModule, MatProgressBarModule, + MatSortModule, MatTableModule, NgxSkeletonLoaderModule, RouterModule @@ -61,6 +65,8 @@ import { catchError, filter, of, Subject, takeUntil } from 'rxjs'; templateUrl: './admin-settings.component.html' }) export class GfAdminSettingsComponent implements OnDestroy, OnInit { + @ViewChild(MatSort) sort: MatSort; + public dataSource = new MatTableDataSource(); public defaultDateFormat: string; public displayedColumns = [ @@ -166,6 +172,8 @@ export class GfAdminSettingsComponent implements OnDestroy, OnInit { }); this.dataSource = new MatTableDataSource(filteredProviders); + this.dataSource.sort = this.sort; + this.dataSource.sortingDataAccessor = get; const ghostfolioApiKey = settings[ PROPERTY_API_KEY_GHOSTFOLIO From 249cf0cdd9ee4000327b9981650a91511497a75a Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Sun, 8 Mar 2026 00:02:42 +0700 Subject: [PATCH 034/138] Bugfix/projected total amount in FIRE calculator (#6490) * Fix projected total amount * Update changelog --- CHANGELOG.md | 4 ++++ .../fire-calculator.component.ts | 23 +++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a837052a..c002057ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Reused the value component in the tag management of the admin control panel - Upgraded `jsonpath` from version `1.1.1` to `1.2.1` +### Fixed + +- Fixed an issue in the _FIRE_ calculator to correctly calculate the projected total amount + ## 2.247.0 - 2026-03-04 ### Changed diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts index 8b472fc47..7a62564c6 100644 --- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts +++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts @@ -16,8 +16,8 @@ import { Input, OnChanges, OnDestroy, - ViewChild, - output + output, + viewChild } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { @@ -55,7 +55,7 @@ import { startOfMonth, sub } from 'date-fns'; -import { isNil, isNumber } from 'lodash'; +import { isNumber } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { debounceTime } from 'rxjs'; @@ -90,8 +90,6 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy { @Input() retirementDate: Date; @Input() savingsRate = 0; - @ViewChild('chartCanvas') chartCanvas: ElementRef; - public calculatorForm = this.formBuilder.group({ annualInterestRate: new FormControl(null), paymentPerPeriod: new FormControl(null), @@ -99,23 +97,30 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy { projectedTotalAmount: new FormControl(null), retirementDate: new FormControl(null) }); + public chart: Chart<'bar'>; public isLoading = true; public minDate = addDays(new Date(), 1); public periodsToRetire = 0; protected readonly annualInterestRateChanged = output(); + protected readonly calculationCompleted = output(); + protected readonly projectedTotalAmountChanged = output(); protected readonly retirementDateChanged = output(); protected readonly savingsRateChanged = output(); private readonly CONTRIBUTION_PERIOD = 12; + private readonly DEFAULT_RETIREMENT_DATE = startOfMonth( addYears(new Date(), 10) ); + private readonly chartCanvas = + viewChild.required>('chartCanvas'); + public constructor( private changeDetectorRef: ChangeDetectorRef, private fireCalculatorService: FireCalculatorService, @@ -272,7 +277,7 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy { const chartData = this.getChartData(); - if (this.chartCanvas) { + if (this.chartCanvas()) { if (this.chart) { this.chart.data.labels = chartData.labels; @@ -282,7 +287,7 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy { this.chart.update(); } else { - this.chart = new Chart<'bar'>(this.chartCanvas.nativeElement, { + this.chart = new Chart<'bar'>(this.chartCanvas().nativeElement, { data: chartData, options: { plugins: { @@ -303,7 +308,7 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy { }).format(totalAmount)}`; }, label: (context) => { - let label = context.dataset.label || ''; + let label = context.dataset.label ?? ''; if (label) { label += ': '; @@ -473,7 +478,7 @@ export class GfFireCalculatorComponent implements OnChanges, OnDestroy { 'projectedTotalAmount' )?.value; - if (!isNil(projectedTotalAmount)) { + if (projectedTotalAmount) { return projectedTotalAmount; } From 4a832f12ca46482d73892bb3684979f26efa7837 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 7 Mar 2026 18:19:25 +0100 Subject: [PATCH 035/138] Task/deprecate order endpoints in favor of activities endpoints (#6446) * Deprecate order endpoints in favor of activities endpoints * Update changelog --- CHANGELOG.md | 1 + .../activities.controller.ts} | 55 ++++++++------ .../activities.module.ts} | 12 +-- .../activities.service.ts} | 73 ++++++++++--------- apps/api/src/app/admin/admin.module.ts | 4 +- apps/api/src/app/admin/admin.service.ts | 8 +- apps/api/src/app/app.module.ts | 4 +- apps/api/src/app/endpoints/ai/ai.module.ts | 4 +- .../endpoints/benchmarks/benchmarks.module.ts | 4 +- .../app/endpoints/public/public.controller.ts | 6 +- .../src/app/endpoints/public/public.module.ts | 4 +- apps/api/src/app/export/export.module.ts | 4 +- apps/api/src/app/export/export.service.ts | 6 +- apps/api/src/app/import/import.module.ts | 4 +- apps/api/src/app/import/import.service.ts | 10 +-- .../roai/portfolio-calculator-cash.spec.ts | 17 ++--- .../portfolio/current-rate.service.spec.ts | 2 +- .../src/app/portfolio/current-rate.service.ts | 13 ++-- .../src/app/portfolio/portfolio.controller.ts | 6 +- .../api/src/app/portfolio/portfolio.module.ts | 4 +- .../src/app/portfolio/portfolio.service.ts | 21 ++++-- apps/api/src/app/user/user.module.ts | 4 +- apps/api/src/app/user/user.service.ts | 6 +- .../events/asset-profile-changed.listener.ts | 8 +- apps/api/src/events/events.module.ts | 4 +- .../portfolio-snapshot.module.ts | 4 +- .../portfolio-snapshot.processor.ts | 6 +- .../holding-detail-dialog.component.ts | 2 +- .../activities/activities-page.component.ts | 4 +- libs/ui/src/lib/services/data.service.ts | 40 +++++----- 30 files changed, 180 insertions(+), 160 deletions(-) rename apps/api/src/app/{order/order.controller.ts => activities/activities.controller.ts} (87%) rename apps/api/src/app/{order/order.module.ts => activities/activities.module.ts} (86%) rename apps/api/src/app/{order/order.service.ts => activities/activities.service.ts} (93%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c002057ee..1279ef62f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Included asset profile data in the holdings of the public page - Reused the value component in the platform management of the admin control panel - Reused the value component in the tag management of the admin control panel +- Deprecated the `api/v1/order` endpoints in favor of the `api/v1/activities` endpoints - Upgraded `jsonpath` from version `1.1.1` to `1.2.1` ### Fixed diff --git a/apps/api/src/app/order/order.controller.ts b/apps/api/src/app/activities/activities.controller.ts similarity index 87% rename from apps/api/src/app/order/order.controller.ts rename to apps/api/src/app/activities/activities.controller.ts index c7021809e..da7aed21d 100644 --- a/apps/api/src/app/order/order.controller.ts +++ b/apps/api/src/app/activities/activities.controller.ts @@ -37,20 +37,24 @@ import { } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; -import { Order as OrderModel, Prisma } from '@prisma/client'; +import { Order, Prisma } from '@prisma/client'; import { parseISO } from 'date-fns'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; -import { OrderService } from './order.service'; +import { ActivitiesService } from './activities.service'; -@Controller('order') -export class OrderController { +@Controller([ + 'activities', + /** @deprecated */ + 'order' +]) +export class ActivitiesController { public constructor( + private readonly activitiesService: ActivitiesService, private readonly apiService: ApiService, private readonly dataProviderService: DataProviderService, private readonly dataGatheringService: DataGatheringService, private readonly impersonationService: ImpersonationService, - private readonly orderService: OrderService, @Inject(REQUEST) private readonly request: RequestWithUser ) {} @@ -58,7 +62,7 @@ export class OrderController { @HasPermission(permissions.deleteOrder) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(TransformDataSourceInRequestInterceptor) - public async deleteOrders( + public async deleteActivities( @Query('accounts') filterByAccounts?: string, @Query('assetClasses') filterByAssetClasses?: string, @Query('dataSource') filterByDataSource?: string, @@ -73,7 +77,7 @@ export class OrderController { filterByTags }); - return this.orderService.deleteOrders({ + return this.activitiesService.deleteActivities({ filters, userId: this.request.user.id }); @@ -82,20 +86,20 @@ export class OrderController { @Delete(':id') @HasPermission(permissions.deleteOrder) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async deleteOrder(@Param('id') id: string): Promise { - const order = await this.orderService.order({ + public async deleteActivity(@Param('id') id: string): Promise { + const activity = await this.activitiesService.order({ id, userId: this.request.user.id }); - if (!order) { + if (!activity) { throw new HttpException( getReasonPhrase(StatusCodes.FORBIDDEN), StatusCodes.FORBIDDEN ); } - return this.orderService.deleteOrder({ + return this.activitiesService.deleteActivity({ id }); } @@ -105,7 +109,7 @@ export class OrderController { @UseInterceptors(RedactValuesInResponseInterceptor) @UseInterceptors(TransformDataSourceInRequestInterceptor) @UseInterceptors(TransformDataSourceInResponseInterceptor) - public async getAllOrders( + public async getAllActivities( @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Query('accounts') filterByAccounts?: string, @Query('assetClasses') filterByAssetClasses?: string, @@ -137,7 +141,7 @@ export class OrderController { await this.impersonationService.validateImpersonationId(impersonationId); const userCurrency = this.request.user.settings.settings.baseCurrency; - const { activities, count } = await this.orderService.getOrders({ + const { activities, count } = await this.activitiesService.getActivities({ endDate, filters, sortColumn, @@ -158,7 +162,7 @@ export class OrderController { @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(RedactValuesInResponseInterceptor) @UseInterceptors(TransformDataSourceInResponseInterceptor) - public async getOrderById( + public async getActivityById( @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Param('id') id: string ): Promise { @@ -166,7 +170,7 @@ export class OrderController { await this.impersonationService.validateImpersonationId(impersonationId); const userCurrency = this.request.user.settings.settings.baseCurrency; - const { activities } = await this.orderService.getOrders({ + const { activities } = await this.activitiesService.getActivities({ userCurrency, includeDrafts: true, userId: impersonationUserId || this.request.user.id, @@ -191,7 +195,7 @@ export class OrderController { @Post() @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(TransformDataSourceInRequestInterceptor) - public async createOrder(@Body() data: CreateOrderDto): Promise { + public async createActivity(@Body() data: CreateOrderDto): Promise { try { await this.dataProviderService.validateActivities({ activitiesDto: [ @@ -227,7 +231,7 @@ export class OrderController { delete data.dataSource; - const order = await this.orderService.createOrder({ + const activity = await this.activitiesService.createActivity({ ...data, date: parseISO(data.date), SymbolProfile: { @@ -252,14 +256,14 @@ export class OrderController { userId: this.request.user.id }); - if (dataSource && !order.isDraft) { + if (dataSource && !activity.isDraft) { // Gather symbol data in the background, if data source is set // (not MANUAL) and not draft this.dataGatheringService.gatherSymbols({ dataGatheringItems: [ { dataSource, - date: order.date, + date: activity.date, symbol: data.symbol } ], @@ -267,19 +271,22 @@ export class OrderController { }); } - return order; + return activity; } @HasPermission(permissions.updateOrder) @Put(':id') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(TransformDataSourceInRequestInterceptor) - public async update(@Param('id') id: string, @Body() data: UpdateOrderDto) { - const originalOrder = await this.orderService.order({ + public async updateActivity( + @Param('id') id: string, + @Body() data: UpdateOrderDto + ) { + const originalActivity = await this.activitiesService.order({ id }); - if (!originalOrder || originalOrder.userId !== this.request.user.id) { + if (!originalActivity || originalActivity.userId !== this.request.user.id) { throw new HttpException( getReasonPhrase(StatusCodes.FORBIDDEN), StatusCodes.FORBIDDEN @@ -302,7 +309,7 @@ export class OrderController { delete data.dataSource; - return this.orderService.updateOrder({ + return this.activitiesService.updateActivity({ data: { ...data, date, diff --git a/apps/api/src/app/order/order.module.ts b/apps/api/src/app/activities/activities.module.ts similarity index 86% rename from apps/api/src/app/order/order.module.ts rename to apps/api/src/app/activities/activities.module.ts index 9bc837aa6..7476ad66a 100644 --- a/apps/api/src/app/order/order.module.ts +++ b/apps/api/src/app/activities/activities.module.ts @@ -15,12 +15,12 @@ import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/sym import { Module } from '@nestjs/common'; -import { OrderController } from './order.controller'; -import { OrderService } from './order.service'; +import { ActivitiesController } from './activities.controller'; +import { ActivitiesService } from './activities.service'; @Module({ - controllers: [OrderController], - exports: [OrderService], + controllers: [ActivitiesController], + exports: [ActivitiesService], imports: [ ApiModule, CacheModule, @@ -35,6 +35,6 @@ import { OrderService } from './order.service'; TransformDataSourceInRequestModule, TransformDataSourceInResponseModule ], - providers: [AccountBalanceService, AccountService, OrderService] + providers: [AccountBalanceService, AccountService, ActivitiesService] }) -export class OrderModule {} +export class ActivitiesModule {} diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/activities/activities.service.ts similarity index 93% rename from apps/api/src/app/order/order.service.ts rename to apps/api/src/app/activities/activities.service.ts index 9a4f1e46b..89b9468f8 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/activities/activities.service.ts @@ -44,7 +44,7 @@ import { groupBy, uniqBy } from 'lodash'; import { randomUUID } from 'node:crypto'; @Injectable() -export class OrderService { +export class ActivitiesService { public constructor( private readonly accountBalanceService: AccountBalanceService, private readonly accountService: AccountService, @@ -62,7 +62,7 @@ export class OrderService { tags, userId }: { tags: Tag[]; userId: string } & AssetProfileIdentifier) { - const orders = await this.prismaService.order.findMany({ + const activities = await this.prismaService.order.findMany({ where: { userId, SymbolProfile: { @@ -73,7 +73,7 @@ export class OrderService { }); await Promise.all( - orders.map(({ id }) => + activities.map(({ id }) => this.prismaService.order.update({ data: { tags: { @@ -96,7 +96,7 @@ export class OrderService { ); } - public async createOrder( + public async createActivity( data: Prisma.OrderCreateInput & { accountId?: string; assetClass?: AssetClass; @@ -201,7 +201,7 @@ export class OrderService { ? false : isAfter(data.date as Date, endOfToday()); - const order = await this.prismaService.order.create({ + const activity = await this.prismaService.order.create({ data: { ...orderData, account, @@ -235,56 +235,56 @@ export class OrderService { this.eventEmitter.emit( AssetProfileChangedEvent.getName(), new AssetProfileChangedEvent({ - currency: order.SymbolProfile.currency, - dataSource: order.SymbolProfile.dataSource, - symbol: order.SymbolProfile.symbol + currency: activity.SymbolProfile.currency, + dataSource: activity.SymbolProfile.dataSource, + symbol: activity.SymbolProfile.symbol }) ); this.eventEmitter.emit( PortfolioChangedEvent.getName(), new PortfolioChangedEvent({ - userId: order.userId + userId: activity.userId }) ); - return order; + return activity; } - public async deleteOrder( + public async deleteActivity( where: Prisma.OrderWhereUniqueInput ): Promise { - const order = await this.prismaService.order.delete({ + const activity = await this.prismaService.order.delete({ where }); const [symbolProfile] = await this.symbolProfileService.getSymbolProfilesByIds([ - order.symbolProfileId + activity.symbolProfileId ]); if (symbolProfile.activitiesCount === 0) { - await this.symbolProfileService.deleteById(order.symbolProfileId); + await this.symbolProfileService.deleteById(activity.symbolProfileId); } this.eventEmitter.emit( PortfolioChangedEvent.getName(), new PortfolioChangedEvent({ - userId: order.userId + userId: activity.userId }) ); - return order; + return activity; } - public async deleteOrders({ + public async deleteActivities({ filters, userId }: { filters?: Filter[]; userId: string; }): Promise { - const { activities } = await this.getOrders({ + const { activities } = await this.getActivities({ filters, userId, includeDrafts: true, @@ -324,7 +324,7 @@ export class OrderService { } /** - * Generates synthetic orders for cash holdings based on account balance history. + * Generates synthetic activities for cash holdings based on account balance history. * Treat currencies as assets with a fixed unit price of 1.0 (in their own currency) to allow * performance tracking based on exchange rate fluctuations. * @@ -334,7 +334,7 @@ export class OrderService { * @param userId - The ID of the user. * @returns A response containing the list of synthetic cash activities. */ - public async getCashOrders({ + public async getCashActivities({ cashDetails, filters = [], userCurrency, @@ -448,7 +448,10 @@ export class OrderService { }; } - public async getLatestOrder({ dataSource, symbol }: AssetProfileIdentifier) { + public async getLatestActivity({ + dataSource, + symbol + }: AssetProfileIdentifier) { return this.prismaService.order.findFirst({ orderBy: { date: 'desc' @@ -459,7 +462,7 @@ export class OrderService { }); } - public async getOrders({ + public async getActivities({ endDate, filters, includeDrafts = false, @@ -742,17 +745,17 @@ export class OrderService { } /** - * Retrieves all orders required for the portfolio calculator, including both standard asset orders - * and optional synthetic orders representing cash activities. + * Retrieves all activities required for the portfolio calculator, including both standard asset activities + * and optional synthetic activities representing cash activities. */ @LogPerformance - public async getOrdersForPortfolioCalculator({ + public async getActivitiesForPortfolioCalculator({ filters, userCurrency, userId, withCash = false }: { - /** Optional filters to apply to the orders. */ + /** Optional filters to apply to the activities. */ filters?: Filter[]; /** The base currency of the user. */ userCurrency: string; @@ -761,7 +764,7 @@ export class OrderService { /** Whether to include cash activities in the result. */ withCash?: boolean; }) { - const orders = await this.getOrders({ + const activities = await this.getActivities({ filters, userCurrency, userId, @@ -775,18 +778,18 @@ export class OrderService { currency: userCurrency }); - const cashOrders = await this.getCashOrders({ + const cashActivities = await this.getCashActivities({ cashDetails, filters, userCurrency, userId }); - orders.activities.push(...cashOrders.activities); - orders.count += cashOrders.count; + activities.activities.push(...cashActivities.activities); + activities.count += cashActivities.count; } - return orders; + return activities; } public async getStatisticsByCurrency( @@ -817,7 +820,7 @@ export class OrderService { }); } - public async updateOrder({ + public async updateActivity({ data, where }: { @@ -882,7 +885,7 @@ export class OrderService { data: { tags: { set: [] } } }); - const order = await this.prismaService.order.update({ + const activity = await this.prismaService.order.update({ where, data: { ...data, @@ -896,11 +899,11 @@ export class OrderService { this.eventEmitter.emit( PortfolioChangedEvent.getName(), new PortfolioChangedEvent({ - userId: order.userId + userId: activity.userId }) ); - return order; + return activity; } private async orders(params: { diff --git a/apps/api/src/app/admin/admin.module.ts b/apps/api/src/app/admin/admin.module.ts index 598b68f17..960a36629 100644 --- a/apps/api/src/app/admin/admin.module.ts +++ b/apps/api/src/app/admin/admin.module.ts @@ -1,4 +1,4 @@ -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module'; @@ -20,6 +20,7 @@ import { QueueModule } from './queue/queue.module'; @Module({ imports: [ + ActivitiesModule, ApiModule, BenchmarkModule, ConfigurationModule, @@ -28,7 +29,6 @@ import { QueueModule } from './queue/queue.module'; DemoModule, ExchangeRateDataModule, MarketDataModule, - OrderModule, PrismaModule, PropertyModule, QueueModule, diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index 1f8745cd1..d2bf6e411 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -1,4 +1,4 @@ -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { environment } from '@ghostfolio/api/environments/environment'; import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; @@ -55,12 +55,12 @@ import { groupBy } from 'lodash'; @Injectable() export class AdminService { public constructor( + private readonly activitiesService: ActivitiesService, private readonly benchmarkService: BenchmarkService, private readonly configurationService: ConfigurationService, private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly marketDataService: MarketDataService, - private readonly orderService: OrderService, private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, private readonly symbolProfileService: SymbolProfileService @@ -475,7 +475,7 @@ export class AdminService { if (isCurrencyAssetProfile) { currency = getCurrencyFromSymbol(symbol); ({ activitiesCount, dateOfFirstActivity } = - await this.orderService.getStatisticsByCurrency(currency)); + await this.activitiesService.getStatisticsByCurrency(currency)); } const [[assetProfile], marketData] = await Promise.all([ @@ -798,7 +798,7 @@ export class AdminService { if (isCurrency(getCurrencyFromSymbol(symbol))) { currency = getCurrencyFromSymbol(symbol); ({ activitiesCount, dateOfFirstActivity } = - await this.orderService.getStatisticsByCurrency(currency)); + await this.activitiesService.getStatisticsByCurrency(currency)); } const lastMarketPrice = lastMarketPriceMap.get( diff --git a/apps/api/src/app/app.module.ts b/apps/api/src/app/app.module.ts index 89f52e1ea..4b790d0db 100644 --- a/apps/api/src/app/app.module.ts +++ b/apps/api/src/app/app.module.ts @@ -25,6 +25,7 @@ import { join } from 'node:path'; import { AccessModule } from './access/access.module'; import { AccountModule } from './account/account.module'; +import { ActivitiesModule } from './activities/activities.module'; import { AdminModule } from './admin/admin.module'; import { AppController } from './app.controller'; import { AssetModule } from './asset/asset.module'; @@ -48,7 +49,6 @@ import { HealthModule } from './health/health.module'; import { ImportModule } from './import/import.module'; import { InfoModule } from './info/info.module'; import { LogoModule } from './logo/logo.module'; -import { OrderModule } from './order/order.module'; import { PlatformModule } from './platform/platform.module'; import { PortfolioModule } from './portfolio/portfolio.module'; import { RedisCacheModule } from './redis-cache/redis-cache.module'; @@ -62,6 +62,7 @@ import { UserModule } from './user/user.module'; AdminModule, AccessModule, AccountModule, + ActivitiesModule, AiModule, ApiKeysModule, AssetModule, @@ -94,7 +95,6 @@ import { UserModule } from './user/user.module'; InfoModule, LogoModule, MarketDataModule, - OrderModule, PlatformModule, PlatformsModule, PortfolioModule, diff --git a/apps/api/src/app/endpoints/ai/ai.module.ts b/apps/api/src/app/endpoints/ai/ai.module.ts index 8a441fde7..eab4ecf8b 100644 --- a/apps/api/src/app/endpoints/ai/ai.module.ts +++ b/apps/api/src/app/endpoints/ai/ai.module.ts @@ -1,6 +1,6 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service'; -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; @@ -29,6 +29,7 @@ import { AiService } from './ai.service'; @Module({ controllers: [AiController], imports: [ + ActivitiesModule, ApiModule, BenchmarkModule, ConfigurationModule, @@ -37,7 +38,6 @@ import { AiService } from './ai.service'; I18nModule, ImpersonationModule, MarketDataModule, - OrderModule, PortfolioSnapshotQueueModule, PrismaModule, PropertyModule, diff --git a/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts index 8bdf79035..2bcd6177d 100644 --- a/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts +++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.module.ts @@ -1,6 +1,6 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service'; -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; @@ -32,6 +32,7 @@ import { BenchmarksService } from './benchmarks.service'; @Module({ controllers: [BenchmarksController], imports: [ + ActivitiesModule, ApiModule, ConfigurationModule, DataProviderModule, @@ -39,7 +40,6 @@ import { BenchmarksService } from './benchmarks.service'; I18nModule, ImpersonationModule, MarketDataModule, - OrderModule, PortfolioSnapshotQueueModule, PrismaModule, PropertyModule, diff --git a/apps/api/src/app/endpoints/public/public.controller.ts b/apps/api/src/app/endpoints/public/public.controller.ts index a1b2b7864..b97640cab 100644 --- a/apps/api/src/app/endpoints/public/public.controller.ts +++ b/apps/api/src/app/endpoints/public/public.controller.ts @@ -1,5 +1,5 @@ import { AccessService } from '@ghostfolio/api/app/access/access.service'; -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; import { UserService } from '@ghostfolio/api/app/user/user.service'; import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor'; @@ -28,9 +28,9 @@ import { StatusCodes, getReasonPhrase } from 'http-status-codes'; export class PublicController { public constructor( private readonly accessService: AccessService, + private readonly activitiesService: ActivitiesService, private readonly configurationService: ConfigurationService, private readonly exchangeRateDataService: ExchangeRateDataService, - private readonly orderService: OrderService, private readonly portfolioService: PortfolioService, @Inject(REQUEST) private readonly request: RequestWithUser, private readonly userService: UserService @@ -81,7 +81,7 @@ export class PublicController { }) ]); - const { activities } = await this.orderService.getOrders({ + const { activities } = await this.activitiesService.getActivities({ sortColumn: 'date', sortDirection: 'desc', take: 10, diff --git a/apps/api/src/app/endpoints/public/public.module.ts b/apps/api/src/app/endpoints/public/public.module.ts index 19e281dde..e8395228f 100644 --- a/apps/api/src/app/endpoints/public/public.module.ts +++ b/apps/api/src/app/endpoints/public/public.module.ts @@ -1,7 +1,7 @@ import { AccessModule } from '@ghostfolio/api/app/access/access.module'; import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service'; -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; @@ -27,13 +27,13 @@ import { PublicController } from './public.controller'; controllers: [PublicController], imports: [ AccessModule, + ActivitiesModule, BenchmarkModule, DataProviderModule, ExchangeRateDataModule, I18nModule, ImpersonationModule, MarketDataModule, - OrderModule, PortfolioSnapshotQueueModule, PrismaModule, RedisCacheModule, diff --git a/apps/api/src/app/export/export.module.ts b/apps/api/src/app/export/export.module.ts index 4f40cc417..6158fe043 100644 --- a/apps/api/src/app/export/export.module.ts +++ b/apps/api/src/app/export/export.module.ts @@ -1,5 +1,5 @@ import { AccountModule } from '@ghostfolio/api/app/account/account.module'; -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; @@ -14,9 +14,9 @@ import { ExportService } from './export.service'; controllers: [ExportController], imports: [ AccountModule, + ActivitiesModule, ApiModule, MarketDataModule, - OrderModule, TagModule, TransformDataSourceInRequestModule ], diff --git a/apps/api/src/app/export/export.service.ts b/apps/api/src/app/export/export.service.ts index 55f8d7dc9..4f2fb3309 100644 --- a/apps/api/src/app/export/export.service.ts +++ b/apps/api/src/app/export/export.service.ts @@ -1,5 +1,5 @@ import { AccountService } from '@ghostfolio/api/app/account/account.service'; -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { environment } from '@ghostfolio/api/environments/environment'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { TagService } from '@ghostfolio/api/services/tag/tag.service'; @@ -17,8 +17,8 @@ import { groupBy, uniqBy } from 'lodash'; export class ExportService { public constructor( private readonly accountService: AccountService, + private readonly activitiesService: ActivitiesService, private readonly marketDataService: MarketDataService, - private readonly orderService: OrderService, private readonly tagService: TagService ) {} @@ -38,7 +38,7 @@ export class ExportService { }); const platformsMap: { [platformId: string]: Platform } = {}; - let { activities } = await this.orderService.getOrders({ + let { activities } = await this.activitiesService.getActivities({ filters, userId, includeDrafts: true, diff --git a/apps/api/src/app/import/import.module.ts b/apps/api/src/app/import/import.module.ts index a4a13f941..ca9b5667b 100644 --- a/apps/api/src/app/import/import.module.ts +++ b/apps/api/src/app/import/import.module.ts @@ -1,6 +1,6 @@ import { AccountModule } from '@ghostfolio/api/app/account/account.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { CacheModule } from '@ghostfolio/api/app/cache/cache.module'; -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; import { PlatformModule } from '@ghostfolio/api/app/platform/platform.module'; import { PortfolioModule } from '@ghostfolio/api/app/portfolio/portfolio.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; @@ -25,6 +25,7 @@ import { ImportService } from './import.service'; controllers: [ImportController], imports: [ AccountModule, + ActivitiesModule, ApiModule, CacheModule, ConfigurationModule, @@ -32,7 +33,6 @@ import { ImportService } from './import.service'; DataProviderModule, ExchangeRateDataModule, MarketDataModule, - OrderModule, PlatformModule, PortfolioModule, PrismaModule, diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index 497b8a7e9..b82f763a0 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -1,5 +1,5 @@ import { AccountService } from '@ghostfolio/api/app/account/account.service'; -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { PlatformService } from '@ghostfolio/api/app/platform/platform.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; import { ApiService } from '@ghostfolio/api/services/api/api.service'; @@ -44,12 +44,12 @@ import { ImportDataDto } from './import-data.dto'; export class ImportService { public constructor( private readonly accountService: AccountService, + private readonly activitiesService: ActivitiesService, private readonly apiService: ApiService, private readonly dataGatheringService: DataGatheringService, private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly marketDataService: MarketDataService, - private readonly orderService: OrderService, private readonly platformService: PlatformService, private readonly portfolioService: PortfolioService, private readonly symbolProfileService: SymbolProfileService, @@ -91,7 +91,7 @@ export class ImportService { userId, withExcludedAccounts: true }), - this.orderService.getOrders({ + this.activitiesService.getActivities({ filters, userCurrency, userId, @@ -548,7 +548,7 @@ export class ImportService { continue; } - order = await this.orderService.createOrder({ + order = await this.activitiesService.createActivity({ comment, currency, date, @@ -645,7 +645,7 @@ export class ImportService { userId: string; }): Promise[]> { const { activities: existingActivities } = - await this.orderService.getOrders({ + await this.activitiesService.getActivities({ userCurrency, userId, includeDrafts: true, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts index a53ebcf05..217a67c49 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts @@ -1,6 +1,6 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service'; -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; @@ -62,11 +62,11 @@ jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { describe('PortfolioCalculator', () => { let accountBalanceService: AccountBalanceService; let accountService: AccountService; + let activitiesService: ActivitiesService; let configurationService: ConfigurationService; let currentRateService: CurrentRateService; let dataProviderService: DataProviderService; let exchangeRateDataService: ExchangeRateDataService; - let orderService: OrderService; let portfolioCalculatorFactory: PortfolioCalculatorFactory; let portfolioSnapshotService: PortfolioSnapshotService; let redisCacheService: RedisCacheService; @@ -106,13 +106,13 @@ describe('PortfolioCalculator', () => { ); currentRateService = new CurrentRateService( - dataProviderService, null, + dataProviderService, null, null ); - orderService = new OrderService( + activitiesService = new ActivitiesService( accountBalanceService, accountService, null, @@ -183,18 +183,17 @@ describe('PortfolioCalculator', () => { .spyOn(dataProviderService, 'getDataSourceForExchangeRates') .mockReturnValue(DataSource.YAHOO); - jest.spyOn(orderService, 'getOrders').mockResolvedValue({ + jest.spyOn(activitiesService, 'getActivities').mockResolvedValue({ activities: [], count: 0 }); - const { activities } = await orderService.getOrdersForPortfolioCalculator( - { + const { activities } = + await activitiesService.getActivitiesForPortfolioCalculator({ userCurrency: 'CHF', userId: userDummyData.id, withCash: true - } - ); + }); jest.spyOn(currentRateService, 'getValues').mockResolvedValue({ dataProviderInfos: [], diff --git a/apps/api/src/app/portfolio/current-rate.service.spec.ts b/apps/api/src/app/portfolio/current-rate.service.spec.ts index d8b7482e7..5f2358679 100644 --- a/apps/api/src/app/portfolio/current-rate.service.spec.ts +++ b/apps/api/src/app/portfolio/current-rate.service.spec.ts @@ -114,9 +114,9 @@ describe('CurrentRateService', () => { marketDataService = new MarketDataService(null); currentRateService = new CurrentRateService( + null, dataProviderService, marketDataService, - null, null ); }); diff --git a/apps/api/src/app/portfolio/current-rate.service.ts b/apps/api/src/app/portfolio/current-rate.service.ts index 5d39a54bb..b454b01cd 100644 --- a/apps/api/src/app/portfolio/current-rate.service.ts +++ b/apps/api/src/app/portfolio/current-rate.service.ts @@ -1,4 +1,4 @@ -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { LogPerformance } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; @@ -24,9 +24,9 @@ export class CurrentRateService { private static readonly MARKET_DATA_PAGE_SIZE = 50000; public constructor( + private readonly activitiesService: ActivitiesService, private readonly dataProviderService: DataProviderService, private readonly marketDataService: MarketDataService, - private readonly orderService: OrderService, @Inject(REQUEST) private readonly request: RequestWithUser ) {} @@ -129,10 +129,11 @@ export class CurrentRateService { if (!value) { // Fallback to unit price of latest activity - const latestActivity = await this.orderService.getLatestOrder({ - dataSource, - symbol - }); + const latestActivity = + await this.activitiesService.getLatestActivity({ + dataSource, + symbol + }); value = { dataSource, diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 67b5229c1..80d7f9acc 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -1,4 +1,4 @@ -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { @@ -63,10 +63,10 @@ import { UpdateHoldingTagsDto } from './update-holding-tags.dto'; @Controller('portfolio') export class PortfolioController { public constructor( + private readonly activitiesService: ActivitiesService, private readonly apiService: ApiService, private readonly configurationService: ConfigurationService, private readonly impersonationService: ImpersonationService, - private readonly orderService: OrderService, private readonly portfolioService: PortfolioService, @Inject(REQUEST) private readonly request: RequestWithUser ) {} @@ -322,7 +322,7 @@ export class PortfolioController { const { endDate, startDate } = getIntervalFromDateRange(dateRange); - const { activities } = await this.orderService.getOrders({ + const { activities } = await this.activitiesService.getActivities({ endDate, filters, startDate, diff --git a/apps/api/src/app/portfolio/portfolio.module.ts b/apps/api/src/app/portfolio/portfolio.module.ts index 6dd5811a3..65a9b71aa 100644 --- a/apps/api/src/app/portfolio/portfolio.module.ts +++ b/apps/api/src/app/portfolio/portfolio.module.ts @@ -1,7 +1,7 @@ import { AccessModule } from '@ghostfolio/api/app/access/access.module'; import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service'; -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { PerformanceLoggingModule } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.module'; @@ -34,6 +34,7 @@ import { RulesService } from './rules.service'; exports: [PortfolioService], imports: [ AccessModule, + ActivitiesModule, ApiModule, BenchmarkModule, ConfigurationModule, @@ -43,7 +44,6 @@ import { RulesService } from './rules.service'; I18nModule, ImpersonationModule, MarketDataModule, - OrderModule, PerformanceLoggingModule, PortfolioSnapshotQueueModule, PrismaModule, diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 1bfad8395..ed72260ca 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1,7 +1,7 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { CashDetails } from '@ghostfolio/api/app/account/interfaces/cash-details.interface'; -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { UserService } from '@ghostfolio/api/app/user/user.service'; import { getFactor } from '@ghostfolio/api/helper/portfolio.helper'; import { AccountClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/account-cluster-risk/current-investment'; @@ -105,13 +105,13 @@ export class PortfolioService { public constructor( private readonly accountBalanceService: AccountBalanceService, private readonly accountService: AccountService, + private readonly activitiesService: ActivitiesService, private readonly benchmarkService: BenchmarkService, private readonly calculatorFactory: PortfolioCalculatorFactory, private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly i18nService: I18nService, private readonly impersonationService: ImpersonationService, - private readonly orderService: OrderService, @Inject(REQUEST) private readonly request: RequestWithUser, private readonly rulesService: RulesService, private readonly symbolProfileService: SymbolProfileService, @@ -406,7 +406,7 @@ export class PortfolioService { const { endDate, startDate } = getIntervalFromDateRange(dateRange); const { activities } = - await this.orderService.getOrdersForPortfolioCalculator({ + await this.activitiesService.getActivitiesForPortfolioCalculator({ filters, userCurrency, userId @@ -490,7 +490,7 @@ export class PortfolioService { ); const { activities } = - await this.orderService.getOrdersForPortfolioCalculator({ + await this.activitiesService.getActivitiesForPortfolioCalculator({ filters, userCurrency, userId @@ -779,7 +779,7 @@ export class PortfolioService { const userCurrency = this.getUserCurrency(user); const { activities } = - await this.orderService.getOrdersForPortfolioCalculator({ + await this.activitiesService.getActivitiesForPortfolioCalculator({ userCurrency, userId }); @@ -1009,7 +1009,7 @@ export class PortfolioService { userId, userCurrency }), - this.orderService.getOrdersForPortfolioCalculator({ + this.activitiesService.getActivitiesForPortfolioCalculator({ filters, userCurrency, userId @@ -1370,7 +1370,12 @@ export class PortfolioService { }) { userId = await this.getUserId(impersonationId, userId); - await this.orderService.assignTags({ dataSource, symbol, tags, userId }); + await this.activitiesService.assignTags({ + dataSource, + symbol, + tags, + userId + }); } private getAggregatedMarkets(holdings: Record): { @@ -1872,7 +1877,7 @@ export class PortfolioService { userId = await this.getUserId(impersonationId, userId); const user = await this.userService.user({ id: userId }); - const { activities } = await this.orderService.getOrders({ + const { activities } = await this.activitiesService.getActivities({ userCurrency, userId, withExcludedAccountsAndActivities: true diff --git a/apps/api/src/app/user/user.module.ts b/apps/api/src/app/user/user.module.ts index 7ca68d275..3f4e898fc 100644 --- a/apps/api/src/app/user/user.module.ts +++ b/apps/api/src/app/user/user.module.ts @@ -1,4 +1,4 @@ -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module'; import { RedactValuesInResponseModule } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; @@ -18,6 +18,7 @@ import { UserService } from './user.service'; controllers: [UserController], exports: [UserService], imports: [ + ActivitiesModule, ConfigurationModule, I18nModule, ImpersonationModule, @@ -25,7 +26,6 @@ import { UserService } from './user.service'; secret: process.env.JWT_SECRET_KEY, signOptions: { expiresIn: '30 days' } }), - OrderModule, PrismaModule, PropertyModule, RedactValuesInResponseModule, diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 97ab8a59f..5a339c090 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -1,4 +1,4 @@ -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { SubscriptionService } from '@ghostfolio/api/app/subscription/subscription.service'; import { environment } from '@ghostfolio/api/environments/environment'; import { PortfolioChangedEvent } from '@ghostfolio/api/events/portfolio-changed.event'; @@ -55,10 +55,10 @@ import { createHmac } from 'node:crypto'; @Injectable() export class UserService { public constructor( + private readonly activitiesService: ActivitiesService, private readonly configurationService: ConfigurationService, private readonly eventEmitter: EventEmitter2, private readonly i18nService: I18nService, - private readonly orderService: OrderService, private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, private readonly subscriptionService: SubscriptionService, @@ -643,7 +643,7 @@ export class UserService { } catch {} try { - await this.orderService.deleteOrders({ + await this.activitiesService.deleteActivities({ userId: where.id }); } catch {} diff --git a/apps/api/src/events/asset-profile-changed.listener.ts b/apps/api/src/events/asset-profile-changed.listener.ts index ad80ee4a5..1ecadec67 100644 --- a/apps/api/src/events/asset-profile-changed.listener.ts +++ b/apps/api/src/events/asset-profile-changed.listener.ts @@ -1,4 +1,4 @@ -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; @@ -13,11 +13,11 @@ import { AssetProfileChangedEvent } from './asset-profile-changed.event'; @Injectable() export class AssetProfileChangedListener { public constructor( + private readonly activitiesService: ActivitiesService, private readonly configurationService: ConfigurationService, private readonly dataGatheringService: DataGatheringService, private readonly dataProviderService: DataProviderService, - private readonly exchangeRateDataService: ExchangeRateDataService, - private readonly orderService: OrderService + private readonly exchangeRateDataService: ExchangeRateDataService ) {} @OnEvent(AssetProfileChangedEvent.getName()) @@ -48,7 +48,7 @@ export class AssetProfileChangedListener { } const { dateOfFirstActivity } = - await this.orderService.getStatisticsByCurrency(event.data.currency); + await this.activitiesService.getStatisticsByCurrency(event.data.currency); if (dateOfFirstActivity) { await this.dataGatheringService.gatherSymbol({ diff --git a/apps/api/src/events/events.module.ts b/apps/api/src/events/events.module.ts index ece67ebe0..772766945 100644 --- a/apps/api/src/events/events.module.ts +++ b/apps/api/src/events/events.module.ts @@ -1,4 +1,4 @@ -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; @@ -12,11 +12,11 @@ import { PortfolioChangedListener } from './portfolio-changed.listener'; @Module({ imports: [ + ActivitiesModule, ConfigurationModule, DataGatheringModule, DataProviderModule, ExchangeRateDataModule, - OrderModule, RedisCacheModule ], providers: [AssetProfileChangedListener, PortfolioChangedListener] diff --git a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.module.ts b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.module.ts index 958636334..553765768 100644 --- a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.module.ts +++ b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.module.ts @@ -1,5 +1,5 @@ import { AccountBalanceModule } from '@ghostfolio/api/app/account-balance/account-balance.module'; -import { OrderModule } from '@ghostfolio/api/app/order/order.module'; +import { ActivitiesModule } from '@ghostfolio/api/app/activities/activities.module'; import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; @@ -22,6 +22,7 @@ import { PortfolioSnapshotProcessor } from './portfolio-snapshot.processor'; exports: [BullModule, PortfolioSnapshotService], imports: [ AccountBalanceModule, + ActivitiesModule, BullModule.registerQueue({ name: PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE, settings: { @@ -36,7 +37,6 @@ import { PortfolioSnapshotProcessor } from './portfolio-snapshot.processor'; DataProviderModule, ExchangeRateDataModule, MarketDataModule, - OrderModule, RedisCacheModule ], providers: [ diff --git a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts index 58a0a8f8a..f3aa6e77e 100644 --- a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts +++ b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.processor.ts @@ -1,5 +1,5 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service'; -import { OrderService } from '@ghostfolio/api/app/order/order.service'; +import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service'; import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; @@ -23,9 +23,9 @@ import { PortfolioSnapshotQueueJob } from './interfaces/portfolio-snapshot-queue export class PortfolioSnapshotProcessor { public constructor( private readonly accountBalanceService: AccountBalanceService, + private readonly activitiesService: ActivitiesService, private readonly calculatorFactory: PortfolioCalculatorFactory, private readonly configurationService: ConfigurationService, - private readonly orderService: OrderService, private readonly redisCacheService: RedisCacheService ) {} @@ -47,7 +47,7 @@ export class PortfolioSnapshotProcessor { ); const { activities } = - await this.orderService.getOrdersForPortfolioCalculator({ + await this.activitiesService.getActivitiesForPortfolioCalculator({ filters: job.data.filters, userCurrency: job.data.userCurrency, userId: job.data.userId, diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts index 427386796..4d89cfbe1 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts @@ -581,7 +581,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { }; this.dataService - .postOrder(activity) + .postActivity(activity) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { this.router.navigate( diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts index cf7a41215..ca3f5b30d 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts @@ -334,7 +334,7 @@ export class GfActivitiesPageComponent implements OnDestroy, OnInit { .subscribe((activity: UpdateOrderDto) => { if (activity) { this.dataService - .putOrder(activity) + .putActivity(activity) .pipe(takeUntil(this.unsubscribeSubject)) .subscribe({ next: () => { @@ -385,7 +385,7 @@ export class GfActivitiesPageComponent implements OnDestroy, OnInit { .pipe(takeUntil(this.unsubscribeSubject)) .subscribe((transaction: CreateOrderDto | null) => { if (transaction) { - this.dataService.postOrder(transaction).subscribe({ + this.dataService.postActivity(transaction).subscribe({ next: () => { this.userService .get(true) diff --git a/libs/ui/src/lib/services/data.service.ts b/libs/ui/src/lib/services/data.service.ts index 37443cd20..62e7b6b4a 100644 --- a/libs/ui/src/lib/services/data.service.ts +++ b/libs/ui/src/lib/services/data.service.ts @@ -241,7 +241,7 @@ export class DataService { params = params.append('take', take); } - return this.http.get('/api/v1/order', { params }).pipe( + return this.http.get('/api/v1/activities', { params }).pipe( map(({ activities, count }) => { for (const activity of activities) { activity.createdAt = parseISO(activity.createdAt); @@ -253,14 +253,18 @@ export class DataService { } public fetchActivity(aActivityId: string) { - return this.http.get(`/api/v1/order/${aActivityId}`).pipe( - map((activity) => { - activity.createdAt = parseISO(activity.createdAt as unknown as string); - activity.date = parseISO(activity.date as unknown as string); + return this.http + .get(`/api/v1/activities/${aActivityId}`) + .pipe( + map((activity) => { + activity.createdAt = parseISO( + activity.createdAt as unknown as string + ); + activity.date = parseISO(activity.date as unknown as string); - return activity; - }) - ); + return activity; + }) + ); } public fetchDividends({ @@ -317,11 +321,11 @@ export class DataService { public deleteActivities({ filters }) { const params = this.buildFiltersAsQueryParams({ filters }); - return this.http.delete('/api/v1/order', { params }); + return this.http.delete('/api/v1/activities', { params }); } public deleteActivity(aId: string) { - return this.http.delete(`/api/v1/order/${aId}`); + return this.http.delete(`/api/v1/activities/${aId}`); } public deleteBenchmark({ dataSource, symbol }: AssetProfileIdentifier) { @@ -761,6 +765,10 @@ export class DataService { ); } + public postActivity(aOrder: CreateOrderDto) { + return this.http.post('/api/v1/activities', aOrder); + } + public postApiKey() { return this.http.post('/api/v1/api-keys', {}); } @@ -783,10 +791,6 @@ export class DataService { return this.http.post(url, marketData); } - public postOrder(aOrder: CreateOrderDto) { - return this.http.post('/api/v1/order', aOrder); - } - public postTag(aTag: CreateTagDto) { return this.http.post(`/api/v1/tags`, aTag); } @@ -807,6 +811,10 @@ export class DataService { return this.http.put(`/api/v1/account/${aAccount.id}`, aAccount); } + public putActivity(aOrder: UpdateOrderDto) { + return this.http.put(`/api/v1/activities/${aOrder.id}`, aOrder); + } + public putAdminSetting(key: string, aData: UpdatePropertyDto) { return this.http.put(`/api/v1/admin/settings/${key}`, aData); } @@ -822,10 +830,6 @@ export class DataService { ); } - public putOrder(aOrder: UpdateOrderDto) { - return this.http.put(`/api/v1/order/${aOrder.id}`, aOrder); - } - public putTag(aTag: UpdateTagDto) { return this.http.put(`/api/v1/tags/${aTag.id}`, aTag); } From 1057f4308485803eb44bf29b4218d596153f7c5b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 7 Mar 2026 18:22:55 +0100 Subject: [PATCH 036/138] Release 2.248.0 (#6493) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1279ef62f..4d8cdd873 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.248.0 - 2026-03-07 ### Added diff --git a/package-lock.json b/package-lock.json index 0ea9bbdce..ed34faf03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.247.0", + "version": "2.248.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.247.0", + "version": "2.248.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 47c9e9ade..b501bf7a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.247.0", + "version": "2.248.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From 7d8f0defb2ab47e2f2b1c30f6ea1a78241e8b705 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 8 Mar 2026 07:05:07 +0100 Subject: [PATCH 037/138] Bugfix/improve types in data service (#6492) * Improve types --- libs/ui/src/lib/services/data.service.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/ui/src/lib/services/data.service.ts b/libs/ui/src/lib/services/data.service.ts index 62e7b6b4a..169de067c 100644 --- a/libs/ui/src/lib/services/data.service.ts +++ b/libs/ui/src/lib/services/data.service.ts @@ -69,10 +69,11 @@ import { Injectable } from '@angular/core'; import { SortDirection } from '@angular/material/sort'; import { utc } from '@date-fns/utc'; import { + Account, AccountBalance, DataSource, MarketData, - Order as OrderModel, + Order, Tag } from '@prisma/client'; import { format, parseISO } from 'date-fns'; @@ -751,11 +752,11 @@ export class DataService { } public postAccess(aAccess: CreateAccessDto) { - return this.http.post('/api/v1/access', aAccess); + return this.http.post('/api/v1/access', aAccess); } public postAccount(aAccount: CreateAccountDto) { - return this.http.post('/api/v1/account', aAccount); + return this.http.post('/api/v1/account', aAccount); } public postAccountBalance(aAccountBalance: CreateAccountBalanceDto) { @@ -766,7 +767,7 @@ export class DataService { } public postActivity(aOrder: CreateOrderDto) { - return this.http.post('/api/v1/activities', aOrder); + return this.http.post('/api/v1/activities', aOrder); } public postApiKey() { From 7ac32ee6f3637c3397f4b50b7e147746bb3b8252 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 8 Mar 2026 13:51:59 +0100 Subject: [PATCH 038/138] Task/add asset profile to portfolio position interface (part 2) (#6500) * Add currency to asset profile --- apps/api/src/app/portfolio/portfolio.service.ts | 2 ++ .../src/lib/interfaces/portfolio-position.interface.ts | 2 ++ libs/ui/src/lib/mocks/holdings.ts | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index ed72260ca..167339487 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -628,6 +628,7 @@ export class PortfolioService { assetSubClass: assetProfile.assetSubClass, countries: assetProfile.countries, dataSource: assetProfile.dataSource, + currency: assetProfile.currency, holdings: assetProfile.holdings.map( ({ allocationInPercentage, name }) => { return { @@ -1699,6 +1700,7 @@ export class PortfolioService { assetClass: AssetClass.LIQUIDITY, assetSubClass: AssetSubClass.CASH, assetProfile: { + currency, assetClass: AssetClass.LIQUIDITY, assetSubClass: AssetSubClass.CASH, countries: [], diff --git a/libs/common/src/lib/interfaces/portfolio-position.interface.ts b/libs/common/src/lib/interfaces/portfolio-position.interface.ts index 742e63d7a..c4ef2e3dc 100644 --- a/libs/common/src/lib/interfaces/portfolio-position.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-position.interface.ts @@ -22,6 +22,7 @@ export interface PortfolioPosition { | 'assetClass' | 'assetSubClass' | 'countries' + | 'currency' | 'dataSource' | 'holdings' | 'name' @@ -42,6 +43,7 @@ export interface PortfolioPosition { /** @deprecated */ countries: Country[]; + /** @deprecated */ currency: string; /** @deprecated */ diff --git a/libs/ui/src/lib/mocks/holdings.ts b/libs/ui/src/lib/mocks/holdings.ts index f426593c1..b32eb527a 100644 --- a/libs/ui/src/lib/mocks/holdings.ts +++ b/libs/ui/src/lib/mocks/holdings.ts @@ -17,6 +17,7 @@ export const holdings: PortfolioPosition[] = [ weight: 1 } ], + currency: 'USD', dataSource: 'YAHOO', holdings: [], sectors: [ @@ -81,6 +82,7 @@ export const holdings: PortfolioPosition[] = [ weight: 1 } ], + currency: 'EUR', dataSource: 'YAHOO', holdings: [], sectors: [ @@ -145,6 +147,7 @@ export const holdings: PortfolioPosition[] = [ weight: 1 } ], + currency: 'USD', dataSource: 'YAHOO', holdings: [], sectors: [ @@ -202,6 +205,7 @@ export const holdings: PortfolioPosition[] = [ assetClass: 'LIQUIDITY', assetSubClass: 'CASH', countries: [], + currency: 'USD', dataSource: 'COINGECKO', holdings: [], sectors: [], @@ -249,6 +253,7 @@ export const holdings: PortfolioPosition[] = [ weight: 1 } ], + currency: 'USD', dataSource: 'YAHOO', holdings: [], sectors: [ @@ -313,6 +318,7 @@ export const holdings: PortfolioPosition[] = [ weight: 1 } ], + currency: 'USD', dataSource: 'YAHOO', holdings: [], sectors: [ @@ -377,6 +383,7 @@ export const holdings: PortfolioPosition[] = [ weight: 1 } ], + currency: 'USD', dataSource: 'YAHOO', holdings: [], sectors: [ From 07b165f79a0eb625071bc5c78f7b7016589eff7c Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 8 Mar 2026 16:02:48 +0100 Subject: [PATCH 039/138] Task/add asset profile to portfolio position interface (part 3) (#6502) * Reorder --- apps/api/src/app/portfolio/portfolio.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 167339487..5dab27939 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -627,8 +627,8 @@ export class PortfolioService { assetClass: assetProfile.assetClass, assetSubClass: assetProfile.assetSubClass, countries: assetProfile.countries, - dataSource: assetProfile.dataSource, currency: assetProfile.currency, + dataSource: assetProfile.dataSource, holdings: assetProfile.holdings.map( ({ allocationInPercentage, name }) => { return { From 2860ebe1cb96f29ea73a07acfd96b33d5bd0fa3a Mon Sep 17 00:00:00 2001 From: Erwin-N <111194281+Erwin-N@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:00:13 +0100 Subject: [PATCH 040/138] Task/improve language localization for NL 20260903 (#6506) * Improve language localization * Update changelog --- CHANGELOG.md | 6 ++++++ apps/client/src/locales/messages.nl.xlf | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8cdd873..457f98884 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Improved the language localization for Dutch (`nl`) + ## 2.248.0 - 2026-03-07 ### Added diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 158ff4fb1..2cf570721 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -3823,7 +3823,7 @@ By - Door + Tegen apps/client/src/app/pages/portfolio/fire/fire-page.html 139 From e5a771671f8f45fcf99b9b0cc1c25cd0223489c1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:42:23 +0100 Subject: [PATCH 041/138] Task/rename order permissions to activity (#6494) * Rename order permissions to activity --- .../app/activities/activities.controller.ts | 8 ++++---- apps/api/src/app/import/import.controller.ts | 2 +- .../src/app/portfolio/portfolio.controller.ts | 2 +- apps/client/src/app/app.component.ts | 12 +++++++++--- .../holding-detail-dialog.html | 2 +- .../interfaces/interfaces.ts | 2 +- .../home-holdings/home-holdings.component.ts | 2 +- .../home-overview/home-overview.component.ts | 2 +- .../pages/accounts/accounts-page.component.ts | 2 +- .../activities/activities-page.component.ts | 4 ++-- .../allocations/allocations-page.component.ts | 2 +- libs/common/src/lib/permissions.ts | 18 +++++++++--------- 12 files changed, 32 insertions(+), 26 deletions(-) diff --git a/apps/api/src/app/activities/activities.controller.ts b/apps/api/src/app/activities/activities.controller.ts index da7aed21d..49c8885a1 100644 --- a/apps/api/src/app/activities/activities.controller.ts +++ b/apps/api/src/app/activities/activities.controller.ts @@ -59,7 +59,7 @@ export class ActivitiesController { ) {} @Delete() - @HasPermission(permissions.deleteOrder) + @HasPermission(permissions.deleteActivity) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(TransformDataSourceInRequestInterceptor) public async deleteActivities( @@ -84,7 +84,7 @@ export class ActivitiesController { } @Delete(':id') - @HasPermission(permissions.deleteOrder) + @HasPermission(permissions.deleteActivity) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async deleteActivity(@Param('id') id: string): Promise { const activity = await this.activitiesService.order({ @@ -191,7 +191,7 @@ export class ActivitiesController { return activity; } - @HasPermission(permissions.createOrder) + @HasPermission(permissions.createActivity) @Post() @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(TransformDataSourceInRequestInterceptor) @@ -274,7 +274,7 @@ export class ActivitiesController { return activity; } - @HasPermission(permissions.updateOrder) + @HasPermission(permissions.updateActivity) @Put(':id') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseInterceptors(TransformDataSourceInRequestInterceptor) diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index 81481fd65..d5724bef2 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -38,7 +38,7 @@ export class ImportController { @Post() @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - @HasPermission(permissions.createOrder) + @HasPermission(permissions.createActivity) @UseInterceptors(TransformDataSourceInRequestInterceptor) @UseInterceptors(TransformDataSourceInResponseInterceptor) public async import( diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 80d7f9acc..73d4320d6 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -639,7 +639,7 @@ export class PortfolioController { return report; } - @HasPermission(permissions.updateOrder) + @HasPermission(permissions.updateActivity) @Put('holding/:dataSource/:symbol/tags') @UseInterceptors(TransformDataSourceInRequestInterceptor) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) diff --git a/apps/client/src/app/app.component.ts b/apps/client/src/app/app.component.ts index a4af01124..3daca607a 100644 --- a/apps/client/src/app/app.component.ts +++ b/apps/client/src/app/app.component.ts @@ -296,15 +296,21 @@ export class GfAppComponent implements OnDestroy, OnInit { ), hasPermissionToCreateActivity: !this.hasImpersonationId && - hasPermission(this.user?.permissions, permissions.createOrder) && + hasPermission( + this.user?.permissions, + permissions.createActivity + ) && !this.user?.settings?.isRestrictedView, hasPermissionToReportDataGlitch: hasPermission( this.user?.permissions, permissions.reportDataGlitch ), - hasPermissionToUpdateOrder: + hasPermissionToUpdateActivity: !this.hasImpersonationId && - hasPermission(this.user?.permissions, permissions.updateOrder) && + hasPermission( + this.user?.permissions, + permissions.updateActivity + ) && !this.user?.settings?.isRestrictedView, locale: this.user?.settings?.locale }, diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html index 86f4676f3..15415e413 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -414,7 +414,7 @@ diff --git a/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts index aab854384..527b13636 100644 --- a/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts @@ -11,7 +11,7 @@ export interface HoldingDetailDialogParams { hasPermissionToAccessAdminControl: boolean; hasPermissionToCreateActivity: boolean; hasPermissionToReportDataGlitch: boolean; - hasPermissionToUpdateOrder: boolean; + hasPermissionToUpdateActivity: boolean; locale: string; symbol: string; } diff --git a/apps/client/src/app/components/home-holdings/home-holdings.component.ts b/apps/client/src/app/components/home-holdings/home-holdings.component.ts index dc444977d..df5e43087 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.component.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.component.ts @@ -107,7 +107,7 @@ export class GfHomeHoldingsComponent implements OnDestroy, OnInit { this.hasPermissionToCreateActivity = hasPermission( this.user.permissions, - permissions.createOrder + permissions.createActivity ); this.initialize(); diff --git a/apps/client/src/app/components/home-overview/home-overview.component.ts b/apps/client/src/app/components/home-overview/home-overview.component.ts index 0d5020904..cb1df1a74 100644 --- a/apps/client/src/app/components/home-overview/home-overview.component.ts +++ b/apps/client/src/app/components/home-overview/home-overview.component.ts @@ -80,7 +80,7 @@ export class GfHomeOverviewComponent implements OnDestroy, OnInit { this.hasPermissionToCreateActivity = hasPermission( this.user.permissions, - permissions.createOrder + permissions.createActivity ); this.update(); diff --git a/apps/client/src/app/pages/accounts/accounts-page.component.ts b/apps/client/src/app/pages/accounts/accounts-page.component.ts index f7e6541b5..a0eef4eba 100644 --- a/apps/client/src/app/pages/accounts/accounts-page.component.ts +++ b/apps/client/src/app/pages/accounts/accounts-page.component.ts @@ -245,7 +245,7 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { hasImpersonationId: this.hasImpersonationId, hasPermissionToCreateActivity: !this.hasImpersonationId && - hasPermission(this.user?.permissions, permissions.createOrder) && + hasPermission(this.user?.permissions, permissions.createActivity) && !this.user?.settings?.isRestrictedView }, height: this.deviceType === 'mobile' ? '98vh' : '80vh', diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts index ca3f5b30d..dd78a0221 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts @@ -407,9 +407,9 @@ export class GfActivitiesPageComponent implements OnDestroy, OnInit { this.hasPermissionToCreateActivity = !this.hasImpersonationId && - hasPermission(this.user.permissions, permissions.createOrder); + hasPermission(this.user.permissions, permissions.createActivity); this.hasPermissionToDeleteActivity = !this.hasImpersonationId && - hasPermission(this.user.permissions, permissions.deleteOrder); + hasPermission(this.user.permissions, permissions.deleteActivity); } } diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index a98adc438..5226c3c12 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -567,7 +567,7 @@ export class GfAllocationsPageComponent implements OnInit { hasImpersonationId: this.hasImpersonationId, hasPermissionToCreateActivity: !this.hasImpersonationId && - hasPermission(this.user?.permissions, permissions.createOrder) && + hasPermission(this.user?.permissions, permissions.createActivity) && !this.user?.settings?.isRestrictedView }, height: this.deviceType === 'mobile' ? '98vh' : '80vh', diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts index cb4eb175b..62ae59fbe 100644 --- a/libs/common/src/lib/permissions.ts +++ b/libs/common/src/lib/permissions.ts @@ -9,10 +9,10 @@ export const permissions = { createAccess: 'createAccess', createAccount: 'createAccount', createAccountBalance: 'createAccountBalance', + createActivity: 'createActivity', createApiKey: 'createApiKey', createMarketData: 'createMarketData', createMarketDataOfOwnAssetProfile: 'createMarketDataOfOwnAssetProfile', - createOrder: 'createOrder', createOwnTag: 'createOwnTag', createPlatform: 'createPlatform', createTag: 'createTag', @@ -21,8 +21,8 @@ export const permissions = { deleteAccess: 'deleteAccess', deleteAccount: 'deleteAccount', deleteAccountBalance: 'deleteAccountBalance', + deleteActivity: 'deleteActivity', deleteAuthDevice: 'deleteAuthDevice', - deleteOrder: 'deleteOrder', deleteOwnUser: 'deleteOwnUser', deletePlatform: 'deletePlatform', deleteTag: 'deleteTag', @@ -53,10 +53,10 @@ export const permissions = { toggleReadOnlyMode: 'toggleReadOnlyMode', updateAccount: 'updateAccount', updateAccess: 'updateAccess', + updateActivity: 'updateActivity', updateAuthDevice: 'updateAuthDevice', updateMarketData: 'updateMarketData', updateMarketDataOfOwnAssetProfile: 'updateMarketDataOfOwnAssetProfile', - updateOrder: 'updateOrder', updateOwnAccessToken: 'updateOwnAccessToken', updatePlatform: 'updatePlatform', updateTag: 'updateTag', @@ -74,19 +74,19 @@ export function getPermissions(aRole: Role): string[] { permissions.createAccess, permissions.createAccount, permissions.createAccountBalance, + permissions.createActivity, permissions.createWatchlistItem, permissions.deleteAccountBalance, permissions.deleteWatchlistItem, permissions.createMarketData, permissions.createMarketDataOfOwnAssetProfile, - permissions.createOrder, permissions.createOwnTag, permissions.createPlatform, permissions.createTag, permissions.deleteAccess, permissions.deleteAccount, + permissions.deleteActivity, permissions.deleteAuthDevice, - permissions.deleteOrder, permissions.deletePlatform, permissions.deleteTag, permissions.deleteUser, @@ -99,10 +99,10 @@ export function getPermissions(aRole: Role): string[] { permissions.readWatchlist, permissions.updateAccount, permissions.updateAccess, + permissions.updateActivity, permissions.updateAuthDevice, permissions.updateMarketData, permissions.updateMarketDataOfOwnAssetProfile, - permissions.updateOrder, permissions.updatePlatform, permissions.updateTag, permissions.updateUserSettings, @@ -125,15 +125,15 @@ export function getPermissions(aRole: Role): string[] { permissions.createAccess, permissions.createAccount, permissions.createAccountBalance, + permissions.createActivity, permissions.createMarketDataOfOwnAssetProfile, - permissions.createOrder, permissions.createOwnTag, permissions.createWatchlistItem, permissions.deleteAccess, permissions.deleteAccount, permissions.deleteAccountBalance, + permissions.deleteActivity, permissions.deleteAuthDevice, - permissions.deleteOrder, permissions.deleteWatchlistItem, permissions.readAiPrompt, permissions.readMarketDataOfOwnAssetProfile, @@ -141,9 +141,9 @@ export function getPermissions(aRole: Role): string[] { permissions.readWatchlist, permissions.updateAccount, permissions.updateAccess, + permissions.updateActivity, permissions.updateAuthDevice, permissions.updateMarketDataOfOwnAssetProfile, - permissions.updateOrder, permissions.updateUserSettings, permissions.updateViewMode ]; From 80057ccc73f2f111e74b798daa5a376ea675f266 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:34:46 +0100 Subject: [PATCH 042/138] Bugfix/redis health check race condition (#6504) * Fix false Redis health check failures caused by race condition * Update changelog --- CHANGELOG.md | 4 ++++ apps/api/src/app/redis-cache/redis-cache.service.ts | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 457f98884..b0bbc8bcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the language localization for Dutch (`nl`) +### Fixed + +- Fixed false _Redis_ health check failures by using unique keys and increasing the timeout to 5s + ## 2.248.0 - 2026-03-07 ### Added diff --git a/apps/api/src/app/redis-cache/redis-cache.service.ts b/apps/api/src/app/redis-cache/redis-cache.service.ts index 1ea0a6137..619d23fc5 100644 --- a/apps/api/src/app/redis-cache/redis-cache.service.ts +++ b/apps/api/src/app/redis-cache/redis-cache.service.ts @@ -6,7 +6,7 @@ import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager'; import { Inject, Injectable, Logger } from '@nestjs/common'; import Keyv from 'keyv'; import ms from 'ms'; -import { createHash } from 'node:crypto'; +import { createHash, randomUUID } from 'node:crypto'; @Injectable() export class RedisCacheService { @@ -75,13 +75,16 @@ export class RedisCacheService { } public async isHealthy() { - const testKey = '__health_check__'; + const HEALTH_CHECK_TIMEOUT = ms('5 seconds'); + + const testKey = `__health_check__${randomUUID().replace(/-/g, '')}`; const testValue = Date.now().toString(); try { await Promise.race([ (async () => { - await this.set(testKey, testValue, ms('1 second')); + await this.set(testKey, testValue, HEALTH_CHECK_TIMEOUT); + const result = await this.get(testKey); if (result !== testValue) { @@ -91,7 +94,7 @@ export class RedisCacheService { new Promise((_, reject) => setTimeout( () => reject(new Error('Redis health check failed: timeout')), - ms('2 seconds') + HEALTH_CHECK_TIMEOUT ) ) ]); From 49d685c8ad52278aa73c979cbb2e13fefea98a51 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:35:54 +0100 Subject: [PATCH 043/138] Task/improve Storybook stories of value component (#6496) * Fix label and support size * Update changelog --- CHANGELOG.md | 1 + libs/ui/src/lib/value/value.component.stories.ts | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0bbc8bcf..e2dd0d4c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Improved the _Storybook_ stories of the value component - Improved the language localization for Dutch (`nl`) ### Fixed diff --git a/libs/ui/src/lib/value/value.component.stories.ts b/libs/ui/src/lib/value/value.component.stories.ts index a1f9d06a0..eeebe9399 100644 --- a/libs/ui/src/lib/value/value.component.stories.ts +++ b/libs/ui/src/lib/value/value.component.stories.ts @@ -16,6 +16,10 @@ export default { deviceType: { control: 'select', options: ['desktop', 'mobile'] + }, + size: { + control: 'select', + options: ['small', 'medium', 'large'] } } } as Meta; @@ -51,7 +55,11 @@ export const Label: Story = { args: { locale: 'en-US', value: 7.25 - } + }, + render: (args) => ({ + props: args, + template: `Label` + }) }; export const PerformancePositive: Story = { From b16314a625e3eb30bfe95bc03d6091fb2b6f96a4 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:36:57 +0100 Subject: [PATCH 044/138] Task/upgrade class-validator to version 0.15.1 (#6489) * Upgrade class-validator to version 0.15.1 * Update changelog --- CHANGELOG.md | 1 + package-lock.json | 10 +++++----- package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2dd0d4c8..3b49eaaaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the _Storybook_ stories of the value component - Improved the language localization for Dutch (`nl`) +- Upgraded `class-validator` from version `0.14.3` to `0.15.1` ### Fixed diff --git a/package-lock.json b/package-lock.json index ed34faf03..1654d1acd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,7 @@ "chartjs-plugin-datalabels": "2.2.0", "cheerio": "1.2.0", "class-transformer": "0.5.1", - "class-validator": "0.14.3", + "class-validator": "0.15.1", "color": "5.0.3", "countries-and-timezones": "3.8.0", "countries-list": "3.2.2", @@ -16400,14 +16400,14 @@ "license": "MIT" }, "node_modules/class-validator": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.3.tgz", - "integrity": "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.15.1.tgz", + "integrity": "sha512-LqoS80HBBSCVhz/3KloUly0ovokxpdOLR++Al3J3+dHXWt9sTKlKd4eYtoxhxyUjoe5+UcIM+5k9MIxyBWnRTw==", "license": "MIT", "dependencies": { "@types/validator": "^13.15.3", "libphonenumber-js": "^1.11.1", - "validator": "^13.15.20" + "validator": "^13.15.22" } }, "node_modules/clean-css": { diff --git a/package.json b/package.json index b501bf7a4..9fe3ef3c2 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "chartjs-plugin-datalabels": "2.2.0", "cheerio": "1.2.0", "class-transformer": "0.5.1", - "class-validator": "0.14.3", + "class-validator": "0.15.1", "color": "5.0.3", "countries-and-timezones": "3.8.0", "countries-list": "3.2.2", From dd895e3112c49dc30e7c25587637a73fee22b8a7 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:37:35 +0100 Subject: [PATCH 045/138] Task/improve localization of resources overview component (#6509) * Improve localization --- .../resources/overview/resources-overview.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.component.html b/apps/client/src/app/pages/resources/overview/resources-overview.component.html index 3a6f18d40..86a334c79 100644 --- a/apps/client/src/app/pages/resources/overview/resources-overview.component.html +++ b/apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -7,7 +7,9 @@

{{ item.title }}

{{ item.description }}

- Explore {{ item.title }} → + Explore {{ item.title }}
} From 41f0dfda652420a43c08bacfed224de0e2bf3373 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:40:10 +0100 Subject: [PATCH 046/138] Task/debounce portfolio and asset profile change listeners (#6505) * Debounce portfolio and asset profile change event listeners * Update changelog --- CHANGELOG.md | 4 ++ .../src/events/asset-profile-changed.event.ts | 12 ++++ .../events/asset-profile-changed.listener.ts | 59 ++++++++++++++++--- .../src/events/portfolio-changed.listener.ts | 30 ++++++++-- 4 files changed, 94 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b49eaaaa..89c34edde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added a debounce to the `PortfolioChangedListener` and `AssetProfileChangedListener` to minimize redundant _Redis_ and database operations + ### Changed - Improved the _Storybook_ stories of the value component diff --git a/apps/api/src/events/asset-profile-changed.event.ts b/apps/api/src/events/asset-profile-changed.event.ts index 46a8c5db4..c08fe59f1 100644 --- a/apps/api/src/events/asset-profile-changed.event.ts +++ b/apps/api/src/events/asset-profile-changed.event.ts @@ -8,4 +8,16 @@ export class AssetProfileChangedEvent { public static getName(): string { return 'assetProfile.changed'; } + + public getCurrency() { + return this.data.currency; + } + + public getDataSource() { + return this.data.dataSource; + } + + public getSymbol() { + return this.data.symbol; + } } diff --git a/apps/api/src/events/asset-profile-changed.listener.ts b/apps/api/src/events/asset-profile-changed.listener.ts index 1ecadec67..cc70edad6 100644 --- a/apps/api/src/events/asset-profile-changed.listener.ts +++ b/apps/api/src/events/asset-profile-changed.listener.ts @@ -4,14 +4,21 @@ import { DataProviderService } from '@ghostfolio/api/services/data-provider/data import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; import { DEFAULT_CURRENCY } from '@ghostfolio/common/config'; +import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; import { Injectable, Logger } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; +import { DataSource } from '@prisma/client'; +import ms from 'ms'; import { AssetProfileChangedEvent } from './asset-profile-changed.event'; @Injectable() export class AssetProfileChangedListener { + private static readonly DEBOUNCE_DELAY = ms('5 seconds'); + + private debounceTimers = new Map(); + public constructor( private readonly activitiesService: ActivitiesService, private readonly configurationService: ConfigurationService, @@ -21,9 +28,47 @@ export class AssetProfileChangedListener { ) {} @OnEvent(AssetProfileChangedEvent.getName()) - public async handleAssetProfileChanged(event: AssetProfileChangedEvent) { + public handleAssetProfileChanged(event: AssetProfileChangedEvent) { + const currency = event.getCurrency(); + const dataSource = event.getDataSource(); + const symbol = event.getSymbol(); + + const key = getAssetProfileIdentifier({ + dataSource, + symbol + }); + + const existingTimer = this.debounceTimers.get(key); + + if (existingTimer) { + clearTimeout(existingTimer); + } + + this.debounceTimers.set( + key, + setTimeout(() => { + this.debounceTimers.delete(key); + + void this.processAssetProfileChanged({ + currency, + dataSource, + symbol + }); + }, AssetProfileChangedListener.DEBOUNCE_DELAY) + ); + } + + private async processAssetProfileChanged({ + currency, + dataSource, + symbol + }: { + currency: string; + dataSource: DataSource; + symbol: string; + }) { Logger.log( - `Asset profile of ${event.data.symbol} (${event.data.dataSource}) has changed`, + `Asset profile of ${symbol} (${dataSource}) has changed`, 'AssetProfileChangedListener' ); @@ -31,16 +76,16 @@ export class AssetProfileChangedListener { this.configurationService.get( 'ENABLE_FEATURE_GATHER_NEW_EXCHANGE_RATES' ) === false || - event.data.currency === DEFAULT_CURRENCY + currency === DEFAULT_CURRENCY ) { return; } const existingCurrencies = this.exchangeRateDataService.getCurrencies(); - if (!existingCurrencies.includes(event.data.currency)) { + if (!existingCurrencies.includes(currency)) { Logger.log( - `New currency ${event.data.currency} has been detected`, + `New currency ${currency} has been detected`, 'AssetProfileChangedListener' ); @@ -48,13 +93,13 @@ export class AssetProfileChangedListener { } const { dateOfFirstActivity } = - await this.activitiesService.getStatisticsByCurrency(event.data.currency); + await this.activitiesService.getStatisticsByCurrency(currency); if (dateOfFirstActivity) { await this.dataGatheringService.gatherSymbol({ dataSource: this.dataProviderService.getDataSourceForExchangeRates(), date: dateOfFirstActivity, - symbol: `${DEFAULT_CURRENCY}${event.data.currency}` + symbol: `${DEFAULT_CURRENCY}${currency}` }); } } diff --git a/apps/api/src/events/portfolio-changed.listener.ts b/apps/api/src/events/portfolio-changed.listener.ts index d12b9558d..f8e2a9229 100644 --- a/apps/api/src/events/portfolio-changed.listener.ts +++ b/apps/api/src/events/portfolio-changed.listener.ts @@ -2,22 +2,44 @@ import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.s import { Injectable, Logger } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; +import ms from 'ms'; import { PortfolioChangedEvent } from './portfolio-changed.event'; @Injectable() export class PortfolioChangedListener { + private static readonly DEBOUNCE_DELAY = ms('5 seconds'); + + private debounceTimers = new Map(); + public constructor(private readonly redisCacheService: RedisCacheService) {} @OnEvent(PortfolioChangedEvent.getName()) handlePortfolioChangedEvent(event: PortfolioChangedEvent) { + const userId = event.getUserId(); + + const existingTimer = this.debounceTimers.get(userId); + + if (existingTimer) { + clearTimeout(existingTimer); + } + + this.debounceTimers.set( + userId, + setTimeout(() => { + this.debounceTimers.delete(userId); + + void this.processPortfolioChanged({ userId }); + }, PortfolioChangedListener.DEBOUNCE_DELAY) + ); + } + + private async processPortfolioChanged({ userId }: { userId: string }) { Logger.log( - `Portfolio of user '${event.getUserId()}' has changed`, + `Portfolio of user '${userId}' has changed`, 'PortfolioChangedListener' ); - this.redisCacheService.removePortfolioSnapshotsByUserId({ - userId: event.getUserId() - }); + await this.redisCacheService.removePortfolioSnapshotsByUserId({ userId }); } } From fa4260d6fc74cdd49c4dd248e7d97a01232e076c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:42:37 +0100 Subject: [PATCH 047/138] Task/update locales (#6410) --- apps/client/src/locales/messages.ca.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.de.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.es.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.fr.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.it.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.ko.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.nl.xlf | 166 +++++++++++++----------- apps/client/src/locales/messages.pl.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.pt.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.tr.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.uk.xlf | 160 ++++++++++++----------- apps/client/src/locales/messages.xlf | 159 ++++++++++++----------- apps/client/src/locales/messages.zh.xlf | 160 ++++++++++++----------- 13 files changed, 1094 insertions(+), 991 deletions(-) diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index d878a63bf..cf0ede34d 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -427,7 +427,7 @@
apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -439,7 +439,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -499,7 +499,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -587,11 +587,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -619,11 +619,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -691,7 +691,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451
@@ -759,7 +759,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -1011,7 +1011,7 @@ El preu de mercat actual és apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -1079,7 +1079,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1099,7 +1099,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1111,7 +1111,7 @@ Mapatge de Símbols apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -1127,7 +1127,7 @@ Configuració del Proveïdor de Dades apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -1135,7 +1135,7 @@ Prova apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -1143,11 +1143,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1163,7 +1163,7 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -1171,7 +1171,7 @@ Notes apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1319,7 +1319,7 @@ Recollida de Dades apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -1391,7 +1391,15 @@ Està segur que vol eliminar aquesta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 + + + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 @@ -1415,7 +1423,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -1431,7 +1439,7 @@ Plataformes apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -1439,7 +1447,7 @@ Etiquetes apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1463,7 +1471,7 @@ Està segur que vol eliminar aquesta etiqueta? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -1555,11 +1563,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -1607,7 +1615,7 @@ Punt de Referència apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -1943,7 +1951,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2351,7 +2359,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -2363,7 +2371,7 @@ 1 any apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -2375,7 +2383,7 @@ 5 anys apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -2395,7 +2403,7 @@ Màx apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -2567,7 +2575,7 @@ Include in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -2623,7 +2631,7 @@ Localització apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -3223,11 +3231,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -3271,7 +3279,7 @@ General apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -3279,7 +3287,7 @@ Núvol apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -3291,7 +3299,7 @@ Autoallotjament apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -3492,7 +3500,7 @@ Mercats apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -4852,11 +4860,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -5433,7 +5441,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5453,7 +5461,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -5473,7 +5481,7 @@ any apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -5493,7 +5501,7 @@ anys apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -5505,7 +5513,7 @@ Perfils d’actius apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -5645,7 +5653,7 @@ Dipòsit libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -5661,7 +5669,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -5673,7 +5681,7 @@ Estalvi libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -5745,7 +5753,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5777,7 +5785,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -6293,7 +6301,7 @@ Vàlid fins a apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -6673,7 +6681,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6725,7 +6733,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6777,7 +6785,7 @@ Close apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7081,7 +7089,7 @@ Set API key apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7187,7 +7195,7 @@ of apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7195,7 +7203,7 @@ daily requests apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7203,7 +7211,7 @@ Remove API key apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7211,7 +7219,7 @@ Do you really want to delete the API key? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7303,7 +7311,7 @@ Save apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7379,7 +7387,7 @@ Please enter your Ghostfolio API key. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7411,7 +7419,7 @@ Lazy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7419,7 +7427,7 @@ Instant apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7427,7 +7435,7 @@ Default Market Price apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7435,7 +7443,7 @@ Mode apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7443,7 +7451,7 @@ Selector apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7451,7 +7459,7 @@ HTTP Request Headers apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7459,7 +7467,7 @@ end of day apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7467,7 +7475,7 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7708,7 +7716,7 @@ () is already in use. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7716,7 +7724,7 @@ An error occurred while updating to (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8067,7 +8075,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8075,7 +8083,7 @@ new apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 54c3f7de8..74365a176 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -106,7 +106,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -118,7 +118,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -234,11 +234,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -266,11 +266,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -366,7 +366,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -382,7 +382,7 @@ Anlageprofile apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -398,7 +398,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -986,7 +986,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1006,7 +1006,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1018,7 +1018,7 @@ Tags apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1082,7 +1082,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -1094,7 +1094,7 @@ 1J apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -1106,7 +1106,7 @@ 5J apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -1126,7 +1126,7 @@ Max apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -1298,7 +1298,7 @@ Lokalität apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -1438,7 +1438,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1714,7 +1714,7 @@ Märkte apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -1934,7 +1934,7 @@ Aktuelle Woche apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2018,7 +2018,7 @@ Kommentar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2546,7 +2546,7 @@ Einlage libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -2562,7 +2562,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -2574,7 +2574,7 @@ Ersparnisse libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -2666,11 +2666,11 @@ Das Formular konnte nicht validiert werden apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -2686,7 +2686,7 @@ Benchmark apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -2802,7 +2802,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3126,7 +3126,7 @@ Symbol Zuordnung apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -3190,7 +3190,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3318,7 +3318,7 @@ Gültig bis apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3638,11 +3638,11 @@ Das Anlageprofil konnte nicht gespeichert werden apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -3845,6 +3845,14 @@ 306 + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 + + By Bis @@ -3866,7 +3874,7 @@ Aktuelles Jahr apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -3882,11 +3890,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -3902,7 +3910,7 @@ Das Anlageprofil wurde gespeichert apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -3910,7 +3918,7 @@ Möchtest du diese Plattform wirklich löschen? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 @@ -3918,7 +3926,7 @@ Plattformen apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -4262,7 +4270,7 @@ Scraper Konfiguration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -4802,11 +4810,11 @@ Die Scraper Konfiguration konnte nicht geparsed werden apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -5500,7 +5508,7 @@ Möchtest du diesen Tag wirklich löschen? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -5792,7 +5800,7 @@ Der aktuelle Marktpreis ist apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5800,7 +5808,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5960,7 +5968,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5980,7 +5988,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6028,7 +6036,7 @@ Jahr apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6048,7 +6056,7 @@ Jahre apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6068,7 +6076,7 @@ Finanzmarktdaten synchronisieren apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6080,7 +6088,7 @@ Allgemein apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6088,7 +6096,7 @@ Cloud apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6100,7 +6108,7 @@ Self-Hosting apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6293,7 +6301,7 @@ Berücksichtigen in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6697,7 +6705,7 @@ Fehler apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6749,7 +6757,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6801,7 +6809,7 @@ Schliessen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7105,7 +7113,7 @@ API-Schlüssel setzen apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7211,7 +7219,7 @@ von apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7219,7 +7227,7 @@ täglichen Anfragen apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7227,7 +7235,7 @@ API-Schlüssel löschen apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7235,7 +7243,7 @@ Möchtest du den API-Schlüssel wirklich löschen? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7327,7 +7335,7 @@ Speichern apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7403,7 +7411,7 @@ Bitte gebe deinen Ghostfolio API-Schlüssel ein. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7435,7 +7443,7 @@ Verzögert apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7443,7 +7451,7 @@ Sofort apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7451,7 +7459,7 @@ Standardmarktpreis apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7459,7 +7467,7 @@ Modus apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7467,7 +7475,7 @@ Selektor apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7475,7 +7483,7 @@ HTTP Request-Headers apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7483,7 +7491,7 @@ Tagesende apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7491,7 +7499,7 @@ in Echtzeit apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7732,7 +7740,7 @@ () wird bereits verwendet. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7740,7 +7748,7 @@ Bei der Änderung zu () ist ein Fehler aufgetreten. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8067,7 +8075,7 @@ Aktueller Monat apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8075,7 +8083,7 @@ neu apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index ba5a38d67..a904cbae8 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -107,7 +107,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -119,7 +119,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -235,11 +235,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -267,11 +267,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -367,7 +367,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -383,7 +383,7 @@ Perfiles de activos. apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -399,7 +399,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -971,7 +971,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -991,7 +991,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1003,7 +1003,7 @@ Etiquetas apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1067,7 +1067,7 @@ Desde principio de año apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -1079,7 +1079,7 @@ 1 año apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -1091,7 +1091,7 @@ 5 años apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -1111,7 +1111,7 @@ Máximo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -1283,7 +1283,7 @@ Ubicación apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -1423,7 +1423,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1699,7 +1699,7 @@ Mercados apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -1919,7 +1919,7 @@ Semana actual apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2003,7 +2003,7 @@ Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2515,7 +2515,7 @@ Ahorros libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -2531,7 +2531,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -2551,7 +2551,7 @@ Depósito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -2651,7 +2651,7 @@ Benchmark apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -2663,11 +2663,11 @@ No se pudo validar el formulario apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -2787,7 +2787,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3111,7 +3111,7 @@ Mapeo de símbolos apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -3175,7 +3175,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3303,7 +3303,7 @@ Válido hasta apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3623,11 +3623,11 @@ No se pudo guardar el perfil del activo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -3822,6 +3822,14 @@ 306 + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 + + By Por @@ -3843,7 +3851,7 @@ Año actual apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -3859,11 +3867,11 @@ ¿La URL? apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -3879,7 +3887,7 @@ El perfil del activo ha sido guardado apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -3887,7 +3895,7 @@ ¿Realmente deseas eliminar esta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 @@ -3895,7 +3903,7 @@ Plataformas apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -4239,7 +4247,7 @@ Configuración del scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -4779,11 +4787,11 @@ No se pudo analizar la configuración del scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -5477,7 +5485,7 @@ ¿Realmente deseas eliminar esta etiqueta? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -5769,7 +5777,7 @@ El precio actual de mercado es apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5777,7 +5785,7 @@ Prueba apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5937,7 +5945,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5957,7 +5965,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6005,7 +6013,7 @@ año apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6025,7 +6033,7 @@ años apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6045,7 +6053,7 @@ Recopilación de datos apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6057,7 +6065,7 @@ General apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6065,7 +6073,7 @@ Nube apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6077,7 +6085,7 @@ Autoalojamiento apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6270,7 +6278,7 @@ Incluir en apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6674,7 +6682,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6726,7 +6734,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6778,7 +6786,7 @@ Cerrar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7082,7 +7090,7 @@ Configurar clave API apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7188,7 +7196,7 @@ de apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7196,7 +7204,7 @@ solicitudes diarias apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7204,7 +7212,7 @@ Eliminar clave API apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7212,7 +7220,7 @@ ¿Realmente deseas eliminar la clave API? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7304,7 +7312,7 @@ Ahorrar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7380,7 +7388,7 @@ Por favor, ingresa tu clave API de Ghostfolio. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7412,7 +7420,7 @@ Perezoso apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7420,7 +7428,7 @@ Instantáneo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7428,7 +7436,7 @@ Precio de mercado por defecto apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7436,7 +7444,7 @@ Modo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7444,7 +7452,7 @@ Selector apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7452,7 +7460,7 @@ Encabezados de solicitud HTTP apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7460,7 +7468,7 @@ final del día apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7468,7 +7476,7 @@ en tiempo real apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7709,7 +7717,7 @@ () ya está en uso. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7717,7 +7725,7 @@ Ocurrió un error al actualizar a (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8068,7 +8076,7 @@ Mes actual apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8076,7 +8084,7 @@ nuevo apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index f343cb2ad..f01a3a505 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -114,7 +114,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -126,7 +126,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -186,7 +186,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -290,11 +290,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -322,11 +322,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -414,7 +414,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -438,7 +438,7 @@ Profils d’Actifs apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -454,7 +454,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -650,7 +650,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -670,7 +670,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -682,7 +682,7 @@ Équivalence de Symboles apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -690,7 +690,7 @@ Note apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -762,7 +762,7 @@ Étiquettes apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -898,11 +898,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -942,7 +942,7 @@ Référence apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -1314,7 +1314,7 @@ CDA apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -1326,7 +1326,7 @@ 1A apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -1338,7 +1338,7 @@ 5A apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -1358,7 +1358,7 @@ Max apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -1586,7 +1586,7 @@ Paramètres régionaux apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -1994,7 +1994,7 @@ Marchés apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -2098,7 +2098,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2438,7 +2438,7 @@ Dépôt libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -2858,7 +2858,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -2870,7 +2870,7 @@ Épargne libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -2934,7 +2934,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -2966,7 +2966,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3302,7 +3302,7 @@ Valide jusqu’au apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3622,11 +3622,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -3821,6 +3821,14 @@ 306 + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 + + By By @@ -3842,7 +3850,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -3858,11 +3866,11 @@ Lien apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -3878,7 +3886,7 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -3886,7 +3894,7 @@ Voulez-vous vraiment supprimer cette plateforme ? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 @@ -3894,7 +3902,7 @@ Platformes apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -4238,7 +4246,7 @@ Configuration du Scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -4778,11 +4786,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -5476,7 +5484,7 @@ Confirmez la suppression de ce tag ? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -5768,7 +5776,7 @@ Le prix actuel du marché est apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5776,7 +5784,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5936,7 +5944,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5956,7 +5964,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6004,7 +6012,7 @@ année apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6024,7 +6032,7 @@ années apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6044,7 +6052,7 @@ Collecter les données apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6056,7 +6064,7 @@ Général apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6064,7 +6072,7 @@ Cloud apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6076,7 +6084,7 @@ Self-Hosting apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6269,7 +6277,7 @@ Include in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6673,7 +6681,7 @@ Erreur apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6725,7 +6733,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6777,7 +6785,7 @@ Fermer apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7081,7 +7089,7 @@ Définir clé API apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7187,7 +7195,7 @@ sur apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7195,7 +7203,7 @@ requêtes journalières apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7203,7 +7211,7 @@ Retirer la clé API apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7211,7 +7219,7 @@ Voulez-vous vraiment supprimer la clé API? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7303,7 +7311,7 @@ Sauvegarder apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7379,7 +7387,7 @@ Veuillez saisir votre clé API Ghostfolio. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7411,7 +7419,7 @@ Paresseux apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7419,7 +7427,7 @@ Instantané apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7427,7 +7435,7 @@ Prix du marché par défaut apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7435,7 +7443,7 @@ Mode apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7443,7 +7451,7 @@ Selecteur apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7451,7 +7459,7 @@ En-têtes de requête HTTP apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7459,7 +7467,7 @@ fin de journée apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7467,7 +7475,7 @@ temps réel apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7708,7 +7716,7 @@ () est déjà utilisé. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7716,7 +7724,7 @@ Une erreur s’est produite lors de la mise à jour vers (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8067,7 +8075,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8075,7 +8083,7 @@ new apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 20bfd1b33..5f06af0b4 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -107,7 +107,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -119,7 +119,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -235,11 +235,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -267,11 +267,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -367,7 +367,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -383,7 +383,7 @@ Profilo dell’asset apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -399,7 +399,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -971,7 +971,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -991,7 +991,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1003,7 +1003,7 @@ Tag apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1067,7 +1067,7 @@ anno corrente apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -1079,7 +1079,7 @@ 1 anno apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -1091,7 +1091,7 @@ 5 anni apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -1111,7 +1111,7 @@ Massimo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -1283,7 +1283,7 @@ Locale apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -1423,7 +1423,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1699,7 +1699,7 @@ Mercati apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -1919,7 +1919,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2003,7 +2003,7 @@ Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2515,7 +2515,7 @@ Risparmio libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -2531,7 +2531,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -2551,7 +2551,7 @@ Deposito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -2651,7 +2651,7 @@ Benchmark apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -2663,11 +2663,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -2787,7 +2787,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3111,7 +3111,7 @@ Mappatura dei simboli apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -3175,7 +3175,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3303,7 +3303,7 @@ Valido fino a apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3623,11 +3623,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -3822,6 +3822,14 @@ 306 + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 + + By By @@ -3843,7 +3851,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -3859,11 +3867,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -3879,7 +3887,7 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -3887,7 +3895,7 @@ Vuoi davvero eliminare questa piattaforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 @@ -3895,7 +3903,7 @@ Piattaforme apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -4239,7 +4247,7 @@ Configurazione dello scraper apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -4779,11 +4787,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -5477,7 +5485,7 @@ Sei sicuro di voler eliminare questo tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -5769,7 +5777,7 @@ L’attuale prezzo di mercato è apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5777,7 +5785,7 @@ Prova apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5937,7 +5945,7 @@ Settimana corrente apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5957,7 +5965,7 @@ Mese corrente apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6005,7 +6013,7 @@ anno apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6025,7 +6033,7 @@ anni apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6045,7 +6053,7 @@ Raccolta Dati apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6057,7 +6065,7 @@ Generale apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6065,7 +6073,7 @@ Cloud apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6077,7 +6085,7 @@ Self-Hosting apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6270,7 +6278,7 @@ Include in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6674,7 +6682,7 @@ Errore apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6726,7 +6734,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6778,7 +6786,7 @@ Chiudi apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7082,7 +7090,7 @@ Imposta API Key apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7188,7 +7196,7 @@ di apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7196,7 +7204,7 @@ richieste giornaliere apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7204,7 +7212,7 @@ Rimuovi API key apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7212,7 +7220,7 @@ Vuoi davvero eliminare l’API key? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7304,7 +7312,7 @@ Salva apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7380,7 +7388,7 @@ Inserisci la tua API key di Ghostfolio. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7412,7 +7420,7 @@ Pigro apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7420,7 +7428,7 @@ Istantaneo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7428,7 +7436,7 @@ Prezzo di mercato predefinito apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7436,7 +7444,7 @@ Modalità apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7444,7 +7452,7 @@ Selettore apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7452,7 +7460,7 @@ Intestazioni della richiesta HTTP apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7460,7 +7468,7 @@ fine giornata apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7468,7 +7476,7 @@ in tempo reale apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7709,7 +7717,7 @@ () e gia in uso. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7717,7 +7725,7 @@ Si è verificato un errore durante l’aggiornamento di (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8068,7 +8076,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8076,7 +8084,7 @@ nuovo apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.ko.xlf b/apps/client/src/locales/messages.ko.xlf index 9b7c4192e..bb361b515 100644 --- a/apps/client/src/locales/messages.ko.xlf +++ b/apps/client/src/locales/messages.ko.xlf @@ -360,7 +360,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -372,7 +372,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -432,7 +432,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -520,11 +520,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -552,11 +552,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -604,7 +604,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -664,7 +664,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -960,7 +960,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -980,7 +980,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -992,7 +992,7 @@ 심볼 매핑 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -1008,7 +1008,7 @@ 스크래퍼 설정 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -1016,7 +1016,7 @@ 메모 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1224,11 +1224,11 @@ 링크 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1244,7 +1244,7 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -1252,7 +1252,15 @@ 정말로 이 플랫폼을 삭제하시겠습니까? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 + + + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 @@ -1276,7 +1284,7 @@ 올해 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -1292,7 +1300,7 @@ 플랫폼 apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -1300,7 +1308,7 @@ 태그 apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1324,7 +1332,7 @@ 이 태그를 정말로 삭제하시겠습니까? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -1416,11 +1424,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -1468,7 +1476,7 @@ 기준 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -1672,7 +1680,7 @@ 이번주 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2140,7 +2148,7 @@ 연초 대비 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -2152,7 +2160,7 @@ 1년 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -2164,7 +2172,7 @@ 5년 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -2184,7 +2192,7 @@ 맥스 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -2340,7 +2348,7 @@ 장소 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2916,11 +2924,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -3160,7 +3168,7 @@ 시장 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -4160,7 +4168,7 @@ 보증금 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -4456,11 +4464,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -5005,7 +5013,7 @@ 자산 프로필 apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -5121,7 +5129,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -5133,7 +5141,7 @@ 저금 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -5205,7 +5213,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5237,7 +5245,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5737,7 +5745,7 @@ 유효기간 apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -5801,7 +5809,7 @@ 현재 시장가격은 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5809,7 +5817,7 @@ 시험 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5977,7 +5985,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -5989,7 +5997,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -6029,7 +6037,7 @@ 년도 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6049,7 +6057,7 @@ 연령 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6082,7 +6090,7 @@ 셀프 호스팅 apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6094,7 +6102,7 @@ 데이터 수집 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6106,7 +6114,7 @@ 일반적인 apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6114,7 +6122,7 @@ 구름 apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6294,7 +6302,7 @@ 포함 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6698,7 +6706,7 @@ 오류 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6710,7 +6718,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6794,7 +6802,7 @@ 닫다 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7106,7 +7114,7 @@ API 키 설정 apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7220,7 +7228,7 @@ ~의 apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7228,7 +7236,7 @@ API 키를 정말로 삭제하시겠습니까? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7236,7 +7244,7 @@ API 키 제거 apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7244,7 +7252,7 @@ 일일 요청 apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7328,7 +7336,7 @@ 구하다 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7404,7 +7412,7 @@ Ghostfolio API 키를 입력하세요. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7436,7 +7444,7 @@ 방법 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7444,7 +7452,7 @@ 기본 시장 가격 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7452,7 +7460,7 @@ 선택자 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7460,7 +7468,7 @@ 즉각적인 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7468,7 +7476,7 @@ 게으른 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7476,7 +7484,7 @@ HTTP 요청 헤더 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7484,7 +7492,7 @@ 실시간 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7492,7 +7500,7 @@ 하루의 끝 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7733,7 +7741,7 @@ ()은(는) 이미 사용 중입니다. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7741,7 +7749,7 @@ ()로 업데이트하는 동안 오류가 발생했습니다. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8068,7 +8076,7 @@ 이번 달 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8076,7 +8084,7 @@ 새로운 apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 2cf570721..fbd87961c 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -106,7 +106,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -118,7 +118,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -234,11 +234,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -266,11 +266,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -366,7 +366,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -382,7 +382,7 @@ Activa Profiel apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -398,7 +398,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -970,7 +970,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -990,7 +990,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1002,7 +1002,7 @@ Tags apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1066,7 +1066,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -1078,7 +1078,7 @@ 1J apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -1090,7 +1090,7 @@ 5J apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -1110,7 +1110,7 @@ Max apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -1282,7 +1282,7 @@ Locatie apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -1422,7 +1422,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -1698,7 +1698,7 @@ Markten apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -1918,7 +1918,7 @@ Huidige week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2002,7 +2002,7 @@ Opmerking apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2514,7 +2514,7 @@ Besparingen libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -2530,7 +2530,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -2550,7 +2550,7 @@ Storting libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -2650,7 +2650,7 @@ Benchmark apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -2662,11 +2662,11 @@ Het formulier kon niet worden gevalideerd. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -2786,7 +2786,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3110,7 +3110,7 @@ Symbool toewijzen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -3174,7 +3174,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3302,7 +3302,7 @@ Geldig tot apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3622,11 +3622,11 @@ Kon het assetprofiel niet opslaan apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -3821,6 +3821,14 @@ 306 + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 + + By Tegen @@ -3842,7 +3850,7 @@ Huidig jaar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -3858,11 +3866,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -3878,7 +3886,7 @@ Het activaprofiel is opgeslagen. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -3886,7 +3894,7 @@ Wil je dit platform echt verwijderen? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 @@ -3894,7 +3902,7 @@ Platforms apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -4238,7 +4246,7 @@ Scraper instellingen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -4778,11 +4786,11 @@ De scraperconfiguratie kon niet worden geparseerd apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -5476,7 +5484,7 @@ Weet u zetker dat u dit label wilt verwijderen? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -5768,7 +5776,7 @@ De huidige markt waarde is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5776,7 +5784,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5821,7 +5829,7 @@ Argentina - Argentinië + Argentinië libs/ui/src/lib/i18n.ts 78 @@ -5936,7 +5944,7 @@ Week tot nu toe apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5956,7 +5964,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6004,7 +6012,7 @@ jaar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6024,7 +6032,7 @@ jaren apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6044,7 +6052,7 @@ Data Verzamelen apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6056,7 +6064,7 @@ Algemeen apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6064,7 +6072,7 @@ Cloud apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6076,7 +6084,7 @@ Zelf Hosten apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6269,7 +6277,7 @@ Opnemen in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6673,7 +6681,7 @@ Fout apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6702,7 +6710,7 @@ , based on your total assets of - opnemen, dit is gebaseerd op uw totale vermogen van + opnemen, dit is gebaseerd op uw totale vermogen van apps/client/src/app/pages/portfolio/fire/fire-page.html 96 @@ -6725,7 +6733,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6777,7 +6785,7 @@ Sluiten apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7054,7 +7062,7 @@ Ghostfolio is a lightweight wealth management application for individuals to keep track of stocks, ETFs or cryptocurrencies and make solid, data-driven investment decisions. - Ghostfolio is een gebruiksvriendelijke applicatie voor vermogensbeheer waarmee particulieren hun aandelen, ETF's of cryptovaluta kunnen volgen en weloverwogen, datagestuurde beleggingsbeslissingen kunnen nemen. + Ghostfolio is een gebruiksvriendelijke applicatie voor vermogensbeheer waarmee particulieren hun aandelen, ETF's of cryptovaluta kunnen volgen en weloverwogen, datagestuurde beleggingsbeslissingen kunnen nemen. apps/client/src/app/pages/about/overview/about-overview-page.html 10 @@ -7081,7 +7089,7 @@ API-sleutel instellen apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7187,7 +7195,7 @@ van apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7195,7 +7203,7 @@ dagelijkse verzoeken apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7203,7 +7211,7 @@ Verwijder API-sleutel apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7211,7 +7219,7 @@ Wilt u de API-sleutel echt verwijderen? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7303,7 +7311,7 @@ Opslaan apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7379,7 +7387,7 @@ Voer uw Ghostfolio API-sleutel in. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7411,7 +7419,7 @@ Lui apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7419,7 +7427,7 @@ Direct apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7427,7 +7435,7 @@ Standaard Marktprijs apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7435,7 +7443,7 @@ Modus apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7443,7 +7451,7 @@ Kiezer apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7451,7 +7459,7 @@ HTTP Verzoek Headers apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7459,7 +7467,7 @@ eind van de dag apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7467,7 +7475,7 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7708,7 +7716,7 @@ () is al in gebruik. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7716,7 +7724,7 @@ Er is een fout opgetreden tijdens het updaten naar (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8067,7 +8075,7 @@ Huidige maand apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8075,7 +8083,7 @@ nieuw apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index bc8b948cd..5de2ed8f4 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -351,7 +351,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -363,7 +363,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -423,7 +423,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -511,11 +511,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -543,11 +543,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -595,7 +595,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -655,7 +655,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -927,7 +927,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -947,7 +947,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -959,7 +959,7 @@ Mapowanie Symboli apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -975,7 +975,7 @@ Konfiguracja Scrapera apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -983,7 +983,7 @@ Notatka apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1191,11 +1191,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1211,7 +1211,7 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -1219,7 +1219,15 @@ Czy naprawdę chcesz usunąć tę platformę? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 + + + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 @@ -1243,7 +1251,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -1259,7 +1267,7 @@ Platformy apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -1267,7 +1275,7 @@ Tagi apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1291,7 +1299,7 @@ Czy naprawdę chcesz usunąć ten tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -1383,11 +1391,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -1435,7 +1443,7 @@ Poziom Odniesienia (Benchmark) apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -1639,7 +1647,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2107,7 +2115,7 @@ Liczony od początku roku (year-to-date) apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -2119,7 +2127,7 @@ 1 rok apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -2131,7 +2139,7 @@ 5 lat apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -2151,7 +2159,7 @@ Maksimum apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -2307,7 +2315,7 @@ Ustawienia Regionalne apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2883,11 +2891,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -3127,7 +3135,7 @@ Rynki apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -4127,7 +4135,7 @@ Depozyt libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -4423,11 +4431,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -4952,7 +4960,7 @@ Profile aktywów apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -5052,7 +5060,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -5064,7 +5072,7 @@ Oszczędności libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -5136,7 +5144,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5168,7 +5176,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5668,7 +5676,7 @@ Ważność do apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -5768,7 +5776,7 @@ Obecna cena rynkowa wynosi apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5776,7 +5784,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5936,7 +5944,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5956,7 +5964,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6004,7 +6012,7 @@ rok apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6024,7 +6032,7 @@ lata apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6044,7 +6052,7 @@ Gromadzenie Danych apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6056,7 +6064,7 @@ Informacje Ogólne apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6064,7 +6072,7 @@ Rozwiązanie w Chmurze apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6076,7 +6084,7 @@ Własny Hosting apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6269,7 +6277,7 @@ Include in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6673,7 +6681,7 @@ Błąd apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6725,7 +6733,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6777,7 +6785,7 @@ Zamknij apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7081,7 +7089,7 @@ Skonfiguruj klucz API apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7187,7 +7195,7 @@ z apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7195,7 +7203,7 @@ codzienne żądania apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7203,7 +7211,7 @@ Usuń klucz API apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7211,7 +7219,7 @@ Czy na pewno chcesz usunąć klucz API?? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7303,7 +7311,7 @@ Zapisz apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7379,7 +7387,7 @@ Wprowadź swój klucz API Ghostfolio. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7411,7 +7419,7 @@ Leniwy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7419,7 +7427,7 @@ Natychmiastowy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7427,7 +7435,7 @@ Domyślna cena rynkowa apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7435,7 +7443,7 @@ Tryb apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7443,7 +7451,7 @@ Selektor apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7451,7 +7459,7 @@ Nagłówki żądań HTTP apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7459,7 +7467,7 @@ koniec dnia apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7467,7 +7475,7 @@ w czasie rzeczywistym apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7708,7 +7716,7 @@ () jest już w użyciu. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7716,7 +7724,7 @@ Wystąpił błąd podczas aktualizacji do (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8067,7 +8075,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8075,7 +8083,7 @@ nowy apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index e49f13b96..72c1e6a3e 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -114,7 +114,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -126,7 +126,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -186,7 +186,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -290,11 +290,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -322,11 +322,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -414,7 +414,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -438,7 +438,7 @@ Perfil de Ativos apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -454,7 +454,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -766,11 +766,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -810,7 +810,7 @@ Referência apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -942,7 +942,7 @@ Depósito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -1214,7 +1214,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1234,7 +1234,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1246,7 +1246,7 @@ Marcadores apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1310,7 +1310,7 @@ AATD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -1322,7 +1322,7 @@ 1A apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -1334,7 +1334,7 @@ 5A apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -1354,7 +1354,7 @@ Máx apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -1590,7 +1590,7 @@ Localidade apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -1974,7 +1974,7 @@ Mercados apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -2078,7 +2078,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2142,7 +2142,7 @@ Nota apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -2758,7 +2758,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -2770,7 +2770,7 @@ Poupanças libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -2806,7 +2806,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3118,7 +3118,7 @@ Mapeamento de Símbolo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -3238,7 +3238,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -3302,7 +3302,7 @@ Válido até apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -3622,11 +3622,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -3821,6 +3821,14 @@ 306 + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 + + By By @@ -3842,7 +3850,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -3858,11 +3866,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -3878,7 +3886,7 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -3886,7 +3894,7 @@ Deseja mesmo eliminar esta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 @@ -3894,7 +3902,7 @@ Plataformas apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -4238,7 +4246,7 @@ Configuração do raspador apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -4778,11 +4786,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -5476,7 +5484,7 @@ Você realmente deseja excluir esta tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -5768,7 +5776,7 @@ O preço de mercado atual é apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5776,7 +5784,7 @@ Teste apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5936,7 +5944,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5956,7 +5964,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6004,7 +6012,7 @@ ano apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6024,7 +6032,7 @@ anos apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6044,7 +6052,7 @@ Coleta de dados apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6056,7 +6064,7 @@ geral apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6064,7 +6072,7 @@ Nuvem apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6076,7 +6084,7 @@ Auto-hospedagem apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6269,7 +6277,7 @@ Include in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6673,7 +6681,7 @@ Erro apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6725,7 +6733,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6777,7 +6785,7 @@ Fechar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7081,7 +7089,7 @@ Definir chave de API apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7187,7 +7195,7 @@ de apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7195,7 +7203,7 @@ solicitações diárias apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7203,7 +7211,7 @@ Remover chave de API apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7211,7 +7219,7 @@ Você realmente deseja excluir a chave de API? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7303,7 +7311,7 @@ Guardar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7379,7 +7387,7 @@ Please enter your Ghostfolio API key. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7411,7 +7419,7 @@ Lazy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7419,7 +7427,7 @@ Instant apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7427,7 +7435,7 @@ Preço de mercado padrão apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7435,7 +7443,7 @@ Mode apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7443,7 +7451,7 @@ Selector apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7451,7 +7459,7 @@ HTTP Request Headers apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7459,7 +7467,7 @@ end of day apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7467,7 +7475,7 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7708,7 +7716,7 @@ () is already in use. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7716,7 +7724,7 @@ An error occurred while updating to (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8067,7 +8075,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8075,7 +8083,7 @@ new apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index abe33aa80..7f51580d7 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -311,7 +311,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -323,7 +323,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -383,7 +383,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -471,11 +471,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -503,11 +503,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -595,7 +595,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -619,7 +619,7 @@ Varlık Profili apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -635,7 +635,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -859,7 +859,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -879,7 +879,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -891,7 +891,7 @@ Sembol Eşleştirme apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -907,7 +907,7 @@ Veri Toplayıcı Yapılandırması apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -915,7 +915,7 @@ Not apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1015,7 +1015,7 @@ Etiketler apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1107,11 +1107,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1127,7 +1127,7 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -1135,7 +1135,15 @@ Bu platformu silmeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 + + + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 @@ -1159,7 +1167,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -1175,7 +1183,7 @@ Platformlar apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -1251,11 +1259,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -1303,7 +1311,7 @@ Karşılaştırma Ölçütü apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -1507,7 +1515,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -1975,7 +1983,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -1987,7 +1995,7 @@ 1Y apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -1999,7 +2007,7 @@ 5Y apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -2019,7 +2027,7 @@ Maks. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -2447,11 +2455,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -2703,7 +2711,7 @@ Piyasalar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -3611,7 +3619,7 @@ Para Yatırma libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -3907,11 +3915,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -4392,7 +4400,7 @@ Geçerli tarih apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -4472,7 +4480,7 @@ Yerel Ayarlar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -4748,7 +4756,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -4760,7 +4768,7 @@ Tasarruflar libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -4832,7 +4840,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -4864,7 +4872,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5476,7 +5484,7 @@ Bu etiketi silmeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -5768,7 +5776,7 @@ Şu anki piyasa fiyatı apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5776,7 +5784,7 @@ Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5936,7 +5944,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5956,7 +5964,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6004,7 +6012,7 @@ Yıl apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6024,7 +6032,7 @@ Yıllar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6044,7 +6052,7 @@ Veri Toplama apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6056,7 +6064,7 @@ Genel apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6064,7 +6072,7 @@ Bulut apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6076,7 +6084,7 @@ Kendini Barındırma apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6269,7 +6277,7 @@ Include in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6673,7 +6681,7 @@ Hata apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6725,7 +6733,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6777,7 +6785,7 @@ Kapat apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7081,7 +7089,7 @@ API anahtarını ayarla apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7187,7 +7195,7 @@ ın apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7195,7 +7203,7 @@ günlük istekler apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7203,7 +7211,7 @@ API anahtarını kaldır apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7211,7 +7219,7 @@ API anahtarını silmek istediğinize emin misiniz? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7303,7 +7311,7 @@ Kaydet apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7379,7 +7387,7 @@ Lütfen Ghostfolio API anahtarınızı girin. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7411,7 +7419,7 @@ Tembel apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7419,7 +7427,7 @@ Anında apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7427,7 +7435,7 @@ Varsayılan Piyasa Fiyatı apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7435,7 +7443,7 @@ Mod apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7443,7 +7451,7 @@ Seçici apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7451,7 +7459,7 @@ HTTP İstek Başlıkları apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7459,7 +7467,7 @@ gün sonu apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7467,7 +7475,7 @@ gerçek zamanlı apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7708,7 +7716,7 @@ () is already in use. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7716,7 +7724,7 @@ Güncelleştirilirken bir hata oluştu (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8067,7 +8075,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8075,7 +8083,7 @@ yeni apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index 95ad50c7c..54bf5a08b 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -443,7 +443,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -455,7 +455,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -515,7 +515,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -603,11 +603,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -635,11 +635,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -707,7 +707,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -783,7 +783,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -999,7 +999,7 @@ Помилка apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -1007,7 +1007,7 @@ Поточна ринкова ціна apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -1059,7 +1059,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1079,7 +1079,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1091,7 +1091,7 @@ Зіставлення символів apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -1107,7 +1107,7 @@ Конфігурація скребка apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -1115,7 +1115,7 @@ Тест apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -1123,11 +1123,11 @@ URL apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1143,7 +1143,7 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -1151,7 +1151,7 @@ Примітка apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1307,7 +1307,7 @@ Збір даних apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -1379,7 +1379,15 @@ Ви дійсно хочете видалити цю платформу? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 + + + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 @@ -1403,7 +1411,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -1427,7 +1435,7 @@ Дійсне до apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -1439,7 +1447,7 @@ з apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -1447,7 +1455,7 @@ щоденних запитів apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -1455,7 +1463,7 @@ Вилучити ключ API apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -1463,7 +1471,7 @@ Встановити ключ API apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -1471,7 +1479,7 @@ Платформи apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -1479,7 +1487,7 @@ Теги apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1495,7 +1503,7 @@ Ви дійсно хочете видалити ключ API? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -1503,7 +1511,7 @@ Будь ласка, введіть ваш ключ API Ghostfolio. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -1587,7 +1595,7 @@ Ви дійсно хочете видалити цей тег? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -1667,11 +1675,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -1719,7 +1727,7 @@ Порівняльний показник apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -2079,7 +2087,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2283,7 +2291,7 @@ Зберегти apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -2563,7 +2571,7 @@ З початку року apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -2575,7 +2583,7 @@ 1 рік apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -2587,7 +2595,7 @@ 5 років apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -2607,7 +2615,7 @@ Максимум apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -2855,7 +2863,7 @@ Include in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -2911,7 +2919,7 @@ Локалізація apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -3503,11 +3511,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -3551,7 +3559,7 @@ Загальні apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -3559,7 +3567,7 @@ Хмара apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -3571,7 +3579,7 @@ Самохостинг apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -3772,7 +3780,7 @@ Ринки apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -5208,11 +5216,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -6163,7 +6171,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -6183,7 +6191,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -6203,7 +6211,7 @@ рік apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6223,7 +6231,7 @@ роки apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6235,7 +6243,7 @@ Профілі активів apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -6375,7 +6383,7 @@ Депозит libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -6391,7 +6399,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -6403,7 +6411,7 @@ Заощадження libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -6491,7 +6499,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -6523,7 +6531,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -6555,7 +6563,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6615,7 +6623,7 @@ Закрити apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7411,7 +7419,7 @@ Lazy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7419,7 +7427,7 @@ Instant apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7427,7 +7435,7 @@ Default Market Price apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7435,7 +7443,7 @@ Mode apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7443,7 +7451,7 @@ Selector apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7451,7 +7459,7 @@ HTTP Request Headers apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7459,7 +7467,7 @@ end of day apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7467,7 +7475,7 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7708,7 +7716,7 @@ () is already in use. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7716,7 +7724,7 @@ An error occurred while updating to (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8067,7 +8075,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8075,7 +8083,7 @@ new apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index b6a54edfe..7db54e0c4 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -334,7 +334,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -346,7 +346,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -404,7 +404,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -490,11 +490,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -521,11 +521,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -570,7 +570,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -625,7 +625,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -893,7 +893,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -912,7 +912,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -923,7 +923,7 @@ Symbol Mapping apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -937,14 +937,14 @@ Scraper Configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 Note apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1129,11 +1129,11 @@ Url apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1148,14 +1148,21 @@ Asset profile has been saved apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 Do you really want to delete this platform? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 + + + + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 @@ -1176,7 +1183,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -1190,14 +1197,14 @@ Platforms apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 Tags apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1219,7 +1226,7 @@ Do you really want to delete this tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -1301,11 +1308,11 @@ Could not validate form apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -1349,7 +1356,7 @@ Benchmark apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -1534,7 +1541,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -1965,7 +1972,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -1976,7 +1983,7 @@ 1Y apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -1987,7 +1994,7 @@ 5Y apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -2005,7 +2012,7 @@ Max apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -2144,7 +2151,7 @@ Locale apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2680,11 +2687,11 @@ Could not parse scraper configuration apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -2903,7 +2910,7 @@ Markets apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -3808,7 +3815,7 @@ Deposit libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -4074,11 +4081,11 @@ Could not save asset profile apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -4570,7 +4577,7 @@ Asset Profiles apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -4673,7 +4680,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -4684,7 +4691,7 @@ Savings libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -4751,7 +4758,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -4782,7 +4789,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5222,7 +5229,7 @@ Valid until apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -5281,14 +5288,14 @@ The current market price is apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 Test apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5438,7 +5445,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -5449,7 +5456,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -5485,7 +5492,7 @@ year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -5504,7 +5511,7 @@ years apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -5534,7 +5541,7 @@ Self-Hosting apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -5545,7 +5552,7 @@ Data Gathering apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -5556,14 +5563,14 @@ General apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 Cloud apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -5721,7 +5728,7 @@ Include in apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6082,7 +6089,7 @@ Error apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6093,7 +6100,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6172,7 +6179,7 @@ Close apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6454,7 +6461,7 @@ Set API key apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -6557,28 +6564,28 @@ of apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 Do you really want to delete the API key? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 Remove API key apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 daily requests apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -6652,7 +6659,7 @@ Save apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6724,7 +6731,7 @@ Please enter your Ghostfolio API key. apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -6752,56 +6759,56 @@ Mode apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 Default Market Price apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 Selector apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 Instant apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 Lazy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 HTTP Request Headers apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 end of day apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7016,14 +7023,14 @@ () is already in use. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 An error occurred while updating to (). apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -7315,14 +7322,14 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 new apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index ac81eebc7..be465e9df 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -360,7 +360,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 309 + 310 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -372,7 +372,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 46 + 58 apps/client/src/app/components/admin-tag/admin-tag.component.html @@ -432,7 +432,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 316 + 317 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -520,11 +520,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 74 + 78 apps/client/src/app/components/admin-tag/admin-tag.component.html - 67 + 71 libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -552,11 +552,11 @@ apps/client/src/app/components/admin-platform/admin-platform.component.html - 85 + 89 apps/client/src/app/components/admin-tag/admin-tag.component.html - 78 + 82 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -604,7 +604,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 448 + 451 @@ -664,7 +664,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 92 + 104 @@ -936,7 +936,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 396 + 399 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -956,7 +956,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 407 + 410 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -968,7 +968,7 @@ 代码映射 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 384 + 387 @@ -984,7 +984,7 @@ 刮削配置 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 471 + 474 @@ -992,7 +992,7 @@ 笔记 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 432 + 435 apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -1200,11 +1200,11 @@ 网址 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 419 + 422 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 550 + 553 apps/client/src/app/components/admin-platform/admin-platform.component.html @@ -1220,7 +1220,7 @@ 资产概况已保存 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 578 + 594 @@ -1228,7 +1228,15 @@ 您真的要删除这个平台吗? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 106 + 112 + + + + Explore + Explore + + apps/client/src/app/pages/resources/overview/resources-overview.component.html + 11 @@ -1252,7 +1260,7 @@ 当前年份 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 @@ -1268,7 +1276,7 @@ 平台 apps/client/src/app/components/admin-settings/admin-settings.component.html - 195 + 212 @@ -1276,7 +1284,7 @@ 标签 apps/client/src/app/components/admin-settings/admin-settings.component.html - 201 + 218 libs/ui/src/lib/tags-selector/tags-selector.component.html @@ -1300,7 +1308,7 @@ 您真的要删除此标签吗? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 109 @@ -1392,11 +1400,11 @@ 无法验证表单 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 554 + 570 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 557 + 573 @@ -1444,7 +1452,7 @@ 基准 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 376 + 379 apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts @@ -1648,7 +1656,7 @@ 当前周 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 @@ -2116,7 +2124,7 @@ 年初至今 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 199 + 204 libs/ui/src/lib/assistant/assistant.component.ts @@ -2128,7 +2136,7 @@ 1年 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 libs/ui/src/lib/assistant/assistant.component.ts @@ -2140,7 +2148,7 @@ 5年 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -2160,7 +2168,7 @@ 最大限度 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 211 + 216 libs/ui/src/lib/assistant/assistant.component.ts @@ -2316,7 +2324,7 @@ 语言环境 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 509 + 512 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2892,11 +2900,11 @@ 无法解析抓取器配置 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 509 + 525 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 512 + 528 @@ -3136,7 +3144,7 @@ 市场 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 378 + 381 apps/client/src/app/components/footer/footer.component.html @@ -4144,7 +4152,7 @@ 存款 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 385 + 390 @@ -4440,11 +4448,11 @@ 无法保存资产概况 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 588 + 604 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 591 + 607 @@ -4989,7 +4997,7 @@ 资产概况 apps/client/src/app/components/admin-settings/admin-settings.component.html - 106 + 123 libs/ui/src/lib/assistant/assistant.html @@ -5105,7 +5113,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 395 + 400 libs/ui/src/lib/i18n.ts @@ -5117,7 +5125,7 @@ 储蓄 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 405 + 410 @@ -5189,7 +5197,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 326 + 327 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5221,7 +5229,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 342 + 343 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -5713,7 +5721,7 @@ 有效期至 apps/client/src/app/components/admin-settings/admin-settings.component.html - 74 + 86 libs/ui/src/lib/membership-card/membership-card.component.html @@ -5777,7 +5785,7 @@ 当前市场价格为 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 706 + 722 @@ -5785,7 +5793,7 @@ 测试 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 568 + 571 @@ -5953,7 +5961,7 @@ 本月至今 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 libs/ui/src/lib/assistant/assistant.component.ts @@ -5965,7 +5973,7 @@ 本周至今 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 191 + 196 libs/ui/src/lib/assistant/assistant.component.ts @@ -6005,7 +6013,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 203 + 208 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6025,7 +6033,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 207 + 212 libs/ui/src/lib/assistant/assistant.component.ts @@ -6058,7 +6066,7 @@ 自托管 apps/client/src/app/pages/faq/faq-page.component.ts - 60 + 52 libs/common/src/lib/routes/routes.ts @@ -6070,7 +6078,7 @@ 数据收集 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 587 + 594 apps/client/src/app/components/admin-overview/admin-overview.html @@ -6082,7 +6090,7 @@ 一般的 apps/client/src/app/pages/faq/faq-page.component.ts - 49 + 41 @@ -6090,7 +6098,7 @@ apps/client/src/app/pages/faq/faq-page.component.ts - 54 + 46 libs/common/src/lib/routes/routes.ts @@ -6270,7 +6278,7 @@ 包含在 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 374 + 377 @@ -6674,7 +6682,7 @@ 错误 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 697 + 713 @@ -6726,7 +6734,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 592 + 599 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -6778,7 +6786,7 @@ 关闭 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 594 + 601 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7082,7 +7090,7 @@ 设置 API 密钥 apps/client/src/app/components/admin-settings/admin-settings.component.html - 171 + 188 @@ -7188,7 +7196,7 @@ apps/client/src/app/components/admin-settings/admin-settings.component.html - 135 + 152 @@ -7196,7 +7204,7 @@ 每日请求 apps/client/src/app/components/admin-settings/admin-settings.component.html - 137 + 154 @@ -7204,7 +7212,7 @@ 移除 API 密钥 apps/client/src/app/components/admin-settings/admin-settings.component.html - 161 + 178 @@ -7212,7 +7220,7 @@ 您确定要删除此 API 密钥吗? apps/client/src/app/components/admin-settings/admin-settings.component.ts - 127 + 133 @@ -7304,7 +7312,7 @@ 保存 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 603 + 610 apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html @@ -7380,7 +7388,7 @@ 请输入您的 Ghostfolio API 密钥。 apps/client/src/app/components/admin-settings/admin-settings.component.ts - 146 + 152 @@ -7412,7 +7420,7 @@ 延迟 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7420,7 +7428,7 @@ 即时 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7428,7 +7436,7 @@ 默认市场价格 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 481 + 484 @@ -7436,7 +7444,7 @@ 模式 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 518 + 521 @@ -7444,7 +7452,7 @@ 选择器 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 534 + 537 @@ -7452,7 +7460,7 @@ HTTP 请求标头 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html - 494 + 497 @@ -7460,7 +7468,7 @@ 收盘 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 225 + 230 @@ -7468,7 +7476,7 @@ 实时 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 229 + 234 @@ -7709,7 +7717,7 @@ () 已在使用中。 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 633 + 649 @@ -7717,7 +7725,7 @@ 在更新到 () 时发生错误。 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 641 + 657 @@ -8068,7 +8076,7 @@ 当前月份 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 195 + 200 @@ -8076,7 +8084,7 @@ 新增 apps/client/src/app/components/admin-settings/admin-settings.component.html - 67 + 79 apps/client/src/app/pages/admin/admin-page.component.ts From d39172f0ebd9763c0d014db79d5b54fac0c9a1c6 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 10 Mar 2026 19:34:25 +0100 Subject: [PATCH 048/138] Task/improve language localization for DE (20260310) (#6511) * Update translation * Update changelog --- CHANGELOG.md | 1 + apps/client/src/locales/messages.de.xlf | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89c34edde..aeadceb93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the _Storybook_ stories of the value component - Improved the language localization for Dutch (`nl`) +- Improved the language localization for German (`de`) - Upgraded `class-validator` from version `0.14.3` to `0.15.1` ### Fixed diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 74365a176..cad4fcc92 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -3847,7 +3847,7 @@ Explore - Explore + Entdecke apps/client/src/app/pages/resources/overview/resources-overview.component.html 11 From efa93a3b988e93a62cb8d0acd36522f901f17f33 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 10 Mar 2026 20:23:03 +0100 Subject: [PATCH 049/138] Feature/setup Bull Dashboard (#6501) * Initial setup * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/app.module.ts | 34 +++++- apps/api/src/app/user/user.service.ts | 10 +- apps/api/src/main.ts | 6 + .../middlewares/bull-board-auth.middleware.ts | 28 +++++ .../configuration/configuration.service.ts | 2 + .../interfaces/environment.interface.ts | 2 + .../data-gathering/data-gathering.module.ts | 14 +++ .../portfolio-snapshot.module.ts | 14 +++ apps/client/proxy.conf.json | 4 + .../admin-jobs/admin-jobs.component.ts | 51 ++++++--- .../app/components/admin-jobs/admin-jobs.html | 9 ++ libs/common/src/lib/config.ts | 8 ++ libs/common/src/lib/permissions.ts | 1 + package-lock.json | 103 +++++++++++++++--- package.json | 5 + 16 files changed, 259 insertions(+), 33 deletions(-) create mode 100644 apps/api/src/middlewares/bull-board-auth.middleware.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index aeadceb93..a01c57e86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Integrated _Bull Dashboard_ for a detailed jobs queue view in the admin control panel (experimental) - Added a debounce to the `PortfolioChangedListener` and `AssetProfileChangedListener` to minimize redundant _Redis_ and database operations ### Changed diff --git a/apps/api/src/app/app.module.ts b/apps/api/src/app/app.module.ts index 4b790d0db..8ebe05928 100644 --- a/apps/api/src/app/app.module.ts +++ b/apps/api/src/app/app.module.ts @@ -1,4 +1,5 @@ import { EventsModule } from '@ghostfolio/api/events/events.module'; +import { BullBoardAuthMiddleware } from '@ghostfolio/api/middlewares/bull-board-auth.middleware'; import { HtmlTemplateMiddleware } from '@ghostfolio/api/middlewares/html-template.middleware'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { CronModule } from '@ghostfolio/api/services/cron/cron.module'; @@ -10,10 +11,13 @@ import { PropertyModule } from '@ghostfolio/api/services/property/property.modul import { DataGatheringModule } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.module'; import { PortfolioSnapshotQueueModule } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.module'; import { + BULL_BOARD_ROUTE, DEFAULT_LANGUAGE_CODE, SUPPORTED_LANGUAGE_CODES } from '@ghostfolio/common/config'; +import { ExpressAdapter } from '@bull-board/express'; +import { BullBoardModule } from '@bull-board/nestjs'; import { BullModule } from '@nestjs/bull'; import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; @@ -70,6 +74,29 @@ import { UserModule } from './user/user.module'; AuthDeviceModule, AuthModule, BenchmarksModule, + ...(process.env.ENABLE_FEATURE_BULL_BOARD === 'true' + ? [ + BullBoardModule.forRoot({ + adapter: ExpressAdapter, + boardOptions: { + uiConfig: { + boardLogo: { + height: 0, + path: '', + width: 0 + }, + boardTitle: 'Job Queues', + favIcon: { + alternative: '/assets/favicon-32x32.png', + default: '/assets/favicon-32x32.png' + } + } + }, + middleware: BullBoardAuthMiddleware, + route: BULL_BOARD_ROUTE + }) + ] + : []), BullModule.forRoot({ redis: { db: parseInt(process.env.REDIS_DB ?? '0', 10), @@ -105,7 +132,12 @@ import { UserModule } from './user/user.module'; RedisCacheModule, ScheduleModule.forRoot(), ServeStaticModule.forRoot({ - exclude: ['/.well-known/*wildcard', '/api/*wildcard', '/sitemap.xml'], + exclude: [ + `${BULL_BOARD_ROUTE}/*wildcard`, + '/.well-known/*wildcard', + '/api/*wildcard', + '/sitemap.xml' + ], rootPath: join(__dirname, '..', 'client'), serveStaticOptions: { setHeaders: (res) => { diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 5a339c090..370f5d422 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -530,8 +530,14 @@ export class UserService { } } - if (!environment.production && hasRole(user, Role.ADMIN)) { - currentPermissions.push(permissions.impersonateAllUsers); + if (hasRole(user, Role.ADMIN)) { + if (this.configurationService.get('ENABLE_FEATURE_BULL_BOARD')) { + currentPermissions.push(permissions.accessAdminControlBullBoard); + } + + if (!environment.production) { + currentPermissions.push(permissions.impersonateAllUsers); + } } user.accounts = user.accounts.sort((a, b) => { diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index a8de3dc5e..f08a09a83 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -1,4 +1,5 @@ import { + BULL_BOARD_ROUTE, DEFAULT_HOST, DEFAULT_PORT, STORYBOOK_PATH, @@ -14,6 +15,7 @@ import { import { ConfigService } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; import type { NestExpressApplication } from '@nestjs/platform-express'; +import cookieParser from 'cookie-parser'; import { NextFunction, Request, Response } from 'express'; import helmet from 'helmet'; @@ -46,6 +48,7 @@ async function bootstrap() { }); app.setGlobalPrefix('api', { exclude: [ + `${BULL_BOARD_ROUTE.substring(1)}{/*wildcard}`, 'sitemap.xml', ...SUPPORTED_LANGUAGE_CODES.map((languageCode) => { // Exclude language-specific routes with an optional wildcard @@ -53,6 +56,7 @@ async function bootstrap() { }) ] }); + app.useGlobalPipes( new ValidationPipe({ forbidNonWhitelisted: true, @@ -64,6 +68,8 @@ async function bootstrap() { // Support 10mb csv/json files for importing activities app.useBodyParser('json', { limit: '10mb' }); + app.use(cookieParser()); + if (configService.get('ENABLE_FEATURE_SUBSCRIPTION') === 'true') { app.use((req: Request, res: Response, next: NextFunction) => { if (req.path.startsWith(STORYBOOK_PATH)) { diff --git a/apps/api/src/middlewares/bull-board-auth.middleware.ts b/apps/api/src/middlewares/bull-board-auth.middleware.ts new file mode 100644 index 000000000..432deb974 --- /dev/null +++ b/apps/api/src/middlewares/bull-board-auth.middleware.ts @@ -0,0 +1,28 @@ +import { BULL_BOARD_COOKIE_NAME } from '@ghostfolio/common/config'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; + +import { ForbiddenException, Injectable, NestMiddleware } from '@nestjs/common'; +import { NextFunction, Request, Response } from 'express'; +import passport from 'passport'; + +@Injectable() +export class BullBoardAuthMiddleware implements NestMiddleware { + public use(req: Request, res: Response, next: NextFunction) { + const token = req.cookies?.[BULL_BOARD_COOKIE_NAME]; + + if (token) { + req.headers.authorization = `Bearer ${token}`; + } + + passport.authenticate('jwt', { session: false }, (error, user) => { + if ( + error || + !hasPermission(user?.permissions, permissions.accessAdminControl) + ) { + next(new ForbiddenException()); + } else { + next(); + } + })(req, res, next); + } +} diff --git a/apps/api/src/services/configuration/configuration.service.ts b/apps/api/src/services/configuration/configuration.service.ts index 5f9d1055d..ad8e84a99 100644 --- a/apps/api/src/services/configuration/configuration.service.ts +++ b/apps/api/src/services/configuration/configuration.service.ts @@ -30,6 +30,7 @@ export class ConfigurationService { API_KEY_FINANCIAL_MODELING_PREP: str({ default: '' }), API_KEY_OPEN_FIGI: str({ default: '' }), API_KEY_RAPID_API: str({ default: '' }), + BULL_BOARD_IS_READ_ONLY: bool({ default: true }), CACHE_QUOTES_TTL: num({ default: ms('1 minute') }), CACHE_TTL: num({ default: CACHE_TTL_NO_CACHE }), DATA_SOURCE_EXCHANGE_RATES: str({ default: DataSource.YAHOO }), @@ -43,6 +44,7 @@ export class ConfigurationService { ENABLE_FEATURE_AUTH_GOOGLE: bool({ default: false }), ENABLE_FEATURE_AUTH_OIDC: bool({ default: false }), ENABLE_FEATURE_AUTH_TOKEN: bool({ default: true }), + ENABLE_FEATURE_BULL_BOARD: bool({ default: false }), ENABLE_FEATURE_FEAR_AND_GREED_INDEX: bool({ default: false }), ENABLE_FEATURE_GATHER_NEW_EXCHANGE_RATES: bool({ default: true }), ENABLE_FEATURE_READ_ONLY_MODE: bool({ default: false }), diff --git a/apps/api/src/services/interfaces/environment.interface.ts b/apps/api/src/services/interfaces/environment.interface.ts index 57c58898e..9664ae144 100644 --- a/apps/api/src/services/interfaces/environment.interface.ts +++ b/apps/api/src/services/interfaces/environment.interface.ts @@ -10,6 +10,7 @@ export interface Environment extends CleanedEnvAccessors { API_KEY_FINANCIAL_MODELING_PREP: string; API_KEY_OPEN_FIGI: string; API_KEY_RAPID_API: string; + BULL_BOARD_IS_READ_ONLY: boolean; CACHE_QUOTES_TTL: number; CACHE_TTL: number; DATA_SOURCE_EXCHANGE_RATES: string; @@ -19,6 +20,7 @@ export interface Environment extends CleanedEnvAccessors { ENABLE_FEATURE_AUTH_GOOGLE: boolean; ENABLE_FEATURE_AUTH_OIDC: boolean; ENABLE_FEATURE_AUTH_TOKEN: boolean; + ENABLE_FEATURE_BULL_BOARD: boolean; ENABLE_FEATURE_FEAR_AND_GREED_INDEX: boolean; ENABLE_FEATURE_GATHER_NEW_EXCHANGE_RATES: boolean; ENABLE_FEATURE_READ_ONLY_MODE: boolean; diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.module.ts b/apps/api/src/services/queues/data-gathering/data-gathering.module.ts index b51823476..f251c8d0c 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.module.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.module.ts @@ -9,6 +9,8 @@ import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathe import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; import { DATA_GATHERING_QUEUE } from '@ghostfolio/common/config'; +import { BullAdapter } from '@bull-board/api/bullAdapter'; +import { BullBoardModule } from '@bull-board/nestjs'; import { BullModule } from '@nestjs/bull'; import { Module } from '@nestjs/common'; import ms from 'ms'; @@ -17,6 +19,18 @@ import { DataGatheringProcessor } from './data-gathering.processor'; @Module({ imports: [ + ...(process.env.ENABLE_FEATURE_BULL_BOARD === 'true' + ? [ + BullBoardModule.forFeature({ + adapter: BullAdapter, + name: DATA_GATHERING_QUEUE, + options: { + displayName: 'Data Gathering', + readOnlyMode: process.env.BULL_BOARD_IS_READ_ONLY !== 'false' + } + }) + ] + : []), BullModule.registerQueue({ limiter: { duration: ms('4 seconds'), diff --git a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.module.ts b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.module.ts index 553765768..1260f1cf0 100644 --- a/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.module.ts +++ b/apps/api/src/services/queues/portfolio-snapshot/portfolio-snapshot.module.ts @@ -13,6 +13,8 @@ import { PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE } from '@ghostfolio/common/config'; +import { BullAdapter } from '@bull-board/api/bullAdapter'; +import { BullBoardModule } from '@bull-board/nestjs'; import { BullModule } from '@nestjs/bull'; import { Module } from '@nestjs/common'; @@ -23,6 +25,18 @@ import { PortfolioSnapshotProcessor } from './portfolio-snapshot.processor'; imports: [ AccountBalanceModule, ActivitiesModule, + ...(process.env.ENABLE_FEATURE_BULL_BOARD === 'true' + ? [ + BullBoardModule.forFeature({ + adapter: BullAdapter, + name: PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE, + options: { + displayName: 'Portfolio Snapshot Computation', + readOnlyMode: process.env.BULL_BOARD_IS_READ_ONLY !== 'false' + } + }) + ] + : []), BullModule.registerQueue({ name: PORTFOLIO_SNAPSHOT_COMPUTATION_QUEUE, settings: { diff --git a/apps/client/proxy.conf.json b/apps/client/proxy.conf.json index a31371d9f..825965b92 100644 --- a/apps/client/proxy.conf.json +++ b/apps/client/proxy.conf.json @@ -1,4 +1,8 @@ { + "/admin/queues": { + "target": "http://0.0.0.0:3333", + "secure": false + }, "/api": { "target": "http://0.0.0.0:3333", "secure": false diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts index de70a7b6e..1537db2a0 100644 --- a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts +++ b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts @@ -1,5 +1,8 @@ +import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { + BULL_BOARD_COOKIE_NAME, + BULL_BOARD_ROUTE, DATA_GATHERING_QUEUE_PRIORITY_HIGH, DATA_GATHERING_QUEUE_PRIORITY_LOW, DATA_GATHERING_QUEUE_PRIORITY_MEDIUM, @@ -7,6 +10,7 @@ import { } from '@ghostfolio/common/config'; import { getDateWithTimeFormatString } from '@ghostfolio/common/helper'; import { AdminJobs, User } from '@ghostfolio/common/interfaces'; +import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { NotificationService } from '@ghostfolio/ui/notifications'; import { AdminService } from '@ghostfolio/ui/services'; @@ -15,10 +19,11 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, - OnDestroy, + DestroyRef, OnInit, ViewChild } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormBuilder, FormGroup, @@ -41,6 +46,7 @@ import { chevronUpCircleOutline, ellipsisHorizontal, ellipsisVertical, + openOutline, pauseOutline, playOutline, removeCircleOutline, @@ -48,8 +54,6 @@ import { } from 'ionicons/icons'; import { get } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -69,7 +73,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./admin-jobs.scss'], templateUrl: './admin-jobs.html' }) -export class GfAdminJobsComponent implements OnDestroy, OnInit { +export class GfAdminJobsComponent implements OnInit { @ViewChild(MatSort) sort: MatSort; public DATA_GATHERING_QUEUE_PRIORITY_LOW = DATA_GATHERING_QUEUE_PRIORITY_LOW; @@ -81,6 +85,7 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { public dataSource = new MatTableDataSource(); public defaultDateTimeFormat: string; public filterForm: FormGroup; + public displayedColumns = [ 'index', 'type', @@ -93,21 +98,24 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { 'status', 'actions' ]; + + public hasPermissionToAccessBullBoard = false; public isLoading = false; public statusFilterOptions = QUEUE_JOB_STATUS_LIST; - public user: User; - private unsubscribeSubject = new Subject(); + private user: User; public constructor( private adminService: AdminService, private changeDetectorRef: ChangeDetectorRef, + private destroyRef: DestroyRef, private formBuilder: FormBuilder, private notificationService: NotificationService, + private tokenStorageService: TokenStorageService, private userService: UserService ) { this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -115,6 +123,11 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { this.defaultDateTimeFormat = getDateWithTimeFormatString( this.user.settings.locale ); + + this.hasPermissionToAccessBullBoard = hasPermission( + this.user.permissions, + permissions.accessAdminControlBullBoard + ); } }); @@ -126,6 +139,7 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { chevronUpCircleOutline, ellipsisHorizontal, ellipsisVertical, + openOutline, pauseOutline, playOutline, removeCircleOutline, @@ -139,7 +153,7 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { }); this.filterForm.valueChanges - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { const currentFilter = this.filterForm.get('status').value; this.fetchJobs(currentFilter ? [currentFilter] : undefined); @@ -151,7 +165,7 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { public onDeleteJob(aId: string) { this.adminService .deleteJob(aId) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.fetchJobs(); }); @@ -162,7 +176,7 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { this.adminService .deleteJobs({ status: currentFilter ? [currentFilter] : undefined }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.fetchJobs(currentFilter ? [currentFilter] : undefined); }); @@ -171,12 +185,20 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { public onExecuteJob(aId: string) { this.adminService .executeJob(aId) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.fetchJobs(); }); } + public onOpenBullBoard() { + const token = this.tokenStorageService.getToken(); + + document.cookie = `${BULL_BOARD_COOKIE_NAME}=${token}; path=${BULL_BOARD_ROUTE}; SameSite=Strict`; + + window.open(BULL_BOARD_ROUTE, '_blank'); + } + public onViewData(aData: AdminJobs['jobs'][0]['data']) { this.notificationService.alert({ title: JSON.stringify(aData, null, ' ') @@ -189,17 +211,12 @@ export class GfAdminJobsComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private fetchJobs(aStatus?: JobStatus[]) { this.isLoading = true; this.adminService .fetchJobs({ status: aStatus }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ jobs }) => { this.dataSource = new MatTableDataSource(jobs); this.dataSource.sort = this.sort; diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.html b/apps/client/src/app/components/admin-jobs/admin-jobs.html index a82294001..cff80498c 100644 --- a/apps/client/src/app/components/admin-jobs/admin-jobs.html +++ b/apps/client/src/app/components/admin-jobs/admin-jobs.html @@ -1,6 +1,15 @@
+ @if (hasPermissionToAccessBullBoard) { +
+ +
+ } +
diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index 5da0e0122..08fa2f030 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -51,6 +51,14 @@ export const ASSET_CLASS_MAPPING = new Map([ [AssetClass.REAL_ESTATE, []] ]); +export const BULL_BOARD_COOKIE_NAME = 'bull_board_token'; + +/** + * WARNING: This route is mirrored in `apps/client/proxy.conf.json`. + * If you update this value, you must also update the proxy configuration. + */ +export const BULL_BOARD_ROUTE = '/admin/queues'; + export const CACHE_TTL_NO_CACHE = 1; export const CACHE_TTL_INFINITE = 0; diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts index 62ae59fbe..a70e61bac 100644 --- a/libs/common/src/lib/permissions.ts +++ b/libs/common/src/lib/permissions.ts @@ -4,6 +4,7 @@ import { Role } from '@prisma/client'; export const permissions = { accessAdminControl: 'accessAdminControl', + accessAdminControlBullBoard: 'accessAdminControlBullBoard', accessAssistant: 'accessAssistant', accessHoldingsChart: 'accessHoldingsChart', createAccess: 'createAccess', diff --git a/package-lock.json b/package-lock.json index 1654d1acd..289fa0ecb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,9 @@ "@angular/platform-browser-dynamic": "21.1.1", "@angular/router": "21.1.1", "@angular/service-worker": "21.1.1", + "@bull-board/api": "6.20.3", + "@bull-board/express": "6.20.3", + "@bull-board/nestjs": "6.20.3", "@codewithdan/observable-store": "2.2.15", "@date-fns/utc": "2.1.1", "@internationalized/number": "3.6.5", @@ -55,6 +58,7 @@ "class-transformer": "0.5.1", "class-validator": "0.15.1", "color": "5.0.3", + "cookie-parser": "1.4.7", "countries-and-timezones": "3.8.0", "countries-list": "3.2.2", "countup.js": "2.9.0", @@ -123,6 +127,7 @@ "@storybook/angular": "10.1.10", "@trivago/prettier-plugin-sort-imports": "5.2.2", "@types/big.js": "6.2.2", + "@types/cookie-parser": "1.4.10", "@types/fast-redact": "3.0.4", "@types/google-spreadsheet": "3.1.5", "@types/jest": "30.0.0", @@ -3641,6 +3646,53 @@ "devOptional": true, "license": "(Apache-2.0 AND BSD-3-Clause)" }, + "node_modules/@bull-board/api": { + "version": "6.20.3", + "resolved": "https://registry.npmjs.org/@bull-board/api/-/api-6.20.3.tgz", + "integrity": "sha512-cDrsJJsmF4DbbY8/5oHxO4qFtyFjxexsWQKHowsud/8H4mtZN7MZg4fCmNzfaxc9Ov7V6r9Y9F5G2Mq6t7ZEJg==", + "license": "MIT", + "dependencies": { + "redis-info": "^3.1.0" + }, + "peerDependencies": { + "@bull-board/ui": "6.20.3" + } + }, + "node_modules/@bull-board/express": { + "version": "6.20.3", + "resolved": "https://registry.npmjs.org/@bull-board/express/-/express-6.20.3.tgz", + "integrity": "sha512-S6BGeSf/PLwjx5W1IrKxoV8G6iiMmLqT/pldZ6BiC1IDldedisTtAdL1z117swXPv1H7/3hy0vr03dUr8bUCPg==", + "license": "MIT", + "dependencies": { + "@bull-board/api": "6.20.3", + "@bull-board/ui": "6.20.3", + "ejs": "^3.1.10", + "express": "^5.2.1" + } + }, + "node_modules/@bull-board/nestjs": { + "version": "6.20.3", + "resolved": "https://registry.npmjs.org/@bull-board/nestjs/-/nestjs-6.20.3.tgz", + "integrity": "sha512-VFi96Z2M8k3G26H1ivzQnpjKszxh90vrUm78VtMZH/sh8wjm88mJFDXcOgFutOaddx7cc9VNXlKsTTcu6okPFQ==", + "license": "MIT", + "peerDependencies": { + "@bull-board/api": "^6.20.3", + "@nestjs/bull-shared": "^10.0.0 || ^11.0.0", + "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0", + "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0", + "reflect-metadata": "^0.1.13 || ^0.2.0", + "rxjs": "^7.8.1" + } + }, + "node_modules/@bull-board/ui": { + "version": "6.20.3", + "resolved": "https://registry.npmjs.org/@bull-board/ui/-/ui-6.20.3.tgz", + "integrity": "sha512-oANyYoW0X+xd0j/09DRyh3u7Q3wqBtXiLEWyZUJIi/Bjp/hINwiw20RwWuRcaFkqkFylEJL9l+pjmeSA9X5L2A==", + "license": "MIT", + "dependencies": { + "@bull-board/api": "6.20.3" + } + }, "node_modules/@chevrotain/cst-dts-gen": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", @@ -12688,6 +12740,16 @@ "@types/node": "*" } }, + "node_modules/@types/cookie-parser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.10.tgz", + "integrity": "sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, "node_modules/@types/d3": { "version": "7.4.3", "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", @@ -14979,7 +15041,6 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, "license": "MIT" }, "node_modules/async-function": { @@ -15373,7 +15434,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, "node_modules/base64-js": { @@ -15627,7 +15687,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -16852,7 +16911,6 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/confbox": { @@ -16924,6 +16982,25 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, "node_modules/cookie-signature": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", @@ -18812,7 +18889,6 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "jake": "^10.8.5" @@ -20253,7 +20329,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, "license": "Apache-2.0", "dependencies": { "minimatch": "^5.0.1" @@ -20263,7 +20338,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -20273,7 +20347,6 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -21485,7 +21558,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "devOptional": true, "license": "MIT", "engines": { "node": ">=8" @@ -23125,7 +23197,6 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "async": "^3.2.3", @@ -23144,7 +23215,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -25916,7 +25986,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -29532,6 +29601,15 @@ "node": ">=4" } }, + "node_modules/redis-info": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redis-info/-/redis-info-3.1.0.tgz", + "integrity": "sha512-ER4L9Sh/vm63DkIE0bkSjxluQlioBiBgf5w1UuldaW/3vPcecdljVDisZhmnCMvsxHNiARTTDDHGg9cGwTfrKg==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.11" + } + }, "node_modules/redis-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", @@ -32233,7 +32311,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" diff --git a/package.json b/package.json index 9fe3ef3c2..33ed6ce65 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,9 @@ "@angular/platform-browser-dynamic": "21.1.1", "@angular/router": "21.1.1", "@angular/service-worker": "21.1.1", + "@bull-board/api": "6.20.3", + "@bull-board/express": "6.20.3", + "@bull-board/nestjs": "6.20.3", "@codewithdan/observable-store": "2.2.15", "@date-fns/utc": "2.1.1", "@internationalized/number": "3.6.5", @@ -100,6 +103,7 @@ "class-transformer": "0.5.1", "class-validator": "0.15.1", "color": "5.0.3", + "cookie-parser": "1.4.7", "countries-and-timezones": "3.8.0", "countries-list": "3.2.2", "countup.js": "2.9.0", @@ -168,6 +172,7 @@ "@storybook/angular": "10.1.10", "@trivago/prettier-plugin-sort-imports": "5.2.2", "@types/big.js": "6.2.2", + "@types/cookie-parser": "1.4.10", "@types/fast-redact": "3.0.4", "@types/google-spreadsheet": "3.1.5", "@types/jest": "30.0.0", From d7a56c5cbc33e68f699255974e5c8097282e2b1c Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 10 Mar 2026 20:24:56 +0100 Subject: [PATCH 050/138] Release 2.249.0 (#6512) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a01c57e86..98bcdb20f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.249.0 - 2026-03-10 ### Added diff --git a/package-lock.json b/package-lock.json index 289fa0ecb..e4cf3382c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.248.0", + "version": "2.249.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.248.0", + "version": "2.249.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 33ed6ce65..03f4a527d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.248.0", + "version": "2.249.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From 8bca0f58303904f427f022d57fd787ad92603769 Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Thu, 12 Mar 2026 01:47:24 +0700 Subject: [PATCH 051/138] Task/improve type safety in portfolio proportion chart component (#6491) * Improve type safety in portfolio proportion chart component --- .../portfolio-proportion-chart.component.ts | 94 ++++++++++--------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts index 7d0203e9c..2f5d9e4f7 100644 --- a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts +++ b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts @@ -13,12 +13,11 @@ import { ChangeDetectionStrategy, Component, ElementRef, - EventEmitter, Input, OnChanges, OnDestroy, - Output, - ViewChild + output, + viewChild } from '@angular/core'; import { DataSource } from '@prisma/client'; import { Big } from 'big.js'; @@ -81,15 +80,16 @@ export class GfPortfolioProportionChartComponent @Input() maxItems?: number; @Input() showLabels = false; - @Output() proportionChartClicked = new EventEmitter(); - - @ViewChild('chartCanvas') chartCanvas: ElementRef; - public chart: Chart<'doughnut'>; public isLoading = true; + protected readonly proportionChartClicked = output(); + private readonly OTHER_KEY = 'OTHER'; + private readonly chartCanvas = + viewChild.required>('chartCanvas'); + private colorMap: { [symbol: string]: string; } = {}; @@ -130,45 +130,45 @@ export class GfPortfolioProportionChartComponent }; if (this.keys.length > 0) { + const primaryKey = this.keys[0]; + const secondaryKey = this.keys[1]; + Object.keys(this.data).forEach((symbol) => { - if (this.data[symbol][this.keys[0]]?.toUpperCase()) { - if (chartData[this.data[symbol][this.keys[0]].toUpperCase()]) { - chartData[this.data[symbol][this.keys[0]].toUpperCase()].value = - chartData[ - this.data[symbol][this.keys[0]].toUpperCase() - ].value.plus(this.data[symbol].value || 0); - - if ( - chartData[this.data[symbol][this.keys[0]].toUpperCase()] - .subCategory[this.data[symbol][this.keys[1]]] - ) { - chartData[ - this.data[symbol][this.keys[0]].toUpperCase() - ].subCategory[this.data[symbol][this.keys[1]]].value = chartData[ - this.data[symbol][this.keys[0]].toUpperCase() - ].subCategory[this.data[symbol][this.keys[1]]].value.plus( - this.data[symbol].value || 0 - ); + const asset = this.data[symbol]; + const assetValue = asset.value || 0; + const primaryKeyValue = (asset[primaryKey] as string)?.toUpperCase(); + const secondaryKeyValue = asset[secondaryKey] as string; + + if (primaryKeyValue) { + if (chartData[primaryKeyValue]) { + chartData[primaryKeyValue].value = + chartData[primaryKeyValue].value.plus(assetValue); + + const targetSubCategory = + chartData[primaryKeyValue].subCategory?.[secondaryKeyValue]; + if (targetSubCategory) { + targetSubCategory.value = + targetSubCategory.value.plus(assetValue); } else { - chartData[ - this.data[symbol][this.keys[0]].toUpperCase() - ].subCategory[this.data[symbol][this.keys[1]] ?? UNKNOWN_KEY] = { - value: new Big(this.data[symbol].value || 0) - }; + if (chartData[primaryKeyValue].subCategory) { + chartData[primaryKeyValue].subCategory[ + secondaryKeyValue ?? UNKNOWN_KEY + ] = { + value: new Big(assetValue) + }; + } } } else { - chartData[this.data[symbol][this.keys[0]].toUpperCase()] = { - name: this.data[symbol][this.keys[0]], + chartData[primaryKeyValue] = { + name: asset[primaryKey] as string, subCategory: {}, - value: new Big(this.data[symbol].value || 0) + value: new Big(assetValue) }; - if (this.data[symbol][this.keys[1]]) { - chartData[ - this.data[symbol][this.keys[0]].toUpperCase() - ].subCategory = { - [this.data[symbol][this.keys[1]]]: { - value: new Big(this.data[symbol].value || 0) + if (secondaryKeyValue) { + chartData[primaryKeyValue].subCategory = { + [secondaryKeyValue]: { + value: new Big(assetValue) } }; } @@ -181,10 +181,10 @@ export class GfPortfolioProportionChartComponent } else { chartData[UNKNOWN_KEY] = { name: this.data[symbol].name, - subCategory: this.keys[1] - ? { [this.keys[1]]: { value: new Big(0) } } + subCategory: secondaryKey + ? { [secondaryKey]: { value: new Big(0) } } : undefined, - value: new Big(this.data[symbol].value || 0) + value: new Big(assetValue) }; } } @@ -278,13 +278,15 @@ export class GfPortfolioProportionChartComponent Object.keys(item.subCategory ?? {}).forEach((subCategory) => { if (item.name === UNKNOWN_KEY) { - backgroundColorSubCategory.push(item.color); + backgroundColorSubCategory.push(item.color ?? ''); } else { backgroundColorSubCategory.push( Color(item.color).lighten(lightnessRatio).hex() ); } - dataSubCategory.push(item.subCategory[subCategory].value.toNumber()); + dataSubCategory.push( + item.subCategory?.[subCategory].value.toNumber() ?? 0 + ); labelSubCategory.push(subCategory); lightnessRatio += 0.1; @@ -334,7 +336,7 @@ export class GfPortfolioProportionChartComponent labels }; - if (this.chartCanvas) { + if (this.chartCanvas()) { if (this.chart) { this.chart.data = data; this.chart.options.plugins ??= {}; @@ -343,7 +345,7 @@ export class GfPortfolioProportionChartComponent this.chart.update(); } else { - this.chart = new Chart<'doughnut'>(this.chartCanvas.nativeElement, { + this.chart = new Chart<'doughnut'>(this.chartCanvas().nativeElement, { data, options: { animation: false, From 8f68bd98c25fcec978d958b3bcba836bc12fec1d Mon Sep 17 00:00:00 2001 From: Erwin-N <111194281+Erwin-N@users.noreply.github.com> Date: Wed, 11 Mar 2026 20:01:25 +0100 Subject: [PATCH 052/138] Task/upgrade svgmap to version 2.19.2 (#6503) * Upgrade svgmap to version 2.19.2 * Update changelog --- CHANGELOG.md | 6 ++++++ apps/client/src/styles.scss | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98bcdb20f..103a09fbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Upgraded `svgmap` from version `2.14.0` to `2.19.2` + ## 2.249.0 - 2026-03-10 ### Added diff --git a/apps/client/src/styles.scss b/apps/client/src/styles.scss index b7a031bfa..142d2ea53 100644 --- a/apps/client/src/styles.scss +++ b/apps/client/src/styles.scss @@ -2,7 +2,7 @@ @import './styles/table'; @import './styles/variables'; -@import 'svgmap/dist/svgMap'; +@import 'svgmap/style.min'; :root { --dark-background: rgb(25, 25, 25); diff --git a/package-lock.json b/package-lock.json index e4cf3382c..9ae63af6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -90,7 +90,7 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.1", "stripe": "20.3.0", - "svgmap": "2.14.0", + "svgmap": "2.19.2", "tablemark": "4.1.0", "twitter-api-v2": "1.29.0", "yahoo-finance2": "3.13.2", @@ -32339,9 +32339,9 @@ "license": "BSD-2-Clause" }, "node_modules/svgmap": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/svgmap/-/svgmap-2.14.0.tgz", - "integrity": "sha512-+Vklx4DO1uv1SFq6wnJWl/dRjX4uRT9CcsIHuADxAcZ+h5X1OSyDVbNdIu837fx5TtYYuaGRhWuFCXIioN/1ww==", + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/svgmap/-/svgmap-2.19.2.tgz", + "integrity": "sha512-mRqRcQiwwSTh9kTOPhjTmd3ywxA9aTfybBHGAoyuGn9CI9PnAQsuZ7H/2/VEIvgJhi1xM5IGBfk8i4/Ke4iTCQ==", "license": "MIT", "dependencies": { "svg-pan-zoom": "^3.6.2" diff --git a/package.json b/package.json index 03f4a527d..fd62729b9 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,7 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.1", "stripe": "20.3.0", - "svgmap": "2.14.0", + "svgmap": "2.19.2", "tablemark": "4.1.0", "twitter-api-v2": "1.29.0", "yahoo-finance2": "3.13.2", From 4dabd8ae68adcffeae4c142ef62439f77d822868 Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Thu, 12 Mar 2026 02:07:32 +0700 Subject: [PATCH 053/138] Task/improve type safety in symbol autocomplete (#6498) * Improve type safety in symbol autocomplete --- .../lib/interfaces/lookup-item.interface.ts | 2 +- .../symbol-autocomplete.component.ts | 61 +++++++++---------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/libs/common/src/lib/interfaces/lookup-item.interface.ts b/libs/common/src/lib/interfaces/lookup-item.interface.ts index fa91ed690..6cedeca09 100644 --- a/libs/common/src/lib/interfaces/lookup-item.interface.ts +++ b/libs/common/src/lib/interfaces/lookup-item.interface.ts @@ -7,7 +7,7 @@ export interface LookupItem { assetSubClass: AssetSubClass; currency: string; dataProviderInfo: DataProviderInfo; - dataSource: DataSource; + dataSource: DataSource | null; name: string; symbol: string; } diff --git a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts index c74e8a077..4b1898b8a 100644 --- a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts +++ b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts @@ -8,15 +8,17 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, DoCheck, ElementRef, Input, OnChanges, - OnDestroy, OnInit, SimpleChanges, - ViewChild + inject, + viewChild } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl, FormsModule, @@ -35,13 +37,12 @@ import { import { MatInput, MatInputModule } from '@angular/material/input'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { isString } from 'lodash'; -import { Subject, tap } from 'rxjs'; +import { tap } from 'rxjs'; import { debounceTime, distinctUntilChanged, filter, - switchMap, - takeUntil + switchMap } from 'rxjs/operators'; import { translate } from '../i18n'; @@ -77,21 +78,21 @@ import { AbstractMatFormField } from '../shared/abstract-mat-form-field'; }) export class GfSymbolAutocompleteComponent extends AbstractMatFormField - implements DoCheck, OnChanges, OnDestroy, OnInit + implements DoCheck, OnChanges, OnInit { @Input() public defaultLookupItems: LookupItem[] = []; @Input() public isLoading = false; - @ViewChild('symbolAutocomplete') public symbolAutocomplete: MatAutocomplete; - @Input() private includeIndices = false; - @ViewChild(MatInput) private input: MatInput; - - public control = new FormControl(); + public readonly control = new FormControl(); public lookupItems: (LookupItem & { assetSubClassString: string })[] = []; - private unsubscribeSubject = new Subject(); + protected readonly symbolAutocomplete = + viewChild.required('symbolAutocomplete'); + + private readonly destroyRef = inject(DestroyRef); + private readonly input = viewChild.required(MatInput); public constructor( public readonly _elementRef: ElementRef, @@ -105,13 +106,22 @@ export class GfSymbolAutocompleteComponent this.controlType = 'symbol-autocomplete'; } + public get empty() { + return this.input().empty; + } + + public set value(value: LookupItem) { + this.control.setValue(value); + super.value = value; + } + public ngOnInit() { if (this.disabled) { this.control.disable(); } this.control.valueChanges - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { if (super.value) { super.value.dataSource = null; @@ -136,7 +146,7 @@ export class GfSymbolAutocompleteComponent }), debounceTime(400), distinctUntilChanged(), - takeUntil(this.unsubscribeSubject), + takeUntilDestroyed(this.destroyRef), switchMap((query: string) => { return this.dataService.fetchSymbols({ query, @@ -168,12 +178,8 @@ export class GfSymbolAutocompleteComponent return aLookupItem?.symbol ?? ''; } - public get empty() { - return this.input?.empty; - } - public focus() { - this.input.focus(); + this.input().focus(); } public isValueInOptions(value: string) { @@ -185,7 +191,7 @@ export class GfSymbolAutocompleteComponent public ngDoCheck() { if (this.ngControl) { this.validateRequired(); - this.errorState = this.ngControl.invalid && this.ngControl.touched; + this.errorState = !!(this.ngControl.invalid && this.ngControl.touched); this.stateChanges.next(); } } @@ -197,18 +203,6 @@ export class GfSymbolAutocompleteComponent } as LookupItem; } - public set value(value: LookupItem) { - this.control.setValue(value); - super.value = value; - } - - public ngOnDestroy() { - super.ngOnDestroy(); - - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private showDefaultOptions() { this.lookupItems = this.defaultLookupItems.map((lookupItem) => { return { @@ -224,8 +218,9 @@ export class GfSymbolAutocompleteComponent const requiredCheck = super.required ? !super.value?.dataSource || !super.value?.symbol : false; + if (requiredCheck) { - this.ngControl.control.setErrors({ invalidData: true }); + this.ngControl.control?.setErrors({ invalidData: true }); } } } From bac3e2ebf36aedad595845bc204e518fe8821ef1 Mon Sep 17 00:00:00 2001 From: Erwin-N <111194281+Erwin-N@users.noreply.github.com> Date: Thu, 12 Mar 2026 17:25:22 +0100 Subject: [PATCH 054/138] Task/eliminate OnDestroy lifecycle hook from FIRE page (#6521) * Eliminate OnDestroy lifecycle hook --- .../portfolio/fire/fire-page.component.ts | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts index 27db6c76e..2f7568982 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts @@ -12,14 +12,18 @@ import { DataService } from '@ghostfolio/ui/services'; import { GfValueComponent } from '@ghostfolio/ui/value'; import { CommonModule, NgStyle } from '@angular/common'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + DestroyRef, + OnInit +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormControl } from '@angular/forms'; import { Big } from 'big.js'; import { DeviceDetectorService } from 'ngx-device-detector'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ imports: [ @@ -36,7 +40,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./fire-page.scss'], templateUrl: './fire-page.html' }) -export class GfFirePageComponent implements OnDestroy, OnInit { +export class GfFirePageComponent implements OnInit { public deviceType: string; public fireWealth: FireWealth; public hasImpersonationId: boolean; @@ -52,11 +56,10 @@ export class GfFirePageComponent implements OnDestroy, OnInit { public withdrawalRatePerYear: Big; public withdrawalRatePerYearProjected: Big; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, private userService: UserService @@ -68,7 +71,7 @@ export class GfFirePageComponent implements OnDestroy, OnInit { this.dataService .fetchPortfolioDetails() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ summary }) => { this.fireWealth = { today: { @@ -92,19 +95,19 @@ export class GfFirePageComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); this.safeWithdrawalRateControl.valueChanges - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((value) => { this.onSafeWithdrawalRateChange(Number(value)); }); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -132,11 +135,11 @@ export class GfFirePageComponent implements OnDestroy, OnInit { public onAnnualInterestRateChange(annualInterestRate: number) { this.dataService .putUserSetting({ annualInterestRate }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -163,11 +166,11 @@ export class GfFirePageComponent implements OnDestroy, OnInit { retirementDate: retirementDate.toISOString(), projectedTotalAmount: null }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -179,11 +182,11 @@ export class GfFirePageComponent implements OnDestroy, OnInit { public onSafeWithdrawalRateChange(safeWithdrawalRate: number) { this.dataService .putUserSetting({ safeWithdrawalRate }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -198,11 +201,11 @@ export class GfFirePageComponent implements OnDestroy, OnInit { public onSavingsRateChange(savingsRate: number) { this.dataService .putUserSetting({ savingsRate }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -217,11 +220,11 @@ export class GfFirePageComponent implements OnDestroy, OnInit { projectedTotalAmount, retirementDate: null }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -230,11 +233,6 @@ export class GfFirePageComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private calculateWithdrawalRates() { if (this.fireWealth && this.user?.settings?.safeWithdrawalRate) { this.withdrawalRatePerYear = new Big( From 55d717ca9397b5e5d3ee5c360b550eedd3dcd5ad Mon Sep 17 00:00:00 2001 From: Erwin-N <111194281+Erwin-N@users.noreply.github.com> Date: Thu, 12 Mar 2026 20:03:37 +0100 Subject: [PATCH 055/138] Task/eliminate OnDestroy lifecycle hook from X-ray page (#6522) * Eliminate OnDestroy lifecycle hook --- .../portfolio/x-ray/x-ray-page.component.ts | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts index 70b748b10..e97fd4876 100644 --- a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts +++ b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts @@ -12,7 +12,8 @@ import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { DataService } from '@ghostfolio/ui/services'; import { NgClass } from '@angular/common'; -import { ChangeDetectorRef, Component } from '@angular/core'; +import { ChangeDetectorRef, Component, DestroyRef } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { @@ -21,7 +22,6 @@ import { warningOutline } from 'ionicons/icons'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Subject, takeUntil } from 'rxjs'; @Component({ imports: [ @@ -48,11 +48,10 @@ export class GfXRayPageComponent { public statistics: PortfolioReportResponse['xRay']['statistics']; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private impersonationStorageService: ImpersonationStorageService, private userService: UserService ) { @@ -62,13 +61,13 @@ export class GfXRayPageComponent { public ngOnInit() { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -91,28 +90,23 @@ export class GfXRayPageComponent { public onRulesUpdated(event: UpdateUserSettingDto) { this.dataService .putUserSetting(event) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(); this.initializePortfolioReport(); }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private initializePortfolioReport() { this.isLoading = true; this.dataService .fetchPortfolioReport() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ xRay: { categories, statistics } }) => { this.categories = categories; this.inactiveRules = this.mergeInactiveRules(categories); From cfa974385adaadd5c0b94ebde95bce341519d02e Mon Sep 17 00:00:00 2001 From: Erwin-N <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 13 Mar 2026 12:08:54 +0100 Subject: [PATCH 056/138] Task/eliminate OnDestroy lifecycle hook from accounts page (#6527) * Eliminate OnDestroy lifecycle hook --- .../pages/accounts/accounts-page.component.ts | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/apps/client/src/app/pages/accounts/accounts-page.component.ts b/apps/client/src/app/pages/accounts/accounts-page.component.ts index a0eef4eba..fdc78a8c4 100644 --- a/apps/client/src/app/pages/accounts/accounts-page.component.ts +++ b/apps/client/src/app/pages/accounts/accounts-page.component.ts @@ -13,7 +13,13 @@ import { GfAccountsTableComponent } from '@ghostfolio/ui/accounts-table'; import { NotificationService } from '@ghostfolio/ui/notifications'; import { DataService } from '@ghostfolio/ui/services'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + DestroyRef, + OnInit +} from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router, RouterModule } from '@angular/router'; @@ -21,8 +27,8 @@ import { Account as AccountModel } from '@prisma/client'; import { addIcons } from 'ionicons'; import { addOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { EMPTY, Subject, Subscription } from 'rxjs'; -import { catchError, takeUntil } from 'rxjs/operators'; +import { EMPTY, Subscription } from 'rxjs'; +import { catchError } from 'rxjs/operators'; import { GfCreateOrUpdateAccountDialogComponent } from './create-or-update-account-dialog/create-or-update-account-dialog.component'; import { CreateOrUpdateAccountDialogParams } from './create-or-update-account-dialog/interfaces/interfaces'; @@ -36,7 +42,7 @@ import { GfTransferBalanceDialogComponent } from './transfer-balance/transfer-ba styleUrls: ['./accounts-page.scss'], templateUrl: './accounts-page.html' }) -export class GfAccountsPageComponent implements OnDestroy, OnInit { +export class GfAccountsPageComponent implements OnInit { public accounts: AccountModel[]; public activitiesCount = 0; public deviceType: string; @@ -48,11 +54,10 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { public totalValueInBaseCurrency = 0; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private dialog: MatDialog, private impersonationStorageService: ImpersonationStorageService, @@ -62,7 +67,7 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { private userService: UserService ) { this.route.queryParams - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((params) => { if (params['accountId'] && params['accountDetailDialog']) { this.openAccountDetailDialog(params['accountId']); @@ -94,13 +99,13 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -124,7 +129,7 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { public fetchAccounts() { this.dataService .fetchAccounts() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe( ({ accounts, @@ -151,11 +156,11 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { this.dataService .deleteAccount(aId) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(); this.fetchAccounts(); @@ -204,18 +209,18 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((account: UpdateAccountDto | null) => { if (account) { this.reset(); this.dataService .putAccount(account) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(); this.fetchAccounts(); @@ -228,11 +233,6 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private openAccountDetailDialog(aAccountId: string) { const dialogRef = this.dialog.open< GfAccountDetailDialogComponent, @@ -254,7 +254,7 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.fetchAccounts(); @@ -284,18 +284,18 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((account: CreateAccountDto | null) => { if (account) { this.reset(); this.dataService .postAccount(account) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(); this.fetchAccounts(); @@ -321,7 +321,7 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { dialogRef .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((data: any) => { if (data) { this.reset(); @@ -343,7 +343,7 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(() => { this.fetchAccounts(); From e127c1af2b74b79005cb351d53b2a16992ab80b4 Mon Sep 17 00:00:00 2001 From: Erwin-N <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:14:13 +0100 Subject: [PATCH 057/138] Task/eliminate OnDestroy lifecycle hook from about page (#6529) * Eliminate OnDestroy lifecycle hook --- .../src/app/pages/about/about-page.component.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/apps/client/src/app/pages/about/about-page.component.ts b/apps/client/src/app/pages/about/about-page.component.ts index 5ddb6b2e0..1e749d1cd 100644 --- a/apps/client/src/app/pages/about/about-page.component.ts +++ b/apps/client/src/app/pages/about/about-page.component.ts @@ -8,9 +8,10 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatTabsModule } from '@angular/material/tabs'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; @@ -24,8 +25,6 @@ import { sparklesOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ host: { class: 'page has-tabs' }, @@ -35,17 +34,16 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./about-page.scss'], templateUrl: './about-page.html' }) -export class AboutPageComponent implements OnDestroy, OnInit { +export class AboutPageComponent implements OnInit { public deviceType: string; public hasPermissionForSubscription: boolean; public tabs: TabConfiguration[] = []; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private userService: UserService ) { @@ -57,7 +55,7 @@ export class AboutPageComponent implements OnDestroy, OnInit { ); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { this.tabs = [ { @@ -118,9 +116,4 @@ export class AboutPageComponent implements OnDestroy, OnInit { public ngOnInit() { this.deviceType = this.deviceService.getDeviceInfo().deviceType; } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 88307cca2863ac905f45d3d9de3cd5ab50101159 Mon Sep 17 00:00:00 2001 From: Erwin-N <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:19:56 +0100 Subject: [PATCH 058/138] Task/eliminate OnDestroy lifecycle hook from portfolio analysis page (#6524) * Eliminate OnDestroy lifecycle hook --- .../analysis/analysis-page.component.ts | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index 5cd24777c..47845ea6f 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -24,10 +24,11 @@ import { Clipboard } from '@angular/cdk/clipboard'; import { ChangeDetectorRef, Component, - OnDestroy, + DestroyRef, OnInit, ViewChild } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu'; @@ -42,8 +43,6 @@ import { isNumber, sortBy } from 'lodash'; import ms from 'ms'; import { DeviceDetectorService } from 'ngx-device-detector'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ imports: [ @@ -64,7 +63,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./analysis-page.scss'], templateUrl: './analysis-page.html' }) -export class GfAnalysisPageComponent implements OnDestroy, OnInit { +export class GfAnalysisPageComponent implements OnInit { @ViewChild(MatMenuTrigger) actionsMenuButton!: MatMenuTrigger; public benchmark: Partial; @@ -102,12 +101,11 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { public unitLongestStreak: string; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private clipboard: Clipboard, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, private snackBar: MatSnackBar, @@ -135,13 +133,13 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -163,11 +161,11 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { public onChangeBenchmark(symbolProfileId: string) { this.dataService .putUserSetting({ benchmark: symbolProfileId }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -193,7 +191,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { mode, filters: this.userService.getFilters() }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ prompt }) => { this.clipboard.copy(prompt); @@ -207,7 +205,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { snackBarRef .onAction() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { window.open('https://duck.ai', '_blank'); }); @@ -222,11 +220,6 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private fetchDividendsAndInvestments() { this.isLoadingDividendTimelineChart = true; this.isLoadingInvestmentTimelineChart = true; @@ -237,7 +230,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { groupBy: this.mode, range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ dividends }) => { this.dividendsByGroup = dividends; @@ -252,7 +245,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { groupBy: this.mode, range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ investments, streaks }) => { this.investmentsByGroup = investments; this.streaks = streaks; @@ -287,7 +280,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { filters: this.userService.getFilters(), range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ chart, firstOrderDate, performance }) => { this.firstOrderDate = firstOrderDate ?? new Date(); @@ -346,7 +339,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { filters: this.userService.getFilters(), range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ holdings }) => { const holdingsSorted = sortBy( holdings.filter(({ netPerformancePercentWithCurrencyEffect }) => { @@ -397,7 +390,7 @@ export class GfAnalysisPageComponent implements OnDestroy, OnInit { range: this.user?.settings?.dateRange, startDate: this.firstOrderDate }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ marketData }) => { this.benchmarkDataItems = marketData.map(({ date, value }) => { return { From 269b981e8625d5196b0a83f2565f7ce88f3f3548 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:28:49 +0100 Subject: [PATCH 059/138] Task/implement OnModuleInit in I18nService (#6448) * Implement onModuleInit --- apps/api/src/services/i18n/i18n.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/api/src/services/i18n/i18n.service.ts b/apps/api/src/services/i18n/i18n.service.ts index cf340d7c6..1cdb811a9 100644 --- a/apps/api/src/services/i18n/i18n.service.ts +++ b/apps/api/src/services/i18n/i18n.service.ts @@ -1,16 +1,16 @@ import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; import * as cheerio from 'cheerio'; import { readFileSync, readdirSync } from 'node:fs'; import { join } from 'node:path'; @Injectable() -export class I18nService { +export class I18nService implements OnModuleInit { private localesPath = join(__dirname, 'assets', 'locales'); private translations: { [locale: string]: cheerio.CheerioAPI } = {}; - public constructor() { + public onModuleInit() { this.loadFiles(); } From 860ae50ad948083fe62d2601ba7d1b6563be076f Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Sat, 14 Mar 2026 09:02:30 +0100 Subject: [PATCH 060/138] Task/eliminate OnDestroy lifecycle hook from home holdings component (#6547) * Eliminate OnDestroy lifecycle hook --- .../home-holdings/home-holdings.component.ts | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/apps/client/src/app/components/home-holdings/home-holdings.component.ts b/apps/client/src/app/components/home-holdings/home-holdings.component.ts index df5e43087..19a48ccd8 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.component.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.component.ts @@ -19,9 +19,10 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatButtonToggleModule } from '@angular/material/button-toggle'; @@ -30,8 +31,6 @@ import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { gridOutline, reorderFourOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ imports: [ @@ -51,7 +50,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./home-holdings.scss'], templateUrl: './home-holdings.html' }) -export class GfHomeHoldingsComponent implements OnDestroy, OnInit { +export class GfHomeHoldingsComponent implements OnInit { public static DEFAULT_HOLDINGS_VIEW_MODE: HoldingsViewMode = 'TABLE'; public deviceType: string; @@ -71,11 +70,10 @@ export class GfHomeHoldingsComponent implements OnDestroy, OnInit { GfHomeHoldingsComponent.DEFAULT_HOLDINGS_VIEW_MODE ); - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, private router: Router, @@ -89,13 +87,13 @@ export class GfHomeHoldingsComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -117,15 +115,15 @@ export class GfHomeHoldingsComponent implements OnDestroy, OnInit { }); this.viewModeFormControl.valueChanges - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((holdingsViewMode) => { this.dataService .putUserSetting({ holdingsViewMode }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -149,11 +147,6 @@ export class GfHomeHoldingsComponent implements OnDestroy, OnInit { } } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private fetchHoldings() { const filters = this.userService.getFilters(); @@ -193,7 +186,7 @@ export class GfHomeHoldingsComponent implements OnDestroy, OnInit { this.holdings = undefined; this.fetchHoldings() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ holdings }) => { this.holdings = holdings; From cdd508dfe699222baa5458db86d44c6817eb2fbc Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Sat, 14 Mar 2026 09:04:24 +0100 Subject: [PATCH 061/138] Task/eliminate OnDestroy lifecycle hook from home market component (#6548) * Eliminate OnDestroy lifecycle hook --- .../home-market/home-market.component.ts | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/apps/client/src/app/components/home-market/home-market.component.ts b/apps/client/src/app/components/home-market/home-market.component.ts index 841c0818a..2ddb89408 100644 --- a/apps/client/src/app/components/home-market/home-market.component.ts +++ b/apps/client/src/app/components/home-market/home-market.component.ts @@ -17,12 +17,11 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ imports: [ @@ -35,7 +34,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./home-market.scss'], templateUrl: './home-market.html' }) -export class GfHomeMarketComponent implements OnDestroy, OnInit { +export class GfHomeMarketComponent implements OnInit { public benchmarks: Benchmark[]; public deviceType: string; public fearAndGreedIndex: number; @@ -47,11 +46,10 @@ export class GfHomeMarketComponent implements OnDestroy, OnInit { public readonly numberOfDays = 365; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private userService: UserService ) { @@ -59,7 +57,7 @@ export class GfHomeMarketComponent implements OnDestroy, OnInit { this.info = this.dataService.fetchInfo(); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -82,7 +80,7 @@ export class GfHomeMarketComponent implements OnDestroy, OnInit { includeHistoricalData: this.numberOfDays, symbol: ghostfolioFearAndGreedIndexSymbol }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ historicalData, marketPrice }) => { this.fearAndGreedIndex = marketPrice; this.historicalDataItems = [ @@ -99,16 +97,11 @@ export class GfHomeMarketComponent implements OnDestroy, OnInit { this.dataService .fetchBenchmarks() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ benchmarks }) => { this.benchmarks = benchmarks; this.changeDetectorRef.markForCheck(); }); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 9f9008c89a37aeb94517a142eb3cdd420aeae316 Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Sat, 14 Mar 2026 09:06:10 +0100 Subject: [PATCH 062/138] Task/eliminate OnDestroy lifecycle hook from home overview component (#6549) * Eliminate OnDestroy lifecycle hook --- .../home-overview/home-overview.component.ts | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/apps/client/src/app/components/home-overview/home-overview.component.ts b/apps/client/src/app/components/home-overview/home-overview.component.ts index cb1df1a74..58284d27d 100644 --- a/apps/client/src/app/components/home-overview/home-overview.component.ts +++ b/apps/client/src/app/components/home-overview/home-overview.component.ts @@ -19,14 +19,13 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { RouterModule } from '@angular/router'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ imports: [ @@ -41,7 +40,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./home-overview.scss'], templateUrl: './home-overview.html' }) -export class GfHomeOverviewComponent implements OnDestroy, OnInit { +export class GfHomeOverviewComponent implements OnInit { public deviceType: string; public errors: AssetProfileIdentifier[]; public hasError: boolean; @@ -62,18 +61,17 @@ export class GfHomeOverviewComponent implements OnDestroy, OnInit { public unit: string; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, private layoutService: LayoutService, private userService: UserService ) { this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -99,7 +97,7 @@ export class GfHomeOverviewComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; @@ -107,17 +105,12 @@ export class GfHomeOverviewComponent implements OnDestroy, OnInit { }); this.layoutService.shouldReloadContent$ - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.update(); }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private update() { this.historicalDataItems = null; this.isLoadingPerformance = true; @@ -126,7 +119,7 @@ export class GfHomeOverviewComponent implements OnDestroy, OnInit { .fetchPortfolioPerformance({ range: this.user?.settings?.dateRange }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ chart, errors, performance }) => { this.errors = errors; this.performance = performance; From 6a714687b54e4e5aa89f7f084ae7c531f61c3c43 Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Sat, 14 Mar 2026 09:07:53 +0100 Subject: [PATCH 063/138] Task/eliminate OnDestroy lifecycle hook from home summary component (#6550) * Eliminate OnDestroy lifecycle hook --- .../home-summary/home-summary.component.ts | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/apps/client/src/app/components/home-summary/home-summary.component.ts b/apps/client/src/app/components/home-summary/home-summary.component.ts index 454d05689..719cfbd29 100644 --- a/apps/client/src/app/components/home-summary/home-summary.component.ts +++ b/apps/client/src/app/components/home-summary/home-summary.component.ts @@ -13,14 +13,13 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatCardModule } from '@angular/material/card'; import { MatSnackBarRef, TextOnlySnackBar } from '@angular/material/snack-bar'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; @Component({ imports: [GfPortfolioSummaryComponent, MatCardModule], @@ -29,7 +28,7 @@ import { takeUntil } from 'rxjs/operators'; styleUrls: ['./home-summary.scss'], templateUrl: './home-summary.html' }) -export class GfHomeSummaryComponent implements OnDestroy, OnInit { +export class GfHomeSummaryComponent implements OnInit { public deviceType: string; public hasImpersonationId: boolean; public hasPermissionForSubscription: boolean; @@ -40,11 +39,10 @@ export class GfHomeSummaryComponent implements OnDestroy, OnInit { public summary: PortfolioSummary; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private impersonationStorageService: ImpersonationStorageService, private userService: UserService @@ -57,7 +55,7 @@ export class GfHomeSummaryComponent implements OnDestroy, OnInit { ); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -77,7 +75,7 @@ export class GfHomeSummaryComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); @@ -86,11 +84,11 @@ export class GfHomeSummaryComponent implements OnDestroy, OnInit { public onChangeEmergencyFund(emergencyFund: number) { this.dataService .putUserSetting({ emergencyFund }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -99,17 +97,12 @@ export class GfHomeSummaryComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private update() { this.isLoading = true; this.dataService .fetchPortfolioDetails() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ summary }) => { this.summary = summary; this.isLoading = false; From 573fbb9a4031f51b3613d02188374a7171b9ca4e Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:16:46 +0700 Subject: [PATCH 064/138] Task/improve type safety of toggle component (#6533) * Improve type safety --- libs/ui/src/lib/toggle/toggle.component.html | 7 +++-- libs/ui/src/lib/toggle/toggle.component.ts | 32 +++++++++++--------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/libs/ui/src/lib/toggle/toggle.component.html b/libs/ui/src/lib/toggle/toggle.component.html index ac2256daa..d6271ef58 100644 --- a/libs/ui/src/lib/toggle/toggle.component.html +++ b/libs/ui/src/lib/toggle/toggle.component.html @@ -3,13 +3,14 @@ [formControl]="optionFormControl" (change)="onValueChange()" > - @for (option of options; track option) { + @for (option of options(); track option) { {{ option.label }}(); + public readonly isLoading = input(false); + public readonly options = input([]); - @Output() valueChange = new EventEmitter>(); + protected readonly optionFormControl = new FormControl(null); + protected readonly valueChange = output>(); - public optionFormControl = new FormControl(undefined); - - public ngOnChanges() { - this.optionFormControl.setValue(this.defaultValue); + public constructor() { + effect(() => { + this.optionFormControl.setValue(this.defaultValue()); + }); } public onValueChange() { - this.valueChange.emit({ value: this.optionFormControl.value }); + const value = this.optionFormControl.value; + + if (value !== null) { + this.valueChange.emit({ value }); + } } } From 439af5f21d9cc69eaa83e0b8a815f683314b77c1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 14 Mar 2026 09:26:47 +0100 Subject: [PATCH 065/138] Task/consolidate sign-out logic (#6526) * Consolidate sign-out logic * Update changelog --- CHANGELOG.md | 1 + apps/client/src/app/app.component.ts | 7 ++-- .../admin-users/admin-users.component.ts | 5 +-- .../user-account-access.component.ts | 5 +-- .../user-account-settings.component.ts | 5 +-- apps/client/src/app/core/auth.guard.ts | 2 +- .../src/app/core/http-response.interceptor.ts | 6 ++-- .../pages/register/register-page.component.ts | 6 ++-- .../src/app/services/token-storage.service.ts | 26 +------------- .../src/app/services/user/user.service.ts | 36 +++++++++++++++++-- 10 files changed, 49 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 103a09fbb..03fbc962c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Consolidated the sign-out logic within the user service to unify cookie, state and token clearance - Upgraded `svgmap` from version `2.14.0` to `2.19.2` ## 2.249.0 - 2026-03-10 diff --git a/apps/client/src/app/app.component.ts b/apps/client/src/app/app.component.ts index 3daca607a..0e7d50a54 100644 --- a/apps/client/src/app/app.component.ts +++ b/apps/client/src/app/app.component.ts @@ -38,7 +38,6 @@ import { GfHeaderComponent } from './components/header/header.component'; import { GfHoldingDetailDialogComponent } from './components/holding-detail-dialog/holding-detail-dialog.component'; import { HoldingDetailDialogParams } from './components/holding-detail-dialog/interfaces/interfaces'; import { ImpersonationStorageService } from './services/impersonation-storage.service'; -import { TokenStorageService } from './services/token-storage.service'; import { UserService } from './services/user/user.service'; @Component({ @@ -82,7 +81,6 @@ export class GfAppComponent implements OnDestroy, OnInit { private route: ActivatedRoute, private router: Router, private title: Title, - private tokenStorageService: TokenStorageService, private userService: UserService ) { this.initializeTheme(); @@ -236,12 +234,11 @@ export class GfAppComponent implements OnDestroy, OnInit { } public onCreateAccount() { - this.tokenStorageService.signOut(); + this.userService.signOut(); } public onSignOut() { - this.tokenStorageService.signOut(); - this.userService.remove(); + this.userService.signOut(); document.location.href = `/${document.documentElement.lang}`; } diff --git a/apps/client/src/app/components/admin-users/admin-users.component.ts b/apps/client/src/app/components/admin-users/admin-users.component.ts index d479f2037..7916acffd 100644 --- a/apps/client/src/app/components/admin-users/admin-users.component.ts +++ b/apps/client/src/app/components/admin-users/admin-users.component.ts @@ -1,7 +1,6 @@ import { UserDetailDialogParams } from '@ghostfolio/client/components/user-detail-dialog/interfaces/interfaces'; import { GfUserDetailDialogComponent } from '@ghostfolio/client/components/user-detail-dialog/user-detail-dialog.component'; import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; -import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { DEFAULT_PAGE_SIZE } from '@ghostfolio/common/config'; import { ConfirmationDialogType } from '@ghostfolio/common/enums'; @@ -106,7 +105,6 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit { private notificationService: NotificationService, private route: ActivatedRoute, private router: Router, - private tokenStorageService: TokenStorageService, private userService: UserService ) { this.deviceType = this.deviceService.getDeviceInfo().deviceType; @@ -229,8 +227,7 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit { this.notificationService.alert({ discardFn: () => { if (aUserId === this.user.id) { - this.tokenStorageService.signOut(); - this.userService.remove(); + this.userService.signOut(); document.location.href = `/${document.documentElement.lang}`; } diff --git a/apps/client/src/app/components/user-account-access/user-account-access.component.ts b/apps/client/src/app/components/user-account-access/user-account-access.component.ts index ef78cccff..4f744a087 100644 --- a/apps/client/src/app/components/user-account-access/user-account-access.component.ts +++ b/apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -1,5 +1,4 @@ import { GfAccessTableComponent } from '@ghostfolio/client/components/access-table/access-table.component'; -import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { CreateAccessDto } from '@ghostfolio/common/dtos'; import { ConfirmationDialogType } from '@ghostfolio/common/enums'; @@ -76,7 +75,6 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { private notificationService: NotificationService, private route: ActivatedRoute, private router: Router, - private tokenStorageService: TokenStorageService, private userService: UserService ) { const { globalPermissions } = this.dataService.fetchInfo(); @@ -161,8 +159,7 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { .subscribe(({ accessToken }) => { this.notificationService.alert({ discardFn: () => { - this.tokenStorageService.signOut(); - this.userService.remove(); + this.userService.signOut(); document.location.href = `/${document.documentElement.lang}`; }, diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts index 44be30b9a..0cf18df36 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -3,7 +3,6 @@ import { KEY_TOKEN, SettingsStorageService } from '@ghostfolio/client/services/settings-storage.service'; -import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service'; import { ConfirmationDialogType } from '@ghostfolio/common/enums'; @@ -108,7 +107,6 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { private notificationService: NotificationService, private settingsStorageService: SettingsStorageService, private snackBar: MatSnackBar, - private tokenStorageService: TokenStorageService, private userService: UserService, public webAuthnService: WebAuthnService ) { @@ -198,8 +196,7 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { takeUntil(this.unsubscribeSubject) ) .subscribe(() => { - this.tokenStorageService.signOut(); - this.userService.remove(); + this.userService.signOut(); document.location.href = `/${document.documentElement.lang}`; }); diff --git a/apps/client/src/app/core/auth.guard.ts b/apps/client/src/app/core/auth.guard.ts index 123a6169a..3292f0ff7 100644 --- a/apps/client/src/app/core/auth.guard.ts +++ b/apps/client/src/app/core/auth.guard.ts @@ -68,7 +68,7 @@ export class AuthGuard { this.dataService .putUserSetting({ language: document.documentElement.lang }) .subscribe(() => { - this.userService.remove(); + this.userService.reset(); setTimeout(() => { window.location.reload(); diff --git a/apps/client/src/app/core/http-response.interceptor.ts b/apps/client/src/app/core/http-response.interceptor.ts index ab99b440f..315e9d64e 100644 --- a/apps/client/src/app/core/http-response.interceptor.ts +++ b/apps/client/src/app/core/http-response.interceptor.ts @@ -1,4 +1,4 @@ -import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service'; import { InfoItem } from '@ghostfolio/common/interfaces'; import { internalRoutes, publicRoutes } from '@ghostfolio/common/routes/routes'; @@ -32,8 +32,8 @@ export class HttpResponseInterceptor implements HttpInterceptor { public constructor( private dataService: DataService, private router: Router, - private tokenStorageService: TokenStorageService, private snackBar: MatSnackBar, + private userService: UserService, private webAuthnService: WebAuthnService ) { this.info = this.dataService.fetchInfo(); @@ -115,7 +115,7 @@ export class HttpResponseInterceptor implements HttpInterceptor { if (this.webAuthnService.isEnabled()) { this.router.navigate(internalRoutes.webauthn.routerLink); } else { - this.tokenStorageService.signOut(); + this.userService.signOut(); } } } diff --git a/apps/client/src/app/pages/register/register-page.component.ts b/apps/client/src/app/pages/register/register-page.component.ts index 3678f0249..db199143f 100644 --- a/apps/client/src/app/pages/register/register-page.component.ts +++ b/apps/client/src/app/pages/register/register-page.component.ts @@ -1,4 +1,5 @@ import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; +import { UserService } from '@ghostfolio/client/services/user/user.service'; import { InfoItem, LineChartItem } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { GfLogoComponent } from '@ghostfolio/ui/logo'; @@ -42,11 +43,12 @@ export class GfRegisterPageComponent implements OnInit { private deviceService: DeviceDetectorService, private dialog: MatDialog, private router: Router, - private tokenStorageService: TokenStorageService + private tokenStorageService: TokenStorageService, + private userService: UserService ) { this.info = this.dataService.fetchInfo(); - this.tokenStorageService.signOut(); + this.userService.signOut(); } public ngOnInit() { diff --git a/apps/client/src/app/services/token-storage.service.ts b/apps/client/src/app/services/token-storage.service.ts index 5b9a29a08..f54aab828 100644 --- a/apps/client/src/app/services/token-storage.service.ts +++ b/apps/client/src/app/services/token-storage.service.ts @@ -1,19 +1,11 @@ -import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service'; - import { Injectable } from '@angular/core'; import { KEY_TOKEN } from './settings-storage.service'; -import { UserService } from './user/user.service'; @Injectable({ providedIn: 'root' }) export class TokenStorageService { - public constructor( - private userService: UserService, - private webAuthnService: WebAuthnService - ) {} - public getToken(): string { return ( window.sessionStorage.getItem(KEY_TOKEN) || @@ -25,23 +17,7 @@ export class TokenStorageService { if (staySignedIn) { window.localStorage.setItem(KEY_TOKEN, token); } - window.sessionStorage.setItem(KEY_TOKEN, token); - } - - public signOut() { - const utmSource = window.localStorage.getItem('utm_source'); - if (this.webAuthnService.isEnabled()) { - this.webAuthnService.deregister().subscribe(); - } - - window.localStorage.clear(); - window.sessionStorage.clear(); - - this.userService.remove(); - - if (utmSource) { - window.localStorage.setItem('utm_source', utmSource); - } + window.sessionStorage.setItem(KEY_TOKEN, token); } } diff --git a/apps/client/src/app/services/user/user.service.ts b/apps/client/src/app/services/user/user.service.ts index bd9d7d04c..44b63e056 100644 --- a/apps/client/src/app/services/user/user.service.ts +++ b/apps/client/src/app/services/user/user.service.ts @@ -1,3 +1,4 @@ +import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service'; import { Filter, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; @@ -26,7 +27,8 @@ export class UserService extends ObservableStore { public constructor( private deviceService: DeviceDetectorService, private dialog: MatDialog, - private http: HttpClient + private http: HttpClient, + private webAuthnService: WebAuthnService ) { super({ trackStateHistory: true }); @@ -93,10 +95,40 @@ export class UserService extends ObservableStore { return this.getFilters().length > 0; } - public remove() { + public reset() { this.setState({ user: null }, UserStoreActions.RemoveUser); } + public signOut() { + const utmSource = window.localStorage.getItem('utm_source'); + + if (this.webAuthnService.isEnabled()) { + this.webAuthnService.deregister().subscribe(); + } + + window.localStorage.clear(); + window.sessionStorage.clear(); + + void this.clearAllCookies(); + + this.reset(); + + if (utmSource) { + window.localStorage.setItem('utm_source', utmSource); + } + } + + private async clearAllCookies() { + if (!('cookieStore' in window)) { + console.warn('Cookie Store API not available in this browser'); + return; + } + + const cookies = await cookieStore.getAll(); + + await Promise.all(cookies.map(({ name }) => cookieStore.delete(name))); + } + private fetchUser(): Observable { return this.http.get('/api/v1/user').pipe( map((user) => { From cf57c156fc5af42379933d2a56d09a3ea45be33d Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 14 Mar 2026 09:28:28 +0100 Subject: [PATCH 066/138] Task/refactor open Bull Board in admin jobs component (#6525) * Refactoring --- .../src/app/components/admin-jobs/admin-jobs.component.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts index 1537db2a0..b9f4d590d 100644 --- a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts +++ b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts @@ -194,7 +194,11 @@ export class GfAdminJobsComponent implements OnInit { public onOpenBullBoard() { const token = this.tokenStorageService.getToken(); - document.cookie = `${BULL_BOARD_COOKIE_NAME}=${token}; path=${BULL_BOARD_ROUTE}; SameSite=Strict`; + document.cookie = [ + `${BULL_BOARD_COOKIE_NAME}=${encodeURIComponent(token)}`, + 'path=/', + 'SameSite=Strict' + ].join('; '); window.open(BULL_BOARD_ROUTE, '_blank'); } From a3b1b922d279b581a29e95432befa840337ede26 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 14 Mar 2026 09:30:20 +0100 Subject: [PATCH 067/138] Task/implement OnModuleInit interface in AssetsController (#6451) * Implement OnModuleInit interface --- apps/api/src/app/endpoints/assets/assets.controller.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/api/src/app/endpoints/assets/assets.controller.ts b/apps/api/src/app/endpoints/assets/assets.controller.ts index a314b3f19..397686d8c 100644 --- a/apps/api/src/app/endpoints/assets/assets.controller.ts +++ b/apps/api/src/app/endpoints/assets/assets.controller.ts @@ -4,6 +4,7 @@ import { interpolate } from '@ghostfolio/common/helper'; import { Controller, Get, + OnModuleInit, Param, Res, Version, @@ -14,12 +15,14 @@ import { readFileSync } from 'node:fs'; import { join } from 'node:path'; @Controller('assets') -export class AssetsController { +export class AssetsController implements OnModuleInit { private webManifest = ''; public constructor( public readonly configurationService: ConfigurationService - ) { + ) {} + + public onModuleInit() { try { this.webManifest = readFileSync( join(__dirname, 'assets', 'site.webmanifest'), From 06492b6012214dbca2c550e2db162a9bce5851a8 Mon Sep 17 00:00:00 2001 From: Akd11111 <70412728+Akd11111@users.noreply.github.com> Date: Sat, 14 Mar 2026 10:11:28 +0100 Subject: [PATCH 068/138] Task/improve language localization for PL (20260312) (#6523) * Improve language localization for PL * Update changelog --- CHANGELOG.md | 1 + apps/client/src/locales/messages.pl.xlf | 64 ++++++++++++------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03fbc962c..13f014146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Consolidated the sign-out logic within the user service to unify cookie, state and token clearance +- Improved the language localization for Polish (`pl`) - Upgraded `svgmap` from version `2.14.0` to `2.19.2` ## 2.249.0 - 2026-03-10 diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index 5de2ed8f4..e2083ccf7 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -660,7 +660,7 @@ and is driven by the efforts of its contributors - and is driven by the efforts of its contributors + i jest rozwijany dzięki pracy jego współtwórców apps/client/src/app/pages/about/overview/about-overview-page.html 49 @@ -1580,7 +1580,7 @@ The source code is fully available as open source software (OSS) under the AGPL-3.0 license - The source code is fully available as open source software (OSS) under the AGPL-3.0 license + Kod źródłowy jest w pełni dostępny jako oprogramowanie open source (OSS) na licencji AGPL-3.0 license apps/client/src/app/pages/about/overview/about-overview-page.html 16 @@ -2148,7 +2148,7 @@ Performance with currency effect - Performance with currency effect + Wynik z efektem walutowym apps/client/src/app/pages/portfolio/analysis/analysis-page.html 135 @@ -2376,7 +2376,7 @@ this is projected to increase to - this is projected to increase to + prognozuje się wzrost tej kwoty do apps/client/src/app/pages/portfolio/fire/fire-page.html 147 @@ -3564,7 +3564,7 @@ and a safe withdrawal rate (SWR) of - and a safe withdrawal rate (SWR) of + oraz bezpiecznej stopy wypłaty (SWR) na poziomie apps/client/src/app/pages/portfolio/fire/fire-page.html 108 @@ -4124,7 +4124,7 @@ annual interest rate - annual interest rate + rocznej stopy zwrotu apps/client/src/app/pages/portfolio/fire/fire-page.html 185 @@ -4464,7 +4464,7 @@ Sustainable retirement income - Sustainable retirement income + Zrównoważony dochód na emeryturze apps/client/src/app/pages/portfolio/fire/fire-page.html 41 @@ -4597,7 +4597,7 @@ per month - per month + miesięcznie apps/client/src/app/pages/portfolio/fire/fire-page.html 94 @@ -5397,7 +5397,7 @@ View Details - View Details + Zobacz szczegóły apps/client/src/app/components/admin-users/admin-users.html 225 @@ -5425,7 +5425,7 @@ Buy - Zakup + Kupno apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html 31 @@ -5469,7 +5469,7 @@ Sell - Sprzedaj + Sprzedaż apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html 44 @@ -5625,7 +5625,7 @@ If you retire today, you would be able to withdraw - If you retire today, you would be able to withdraw + Gdybyś przeszedł na emeryturę dziś, mógłbyś wypłacać apps/client/src/app/pages/portfolio/fire/fire-page.html 68 @@ -6710,7 +6710,7 @@ , based on your total assets of - , based on your total assets of + , na podstawie całkowitej wartości aktywów wynoszącej apps/client/src/app/pages/portfolio/fire/fire-page.html 96 @@ -6974,7 +6974,7 @@ , assuming a - , assuming a + , przyjmując apps/client/src/app/pages/portfolio/fire/fire-page.html 174 @@ -7062,7 +7062,7 @@ Ghostfolio is a lightweight wealth management application for individuals to keep track of stocks, ETFs or cryptocurrencies and make solid, data-driven investment decisions. - Ghostfolio is a lightweight wealth management application for individuals to keep track of stocks, ETFs or cryptocurrencies and make solid, data-driven investment decisions. + Ghostfolio to aplikacja do zarządzania majątkiem, przeznaczona dla osób prywatnych do śledzenia akcji, ETF‑ów i kryptowalut oraz podejmowania solidnych, opartych na danych decyzji inwestycyjnych. apps/client/src/app/pages/about/overview/about-overview-page.html 10 @@ -7392,7 +7392,7 @@ Change with currency effect - Change with currency effect + Zmiana z efektem walutowym apps/client/src/app/pages/portfolio/analysis/analysis-page.html 116 @@ -7532,7 +7532,7 @@ The project has been initiated by - The project has been initiated by + Projekt został zainicjowany przez apps/client/src/app/pages/about/overview/about-overview-page.html 40 @@ -7556,7 +7556,7 @@ Total amount - Total amount + Wartość portfela apps/client/src/app/pages/portfolio/analysis/analysis-page.html 95 @@ -7898,7 +7898,7 @@ Fee Ratio - Fee Ratio + Wskaźnik opłat apps/client/src/app/pages/i18n/i18n-page.html 152 @@ -8333,7 +8333,7 @@ Account Cluster Risks - Account Cluster Risks + Ryzyka skupienia w obrębie rachunków apps/client/src/app/pages/i18n/i18n-page.html 14 @@ -8341,7 +8341,7 @@ Asset Class Cluster Risks - Asset Class Cluster Risks + Ryzyka skupienia w obrębie klas aktywów apps/client/src/app/pages/i18n/i18n-page.html 39 @@ -8349,7 +8349,7 @@ Currency Cluster Risks - Currency Cluster Risks + Ryzyka koncentracji walutowej apps/client/src/app/pages/i18n/i18n-page.html 83 @@ -8357,7 +8357,7 @@ Economic Market Cluster Risks - Economic Market Cluster Risks + Ryzyka skupienia w obrębie segmentów rynku gospodarczego apps/client/src/app/pages/i18n/i18n-page.html 106 @@ -8373,7 +8373,7 @@ Fees - Fees + Opłaty apps/client/src/app/pages/i18n/i18n-page.html 161 @@ -8381,7 +8381,7 @@ Liquidity - Liquidity + Płynność apps/client/src/app/pages/i18n/i18n-page.html 70 @@ -8389,7 +8389,7 @@ Buying Power - Buying Power + Siła nabywcza apps/client/src/app/pages/i18n/i18n-page.html 71 @@ -8413,7 +8413,7 @@ Your buying power exceeds ${thresholdMin} ${baseCurrency} - Your buying power exceeds ${thresholdMin} ${baseCurrency} + Twoja siła nabywcza przekracza ${thresholdMin} ${baseCurrency} apps/client/src/app/pages/i18n/i18n-page.html 80 @@ -8421,7 +8421,7 @@ Regional Market Cluster Risks - Regional Market Cluster Risks + Ryzyka skupienia w obrębie regionów rynkowych apps/client/src/app/pages/i18n/i18n-page.html 163 @@ -8437,7 +8437,7 @@ Developed Markets - Developed Markets + Rynki rozwinięte apps/client/src/app/pages/i18n/i18n-page.html 109 @@ -8469,7 +8469,7 @@ Emerging Markets - Emerging Markets + Rynki wschodzące apps/client/src/app/pages/i18n/i18n-page.html 127 @@ -8581,7 +8581,7 @@ Europe - Europe + Europa apps/client/src/app/pages/i18n/i18n-page.html 195 @@ -8613,7 +8613,7 @@ Japan - Japan + Japonia apps/client/src/app/pages/i18n/i18n-page.html 209 From 27c50bf5096c5d561af4e35d97d6f55ad1e81ad9 Mon Sep 17 00:00:00 2001 From: Kenrick Tandrian <60643640+KenTandrian@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:06:46 +0700 Subject: [PATCH 069/138] Task/improve type safety of benchmark component (#6555) * Improve type safety --- .../interfaces/interfaces.ts | 2 +- .../lib/benchmark/benchmark.component.html | 16 +- .../src/lib/benchmark/benchmark.component.ts | 147 +++++++++--------- 3 files changed, 79 insertions(+), 86 deletions(-) diff --git a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/interfaces/interfaces.ts b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/interfaces/interfaces.ts index 291f4c973..b01403284 100644 --- a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/interfaces/interfaces.ts +++ b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/interfaces/interfaces.ts @@ -3,7 +3,7 @@ import { ColorScheme } from '@ghostfolio/common/types'; import { DataSource } from '@prisma/client'; export interface BenchmarkDetailDialogParams { - colorScheme: ColorScheme; + colorScheme?: ColorScheme; dataSource: DataSource; deviceType: string; locale: string; diff --git a/libs/ui/src/lib/benchmark/benchmark.component.html b/libs/ui/src/lib/benchmark/benchmark.component.html index ab6db8887..8820f2ec1 100644 --- a/libs/ui/src/lib/benchmark/benchmark.component.html +++ b/libs/ui/src/lib/benchmark/benchmark.component.html @@ -15,7 +15,7 @@
{{ element?.name }}
- @if (showSymbol) { + @if (showSymbol()) {
{{ element?.symbol }}
@@ -98,7 +98,7 @@ @if (element?.performances?.allTimeHigh?.date) { } @@ -123,7 +123,7 @@
- @if (hasPermissionToDeleteItem) { + @if (hasPermissionToDeleteItem()) {
- + @if (isLoading()) { } -@if (dataSource.data.length > pageSize && !isLoading()) { +@if (dataSource.data.length > pageSize() && !isLoading()) {
+ } + + @if (value || value === 0 || value === null) {
} + @if (!hasLabel) { + + }
} @@ -88,6 +110,9 @@ @if (size === 'large') {
+ @if (hasLabel) { + + } @if (subLabel) { {{ subLabel }} } @@ -95,6 +120,9 @@ } @else { + @if (hasLabel) { + + } }
diff --git a/libs/ui/src/lib/value/value.component.stories.ts b/libs/ui/src/lib/value/value.component.stories.ts index eeebe9399..214331efc 100644 --- a/libs/ui/src/lib/value/value.component.stories.ts +++ b/libs/ui/src/lib/value/value.component.stories.ts @@ -1,3 +1,4 @@ +import '@angular/localize/init'; import { moduleMetadata } from '@storybook/angular'; import type { Meta, StoryObj } from '@storybook/angular'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @@ -17,6 +18,9 @@ export default { control: 'select', options: ['desktop', 'mobile'] }, + enableCopyToClipboardButton: { + control: 'boolean' + }, size: { control: 'select', options: ['small', 'medium', 'large'] @@ -58,7 +62,7 @@ export const Label: Story = { }, render: (args) => ({ props: args, - template: `Label` + template: `Label` }) }; diff --git a/libs/ui/src/lib/value/value.component.ts b/libs/ui/src/lib/value/value.component.ts index 795e16491..9c3330466 100644 --- a/libs/ui/src/lib/value/value.component.ts +++ b/libs/ui/src/lib/value/value.component.ts @@ -1,30 +1,41 @@ import { getLocale } from '@ghostfolio/common/helper'; +import { Clipboard } from '@angular/cdk/clipboard'; import { CommonModule } from '@angular/common'; import { - CUSTOM_ELEMENTS_SCHEMA, + AfterViewInit, ChangeDetectionStrategy, + ChangeDetectorRef, Component, + computed, + CUSTOM_ELEMENTS_SCHEMA, + ElementRef, + input, Input, OnChanges, - computed, - input + ViewChild } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatSnackBar } from '@angular/material/snack-bar'; import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { copyOutline } from 'ionicons/icons'; import { isNumber } from 'lodash'; +import ms from 'ms'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [CommonModule, IonIcon, NgxSkeletonLoaderModule], + imports: [CommonModule, IonIcon, MatButtonModule, NgxSkeletonLoaderModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-value', styleUrls: ['./value.component.scss'], templateUrl: './value.component.html' }) -export class GfValueComponent implements OnChanges { +export class GfValueComponent implements AfterViewInit, OnChanges { @Input() colorizeSign = false; @Input() deviceType: string; + @Input() enableCopyToClipboardButton = false; @Input() icon = ''; @Input() isAbsolute = false; @Input() isCurrency = false; @@ -37,12 +48,26 @@ export class GfValueComponent implements OnChanges { @Input() unit = ''; @Input() value: number | string = ''; + @ViewChild('labelContent', { static: false }) + labelContent!: ElementRef; + public absoluteValue = 0; public formattedValue = ''; + public hasLabel = false; public isNumber = false; public isString = false; public useAbsoluteValue = false; + public constructor( + private changeDetectorRef: ChangeDetectorRef, + private clipboard: Clipboard, + private snackBar: MatSnackBar + ) { + addIcons({ + copyOutline + }); + } + public readonly precision = input(); private readonly formatOptions = computed(() => { @@ -59,6 +84,17 @@ export class GfValueComponent implements OnChanges { return precision !== undefined && precision >= 0; } + public ngAfterViewInit() { + if (this.labelContent) { + const element = this.labelContent.nativeElement; + + this.hasLabel = + element.children.length > 0 || element.textContent.trim().length > 0; + + this.changeDetectorRef.markForCheck(); + } + } + public ngOnChanges() { this.initializeVariables(); @@ -137,6 +173,18 @@ export class GfValueComponent implements OnChanges { } } + public onCopyValueToClipboard() { + this.clipboard.copy(String(this.value)); + + this.snackBar.open( + '✅ ' + $localize`${this.value} has been copied to the clipboard`, + undefined, + { + duration: ms('3 seconds') + } + ); + } + private initializeVariables() { this.absoluteValue = 0; this.formattedValue = ''; From d98dc15c34bb41ec336e1f9b2bbd59070b8b3718 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 31 Mar 2026 17:41:49 +0200 Subject: [PATCH 119/138] Feature/add copy-to-clipboard buttons to holding detail dialog (#6640) * Add copy to clipboard buttons for symbol and ISIN * Update changelog --- CHANGELOG.md | 2 ++ .../holding-detail-dialog/holding-detail-dialog.html | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6721e3022..274851846 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added support for a copy-to-clipboard functionality in the value component +- Extended the holding detail dialog by adding a copy-to-clipboard button for the ISIN number (experimental) +- Extended the holding detail dialog by adding a copy-to-clipboard button for the symbol (experimental) ### Changed diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html index 15415e413..b8cb8dda2 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -310,6 +310,9 @@ Symbol ISIN Date: Tue, 31 Mar 2026 17:48:14 +0200 Subject: [PATCH 120/138] Task/update locales (#6513) * Update locales --- apps/client/src/locales/messages.ca.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.de.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.es.xlf | 220 ++++++++++++----------- apps/client/src/locales/messages.fr.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.it.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.ko.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.nl.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.pl.xlf | 224 +++++++++++++----------- apps/client/src/locales/messages.pt.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.tr.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.uk.xlf | 218 ++++++++++++----------- apps/client/src/locales/messages.xlf | 217 ++++++++++++----------- apps/client/src/locales/messages.zh.xlf | 218 ++++++++++++----------- 13 files changed, 1524 insertions(+), 1317 deletions(-) diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index cf0ede34d..566d91cc7 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -38,7 +38,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -659,7 +659,7 @@ Tipus apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -679,7 +679,7 @@ Perfil d’Actiu apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -687,7 +687,7 @@ Dades Històriques de Mercat apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -699,7 +699,7 @@ Origen de les Dades apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -723,7 +723,7 @@ Prioritat apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -731,7 +731,7 @@ Intents apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -739,7 +739,7 @@ Creat apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -747,7 +747,7 @@ Finalitzat apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -755,7 +755,7 @@ Estat apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -775,7 +775,7 @@ Aturar Processos apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -783,7 +783,7 @@ Veure les Dades apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -791,7 +791,7 @@ Veure Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -799,7 +799,7 @@ Executar Procés apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -807,7 +807,7 @@ Suprimir Procés apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -859,7 +859,7 @@ Punts de referència apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -867,7 +867,7 @@ Divises apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -879,7 +879,7 @@ ETFs sense País apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -887,7 +887,7 @@ ETFs sense Sector apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -895,7 +895,7 @@ Filtra per... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -1231,7 +1231,7 @@ Està segur qeu vol eliminar aquest cupó? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -1239,7 +1239,7 @@ Està segur que vol eliminar aquest missatge del sistema? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -1247,7 +1247,7 @@ Està segur que vol depurar el cache? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -1255,7 +1255,7 @@ Si us plau, afegeixi el seu missatge del sistema: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -1391,7 +1391,7 @@ Està segur que vol eliminar aquesta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -1423,7 +1423,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -1471,7 +1471,7 @@ Està segur que vol eliminar aquesta etiqueta? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -1495,7 +1495,7 @@ Està segur que vol eliminar aquest usuari? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -1691,15 +1691,15 @@ Oooh! El testimoni de seguretat és incorrecte. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -1779,7 +1779,7 @@ Informar d’un Problema amb les Dades apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1787,7 +1787,7 @@ en Actiiu apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -1795,7 +1795,7 @@ Finalitzat apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -1819,7 +1819,7 @@ Gestionar Activitats apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1827,11 +1827,11 @@ Por apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -1843,11 +1843,11 @@ Cobdícia apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -1951,7 +1951,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -2359,7 +2359,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -2371,7 +2371,7 @@ 1 any apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -2383,7 +2383,7 @@ 5 anys apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -2403,7 +2403,7 @@ Màx apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -2547,7 +2547,7 @@ Automàtic apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2559,7 +2559,7 @@ De debò vols tancar el teu compte de Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -2567,7 +2567,7 @@ De debò vols eliminar aquest mètode d’inici de sessió? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -2583,7 +2583,7 @@ Ups! Hi ha hagut un error en configurar l’autenticació biomètrica. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -2775,7 +2775,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2795,7 +2795,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2811,7 +2811,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -2947,7 +2947,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -3051,7 +3051,7 @@ Dades de mercat apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -3085,6 +3085,10 @@ Overview Visió general + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -3972,7 +3976,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -4028,7 +4032,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -4148,7 +4152,7 @@ Importar dividends apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -4164,7 +4168,7 @@ S’estan important dades... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -4172,7 +4176,7 @@ La importació s’ha completat apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -4188,7 +4192,7 @@ S’estan validant les dades... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -4504,7 +4508,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -4524,11 +4528,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -4548,7 +4552,7 @@ Mensualment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -4556,7 +4560,7 @@ Anualment apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -4564,7 +4568,7 @@ Close Holding apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -4942,6 +4946,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Personal Finance Tools @@ -5441,7 +5449,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5461,7 +5469,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -5481,7 +5489,7 @@ any apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -5501,7 +5509,7 @@ anys apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -5653,7 +5661,7 @@ Dipòsit libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -5669,7 +5677,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -5681,7 +5689,7 @@ Estalvi libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -5921,7 +5929,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -5937,7 +5945,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -5969,7 +5977,7 @@ Símbol apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -5985,7 +5993,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -6333,11 +6341,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -6857,7 +6865,7 @@ Portfolio Snapshot apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6924,6 +6932,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning From the beginning @@ -7363,7 +7379,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7403,7 +7419,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7419,7 +7435,7 @@ Lazy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7427,7 +7443,7 @@ Instant apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7467,7 +7483,7 @@ end of day apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7475,7 +7491,7 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7483,7 +7499,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7503,7 +7519,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7515,7 +7531,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7523,11 +7539,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7631,11 +7647,11 @@ Security token apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7643,7 +7659,7 @@ Do you really want to generate a new security token for this user? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7788,7 +7804,7 @@ someone apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7820,7 +7836,7 @@ Do you really want to delete this item? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7861,7 +7877,7 @@ Demo user account has been synced. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8075,7 +8091,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8244,7 +8260,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8268,7 +8284,7 @@ Stocks apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8280,7 +8296,7 @@ Cryptocurrencies apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8300,7 +8316,7 @@ Manage Asset Profile apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index cad4fcc92..1a1df8cc1 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -50,7 +50,7 @@ Typ apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -306,7 +306,7 @@ Jobs löschen apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -314,7 +314,7 @@ Datenquelle apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -338,7 +338,7 @@ Versuche apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -346,7 +346,7 @@ Erstellt apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -354,7 +354,7 @@ Abgeschlossen apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -362,7 +362,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -394,7 +394,7 @@ Historische Marktdaten apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -406,7 +406,7 @@ Daten anzeigen apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -414,7 +414,7 @@ Stacktrace anzeigen apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -422,7 +422,7 @@ Job löschen apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -514,7 +514,7 @@ Möchtest du diesen Gutscheincode wirklich löschen? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -522,7 +522,7 @@ Möchtest du den Cache wirklich leeren? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -530,7 +530,7 @@ Bitte gebe deine Systemmeldung ein: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -650,7 +650,7 @@ Möchtest du diesen Benutzer wirklich löschen? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -758,7 +758,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -778,15 +778,15 @@ Ups! Falsches Sicherheits-Token. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -794,7 +794,7 @@ Aktivitäten verwalten apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1034,7 +1034,7 @@ Datenfehler melden apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1082,7 +1082,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -1094,7 +1094,7 @@ 1J apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -1106,7 +1106,7 @@ 5J apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -1126,7 +1126,7 @@ Max apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -1146,7 +1146,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -1238,7 +1238,7 @@ Möchtest du diese Anmeldemethode wirklich löschen? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -1394,7 +1394,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -1676,6 +1676,10 @@ Overview Übersicht + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -1934,7 +1938,7 @@ Aktuelle Woche apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -2058,7 +2062,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2082,7 +2086,7 @@ Daten importieren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -2090,7 +2094,7 @@ Der Import wurde abgeschlossen apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -2208,6 +2212,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Resources @@ -2398,7 +2406,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2410,7 +2418,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2530,7 +2538,7 @@ Monatlich apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -2546,7 +2554,7 @@ Einlage libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -2562,7 +2570,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -2574,7 +2582,7 @@ Ersparnisse libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -2598,11 +2606,11 @@ Angst apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -2614,11 +2622,11 @@ Gier apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -2630,7 +2638,7 @@ Filtern nach... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -2714,7 +2722,7 @@ Automatisch apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2826,7 +2834,7 @@ Symbol apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2842,7 +2850,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -2998,7 +3006,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -3018,11 +3026,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -3170,7 +3178,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -3218,7 +3226,7 @@ Daten validieren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -3242,7 +3250,7 @@ Marktdaten apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -3294,7 +3302,7 @@ Jährlich apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -3302,7 +3310,7 @@ Dividenden importieren apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3362,7 +3370,7 @@ Keine Aktivitäten apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -3874,7 +3882,7 @@ Aktuelles Jahr apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -3918,7 +3926,7 @@ Möchtest du diese Plattform wirklich löschen? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -4514,7 +4522,7 @@ ETFs ohne Länder apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -4522,7 +4530,7 @@ ETFs ohne Sektoren apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -4702,7 +4710,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -4758,7 +4766,7 @@ Währungen apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -5508,7 +5516,7 @@ Möchtest du diesen Tag wirklich löschen? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -5608,7 +5616,7 @@ Anlageprofil apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -5740,7 +5748,7 @@ Möchtest du diese Systemmeldung wirklich löschen? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -5896,11 +5904,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5920,7 +5928,7 @@ Position abschliessen apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5968,7 +5976,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5988,7 +5996,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6036,7 +6044,7 @@ Jahr apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6056,7 +6064,7 @@ Jahre apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6149,7 +6157,7 @@ Aktiv apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6157,7 +6165,7 @@ Abgeschlossen apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6189,7 +6197,7 @@ Job ausführen apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6197,7 +6205,7 @@ Priorität apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6253,7 +6261,7 @@ Möchtest du dieses Ghostfolio Konto wirklich schliessen? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6309,7 +6317,7 @@ Ups! Beim Einrichten der biometrischen Authentifizierung ist ein Fehler aufgetreten. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6325,7 +6333,7 @@ Benchmarks apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6881,7 +6889,7 @@ Portfolio Snapshot apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6948,6 +6956,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning Seit Beginn @@ -7387,7 +7403,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7427,7 +7443,7 @@ KI-Anweisung wurde in die Zwischenablage kopiert apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7443,7 +7459,7 @@ Verzögert apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7451,7 +7467,7 @@ Sofort apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7491,7 +7507,7 @@ Tagesende apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7499,7 +7515,7 @@ in Echtzeit apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7507,7 +7523,7 @@ Öffne Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7527,7 +7543,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7539,7 +7555,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7547,11 +7563,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7655,11 +7671,11 @@ Sicherheits-Token apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7667,7 +7683,7 @@ Möchtest du für diesen Benutzer wirklich ein neues Sicherheits-Token generieren? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7788,7 +7804,7 @@ jemand apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7820,7 +7836,7 @@ Möchtest du diesen Eintrag wirklich löschen? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7861,7 +7877,7 @@ Demo Benutzerkonto wurde synchronisiert. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8075,7 +8091,7 @@ Aktueller Monat apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8244,7 +8260,7 @@ Möchtest du wirklich ein neues Sicherheits-Token generieren? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8268,7 +8284,7 @@ Aktien apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8280,7 +8296,7 @@ Kryptowährungen apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8300,7 +8316,7 @@ Anlageprofil verwalten apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index 9a932471c..26c76ef6c 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -51,7 +51,7 @@ Tipo apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -307,7 +307,7 @@ Eliminar trabajos apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -315,7 +315,7 @@ Fuente de datos apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -339,7 +339,7 @@ Intentos apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -347,7 +347,7 @@ Creado apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -355,7 +355,7 @@ Finalizado apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -363,7 +363,7 @@ Estado apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -395,7 +395,7 @@ Datos históricos del mercado apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -407,7 +407,7 @@ Ver datos apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -415,7 +415,7 @@ Ver Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -423,7 +423,7 @@ Eliminar trabajo apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -515,7 +515,7 @@ ¿Seguro que quieres eliminar este cupón? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -523,7 +523,7 @@ ¿Seguro que quieres limpiar la caché? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -531,7 +531,7 @@ Por favor, establece tu mensaje del sistema: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -635,7 +635,7 @@ ¿Seguro que quieres eliminar este usuario? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -743,7 +743,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -763,15 +763,15 @@ ¡Vaya! Token de seguridad incorrecto. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -779,7 +779,7 @@ Gestionar operaciones apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1019,7 +1019,7 @@ Reportar anomalía en los datos apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1067,7 +1067,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -1079,7 +1079,7 @@ 1 año apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -1091,7 +1091,7 @@ 5 años apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -1111,7 +1111,7 @@ Máximo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -1131,7 +1131,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -1223,7 +1223,7 @@ ¿Seguro que quieres eliminar este método de acceso? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -1379,7 +1379,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -1661,6 +1661,10 @@ Overview Visión general + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -1919,7 +1923,7 @@ Semana actual apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -2043,7 +2047,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2067,7 +2071,7 @@ Importando datos... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -2075,7 +2079,7 @@ La importación se ha completado apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -2193,6 +2197,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Resources @@ -2379,7 +2387,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2395,7 +2403,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2515,7 +2523,7 @@ Ahorros libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -2531,7 +2539,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -2551,7 +2559,7 @@ Depósito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -2559,7 +2567,7 @@ Mensual apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -2583,11 +2591,11 @@ Miedo apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -2599,11 +2607,11 @@ Codicia apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -2615,7 +2623,7 @@ Filtrar por... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -2699,7 +2707,7 @@ Automático apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2811,7 +2819,7 @@ Símbolo apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2827,7 +2835,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -2983,7 +2991,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -3003,11 +3011,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -3147,7 +3155,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -3203,7 +3211,7 @@ Validando datos... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -3227,7 +3235,7 @@ Datos del mercado apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -3279,7 +3287,7 @@ Anual apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -3287,7 +3295,7 @@ Importar dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3347,7 +3355,7 @@ Sin operaciones apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -3851,7 +3859,7 @@ Año actual apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -3895,7 +3903,7 @@ ¿Seguro que quieres eliminar esta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -4491,7 +4499,7 @@ ETFs sin países apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -4499,7 +4507,7 @@ ETFs sin sectores apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -4679,7 +4687,7 @@ ID del trabajo apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -4735,7 +4743,7 @@ Divisas apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -4964,7 +4972,7 @@ caring about diversifying your financial resources - preocupado por diversificar tus recursos financieros + preocupado por diversificar tus recursos financieros apps/client/src/app/pages/landing/landing-page.html 201 @@ -5485,7 +5493,7 @@ ¿Seguro que quieres eliminar esta etiqueta? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -5585,7 +5593,7 @@ Perfil de activo apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -5717,7 +5725,7 @@ ¿Seguro que quieres eliminar este mensaje del sistema? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -5873,11 +5881,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5897,7 +5905,7 @@ Cerrar posición apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5945,7 +5953,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5965,7 +5973,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6013,7 +6021,7 @@ año apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6033,7 +6041,7 @@ años apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6126,7 +6134,7 @@ Activo apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6134,7 +6142,7 @@ Cerrado apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6166,7 +6174,7 @@ Ejecutar trabajo apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6174,7 +6182,7 @@ Prioridad apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6230,7 +6238,7 @@ ¿Seguro que quieres eliminar tu cuenta de Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6286,7 +6294,7 @@ ¡Vaya! Hubo un error al configurar la autenticación biométrica. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6302,7 +6310,7 @@ Índices de referencia apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6858,7 +6866,7 @@ Instantánea de la cartera apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6925,6 +6933,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning Desde el principio @@ -7364,7 +7380,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7404,7 +7420,7 @@ El prompt para la IA ha sido copiado al portapapeles apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7420,7 +7436,7 @@ Bajo demanda apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7428,7 +7444,7 @@ Instantáneo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7468,7 +7484,7 @@ final del día apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7476,7 +7492,7 @@ en tiempo real apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7484,7 +7500,7 @@ Abrir Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7504,7 +7520,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7516,7 +7532,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7524,11 +7540,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7632,11 +7648,11 @@ Token de seguridad apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7644,7 +7660,7 @@ ¿Seguro que quieres generar un nuevo token de seguridad para este usuario? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7789,7 +7805,7 @@ alguien apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7821,7 +7837,7 @@ ¿Seguro que quieres eliminar este elemento? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7862,7 +7878,7 @@ La cuenta de usuario de demostración se ha sincronizado. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8076,7 +8092,7 @@ Mes actual apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8245,7 +8261,7 @@ ¿Seguro que quieres generar un nuevo token de seguridad? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8269,7 +8285,7 @@ Acciones apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8281,7 +8297,7 @@ Criptomonedas apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8301,7 +8317,7 @@ Gestionar perfil de activo apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index f01a3a505..eec144e92 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -42,7 +42,7 @@ Type apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -362,7 +362,7 @@ Source Données apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -386,7 +386,7 @@ Tentatives apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -394,7 +394,7 @@ Créé apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -402,7 +402,7 @@ Terminé apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -410,7 +410,7 @@ Statut apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -430,7 +430,7 @@ Supprimer Tâches apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -450,7 +450,7 @@ Données historiques du marché apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -462,7 +462,7 @@ Voir Données apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -470,7 +470,7 @@ Voir la Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -478,7 +478,7 @@ Supprimer Tâche apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -530,7 +530,7 @@ Filtrer par... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -706,7 +706,7 @@ Voulez-vous vraiment supprimer ce code promotionnel ? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -714,7 +714,7 @@ Voulez-vous vraiment vider le cache ? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -722,7 +722,7 @@ Veuillez définir votre message système : apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -846,7 +846,7 @@ Voulez-vous vraiment supprimer cet·te utilisateur·rice ? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -978,7 +978,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -998,15 +998,15 @@ Oups! Jeton de Sécurité Incorrect. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -1014,7 +1014,7 @@ Gérer les Activités apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1022,11 +1022,11 @@ Peur apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -1038,11 +1038,11 @@ Avidité apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -1294,7 +1294,7 @@ Signaler une Erreur de Données apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1314,7 +1314,7 @@ CDA apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -1326,7 +1326,7 @@ 1A apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -1338,7 +1338,7 @@ 5A apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -1358,7 +1358,7 @@ Max apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -1386,7 +1386,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -1398,7 +1398,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -1414,7 +1414,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -1474,7 +1474,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -1518,7 +1518,7 @@ Voulez-vous vraiment supprimer cette méthode de connexion ? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -1714,7 +1714,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -1762,7 +1762,7 @@ Données du marché apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -2066,7 +2066,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2098,7 +2098,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -2162,7 +2162,7 @@ Import des données... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -2170,7 +2170,7 @@ L’import est terminé apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -2186,7 +2186,7 @@ Validation des données... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -2418,7 +2418,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -2438,7 +2438,7 @@ Dépôt libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -2446,7 +2446,7 @@ Mensuel apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -2648,6 +2648,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Resources @@ -2700,6 +2704,10 @@ Overview Aperçu + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -2858,7 +2866,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -2870,7 +2878,7 @@ Épargne libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -3006,7 +3014,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -3014,7 +3022,7 @@ Symbole apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -3030,7 +3038,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -3242,11 +3250,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -3278,7 +3286,7 @@ Annuel apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -3286,7 +3294,7 @@ Importer Dividendes apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3346,7 +3354,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -3850,7 +3858,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -3894,7 +3902,7 @@ Voulez-vous vraiment supprimer cette plateforme ? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -4490,7 +4498,7 @@ ETF sans Pays apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -4498,7 +4506,7 @@ ETF sans Secteurs apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -4678,7 +4686,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -4734,7 +4742,7 @@ Devises apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -5484,7 +5492,7 @@ Confirmez la suppression de ce tag ? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -5584,7 +5592,7 @@ Profil d’Actif apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -5716,7 +5724,7 @@ Confirmer la suppresion de ce message système? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -5872,11 +5880,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5896,7 +5904,7 @@ Close Holding apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5944,7 +5952,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5964,7 +5972,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6012,7 +6020,7 @@ année apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6032,7 +6040,7 @@ années apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6125,7 +6133,7 @@ Actif apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6133,7 +6141,7 @@ Clôturé apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6165,7 +6173,7 @@ Execute la tâche apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6173,7 +6181,7 @@ Priorité apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6229,7 +6237,7 @@ Confirmer la suppresion de votre compte Ghostfolio ? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6285,7 +6293,7 @@ Oops! Une erreur s’est produite lors de la configuration de l’authentification biométrique. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6301,7 +6309,7 @@ Benchmarks apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6857,7 +6865,7 @@ Résumé du portefeuille apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6924,6 +6932,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning Depuis le début @@ -7363,7 +7379,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7403,7 +7419,7 @@ Le prompt IA a été copié dans le presse-papiers apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7419,7 +7435,7 @@ Paresseux apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7427,7 +7443,7 @@ Instantané apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7467,7 +7483,7 @@ fin de journée apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7475,7 +7491,7 @@ temps réel apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7483,7 +7499,7 @@ Ouvrir Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7503,7 +7519,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7515,7 +7531,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7523,11 +7539,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7631,11 +7647,11 @@ Jeton de sécurité apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7643,7 +7659,7 @@ Voulez-vous vraiment générer un nouveau jeton de sécurité pour cet utilisateur ? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7788,7 +7804,7 @@ quelqu’un apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7820,7 +7836,7 @@ Voulez-vous vraiment supprimer cet élément? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7861,7 +7877,7 @@ Le compte utilisateur de démonstration a été synchronisé. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8075,7 +8091,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8244,7 +8260,7 @@ Voulez-vous vraiment générer un nouveau jeton de sécurité? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8268,7 +8284,7 @@ Actions apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8280,7 +8296,7 @@ Crypto-monnaies apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8300,7 +8316,7 @@ Gérer le profil d’actif apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 5f06af0b4..b143bbde3 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -51,7 +51,7 @@ Tipo apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -307,7 +307,7 @@ Elimina i lavori apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -315,7 +315,7 @@ Sorgente dei dati apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -339,7 +339,7 @@ Tentativi apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -347,7 +347,7 @@ Creato apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -355,7 +355,7 @@ Finito apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -363,7 +363,7 @@ Stato apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -395,7 +395,7 @@ Dati storici del mercato apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -407,7 +407,7 @@ Visualizza i dati apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -415,7 +415,7 @@ Visualizza Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -423,7 +423,7 @@ Elimina il lavoro apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -515,7 +515,7 @@ Vuoi davvero eliminare questo buono? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -523,7 +523,7 @@ Vuoi davvero svuotare la cache? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -531,7 +531,7 @@ Imposta il messaggio di sistema: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -635,7 +635,7 @@ Vuoi davvero eliminare questo utente? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -743,7 +743,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -763,15 +763,15 @@ Ops! Token di sicurezza errato. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -779,7 +779,7 @@ Gestione delle attività apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1019,7 +1019,7 @@ Segnala un’anomalia dei dati apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1067,7 +1067,7 @@ anno corrente apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -1079,7 +1079,7 @@ 1 anno apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -1091,7 +1091,7 @@ 5 anni apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -1111,7 +1111,7 @@ Massimo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -1131,7 +1131,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -1223,7 +1223,7 @@ Vuoi davvero rimuovere questo metodo di accesso? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -1379,7 +1379,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -1661,6 +1661,10 @@ Overview Panoramica + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -1919,7 +1923,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -2043,7 +2047,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2067,7 +2071,7 @@ Importazione dei dati... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -2075,7 +2079,7 @@ L’importazione è stata completata apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -2193,6 +2197,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Resources @@ -2379,7 +2387,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2395,7 +2403,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2515,7 +2523,7 @@ Risparmio libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -2531,7 +2539,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -2551,7 +2559,7 @@ Deposito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -2559,7 +2567,7 @@ Mensile apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -2583,11 +2591,11 @@ Paura apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -2599,11 +2607,11 @@ Avidità apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -2615,7 +2623,7 @@ Filtra per... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -2699,7 +2707,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2811,7 +2819,7 @@ Simbolo apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2827,7 +2835,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -2983,7 +2991,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -3003,11 +3011,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -3147,7 +3155,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -3203,7 +3211,7 @@ Convalida dei dati... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -3227,7 +3235,7 @@ Dati del mercato apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -3279,7 +3287,7 @@ Annuale apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -3287,7 +3295,7 @@ Importa i dividendi apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3347,7 +3355,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -3851,7 +3859,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -3895,7 +3903,7 @@ Vuoi davvero eliminare questa piattaforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -4491,7 +4499,7 @@ ETF senza paesi apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -4499,7 +4507,7 @@ ETF senza settori apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -4679,7 +4687,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -4735,7 +4743,7 @@ Valute apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -5485,7 +5493,7 @@ Sei sicuro di voler eliminare questo tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -5585,7 +5593,7 @@ Profilo dell’asset apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -5717,7 +5725,7 @@ Confermi di voler cancellare questo messaggio di sistema? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -5873,11 +5881,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5897,7 +5905,7 @@ Close Holding apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5945,7 +5953,7 @@ Settimana corrente apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5965,7 +5973,7 @@ Mese corrente apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6013,7 +6021,7 @@ anno apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6033,7 +6041,7 @@ anni apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6126,7 +6134,7 @@ Attivo apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6134,7 +6142,7 @@ Chiuso apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6166,7 +6174,7 @@ Esegui il lavoro apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6174,7 +6182,7 @@ Priorità apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6230,7 +6238,7 @@ Confermi di voler chiudere il tuo account Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6286,7 +6294,7 @@ Ops! C’è stato un errore impostando l’autenticazione biometrica. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6302,7 +6310,7 @@ Benchmarks apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6858,7 +6866,7 @@ Stato del Portfolio apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6925,6 +6933,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning Dall’inizio @@ -7364,7 +7380,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7404,7 +7420,7 @@ L’AI prompt è stato copiato negli appunti apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7420,7 +7436,7 @@ Pigro apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7428,7 +7444,7 @@ Istantaneo apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7468,7 +7484,7 @@ fine giornata apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7476,7 +7492,7 @@ in tempo reale apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7484,7 +7500,7 @@ Apri Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7504,7 +7520,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7516,7 +7532,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7524,11 +7540,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7632,11 +7648,11 @@ Token di sicurezza apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7644,7 +7660,7 @@ Vuoi davvero generare un nuovo token di sicurezza per questo utente? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7789,7 +7805,7 @@ qualcuno apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7821,7 +7837,7 @@ Vuoi davvero eliminare questo elemento? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7862,7 +7878,7 @@ L’account utente demo è stato sincronizzato. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8076,7 +8092,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8245,7 +8261,7 @@ Vuoi davvero generare un nuovo token di sicurezza? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8269,7 +8285,7 @@ Azioni apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8281,7 +8297,7 @@ criptovalute apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8301,7 +8317,7 @@ Gestisci profilo risorsa apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.ko.xlf b/apps/client/src/locales/messages.ko.xlf index bb361b515..4f544e4aa 100644 --- a/apps/client/src/locales/messages.ko.xlf +++ b/apps/client/src/locales/messages.ko.xlf @@ -252,7 +252,7 @@ 유형 apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -592,7 +592,7 @@ 자산 프로필 apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -600,7 +600,7 @@ 과거 시장 데이터 apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -612,7 +612,7 @@ 데이터 소스 apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -636,7 +636,7 @@ 시도 횟수 apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -644,7 +644,7 @@ 생성됨 apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -652,7 +652,7 @@ 완료됨 apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -660,7 +660,7 @@ 상태 apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -680,7 +680,7 @@ 작업 삭제 apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -688,7 +688,7 @@ 데이터 보기 apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -696,7 +696,7 @@ 스택트레이스 보기 apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -704,7 +704,7 @@ 작업 삭제 apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -756,7 +756,7 @@ 통화 apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -768,7 +768,7 @@ 국가 정보 없는 ETF apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -776,7 +776,7 @@ 섹터 정보 없는 ETF apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -792,7 +792,7 @@ 다음 기준으로 필터... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -1076,7 +1076,7 @@ 이 쿠폰을 정말 삭제하시겠습니까? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -1084,7 +1084,7 @@ 이 시스템 메시지를 정말 삭제하시겠습니까? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -1092,7 +1092,7 @@ 정말로 캐시를 플러시하시겠습니까? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -1100,7 +1100,7 @@ 시스템 메시지를 설정하십시오: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -1252,7 +1252,7 @@ 정말로 이 플랫폼을 삭제하시겠습니까? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -1284,7 +1284,7 @@ 올해 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -1332,7 +1332,7 @@ 이 태그를 정말로 삭제하시겠습니까? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -1356,7 +1356,7 @@ 이 사용자를 정말로 삭제하시겠습니까? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -1512,7 +1512,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1532,15 +1532,15 @@ 이런! 잘못된 보안 토큰. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -1548,7 +1548,7 @@ 활동 관리 apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1556,11 +1556,11 @@ 두려움 apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -1572,11 +1572,11 @@ 탐욕 apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -1680,7 +1680,7 @@ 이번주 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -1960,7 +1960,7 @@ 데이터 결함 보고 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -2148,7 +2148,7 @@ 연초 대비 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -2160,7 +2160,7 @@ 1년 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -2172,7 +2172,7 @@ 5년 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -2192,7 +2192,7 @@ 맥스 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -2296,7 +2296,7 @@ 자동 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2308,7 +2308,7 @@ 이 로그인 방법을 정말로 제거하시겠습니까? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -2492,7 +2492,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2504,7 +2504,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2520,7 +2520,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -2648,7 +2648,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2744,7 +2744,7 @@ 시장 데이터 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -2778,6 +2778,10 @@ Overview 개요 + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -3624,7 +3628,7 @@ 작업 ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -3680,7 +3684,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -3808,7 +3812,7 @@ 배당금 가져오기 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3824,7 +3828,7 @@ 데이터 가져오는 중... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -3832,7 +3836,7 @@ 가져오기가 완료되었습니다. apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -3848,7 +3852,7 @@ 데이터 유효성을 검사하는 중... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -4148,7 +4152,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -4168,7 +4172,7 @@ 보증금 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -4176,7 +4180,7 @@ 월간 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -4184,7 +4188,7 @@ 매년 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -4538,6 +4542,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Personal Finance Tools @@ -5129,7 +5137,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -5141,7 +5149,7 @@ 저금 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -5373,7 +5381,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -5389,7 +5397,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -5421,7 +5429,7 @@ 상징 apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -5437,7 +5445,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -5777,11 +5785,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5897,7 +5905,7 @@ 닫기 보유 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5921,11 +5929,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5985,7 +5993,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -5997,7 +6005,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -6037,7 +6045,7 @@ 년도 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6057,7 +6065,7 @@ 연령 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6150,7 +6158,7 @@ 닫은 apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6158,7 +6166,7 @@ 활동적인 apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6190,7 +6198,7 @@ 작업 실행 apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6206,7 +6214,7 @@ 우선 사항 apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6262,7 +6270,7 @@ 정말로 Ghostfolio 계정을 폐쇄하시겠습니까? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6310,7 +6318,7 @@ 이런! 생체 인증을 설정하는 중에 오류가 발생했습니다. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6350,7 +6358,7 @@ 벤치마크 apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6898,7 +6906,7 @@ 포트폴리오 스냅샷 apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6957,6 +6965,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + offers a free plan 은(는) 무료 요금제를 제공합니다 @@ -7404,7 +7420,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7428,7 +7444,7 @@ AI 프롬프트가 클립보드에 복사되었습니다. apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7468,7 +7484,7 @@ 즉각적인 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7476,7 +7492,7 @@ 게으른 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7492,7 +7508,7 @@ 실시간 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7500,7 +7516,7 @@ 하루의 끝 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7508,7 +7524,7 @@ 오픈 Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7528,7 +7544,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7540,7 +7556,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7548,11 +7564,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7656,7 +7672,7 @@ 정말로 이 사용자에 대한 새 보안 토큰을 생성하시겠습니까? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7672,11 +7688,11 @@ 보안 토큰 apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7789,7 +7805,7 @@ 누구 apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7821,7 +7837,7 @@ 이 항목을 정말로 삭제하시겠습니까? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7870,7 +7886,7 @@ 데모 사용자 계정이 동기화되었습니다. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8076,7 +8092,7 @@ 이번 달 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8261,7 +8277,7 @@ 정말로 새로운 보안 토큰을 생성하시겠습니까? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8269,7 +8285,7 @@ 암호화폐 apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8281,7 +8297,7 @@ 주식 apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8301,7 +8317,7 @@ 자산 프로필 관리 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index fbd87961c..039969da0 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -50,7 +50,7 @@ Type apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -306,7 +306,7 @@ Taken verwijderen apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -314,7 +314,7 @@ Gegevensbron apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -338,7 +338,7 @@ Pogingen apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -346,7 +346,7 @@ Aangemaakt apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -354,7 +354,7 @@ Voltooid apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -362,7 +362,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -394,7 +394,7 @@ Historische marktgegevens apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -406,7 +406,7 @@ Bekijk gegevens apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -414,7 +414,7 @@ Bekijk Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -422,7 +422,7 @@ Taak verwijderen apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -514,7 +514,7 @@ Wil je deze coupon echt verwijderen? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -522,7 +522,7 @@ Wil je echt de cache legen? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -530,7 +530,7 @@ Stel je systeemboodschap in: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -634,7 +634,7 @@ Wilt je deze gebruiker echt verwijderen? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -742,7 +742,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -762,15 +762,15 @@ Oeps! Onjuiste beveiligingstoken. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -778,7 +778,7 @@ Activiteiten beheren apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1018,7 +1018,7 @@ Gegevensstoring melden apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1066,7 +1066,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -1078,7 +1078,7 @@ 1J apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -1090,7 +1090,7 @@ 5J apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -1110,7 +1110,7 @@ Max apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -1130,7 +1130,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -1222,7 +1222,7 @@ Wil je deze aanmeldingsmethode echt verwijderen? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -1378,7 +1378,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -1660,6 +1660,10 @@ Overview Overzicht + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -1918,7 +1922,7 @@ Huidige week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -2042,7 +2046,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2066,7 +2070,7 @@ Gegevens importeren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -2074,7 +2078,7 @@ Importeren is voltooid apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -2192,6 +2196,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Resources @@ -2378,7 +2386,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2394,7 +2402,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2514,7 +2522,7 @@ Besparingen libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -2530,7 +2538,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -2550,7 +2558,7 @@ Storting libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -2558,7 +2566,7 @@ Maandelijks apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -2582,11 +2590,11 @@ Angst apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -2598,11 +2606,11 @@ Hebzucht apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -2614,7 +2622,7 @@ Filter op... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -2698,7 +2706,7 @@ Automatisch apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2810,7 +2818,7 @@ Symbool apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2826,7 +2834,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -2982,7 +2990,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -3002,11 +3010,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -3146,7 +3154,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -3202,7 +3210,7 @@ Gegevens valideren... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -3226,7 +3234,7 @@ Marktgegevens apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -3278,7 +3286,7 @@ Jaarlijks apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -3286,7 +3294,7 @@ Importeer dividenden apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3346,7 +3354,7 @@ Geen activiteiten apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -3850,7 +3858,7 @@ Huidig jaar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -3894,7 +3902,7 @@ Wil je dit platform echt verwijderen? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -4490,7 +4498,7 @@ ETF’s zonder Landen apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -4498,7 +4506,7 @@ ETF’s zonder Sectoren apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -4678,7 +4686,7 @@ Opdracht ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -4734,7 +4742,7 @@ Valuta apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -5484,7 +5492,7 @@ Weet u zetker dat u dit label wilt verwijderen? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -5584,7 +5592,7 @@ Bezittingen Profiel apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -5716,7 +5724,7 @@ Wilt u dit systeembericht echt verwijderen? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -5872,11 +5880,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5896,7 +5904,7 @@ Sluit Holding apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5944,7 +5952,7 @@ Week tot nu toe apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5964,7 +5972,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6012,7 +6020,7 @@ jaar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6032,7 +6040,7 @@ jaren apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6125,7 +6133,7 @@ Actief apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6133,7 +6141,7 @@ Gesloten apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6165,7 +6173,7 @@ Opdracht Uitvoeren apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6173,7 +6181,7 @@ Prioriteit apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6229,7 +6237,7 @@ Wilt u uw Ghostfolio account echt sluiten? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6285,7 +6293,7 @@ Oeps! Er is een fout opgetreden met het instellen van de biometrische authenticatie. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6301,7 +6309,7 @@ Benchmarks apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6857,7 +6865,7 @@ Portfolio Momentopname apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6924,6 +6932,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning Vanaf het begin @@ -7363,7 +7379,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7403,7 +7419,7 @@ AI-prompt is naar het klembord gekopieerd apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7419,7 +7435,7 @@ Lui apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7427,7 +7443,7 @@ Direct apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7467,7 +7483,7 @@ eind van de dag apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7475,7 +7491,7 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7483,7 +7499,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7503,7 +7519,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7515,7 +7531,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7523,11 +7539,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7631,11 +7647,11 @@ Beveiligingstoken apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7643,7 +7659,7 @@ Wilt u echt een nieuw beveiligingstoken voor deze gebruiker aanmaken? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7788,7 +7804,7 @@ iemand apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7820,7 +7836,7 @@ Wilt u dit item echt verwijderen? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7861,7 +7877,7 @@ Demo-gebruikersaccount is gesynchroniseerd. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8075,7 +8091,7 @@ Huidige maand apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8244,7 +8260,7 @@ Wilt u echt een nieuwe securitytoken genereren? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8268,7 +8284,7 @@ Aandelen apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8280,7 +8296,7 @@ Cryptovaluta apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8300,7 +8316,7 @@ Beheer activaprofiel apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index c7c07967f..a15609e6a 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -251,7 +251,7 @@ Typ apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -583,7 +583,7 @@ Profil Aktywów apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -591,7 +591,7 @@ Historyczne Dane Rynkowe apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -603,7 +603,7 @@ Źródło Danych apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -627,7 +627,7 @@ Próby apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -635,7 +635,7 @@ Utworzono apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -643,7 +643,7 @@ Zakończono apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -651,7 +651,7 @@ Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -660,7 +660,7 @@ and is driven by the efforts of its contributors - i jest rozwijany dzięki pracy jego współtwórców + i jest rozwijany dzięki pracy jego współtwórców apps/client/src/app/pages/about/overview/about-overview-page.html 49 @@ -671,7 +671,7 @@ Usuń Zadania apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -679,7 +679,7 @@ Zobacz Dane apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -687,7 +687,7 @@ Wyświetl Stos Wywołań apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -695,7 +695,7 @@ Usuń Zadanie apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -747,7 +747,7 @@ Waluty apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -759,7 +759,7 @@ ETF-y bez Krajów apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -767,7 +767,7 @@ ETF-y bez Sektorów apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -783,7 +783,7 @@ Filtruj według... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -1043,7 +1043,7 @@ Czy naprawdę chcesz usunąć ten kupon? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -1051,7 +1051,7 @@ Czy naprawdę chcesz usunąć tę wiadomość systemową? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -1059,7 +1059,7 @@ Czy naprawdę chcesz wyczyścić pamięć podręczną? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -1067,7 +1067,7 @@ Proszę ustawić swoją wiadomość systemową: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -1219,7 +1219,7 @@ Czy naprawdę chcesz usunąć tę platformę? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -1251,7 +1251,7 @@ Obecny rok apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -1299,7 +1299,7 @@ Czy naprawdę chcesz usunąć ten tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -1323,7 +1323,7 @@ Czy na pewno chcesz usunąć tego użytkownika? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -1479,7 +1479,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1499,15 +1499,15 @@ Ups! Nieprawidłowy token bezpieczeństwa. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -1515,7 +1515,7 @@ Zarządzaj Aktywnościami apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1523,11 +1523,11 @@ Zagrożenie apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -1539,11 +1539,11 @@ Zachłanność apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -1580,7 +1580,7 @@ The source code is fully available as open source software (OSS) under the AGPL-3.0 license - Kod źródłowy jest w pełni dostępny jako oprogramowanie open source (OSS) na licencji AGPL-3.0 license + Kod źródłowy jest w pełni dostępny jako oprogramowanie open source (OSS) na licencji AGPL-3.0 license apps/client/src/app/pages/about/overview/about-overview-page.html 16 @@ -1647,7 +1647,7 @@ Obecny tydzień apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -1927,7 +1927,7 @@ Zgłoś Błąd Danych apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -2115,7 +2115,7 @@ Liczony od początku roku (year-to-date) apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -2127,7 +2127,7 @@ 1 rok apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -2139,7 +2139,7 @@ 5 lat apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -2159,7 +2159,7 @@ Maksimum apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -2263,7 +2263,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2275,7 +2275,7 @@ Czy na pewno chcesz usunąć tą metode logowania? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -2459,7 +2459,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2471,7 +2471,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2487,7 +2487,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -2615,7 +2615,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2711,7 +2711,7 @@ Dane Rynkowe apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -2745,6 +2745,10 @@ Overview Przegląd + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -3591,7 +3595,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -3647,7 +3651,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -3775,7 +3779,7 @@ Impotruj Dywidendy apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3791,7 +3795,7 @@ Importowanie danych... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -3799,7 +3803,7 @@ Importowanie zakończone apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -3815,7 +3819,7 @@ Weryfikacja danych... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -4115,7 +4119,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -4135,7 +4139,7 @@ Depozyt libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -4143,7 +4147,7 @@ Miesięcznie apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -4151,7 +4155,7 @@ Rocznie apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -4505,6 +4509,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Personal Finance Tools @@ -4617,7 +4625,7 @@ Website of Thomas Kaul - Strona internetowa Thomas'a Kaul'a + Strona internetowa Thomas'a Kaul'a apps/client/src/app/pages/about/overview/about-overview-page.html 44 @@ -5060,7 +5068,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -5072,7 +5080,7 @@ Oszczędności libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -5304,7 +5312,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -5320,7 +5328,7 @@ Brak transakcji apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -5352,7 +5360,7 @@ Symbol apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -5368,7 +5376,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -5708,11 +5716,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5872,11 +5880,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5896,7 +5904,7 @@ Zamknij pozycję apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5944,7 +5952,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5964,7 +5972,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6012,7 +6020,7 @@ rok apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6032,7 +6040,7 @@ lata apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6125,7 +6133,7 @@ Antywne apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6133,7 +6141,7 @@ Zamknięte apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6165,7 +6173,7 @@ Wykonaj Zadanie apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6173,7 +6181,7 @@ Priorytet apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6229,7 +6237,7 @@ Czy na pewno chcesz zamknąć swoje konto Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6285,7 +6293,7 @@ Ups! Wystąpił błąd podczas konfigurowania uwierzytelniania biometrycznego. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6301,7 +6309,7 @@ Punkty Odniesienia apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6857,7 +6865,7 @@ Przegląd portfela apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6924,6 +6932,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning Od samego początku @@ -7363,7 +7379,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7403,7 +7419,7 @@ Prompt AI został skopiowany do schowka apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7419,7 +7435,7 @@ Leniwy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7427,7 +7443,7 @@ Natychmiastowy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7467,7 +7483,7 @@ koniec dnia apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7475,7 +7491,7 @@ w czasie rzeczywistym apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7483,7 +7499,7 @@ Otwórz Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7503,7 +7519,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7515,7 +7531,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7523,11 +7539,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7631,11 +7647,11 @@ Token bezpieczeństwa apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7643,7 +7659,7 @@ Czy napewno chcesz wygenerować nowy token bezpieczeństwa dla tego użytkownika? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7788,7 +7804,7 @@ ktoś apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7820,7 +7836,7 @@ Czy na pewno chcesz usunąć ten element? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7861,7 +7877,7 @@ Konto użytkownika demonstracyjnego zostało zsynchronizowane. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8075,7 +8091,7 @@ Bieżący miesiąc apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8244,7 +8260,7 @@ Czy na pewno chcesz wygenerować nowy token bezpieczeństwa? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8268,7 +8284,7 @@ Akcje apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8280,7 +8296,7 @@ Kryptowaluty apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8300,7 +8316,7 @@ Zarządzaj profilem aktywów apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 72c1e6a3e..3531f84d7 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -42,7 +42,7 @@ Tipo apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -362,7 +362,7 @@ Fonte de dados apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -386,7 +386,7 @@ Tentativas apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -394,7 +394,7 @@ Criado apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -402,7 +402,7 @@ Terminado apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -410,7 +410,7 @@ Estado apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -430,7 +430,7 @@ Eliminar Tarefas apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -450,7 +450,7 @@ Histórico de Dados de Mercado apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -462,7 +462,7 @@ Visualizar dados apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -470,7 +470,7 @@ Ver Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -478,7 +478,7 @@ Apagar Tarefa apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -530,7 +530,7 @@ Filtrar por... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -606,7 +606,7 @@ Deseja realmente eliminar este cupão? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -614,7 +614,7 @@ Deseja realmente limpar a cache? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -622,7 +622,7 @@ Por favor, defina a sua mensagem do sistema: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -714,7 +714,7 @@ Deseja realmente excluir este utilizador? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -846,7 +846,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -866,15 +866,15 @@ Oops! Token de Segurança Incorreto. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -882,7 +882,7 @@ Gerir Atividades apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -890,11 +890,11 @@ Medo apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -906,11 +906,11 @@ Ganância apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -942,7 +942,7 @@ Depósito libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -1262,7 +1262,7 @@ Dados do Relatório com Problema apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1310,7 +1310,7 @@ AATD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -1322,7 +1322,7 @@ 1A apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -1334,7 +1334,7 @@ 5A apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -1354,7 +1354,7 @@ Máx apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -1382,7 +1382,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -1394,7 +1394,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -1410,7 +1410,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -1470,7 +1470,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -1514,7 +1514,7 @@ Deseja realmente remover este método de início de sessão? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -1718,7 +1718,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -1936,6 +1936,10 @@ Overview Visão geral + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -2046,7 +2050,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2078,7 +2082,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -2158,7 +2162,7 @@ A importar dados... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -2166,7 +2170,7 @@ A importação foi concluída apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -2362,7 +2366,7 @@ Mensalmente apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -2584,6 +2588,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Resources @@ -2758,7 +2766,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -2770,7 +2778,7 @@ Poupanças libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -2850,7 +2858,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -2858,7 +2866,7 @@ Símbolo apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -2874,7 +2882,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -3086,11 +3094,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -3134,7 +3142,7 @@ Dados de Mercado apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -3158,7 +3166,7 @@ A validar dados... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -3210,7 +3218,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -3278,7 +3286,7 @@ Anualmente apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -3286,7 +3294,7 @@ Importar Dividendos apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3346,7 +3354,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -3850,7 +3858,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -3894,7 +3902,7 @@ Deseja mesmo eliminar esta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -4490,7 +4498,7 @@ ETFs sem países apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -4498,7 +4506,7 @@ ETFs sem setores apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -4678,7 +4686,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -4734,7 +4742,7 @@ Moedas apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -5484,7 +5492,7 @@ Você realmente deseja excluir esta tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -5584,7 +5592,7 @@ Perfil de ativos apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -5716,7 +5724,7 @@ Você realmente deseja excluir esta mensagem do sistema? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -5872,11 +5880,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5896,7 +5904,7 @@ Close Holding apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5944,7 +5952,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5964,7 +5972,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6012,7 +6020,7 @@ ano apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6032,7 +6040,7 @@ anos apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6125,7 +6133,7 @@ Ativo apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6133,7 +6141,7 @@ Fechado apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6165,7 +6173,7 @@ Executar trabalho apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6173,7 +6181,7 @@ Prioridade apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6229,7 +6237,7 @@ Você realmente deseja encerrar sua conta Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6285,7 +6293,7 @@ Ops! Ocorreu um erro ao configurar a autenticação biométrica. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6301,7 +6309,7 @@ Referências apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6857,7 +6865,7 @@ Visão geral do portfólio apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6924,6 +6932,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning Desde o início @@ -7363,7 +7379,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7403,7 +7419,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7419,7 +7435,7 @@ Lazy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7427,7 +7443,7 @@ Instant apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7467,7 +7483,7 @@ end of day apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7475,7 +7491,7 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7483,7 +7499,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7503,7 +7519,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7515,7 +7531,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7523,11 +7539,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7631,11 +7647,11 @@ Security token apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7643,7 +7659,7 @@ Do you really want to generate a new security token for this user? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7788,7 +7804,7 @@ someone apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7820,7 +7836,7 @@ Do you really want to delete this item? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7861,7 +7877,7 @@ Demo user account has been synced. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8075,7 +8091,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8244,7 +8260,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8268,7 +8284,7 @@ Stocks apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8280,7 +8296,7 @@ Criptomoedas apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8300,7 +8316,7 @@ Gerenciar perfil de ativos apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index 7f51580d7..e4547a2de 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -223,7 +223,7 @@ Tip apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -543,7 +543,7 @@ Veri Kaynağı apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -567,7 +567,7 @@ Deneme apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -575,7 +575,7 @@ Oluşturuldu apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -583,7 +583,7 @@ Tamamlandı apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -591,7 +591,7 @@ Durum apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -611,7 +611,7 @@ İşleri Sil apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -631,7 +631,7 @@ Tarihsel Piyasa Verisi apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -643,7 +643,7 @@ Veri Gör apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -651,7 +651,7 @@ Hata İzini Görüntüle apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -659,7 +659,7 @@ İşleri Sil apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -711,7 +711,7 @@ Para Birimleri apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -723,7 +723,7 @@ Ülkesi Olmayan ETF’ler apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -731,7 +731,7 @@ Sektörü Olmayan ETF’ler apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -739,7 +739,7 @@ Filtrele... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -959,7 +959,7 @@ Bu kuponu gerçekten silmek istiyor musunuz? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -967,7 +967,7 @@ Önbelleği temizlemeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -975,7 +975,7 @@ Lütfen sistem mesajınızı belirleyin: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -1135,7 +1135,7 @@ Bu platformu silmeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -1167,7 +1167,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -1191,7 +1191,7 @@ Bu kullanıcıyı silmeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -1347,7 +1347,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1367,15 +1367,15 @@ Hay Allah! Güvenlik anahtarı yanlış. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -1383,7 +1383,7 @@ İşlemleri Yönet apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1391,11 +1391,11 @@ Korku apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -1407,11 +1407,11 @@ Açgözlülük apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -1515,7 +1515,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -1795,7 +1795,7 @@ Rapor Veri Sorunu apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1983,7 +1983,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -1995,7 +1995,7 @@ 1Y apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -2007,7 +2007,7 @@ 5Y apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -2027,7 +2027,7 @@ Maks. apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -2055,7 +2055,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2067,7 +2067,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2083,7 +2083,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -2211,7 +2211,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2275,7 +2275,7 @@ Piyasa Verileri apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -2309,6 +2309,10 @@ Overview Özet + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -3099,7 +3103,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -3147,7 +3151,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -3251,7 +3255,7 @@ Temettüleri İçe Aktar apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3267,7 +3271,7 @@ Veri içe aktarılıyor... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -3275,7 +3279,7 @@ İçe aktarma tamamlandı apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -3291,7 +3295,7 @@ Veri doğrulanıyor... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -3599,7 +3603,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -3619,7 +3623,7 @@ Para Yatırma libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -3627,7 +3631,7 @@ Aylık apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -3635,7 +3639,7 @@ Yıllık apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -4009,6 +4013,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Personal Finance Tools @@ -4348,7 +4356,7 @@ Otomatik apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -4392,7 +4400,7 @@ Bu giriş yöntemini kaldırmayı gerçekten istiyor musunuz? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -4756,7 +4764,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -4768,7 +4776,7 @@ Tasarruflar libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -5000,7 +5008,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -5016,7 +5024,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -5048,7 +5056,7 @@ Sembol apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -5064,7 +5072,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -5352,11 +5360,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5484,7 +5492,7 @@ Bu etiketi silmeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -5584,7 +5592,7 @@ Varlık Profili apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -5716,7 +5724,7 @@ Bu sistem mesajını silmeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -5872,11 +5880,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5896,7 +5904,7 @@ Close Holding apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5944,7 +5952,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5964,7 +5972,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6012,7 +6020,7 @@ Yıl apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6032,7 +6040,7 @@ Yıllar apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6125,7 +6133,7 @@ Aktif apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6133,7 +6141,7 @@ Kapalı apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6165,7 +6173,7 @@ İşlemi Yürüt apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6173,7 +6181,7 @@ Öncelik apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6229,7 +6237,7 @@ Ghostfolio hesabınızı kapatmak istediğinize emin misiniz? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6285,7 +6293,7 @@ Oops! Biyometrik kimlik doğrulama ayarlanırken bir hata oluştu. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6301,7 +6309,7 @@ Kıyaslamalar apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6857,7 +6865,7 @@ Portföy Anlık Görüntüsü apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6924,6 +6932,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning Başlangıçtan beri @@ -7363,7 +7379,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7403,7 +7419,7 @@ Yapay zeka istemi panoya kopyalandı apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7419,7 +7435,7 @@ Tembel apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7427,7 +7443,7 @@ Anında apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7467,7 +7483,7 @@ gün sonu apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7475,7 +7491,7 @@ gerçek zamanlı apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7483,7 +7499,7 @@ Duck.ai’yi aç apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7503,7 +7519,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7515,7 +7531,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7523,11 +7539,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7631,11 +7647,11 @@ Güvenlik belirteci apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7643,7 +7659,7 @@ Bu kullanıcı için yeni bir güvenlik belirteci oluşturmak istediğinize emin misiniz? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7788,7 +7804,7 @@ birisi apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7820,7 +7836,7 @@ Bu öğeyi silmek istediğinize emin misiniz? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7861,7 +7877,7 @@ Demo kullanıcı hesabı senkronize edildi. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8075,7 +8091,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8244,7 +8260,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8268,7 +8284,7 @@ Stocks apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8280,7 +8296,7 @@ Cryptocurrencies apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8300,7 +8316,7 @@ Manage Asset Profile apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index 54bf5a08b..12b5c2bc3 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -38,7 +38,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -675,7 +675,7 @@ Тип apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -695,7 +695,7 @@ Профіль активу apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -703,7 +703,7 @@ Історичні ринкові дані apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -715,7 +715,7 @@ Знімок портфеля apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -723,7 +723,7 @@ Джерело даних apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -747,7 +747,7 @@ Пріоритет apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -755,7 +755,7 @@ Спроби apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -763,7 +763,7 @@ Створено apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -771,7 +771,7 @@ Завершено apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -779,7 +779,7 @@ Статус apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -799,7 +799,7 @@ Видалити завдання apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -807,7 +807,7 @@ Переглянути дані apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -815,7 +815,7 @@ Переглянути трасування apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -823,7 +823,7 @@ Виконати завдання apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -831,7 +831,7 @@ Видалити завдання apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -839,7 +839,7 @@ Порівняльні показники apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -847,7 +847,7 @@ Валюти apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -859,7 +859,7 @@ ETF без країн apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -867,7 +867,7 @@ ETF без секторів apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -875,7 +875,7 @@ Фільтрувати за... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -1227,7 +1227,7 @@ Ви дійсно хочете видалити цей купон? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -1235,7 +1235,7 @@ Ви дійсно хочете видалити це системне повідомлення? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -1243,7 +1243,7 @@ Ви дійсно хочете очистити кеш? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -1251,7 +1251,7 @@ Будь ласка, встановіть ваше системне повідомлення: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -1379,7 +1379,7 @@ Ви дійсно хочете видалити цю платформу? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -1411,7 +1411,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -1595,7 +1595,7 @@ Ви дійсно хочете видалити цей тег? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -1619,7 +1619,7 @@ Ви дійсно хочете видалити цього користувача? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -1803,15 +1803,15 @@ Упс! Неправильний Секретний Токен. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -1915,7 +1915,7 @@ Повідомити про збій даних apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1923,7 +1923,7 @@ Активний apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -1931,7 +1931,7 @@ Закритий apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -1955,7 +1955,7 @@ Керування діяльністю apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1963,11 +1963,11 @@ Страх apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -1979,11 +1979,11 @@ Жадібність apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -2087,7 +2087,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -2571,7 +2571,7 @@ З початку року apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -2583,7 +2583,7 @@ 1 рік apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -2595,7 +2595,7 @@ 5 років apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -2615,7 +2615,7 @@ Максимум apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -2687,7 +2687,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -2735,7 +2735,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -2835,7 +2835,7 @@ Автоматичний apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2847,7 +2847,7 @@ Ви дійсно хочете закрити ваш обліковий запис Ghostfolio? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -2855,7 +2855,7 @@ Ви дійсно хочете вилучити цей спосіб входу? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -2871,7 +2871,7 @@ Упс! Виникла помилка під час налаштування біометричної автентифікації. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -3063,7 +3063,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -3083,7 +3083,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -3219,7 +3219,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -3323,7 +3323,7 @@ Ринкові дані apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -3357,6 +3357,10 @@ Overview Огляд + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -4252,7 +4256,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -4308,7 +4312,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -4448,7 +4452,7 @@ Імпорт дивідендів apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -4464,7 +4468,7 @@ Імпортуються дані... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -4472,7 +4476,7 @@ Імпорт завершено apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -4488,7 +4492,7 @@ Перевірка даних... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -4820,7 +4824,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -4840,11 +4844,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -4864,7 +4868,7 @@ Щомісячно apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -4872,7 +4876,7 @@ Щорічно apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -4880,7 +4884,7 @@ Close Holding apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5247,6 +5251,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning З початку @@ -5314,6 +5326,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Glossary @@ -6171,7 +6187,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -6191,7 +6207,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -6211,7 +6227,7 @@ рік apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6231,7 +6247,7 @@ роки apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6383,7 +6399,7 @@ Депозит libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -6399,7 +6415,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -6411,7 +6427,7 @@ Заощадження libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -6763,7 +6779,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -6787,7 +6803,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -6819,7 +6835,7 @@ Символ apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -6835,7 +6851,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -7371,11 +7387,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -7411,7 +7427,7 @@ Запит AI скопійовано в буфер обміну apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7419,7 +7435,7 @@ Lazy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7427,7 +7443,7 @@ Instant apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7467,7 +7483,7 @@ end of day apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7475,7 +7491,7 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7483,7 +7499,7 @@ Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7503,7 +7519,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7515,7 +7531,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7523,11 +7539,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7631,11 +7647,11 @@ Security token apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7643,7 +7659,7 @@ Do you really want to generate a new security token for this user? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7788,7 +7804,7 @@ someone apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7820,7 +7836,7 @@ Do you really want to delete this item? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7861,7 +7877,7 @@ Demo user account has been synced. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8075,7 +8091,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8244,7 +8260,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8268,7 +8284,7 @@ Stocks apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8280,7 +8296,7 @@ Cryptocurrencies apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8300,7 +8316,7 @@ Manage Asset Profile apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 7db54e0c4..fa9e6b874 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -235,7 +235,7 @@ Type apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -559,14 +559,14 @@ Asset Profile apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 Historical Market Data apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -577,7 +577,7 @@ Data Source apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -600,28 +600,28 @@ Attempts apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 Created apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 Finished apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 Status apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -639,28 +639,28 @@ Delete Jobs apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 View Data apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 View Stacktrace apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 Delete Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -708,7 +708,7 @@ Currencies apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -719,14 +719,14 @@ ETFs without Countries apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 ETFs without Sectors apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -740,7 +740,7 @@ Filter by... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -999,28 +999,28 @@ Do you really want to delete this coupon? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 Do you really want to delete this system message? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 Do you really want to flush the cache? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 Please set your system message: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -1155,7 +1155,7 @@ Do you really want to delete this platform? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -1183,7 +1183,7 @@ Current year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -1226,7 +1226,7 @@ Do you really want to delete this tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -1247,7 +1247,7 @@ Do you really want to delete this user? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -1389,7 +1389,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1408,33 +1408,33 @@ Oops! Incorrect Security Token. apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 Manage Activities apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 Fear apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -1445,11 +1445,11 @@ Greed apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -1541,7 +1541,7 @@ Current week apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -1797,7 +1797,7 @@ Report Data Glitch apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -1972,7 +1972,7 @@ YTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -1983,7 +1983,7 @@ 1Y apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -1994,7 +1994,7 @@ 5Y apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -2012,7 +2012,7 @@ Max apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -2105,7 +2105,7 @@ Auto apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2116,7 +2116,7 @@ Do you really want to remove this sign in method? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -2280,7 +2280,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2291,7 +2291,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2306,7 +2306,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -2425,7 +2425,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2512,7 +2512,7 @@ Market Data apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -2543,6 +2543,10 @@ Overview + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -3323,7 +3327,7 @@ Job ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -3375,7 +3379,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -3491,7 +3495,7 @@ Import Dividends apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3506,14 +3510,14 @@ Importing data... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 Import has been completed apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -3527,7 +3531,7 @@ Validating data... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -3797,7 +3801,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -3815,21 +3819,21 @@ Deposit libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 Monthly apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 Yearly apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -4147,6 +4151,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Personal Finance Tools @@ -4680,7 +4688,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -4691,7 +4699,7 @@ Savings libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -4904,7 +4912,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -4918,7 +4926,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -4939,7 +4947,7 @@ Symbol apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -4955,7 +4963,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -5259,11 +5267,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5366,7 +5374,7 @@ Close Holding apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5388,11 +5396,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5445,7 +5453,7 @@ MTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -5456,7 +5464,7 @@ WTD apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -5492,7 +5500,7 @@ year apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -5511,7 +5519,7 @@ years apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -5595,14 +5603,14 @@ Closed apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 Active apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -5630,7 +5638,7 @@ Execute Job apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -5644,7 +5652,7 @@ Priority apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -5693,7 +5701,7 @@ Do you really want to close your Ghostfolio account? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -5735,7 +5743,7 @@ Oops! There was an error setting up biometric authentication. apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -5770,7 +5778,7 @@ Benchmarks apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6268,7 +6276,7 @@ Portfolio Snapshot apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6320,6 +6328,13 @@ 42 + + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + offers a free plan @@ -6724,7 +6739,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -6745,7 +6760,7 @@ AI prompt has been copied to the clipboard apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -6780,14 +6795,14 @@ Instant apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 Lazy apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -6801,21 +6816,21 @@ real-time apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 end of day apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 Open Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -6833,7 +6848,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -6844,7 +6859,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -6852,11 +6867,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -6947,7 +6962,7 @@ Do you really want to generate a new security token for this user? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -6961,11 +6976,11 @@ Security token apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7065,7 +7080,7 @@ someone apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7094,7 +7109,7 @@ Do you really want to delete this item? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7138,7 +7153,7 @@ Demo user account has been synced. apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -7322,7 +7337,7 @@ Current month apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -7485,14 +7500,14 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 Cryptocurrencies apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -7503,7 +7518,7 @@ Stocks apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -7521,7 +7536,7 @@ Manage Asset Profile apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index be465e9df..78c9b717d 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -252,7 +252,7 @@ 类型 apps/client/src/app/components/admin-jobs/admin-jobs.html - 48 + 57 apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html @@ -592,7 +592,7 @@ 资产概况 apps/client/src/app/components/admin-jobs/admin-jobs.html - 52 + 61 @@ -600,7 +600,7 @@ 历史市场数据 apps/client/src/app/components/admin-jobs/admin-jobs.html - 54 + 63 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -612,7 +612,7 @@ 数据源 apps/client/src/app/components/admin-jobs/admin-jobs.html - 82 + 91 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -636,7 +636,7 @@ 尝试次数 apps/client/src/app/components/admin-jobs/admin-jobs.html - 120 + 129 @@ -644,7 +644,7 @@ 创建 apps/client/src/app/components/admin-jobs/admin-jobs.html - 134 + 143 @@ -652,7 +652,7 @@ 完成 apps/client/src/app/components/admin-jobs/admin-jobs.html - 143 + 152 @@ -660,7 +660,7 @@ 状态 apps/client/src/app/components/admin-jobs/admin-jobs.html - 152 + 161 apps/client/src/app/components/admin-settings/admin-settings.component.html @@ -680,7 +680,7 @@ 删除任务 apps/client/src/app/components/admin-jobs/admin-jobs.html - 193 + 202 @@ -688,7 +688,7 @@ 查看数据 apps/client/src/app/components/admin-jobs/admin-jobs.html - 208 + 217 @@ -696,7 +696,7 @@ 查看堆栈跟踪 apps/client/src/app/components/admin-jobs/admin-jobs.html - 216 + 225 @@ -704,7 +704,7 @@ 删除任务 apps/client/src/app/components/admin-jobs/admin-jobs.html - 224 + 233 @@ -756,7 +756,7 @@ 货币 apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 131 + 130 apps/client/src/app/pages/public/public-page.html @@ -768,7 +768,7 @@ 没有国家的 ETF apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 136 + 135 @@ -776,7 +776,7 @@ 无行业类别的 ETF apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 141 + 140 @@ -792,7 +792,7 @@ 过滤... apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 390 + 383 @@ -1052,7 +1052,7 @@ 您确实要删除此优惠券吗? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 193 + 196 @@ -1060,7 +1060,7 @@ 您真的要删除这条系统消息吗? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 206 + 209 @@ -1068,7 +1068,7 @@ 您真的要刷新缓存吗? apps/client/src/app/components/admin-overview/admin-overview.component.ts - 230 + 233 @@ -1076,7 +1076,7 @@ 请设置您的系统消息: apps/client/src/app/components/admin-overview/admin-overview.component.ts - 250 + 253 @@ -1228,7 +1228,7 @@ 您真的要删除这个平台吗? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 112 + 111 @@ -1260,7 +1260,7 @@ 当前年份 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 @@ -1308,7 +1308,7 @@ 您真的要删除此标签吗? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 109 + 108 @@ -1332,7 +1332,7 @@ 您真的要删除该用户吗? apps/client/src/app/components/admin-users/admin-users.component.ts - 218 + 215 @@ -1488,7 +1488,7 @@ apps/client/src/app/components/header/header.component.ts - 297 + 298 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1508,15 +1508,15 @@ 哎呀!安全令牌不正确。 apps/client/src/app/components/header/header.component.ts - 312 + 313 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 154 + 152 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 193 + 191 @@ -1524,7 +1524,7 @@ 管理活动 apps/client/src/app/components/home-holdings/home-holdings.html - 65 + 64 @@ -1532,11 +1532,11 @@ 恐惧 apps/client/src/app/components/home-market/home-market.component.ts - 42 + 41 apps/client/src/app/components/markets/markets.component.ts - 47 + 46 libs/ui/src/lib/i18n.ts @@ -1548,11 +1548,11 @@ 贪婪 apps/client/src/app/components/home-market/home-market.component.ts - 43 + 42 apps/client/src/app/components/markets/markets.component.ts - 48 + 47 libs/ui/src/lib/i18n.ts @@ -1656,7 +1656,7 @@ 当前周 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 @@ -1936,7 +1936,7 @@ 报告数据故障 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 450 + 456 @@ -2124,7 +2124,7 @@ 年初至今 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 204 + 205 libs/ui/src/lib/assistant/assistant.component.ts @@ -2136,7 +2136,7 @@ 1年 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 libs/ui/src/lib/assistant/assistant.component.ts @@ -2148,7 +2148,7 @@ 5年 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -2168,7 +2168,7 @@ 最大限度 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 216 + 217 libs/ui/src/lib/assistant/assistant.component.ts @@ -2272,7 +2272,7 @@ 自动 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 70 + 69 apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -2284,7 +2284,7 @@ 您确实要删除此登录方法吗? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 282 + 279 @@ -2468,7 +2468,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 195 + 194 @@ -2480,7 +2480,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 193 + 192 @@ -2496,7 +2496,7 @@ apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 196 + 195 @@ -2624,7 +2624,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 375 + 381 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -2720,7 +2720,7 @@ 市场数据 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 397 + 403 libs/common/src/lib/routes/routes.ts @@ -2754,6 +2754,10 @@ Overview 概述 + + apps/client/src/app/components/admin-jobs/admin-jobs.html + 7 + apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 114 @@ -3608,7 +3612,7 @@ 作业 ID apps/client/src/app/components/admin-jobs/admin-jobs.html - 34 + 43 @@ -3664,7 +3668,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 342 + 348 apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -3792,7 +3796,7 @@ 导入股息 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 137 + 136 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3808,7 +3812,7 @@ 正在导入数据... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 175 + 174 @@ -3816,7 +3820,7 @@ 导入已完成 apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 185 + 184 @@ -3832,7 +3836,7 @@ 验证数据... apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts - 299 + 293 @@ -4132,7 +4136,7 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 76 + 75 libs/ui/src/lib/i18n.ts @@ -4152,7 +4156,7 @@ 存款 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 390 + 404 @@ -4160,7 +4164,7 @@ 每月 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 91 + 90 @@ -4168,7 +4172,7 @@ 每年 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 92 + 91 @@ -4522,6 +4526,10 @@ apps/client/src/app/pages/register/user-account-registration-dialog/user-account-registration-dialog.html 88 + + libs/ui/src/lib/value/value.component.html + 18 + Personal Finance Tools @@ -5113,7 +5121,7 @@ libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 400 + 414 libs/ui/src/lib/i18n.ts @@ -5125,7 +5133,7 @@ 储蓄 libs/ui/src/lib/fire-calculator/fire-calculator.component.ts - 410 + 424 @@ -5357,7 +5365,7 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 449 + 451 @@ -5373,7 +5381,7 @@ No Activities apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 146 + 145 @@ -5397,7 +5405,7 @@ 代码 apps/client/src/app/components/admin-jobs/admin-jobs.html - 68 + 77 apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -5413,7 +5421,7 @@ apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 315 + 318 libs/ui/src/lib/i18n.ts @@ -5753,11 +5761,11 @@ libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 451 + 453 libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts - 465 + 467 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5873,7 +5881,7 @@ 关闭持仓 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 441 + 447 @@ -5897,11 +5905,11 @@ apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 81 + 80 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 97 + 96 apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts @@ -5961,7 +5969,7 @@ 本月至今 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 libs/ui/src/lib/assistant/assistant.component.ts @@ -5973,7 +5981,7 @@ 本周至今 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 196 + 197 libs/ui/src/lib/assistant/assistant.component.ts @@ -6013,7 +6021,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 208 + 209 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -6033,7 +6041,7 @@ apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 212 + 213 libs/ui/src/lib/assistant/assistant.component.ts @@ -6126,7 +6134,7 @@ 已关闭 apps/client/src/app/components/home-holdings/home-holdings.component.ts - 65 + 64 @@ -6134,7 +6142,7 @@ 活跃 apps/client/src/app/components/home-holdings/home-holdings.component.ts - 64 + 63 @@ -6166,7 +6174,7 @@ 执行作业 apps/client/src/app/components/admin-jobs/admin-jobs.html - 220 + 229 @@ -6174,7 +6182,7 @@ 优先级 apps/client/src/app/components/admin-jobs/admin-jobs.html - 96 + 105 @@ -6230,7 +6238,7 @@ 您确定要关闭您的 Ghostfolio 账户吗? apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 208 + 205 @@ -6286,7 +6294,7 @@ 哎呀!设置生物识别认证时发生错误。 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts - 336 + 333 @@ -6302,7 +6310,7 @@ 基准 apps/client/src/app/components/admin-market-data/admin-market-data.component.ts - 126 + 125 @@ -6858,7 +6866,7 @@ 投资组合快照 apps/client/src/app/components/admin-jobs/admin-jobs.html - 56 + 65 @@ -6925,6 +6933,14 @@ 42 + + has been copied to the clipboard + has been copied to the clipboard + + libs/ui/src/lib/value/value.component.ts + 180 + + From the beginning 从头开始 @@ -7364,7 +7380,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 260 + 257 @@ -7404,7 +7420,7 @@ AI 提示已复制到剪贴板 apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 201 + 199 @@ -7420,7 +7436,7 @@ 延迟 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7428,7 +7444,7 @@ 即时 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7468,7 +7484,7 @@ 收盘 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 230 + 231 @@ -7476,7 +7492,7 @@ 实时 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 234 + 235 @@ -7484,7 +7500,7 @@ 打开 Duck.ai apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts - 202 + 200 @@ -7504,7 +7520,7 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 @@ -7516,7 +7532,7 @@ apps/client/src/app/components/home-overview/home-overview.component.ts - 55 + 54 libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -7524,11 +7540,11 @@ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 375 + 377 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts - 388 + 390 @@ -7632,11 +7648,11 @@ 安全令牌 apps/client/src/app/components/admin-users/admin-users.component.ts - 239 + 235 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 170 + 167 @@ -7644,7 +7660,7 @@ 您确定要为此用户生成新的安全令牌吗? apps/client/src/app/components/admin-users/admin-users.component.ts - 244 + 240 @@ -7789,7 +7805,7 @@ 某人 apps/client/src/app/pages/public/public-page.component.ts - 59 + 61 @@ -7821,7 +7837,7 @@ 您确定要删除此项目吗? libs/ui/src/lib/benchmark/benchmark.component.ts - 144 + 139 @@ -7862,7 +7878,7 @@ 演示用户账户已同步。 apps/client/src/app/components/admin-overview/admin-overview.component.ts - 274 + 277 @@ -8076,7 +8092,7 @@ 当前月份 apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts - 200 + 201 @@ -8245,7 +8261,7 @@ 您真的想要生成一个新的安全令牌吗? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 175 + 172 @@ -8269,7 +8285,7 @@ 股票 apps/client/src/app/components/markets/markets.component.ts - 52 + 51 apps/client/src/app/pages/features/features-page.html @@ -8281,7 +8297,7 @@ 加密货币 apps/client/src/app/components/markets/markets.component.ts - 53 + 52 apps/client/src/app/pages/features/features-page.html @@ -8301,7 +8317,7 @@ 管理资产概况 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 465 + 471 From 584d74c3c932f7c75b918059f067e24df0a0ffca Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 31 Mar 2026 17:52:47 +0200 Subject: [PATCH 121/138] Task/upgrade stripe to version 20.4.1 (#6631) * Upgrade stripe to version 20.4.1 * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/subscription/subscription.service.ts | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 274851846..01ca53dc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the language localization for Spanish (`es`) - Upgraded `countries-list` from version `3.2.2` to `3.3.0` - Upgraded `ng-extract-i18n-merge` from `3.2.1` to `3.3.0` +- Upgraded `stripe` from version `20.3.0` to `20.4.1` ## 2.251.0 - 2026-03-24 diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index 689ee3e6a..877ea0ee4 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -35,7 +35,7 @@ export class SubscriptionService { this.stripe = new Stripe( this.configurationService.get('STRIPE_SECRET_KEY'), { - apiVersion: '2026-01-28.clover' + apiVersion: '2026-02-25.clover' } ); } diff --git a/package-lock.json b/package-lock.json index 81128f284..1f4295a6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,7 +89,7 @@ "passport-openidconnect": "0.1.2", "reflect-metadata": "0.2.2", "rxjs": "7.8.1", - "stripe": "20.3.0", + "stripe": "20.4.1", "svgmap": "2.19.2", "tablemark": "4.1.0", "twitter-api-v2": "1.29.0", @@ -32351,9 +32351,9 @@ } }, "node_modules/stripe": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-20.3.0.tgz", - "integrity": "sha512-DYzcmV1MfYhycr1GwjCjeQVYk9Gu8dpxyTlu7qeDCsuguug7oUTxPsUQuZeSf/OPzK7pofqobvOKVqAwlpgf/Q==", + "version": "20.4.1", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-20.4.1.tgz", + "integrity": "sha512-axCguHItc8Sxt0HC6aSkdVRPffjYPV7EQqZRb2GkIa8FzWDycE7nHJM19C6xAIynH1Qp1/BHiopSi96jGBxT0w==", "license": "MIT", "engines": { "node": ">=16" diff --git a/package.json b/package.json index 535469559..b7f9bc2e7 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "passport-openidconnect": "0.1.2", "reflect-metadata": "0.2.2", "rxjs": "7.8.1", - "stripe": "20.3.0", + "stripe": "20.4.1", "svgmap": "2.19.2", "tablemark": "4.1.0", "twitter-api-v2": "1.29.0", From 7e182aa6a23614f8a40c7c9add6c13b550da9e68 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 31 Mar 2026 18:58:03 +0200 Subject: [PATCH 122/138] Task/improve language localization for DE 20260331 (#6642) * Improve translation * Update changelog --- CHANGELOG.md | 1 + apps/client/src/locales/messages.de.xlf | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01ca53dc4..89055d018 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Improved the language localization for German (`de`) - Improved the language localization for Spanish (`es`) - Upgraded `countries-list` from version `3.2.2` to `3.3.0` - Upgraded `ng-extract-i18n-merge` from `3.2.1` to `3.3.0` diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 1a1df8cc1..ff12aebcb 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -6958,7 +6958,7 @@ has been copied to the clipboard - has been copied to the clipboard + wurde in die Zwischenablage kopiert libs/ui/src/lib/value/value.component.ts 180 From d702685ce39f5646cdd8abd3076764c050dae705 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 31 Mar 2026 19:03:07 +0200 Subject: [PATCH 123/138] Feature/add copy-to-clipboard button to user detail dialog (#6641) * Add copy-to-clipboard button to user id * Update changelog --- CHANGELOG.md | 1 + .../components/user-detail-dialog/user-detail-dialog.html | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89055d018..407767cac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for a copy-to-clipboard functionality in the value component - Extended the holding detail dialog by adding a copy-to-clipboard button for the ISIN number (experimental) - Extended the holding detail dialog by adding a copy-to-clipboard button for the symbol (experimental) +- Extended the user detail dialog of the admin control panel’s users section by adding a copy-to-clipboard button for the user id ### Changed diff --git a/apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html b/apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html index 570dcf4d6..e9af86942 100644 --- a/apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html +++ b/apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -27,7 +27,13 @@
- User ID + User ID
- @if (user?.settings?.isExperimentalFeatures) { + @if (user()?.settings?.isExperimentalFeatures) {
GET {{ baseUrl }}/api/v1/public/{{ @@ -69,7 +69,7 @@ class="no-max-width" xPosition="before" > - @if (user?.settings?.isExperimentalFeatures) { + @if (user()?.settings?.isExperimentalFeatures) { } @if ( - user?.settings?.isExperimentalFeatures || element.type === 'PUBLIC' + user()?.settings?.isExperimentalFeatures || + element.type === 'PUBLIC' ) {
} @@ -100,7 +101,7 @@ - - + +
diff --git a/apps/client/src/app/components/access-table/access-table.component.ts b/apps/client/src/app/components/access-table/access-table.component.ts index 76548c45d..122b4f88b 100644 --- a/apps/client/src/app/components/access-table/access-table.component.ts +++ b/apps/client/src/app/components/access-table/access-table.component.ts @@ -7,11 +7,12 @@ import { Clipboard, ClipboardModule } from '@angular/cdk/clipboard'; import { ChangeDetectionStrategy, Component, + computed, CUSTOM_ELEMENTS_SCHEMA, - EventEmitter, - Input, - OnChanges, - Output + effect, + inject, + input, + output } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatMenuModule } from '@angular/material/menu'; @@ -46,23 +47,32 @@ import ms from 'ms'; templateUrl: './access-table.component.html', styleUrls: ['./access-table.component.scss'] }) -export class GfAccessTableComponent implements OnChanges { - @Input() accesses: Access[]; - @Input() showActions: boolean; - @Input() user: User; - - @Output() accessDeleted = new EventEmitter(); - @Output() accessToUpdate = new EventEmitter(); - - public baseUrl = window.location.origin; - public dataSource: MatTableDataSource; - public displayedColumns = []; - - public constructor( - private clipboard: Clipboard, - private notificationService: NotificationService, - private snackBar: MatSnackBar - ) { +export class GfAccessTableComponent { + public readonly accesses = input.required(); + public readonly showActions = input(false); + public readonly user = input.required(); + + public readonly accessDeleted = output(); + public readonly accessToUpdate = output(); + + protected readonly baseUrl = window.location.origin; + protected readonly dataSource = new MatTableDataSource(); + + protected readonly displayedColumns = computed(() => { + const columns = ['alias', 'grantee', 'type', 'details']; + + if (this.showActions()) { + columns.push('actions'); + } + + return columns; + }); + + private readonly clipboard = inject(Clipboard); + private readonly notificationService = inject(NotificationService); + private readonly snackBar = inject(MatSnackBar); + + public constructor() { addIcons({ copyOutline, createOutline, @@ -72,27 +82,19 @@ export class GfAccessTableComponent implements OnChanges { lockOpenOutline, removeCircleOutline }); - } - public ngOnChanges() { - this.displayedColumns = ['alias', 'grantee', 'type', 'details']; - - if (this.showActions) { - this.displayedColumns.push('actions'); - } - - if (this.accesses) { - this.dataSource = new MatTableDataSource(this.accesses); - } + effect(() => { + this.dataSource.data = this.accesses() ?? []; + }); } - public getPublicUrl(aId: string): string { - const languageCode = this.user.settings.language; + protected getPublicUrl(aId: string) { + const languageCode = this.user().settings.language; return `${this.baseUrl}/${languageCode}/${publicRoutes.public.path}/${aId}`; } - public onCopyUrlToClipboard(aId: string): void { + protected onCopyUrlToClipboard(aId: string) { this.clipboard.copy(this.getPublicUrl(aId)); this.snackBar.open( @@ -104,7 +106,7 @@ export class GfAccessTableComponent implements OnChanges { ); } - public onDeleteAccess(aId: string) { + protected onDeleteAccess(aId: string) { this.notificationService.confirm({ confirmFn: () => { this.accessDeleted.emit(aId); @@ -114,7 +116,7 @@ export class GfAccessTableComponent implements OnChanges { }); } - public onUpdateAccess(aId: string) { + protected onUpdateAccess(aId: string) { this.accessToUpdate.emit(aId); } } From 7056b2b9923bfcfa2e0a45853abfe2d7938af651 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 2 Apr 2026 17:28:06 +0200 Subject: [PATCH 125/138] Task/refresh cryptocurrencies list 20260401 (#6647) * Update cryptocurrencies.json * Update changelog --- CHANGELOG.md | 1 + .../cryptocurrencies/cryptocurrencies.json | 252 ++++++++++++++---- 2 files changed, 201 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 407767cac..aabb98610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Refreshed the cryptocurrencies list - Improved the language localization for German (`de`) - Improved the language localization for Spanish (`es`) - Upgraded `countries-list` from version `3.2.2` to `3.3.0` diff --git a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json index d00ded6ef..96502ca05 100644 --- a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json +++ b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json @@ -443,12 +443,14 @@ "AIAGENTAPP": "Aiagent.app", "AIAI": "All In AI", "AIAKITA": "AiAkita", + "AIAO": "AlgosOne AI Token", "AIAT": "AI Analysis Token", "AIAV": "AI AVatar", "AIB": "AdvancedInternetBlock", "AIBABYDOGE": "AIBabyDoge", "AIBB": "AiBB", "AIBCOIN": "AIBLOCK", + "AIBINANCE": "AI Binance", "AIBK": "AIB Utility Token", "AIBOT": "CherryAI", "AIBU": "AIBUZZ TOKEN", @@ -567,6 +569,7 @@ "AIX9": "AthenaX9", "AIXBT": "aixbt by Virtuals", "AIXCB": "aixCB by Virtuals", + "AIXDROP": "AIXDROP", "AIXERC": "AI-X", "AIXT": "AIXTerminal", "AJC": "AI Judge Companion", @@ -653,6 +656,7 @@ "ALLIN": "All in", "ALLMEE": "All.me", "ALLO": "Allora", + "ALLOCA": "Alloca", "ALM": "Alium Finance", "ALMAN": "Alman", "ALMANAK": "Almanak", @@ -676,6 +680,7 @@ "ALPHAAI": "Alpha AI", "ALPHABET": "Alphabet", "ALPHAC": "Alpha Coin", + "ALPHADEX": "Alpha DEX", "ALPHAF": "Alpha Fi", "ALPHAG": "Alpha Gardeners", "ALPHAPETTO": "Alpha Petto Shells", @@ -760,6 +765,7 @@ "AMX": "Amero", "AMY": "Amygws", "AMZE": "The Amaze World", + "AMZNON": "Amazon (Ondo Tokenized)", "AMZNX": "Amazon xStocks", "ANA": "Nirvana ANA", "ANAL": "AnalCoin", @@ -792,12 +798,13 @@ "ANGLE": "ANGLE", "ANGO": "Aureus Nummus Gold", "ANGRYSLERF": "ANGRYSLERF", - "ANI": "Anime Token", + "ANI": "Ani Grok Companion (anicompanion.net)", "ANIM": "Animalia", "ANIMA": "Realm Anima", "ANIME": "Animecoin", "ANIMECOIN": "Animecoin", "ANIMEONBASE": "Anime", + "ANIMETOKEN": "Anime Token (animetoken.in)", "ANITA": "Anita AI", "ANJ": "Aragon Court", "ANJI": "Anji", @@ -839,6 +846,7 @@ "ANVL": "Anvil", "ANVLV1": "Anvil v1", "ANW": "Anchor Neural World", + "ANWANG": "SAFE", "ANY": "Anyswap", "ANYONE": "ANyONe Protocol", "ANZENUSD": "Anzen Finance", @@ -1030,6 +1038,7 @@ "ARRO": "Arro Social", "ARROW": "Arrow Token", "ARRR": "Pirate Chain", + "ARSE": "ARSe", "ARSL": "Aquarius Loan", "ARSW": "ArthSwap", "ART": "LiveArt", @@ -1117,6 +1126,7 @@ "ASTONV": "Aston Villa Fan Token", "ASTR": "Astar", "ASTRA": "Astra Protocol", + "ASTRAAI": "AstraAI", "ASTRADAO": "Astra DAO", "ASTRAFER": "Astrafer", "ASTRAFERV1": "Astrafer v1", @@ -1216,11 +1226,12 @@ "AUN": "Authoreon", "AUNIT": "Aunit", "AUPC": "Authpaper", - "AUR": "AUREO", + "AUR": "Aurix", "AURA": "aura", "AURABAL": "Aura BAL", "AURAF": "Aura Finance", "AURANET": "Aura Network", + "AUREO": "AUREO", "AURO": "Aurora", "AURORA": "Aurora", "AURORAC": "Auroracoin", @@ -1277,6 +1288,7 @@ "AVINOC": "AVINOC", "AVIVE": "Avive World", "AVL": "AVL", + "AVLT": "Altura Vault Tokens", "AVM": "AVM (Atomicals)", "AVME": "AVME", "AVN": "AVNRich", @@ -1420,6 +1432,7 @@ "BABYFB": "Baby Floki Billionaire", "BABYFLOKI": "BabyFloki", "BABYFLOKIZILLA": "BabyFlokiZilla", + "BABYFROG": "Baby Frog Coin", "BABYG": "BabyGME", "BABYGME": "Baby GameStop", "BABYGOAT": "Baby Goat", @@ -1576,7 +1589,7 @@ "BAOV1": "BaoToken v1", "BAP3X": "bAP3X", "BAR": "FC Barcelona Fan Token", - "BARA": "Capybara", + "BARA": "Capybara Nation", "BARAKATUH": "Barakatuh", "BARC": "The Blu Arctic Water Company", "BARD": "Lombard", @@ -1589,7 +1602,6 @@ "BART": "BarterTrade", "BARTKRC": "BART Token", "BARY": "Bary", - "BAS": "Basis Share", "BASEAI": "BaseAI", "BASEBEAR": "BBQ", "BASECAT": "BASE CAT", @@ -1605,6 +1617,7 @@ "BASEDP": "Based Pepe", "BASEDR": "Based Rabbit", "BASEDS": "BasedSwap", + "BASEDSB": "Based Street Bets", "BASEDTURBO": "Based Turbo", "BASEDV1": "Based Money v1", "BASEHEROES": "Baseheroes", @@ -1620,6 +1633,8 @@ "BASIL": "Basilisk", "BASIS": "Basis", "BASISCOIN": "Basis Coin", + "BASISSHAREV1": "Basis Share", + "BASISSHAREV2": "Basis Share", "BASK": "BasketDAO", "BAST": "Bast", "BASTET": "Bastet Goddess", @@ -1684,6 +1699,7 @@ "BCA": "Bitcoin Atom", "BCAC": "Business Credit Alliance Chain", "BCAI": "Bright Crypto Ai", + "BCAK": "BCAK", "BCAP": "Blockchain Capital", "BCAPV1": "Blockchain Capital v1", "BCAT": "BitClave", @@ -1740,6 +1756,7 @@ "BCZERO": "Buggyra Coin Zero", "BD": "BlastDEX", "BD20": "BRC-20 DEX", + "BDAG": "BlockDAG", "BDAY": "Birthday Cake", "BDB": "Big Data Block", "BDC": "BILLION•DOLLAR•CAT", @@ -1983,6 +2000,7 @@ "BIGSB": "BigShortBets", "BIGTIME": "Big Time", "BIGTOWN": "Burp", + "BIGTROUT": "The Big Trout", "BIGUP": "BigUp", "BIH": "BitHostCoin", "BIHU": "Key", @@ -1998,6 +2016,8 @@ "BIN": "Binemon", "BINA": "Binance Mascort Dog", "BINAN": "Binance Mascot", + "BINANCEAI": "Binance AI", + "BINANCEAIPRO": "Binance Ai Pro", "BINANCED": "BinanceDog On Sol", "BINANCEDOG": "Binancedog", "BINANCIENS": "Binanciens", @@ -2106,6 +2126,7 @@ "BITUSD": "bitUSD", "BITV": "Bitvolt", "BITVOLT": "BitVolt", + "BITWHITE": "BitWhite", "BITWORLD": "Bit World Token", "BITX": "BitScreener", "BITXOXO": "Bitxoxo", @@ -2492,7 +2513,8 @@ "BOOKIE": "BookieBot", "BOOKO": "Book of Pets", "BOOKOF": "BOOK OF NOTHING", - "BOOM": "Boomco", + "BOOM": "Boom", + "BOOMCO": "BOOM", "BOOMCOIN": "Boom Token", "BOOMDAO": "BOOM DAO", "BOOMER": "Boomer", @@ -2530,6 +2552,7 @@ "BOSSBABY": "BossBaby", "BOSSBURGER": "Boss Burger", "BOSSCOQ": "THE COQFATHER", + "BOSSIE": "BOSSIE", "BOST": "BoostCoin", "BOSU": "Bosu Inu", "BOT": "HyperBot", @@ -2718,7 +2741,7 @@ "BSAFU": "BlockSAFU", "BSAI": "Bitcoin Silver AI", "BSATOSHI": "BabySatoshi", - "BSB": "Based Street Bets", + "BSB": "Block Street", "BSC": "BSC Layer", "BSCAKE": "Bunscake", "BSCBURN": "BSCBURN", @@ -2888,9 +2911,10 @@ "BTTY": "Bitcointry Token", "BTU": "BTU Protocol", "BTV": "Bitvote", - "BTW": "BitWhite", + "BTW": "Bitway", "BTX": "Bitradex Token", "BTXC": "Bettex coin", + "BTXEX": "BTXEX", "BTY": "Bityuan", "BTYC": "BigTycoon", "BTZ": "BitzCoin", @@ -3110,6 +3134,7 @@ "CAL": "FitBurn", "CALC": "CaliphCoin", "CALCI": "Calcium", + "CALCIFY": "CalcifyTech", "CALI": "CaliCoin", "CALL": "Global Crypto Alliance", "CALLISTO": "Callisto Network", @@ -3151,6 +3176,7 @@ "CAPY": "Capybara", "CAPYBARA": "Capybara", "CAPYBARA1995": "Capybara", + "CAPYBARACOIN": "Capybara", "CAR": "Central African Republic Meme", "CARAT": "AlaskaGoldRush", "CARATSTOKEN": "Carats Token", @@ -3507,6 +3533,7 @@ "CHH": "Chihuahua Token", "CHI": "Chi Gastoken", "CHIB": "Chiba Inu", + "CHIBI": "Chibification", "CHICA": "CHICA", "CHICKS": "SolChicks", "CHIDO": "Chinese Doge Wow", @@ -3771,6 +3798,7 @@ "COBE": "Castle of Blackwater", "COBY": "Coby", "COC": "Coin of the champions", + "COCA": "COCA", "COCAINE": "THE GOOD STUFF", "COCK": "Shibacock", "COCO": "coco", @@ -4027,6 +4055,7 @@ "CRBRUS": "Cerberus", "CRC": "CryCash", "CRCL": "Circle", + "CRCLON": "Circle Internet Group (Ondo Tokenized)", "CRCLX": "Circle xStock", "CRD": "CRD Network", "CRDC": "Cardiocoin", @@ -4111,6 +4140,7 @@ "CRTAI": "CRT AI Network", "CRTB": "Coritiba F.C. Fan Token", "CRTM": "Cryptum", + "CRTR": "CREATOR", "CRTS": "Cratos", "CRU": "Crust Network", "CRUD": "CRUDE OIL BRENT", @@ -4135,6 +4165,7 @@ "CRYPT": "CryptCoin", "CRYPTAL": "CrypTalk", "CRYPTER": "Crypteriumcoin", + "CRYPTO": "Cryptocurrency Coin", "CRYPTOA": "CryptoAI", "CRYPTOAGENT": "CRYPTO AGENT TRUMP", "CRYPTOAI": "CryptoAI", @@ -4345,11 +4376,12 @@ "CYBONK": "CYBONK", "CYBR": "CYBR", "CYBRO": "Cybro Token", - "CYC": "Cyclone Protocol", + "CYC": "Cycle Network Token", "CYCAT": "Chi Yamada Cat", "CYCE": "Crypto Carbon Energy", "CYCEV1": "Crypto Carbon Energy v1", "CYCLE": "Cycle Finance", + "CYCLONEPROTOCOL": "Cyclone Protocol", "CYCLUB": "Cyclub", "CYCON": "CONUN", "CYDER": "Cyder Coin", @@ -4369,6 +4401,7 @@ "CYS": "Cysic", "CYT": "Cryptokenz", "CZ": "CHANGPENG ZHAO (changpengzhao.club)", + "CZAI": "CZ AI Agent", "CZBOOK": "CZ BOOK", "CZBROCCOLI": "Cz Broccoli", "CZC": "Crazy Coin", @@ -4401,7 +4434,8 @@ "DACS": "Dacsee", "DACXI": "Dacxi", "DAD": "DAD", - "DADA": "DADA", + "DADA": "DADACOIN", + "DADACOINTOP": "DADA", "DADDY": "Daddy Tate", "DADDYCHILL": "Daddy Chill", "DADDYDOGE": "Daddy Doge", @@ -4857,7 +4891,8 @@ "DILIGENT": "Diligent Pepe", "DILL": "dillwifit", "DIM": "DIMCOIN", - "DIME": "DimeCoin", + "DIME": "DIME", + "DIMECOIN": "DimeCoin", "DIMO": "DIMO", "DIN": "DIN", "DINE": "Dinero", @@ -4886,6 +4921,7 @@ "DISCOVERY": "DiscoveryIoT", "DISK": "Dark Lisk", "DISPEPE": "Disabled Pepe", + "DISTORTED": "Distorted Face", "DISTR": "Distributed Autonomous Organization", "DISTRIBUTE": "DISTRIBUTE", "DIT": "Ditcoin", @@ -5325,7 +5361,8 @@ "DUCKIES": "Yellow Duckies", "DUCKO": "Duck Off Coin", "DUCKV1": "UNITPROV1", - "DUCKY": "Ducky Duck", + "DUCKY": "Ducky", + "DUCKY0X71": "Ducky Duck", "DUCX": "DucatusX", "DUDE": "DuDe", "DUEL": "GameGPT", @@ -5493,6 +5530,7 @@ "ECHOD": "EchoDEX", "ECHT": "e-Chat", "ECI": "Euro Cup Inu", + "ECKODAO": "eckoDAO", "ECL": "ECLAT", "ECLD": "Ethernity Cloud", "ECLIP": "Eclipse Fi", @@ -5891,7 +5929,8 @@ "ESN": "Ethersocial", "ESNC": "Galaxy Arena Metaverse", "ESOL": "Earn Solana", - "ESP": "Espers", + "ESP": "Espresso", + "ESPERS": "Espers", "ESPL": "ESPL ARENA", "ESPORTS": "Yooldo Games", "ESPR": "Espresso Bot", @@ -6250,7 +6289,7 @@ "FCT": "FirmaChain", "FCTC": "FaucetCoin", "FCTR": "FactorDAO", - "FDC": "Fidance", + "FDC": "FDrive Coin", "FDGC": "FINTECH DIGITAL GOLD COIN", "FDLS": "FIDELIS", "FDM": "Fandom", @@ -6323,6 +6362,7 @@ "FIC": "Filecash", "FID": "Fidira", "FIDA": "Bonfida", + "FIDANCE": "Fidance", "FIDD": "Fidelity Digital Dollar", "FIDLE": "Fidlecoin", "FIDO": "FIDO", @@ -6334,6 +6374,7 @@ "FIFTY": "FIFTYONEFIFTY", "FIG": "FlowCom", "FIGH": "FIGHT FIGHT FIGHT", + "FIGHT": "FIGHT", "FIGHT2MAGA": "Fight to MAGA", "FIGHTMAGA": "FIGHT MAGA", "FIGHTPEPE": "FIGHT PEPE", @@ -6605,6 +6646,7 @@ "FORTKNOX": "Fort Knox", "FORTUNA": "Fortuna", "FORTUNE": "Fortune", + "FORU": "ForU AI", "FORWARD": "Forward Protocol", "FOTA": "Fight Of The Ages", "FOTO": "Unique Photo", @@ -6639,6 +6681,7 @@ "FR": "Freedom Reserve", "FRA": "Findora", "FRAC": "FractalCoin", + "FRACTON": "Fracton Protocol", "FRAG": "Fragmetric", "FRANK": "Frank", "FRANKLIN": "Franklin", @@ -6662,10 +6705,13 @@ "FREEDO": "Freedom", "FREEDOG": "Freedogs", "FREEDOM": "Freedom Protocol Token", + "FREEDOMOFMONEY": "Freedom of Money", "FREELA": "DecentralFree", "FREEPAVEL": "Free Pavel", "FREEROSS": "FreeRossDAO", "FREET": "FreeTrump", + "FREEWAYV1": "Freeway Token", + "FREEWAYV2": "Freeway Token", "FREL": "Freela", "FREN": "FREN", "FRENC": "Frencoin", @@ -6737,7 +6783,7 @@ "FSTC": "FastCoin", "FSTR": "Fourth Star", "FSW": "Falconswap", - "FT": "Fracton Protocol", + "FT": "Flying Tulip", "FTB": "Fit&Beat", "FTC": "Futurex", "FTD": "42DAO", @@ -6831,8 +6877,9 @@ "FWCL": "Legends", "FWH": "FigureWifHat", "FWOG": "Fwog", - "FWT": "Freeway Token", + "FWT": "FadeWallet Token", "FWW": "Farmers World Wood", + "FWX": "Future Warriors X", "FX": "Function X", "FXAKV": "Akiverse Governance", "FXB": "FxBox", @@ -6865,6 +6912,7 @@ "GAD": "Green App Development", "GAFA": "Gafa", "GAFI": "GameFi", + "GAG": "GAG Token", "GAGA": "Gaga", "GAI": "GraphAI", "GAIA": "Gaia Token", @@ -6909,9 +6957,10 @@ "GAMEIN": "Game Infinity", "GAMER": "GameStation", "GAMERFI": "GamerFI", - "GAMES": "Gamestarter", + "GAMES": "GAME•OF•BITCOIN", "GAMEST": "GameStop Coin", "GAMESTARS": "Game Stars", + "GAMESTARTER": "Gamestarter", "GAMESTO": "GameStop", "GAMESTOP": "GameStop", "GAMESTUMP": "GAMESTUMP", @@ -7066,6 +7115,7 @@ "GEO": "GeoCoin", "GEOD": "GEODNET", "GEODB": "GeoDB", + "GEODE": "Geode Chain", "GEOJ": "Geojam", "GEOL": "GeoLeaf", "GEON": "Geon", @@ -7081,6 +7131,7 @@ "GETA": "Getaverse", "GETH": "Guarded Ether", "GETLIT": "LIT", + "GETRICHQUICK": "GET RICH QUICK", "GETX": "Guaranteed Ethurance Token Extra", "GEX": "Gexan", "GEZY": "EZZY GAME GEZY", @@ -7420,7 +7471,7 @@ "GOW39": "God Of Wealth", "GOYOO": "GoYoo", "GOZ": "Göztepe S.K. Fan Token", - "GP": "Wizards And Dragons", + "GP": "Graphite", "GPAWS": "Golden Paws", "GPBP": "Genius Playboy Billionaire Philanthropist", "GPCX": "Good Person Coin", @@ -7428,11 +7479,13 @@ "GPKR": "Gold Poker", "GPL": "Gold Pressed Latinum", "GPLX": "Gplx", + "GPM": "GOLD PUMP MEME", "GPN": "Gamepass Network", "GPO": "GoldPesa Option", "GPPT": "Pluto Project Coin", "GPRO": "GoldPro", "GPS": "GoPlus Security", + "GPST": "GPStarter", "GPSTOKEN": "GPS Token", "GPT": "QnA3.AI", "GPT4O": "GPT-4o", @@ -7456,7 +7509,8 @@ "GRAM": "Gram", "GRAND": "Grand Theft Ape", "GRANDCOIN": "GrandCoin", - "GRANDMA": "Grandma", + "GRANDMA": "Minecraft Grandma Fund", + "GRANDMASOL": "Grandma", "GRANT": "GrantiX Token", "GRAPE": "GrapeCoin", "GRAPHGRAIAI": "GraphGrail AI", @@ -7682,10 +7736,12 @@ "HAC": "Hackspace Capital", "HACD": "Hacash Diamond", "HACH": "Hachiko", - "HACHI": "Hachi", + "HACHI": "Hachiko", "HACHIK": "Hachiko", "HACHIKO": "Hachiko Inu Token", + "HACHIKOINU": "Hachiko Inu", "HACHIONB": "Hachi On Base", + "HACHITOKEN": "Hachi", "HACK": "HACK", "HADES": "Hades", "HAEDAL": "Haedal Protocol", @@ -7732,6 +7788,7 @@ "HAR": "Harambe Coin", "HARAM": "HARAM", "HARAMBE": "Harambe on Solana", + "HARAMBEAI": "Harambe AI Token", "HARD": "Kava Lend", "HARE": "Hare Token", "HAREPLUS": "Hare Plus", @@ -7878,6 +7935,7 @@ "HFUN": "Hypurr Fun", "HGEN": "HGEN DAO", "HGET": "Hedget", + "HGG": "Hedera Guild Game", "HGHG": "HUGHUG Coin", "HGO": "HireGo", "HGOLD": "HollyGold", @@ -7993,6 +8051,7 @@ "HNC": "Hellenic Coin", "HNCN": "Huncoin", "HND": "Hundred Finance", + "HNO": "HNO Coin", "HNS": "Handshake", "HNST": "Honest", "HNT": "Helium", @@ -8323,6 +8382,7 @@ "IDOLINU": "IDOLINU", "IDOODLES": "IDOODLES", "IDORU": "Vip2Fan", + "IDOS": "IDOS", "IDRISS": "IDRISS", "IDRT": "Rupiah Token", "IDRX": "IDRX", @@ -8465,6 +8525,7 @@ "INN": "Innova", "INNBC": "Innovative Bioresearch Coin", "INNOU": "Innou", + "INNOVAMINEX": "InnovaMinex", "INO": "Ino Coin", "INOVAI": "INOVAI", "INP": "Ionic Pocket Token", @@ -8477,6 +8538,7 @@ "INSANITY": "Insanity Coin", "INSC": "INSC (Ordinals)", "INSE": "INSECT", + "INSIGHTPROTOCOL": "Insight Protocol", "INSN": "Industry Sonic", "INSP": "Inspect", "INSPI": "InspireAI", @@ -8515,7 +8577,7 @@ "INVITE": "INVITE Token", "INVOX": "Invox Finance", "INVX": "Investx", - "INX": "Insight Protocol", + "INX": "Infinex", "INXM": "InMax", "INXT": "Internxt", "INXTOKEN": "INX Token", @@ -8643,6 +8705,7 @@ "IVIP": "iVipCoin", "IVN": "IVN Security", "IVPAY": "ivendPay", + "IVT": "ivault Token", "IVY": "IvyKoin", "IVZ": "InvisibleCoin", "IW": "iWallet", @@ -8886,6 +8949,7 @@ "JUP": "Jupiter", "JUPI": "Jupiter", "JUPSOL": "Jupiter Staked SOL", + "JUPUSD": "Jupiter USD", "JUR": "Jur", "JUS": "Just The Tip", "JUSD": "JUSD Stable Token", @@ -8970,6 +9034,7 @@ "KARA": "KarateCat", "KARAT": "KARAT Galaxy", "KARATE": "Karate Combat", + "KARATTOKEN": "Karat", "KAREN": "KarenCoin", "KARMA": "Karma", "KARMAD": "Karma DAO", @@ -8985,10 +9050,9 @@ "KASSIAHOME": "Kassia Home", "KASTA": "Kasta", "KASTER": "King Aster", - "KAT": "Karat", + "KAT": "Katana Network", "KATA": "Katana Inu", "KATANA": "Katana Finance", - "KATANANET": "Katana Network", "KATCHU": "Katchu Coin", "KATT": "Katt Daddy", "KATYCAT": "Katy Perry Fans", @@ -8998,6 +9062,7 @@ "KAWA": "Kawakami Inu", "KAWS": "Kaws", "KAYI": "Kayı", + "KAYYO": "Kayyo", "KBBB": "KILL BIG BEAUTIFUL BILL", "KBC": "Karatgold coin", "KBD": "Kyberdyne", @@ -9029,7 +9094,7 @@ "KDOE": "Kudoe", "KDOGE": "KingDoge", "KDT": "Kenyan Digital Token", - "KDX": "eckoDAO", + "KDX": "Kodexa", "KEANU": "Keanu Inu", "KEC": "KEYCO", "KED": "Klingon Empire Darsek", @@ -9114,11 +9179,15 @@ "KIMA": "Kima", "KIMBA": "The White Lion", "KIMBO": "Kimbo", - "KIMCHI": "KIMCHI.finance", + "KIMCH": "Kimchi", + "KIMCHI": "Kimchi Coin", + "KIMCHICTO": "Kimchi", + "KIMCHIFINANCE": "KIMCHI.finance", "KIMIAI": "Kimi AI Agent", - "KIN": "Kin", + "KIN": "KinToken", "KIND": "Kind Ads", "KINE": "Kine Protocol", + "KINECOSYSTEM": "Kin", "KINET": "KinetixFi", "KING": "LRT Squared", "KING93": "King93", @@ -9237,6 +9306,7 @@ "KNUT": "Knut From Zoo", "KNUXX": "Knuxx Bully of ETH", "KNW": "Knowledge", + "KNX": "KnoxNet", "KO": "Kyuzo's Friends", "KOAI": "KOI", "KOALA": "KOALA", @@ -9380,6 +9450,7 @@ "KUSH": "KushCoin", "KUSUNOKI": "Kusunoki Samurai", "KUV": "Kuverit", + "KVAI": "Kvants AI", "KVERSE": "KEEPs Coin", "KVI": "KVI Chain", "KVNT": "KVANT", @@ -9398,7 +9469,7 @@ "KXUSD": "kxUSD", "KYCC": "KYCCOIN", "KYL": "Kylin Network", - "KYO": "Kayyo", + "KYO": "Kyo", "KYOKO": "Kyoko", "KYRA": "KYRA", "KYSOL": "Kyros Restaked SOL", @@ -9571,6 +9642,7 @@ "LENARD": "Lenard", "LEND": "Aave", "LENDA": "Lenda", + "LENDFLARE": "Lend Flare Dao", "LENDS": "Lends", "LENFI": "Lenfi", "LENIN": "LeninCoin", @@ -9615,7 +9687,7 @@ "LFI": "LunaFi", "LFIT": "LFIT", "LFNTY": "Lifinity", - "LFT": "Lend Flare Dao", + "LFT": "LIFEFORM Token", "LFW": "Linked Finance World", "LGBT": "Let's Go Brandon Token", "LGBTQ": "LGBTQoin", @@ -9721,6 +9793,7 @@ "LISTEN": "Listen", "LISUSD": "lisUSD", "LIT": "Lighter", + "LITCOIN": "Litcoin", "LITE": "Lite USD", "LITEBTC": "LiteBitcoin", "LITENETT": "Litenett", @@ -9790,6 +9863,7 @@ "LNQ": "LinqAI", "LNR": "LNR", "LNRV2": "Lunar", + "LNS": "LIFE Coin", "LNT": "Lottonation", "LNX": "Lunox Token", "LOA": "League of Ancients", @@ -9798,6 +9872,7 @@ "LOAN": "Lendoit", "LOBO": "LOBO•THE•WOLF•PUP", "LOBS": "Lobstex", + "LOBSTAR": "Lobstar", "LOC": "LockTrip", "LOCAT": "LOVE CAT", "LOCC": "Low Orbit Crypto Cannon", @@ -9830,6 +9905,7 @@ "LOLLY": "Lollipop", "LOLLYBOMB": "LollyBomb", "LOLO": "Lolo", + "LOLONBSC": "LOL", "LON": "Tokenlon", "LONG": "Longdrink Finance", "LONGEVITY": "longevity", @@ -9843,8 +9919,9 @@ "LOOMV1": "Loom Network v1", "LOON": "Loon Network", "LOONG": "PlumpyDragons", - "LOOP": "LOOP", + "LOOP": "LoopNetwork", "LOOPIN": "LooPIN Network", + "LOOPMARKETS": "LOOP", "LOOPY": "Loopy", "LOOT": "LootBot", "LOOTEX": "Lootex", @@ -9988,8 +10065,9 @@ "LULU": "LULU", "LUM": "Luminous", "LUMA": "LUMA Token", - "LUMI": "LUMI Credits", + "LUMI": "LumiShare", "LUMIA": "Lumia", + "LUMICREDITS": "LUMI Credits", "LUMIO": "Solana Mascot", "LUMO": "Lumo-8B-Instruct", "LUMOS": "Lumos", @@ -10079,6 +10157,7 @@ "MABA": "Make America Based Again", "MAC": "MachineCoin", "MACHO": "macho", + "MACMINI": "Mac mini", "MACRO": "Macro Millions", "MACROPROTOCOL": "Macro Protocol", "MADA": "MilkADA", @@ -10178,6 +10257,7 @@ "MANTA": "Manta Network", "MANTI": "Mantis", "MANTLE": "Mantle", + "MANTRA": "MANTRA", "MANUSAI": "Manus AI Agent", "MANYU": "Manyu", "MANYUDOG": "MANYU", @@ -10210,10 +10290,11 @@ "MARMAJ": "marmaj", "MAROV1": "TTC PROTOCOL", "MAROV2": "Maro", - "MARS": "Mars", + "MARS": "MetaMars", "MARS4": "MARS4", "MARSC": "MarsCoin", "MARSCOIN": "MarsCoin", + "MARSERC": "Mars", "MARSH": "Unmarshal", "MARSMI": "MarsMi", "MARSO": "Marso.Tech", @@ -10544,6 +10625,7 @@ "METANIA": "METANIA V2", "METANIAV1": "METANIAGAMES", "METANO": "Metano", + "METAON": "Meta Platforms (Ondo Tokenized)", "METAPK": "Metapocket", "METAPLACE": "Metaplace", "METAQ": "MetaQ", @@ -10739,7 +10821,7 @@ "MINTYS": "MintySwap", "MINU": "Minu", "MINUTE": "MINUTE Vault (NFTX)", - "MINX": "InnovaMinex", + "MINX": "Modern Innovation Network Token", "MIO": "Miner One token", "MIODIO": "MIODIOCOIN", "MIOTA": "IOTA", @@ -10949,7 +11031,9 @@ "MOLK": "Mobilink Token", "MOLLARS": "MollarsToken", "MOLLY": "Molly", + "MOLO": "MOLO CHAIN", "MOLT": "Moltbook", + "MOLTID": "MoltID", "MOM": "Mother of Memes", "MOMA": "Mochi Market", "MOMIJI": "MAGA Momiji", @@ -10986,6 +11070,7 @@ "MONKAS": "Monkas", "MONKE": "Monkecoin", "MONKEY": "Monkey", + "MONKEYC": "Monkey Cult", "MONKEYS": "Monkeys Token", "MONKU": "Monku", "MONKY": "Wise Monkey", @@ -10998,6 +11083,7 @@ "MONST": "Monstock", "MONSTA": "Cake Monster", "MONSTE": "Monster", + "MONSTRO": "Monstro DeFi", "MONT": "Monarch Token", "MONTE": "Monte", "MOO": "MooMonster", @@ -11027,6 +11113,7 @@ "MOOND": "Dark Moon", "MOONDAY": "Moonday Finance", "MOONDO": "MOON DOGE", + "MOONDOG": "MOONDOGE", "MOONDOGE": "MOONDOGE", "MOONED": "MoonEdge", "MOONER": "CoinMooner", @@ -11077,6 +11164,7 @@ "MOUNTA": "Mountain Protocol", "MOUTAI": "Moutai", "MOV": "MovieCoin", + "MOVA": "MOVA", "MOVD": "MOVE Network", "MOVE": "Movement", "MOVER": "Mover", @@ -11107,6 +11195,7 @@ "MPLUS": "M+Plus", "MPLX": "Metaplex", "MPM": "Monopoly Meta", + "MPP": "MegPrime Token", "MPRO": "MediumProject", "MPS": "Mt Pelerin Shares", "MPT": "Miracleplay Token", @@ -11177,6 +11266,7 @@ "MSTAR": "MerlinStarter", "MSTETH": "Eigenpie mstETH", "MSTO": "Millennium Sapphire", + "MSTRON": "MicroStrategy (Ondo Tokenized)", "MSTRX": "MicroStrategy xStock", "MSU": "MetaSoccer", "MSUSHI": "Sushi (Multichain)", @@ -11264,6 +11354,7 @@ "MUON": "Micron Technology (Ondo Tokenized)", "MURA": "Murasaki", "MURATIAI": "MuratiAI", + "MUSA": "Mansa AI", "MUSCAT": "MusCat", "MUSD": "MetaMask USD", "MUSDC": "USD Coin (Multichain)", @@ -11662,6 +11753,7 @@ "NIC": "NewInvestCoin", "NICE": "Nice", "NICEC": "NiceCoin", + "NICKELS": "Nickel", "NIETZSCHEAN": "Nietzschean Penguin", "NIF": "Unifty", "NIFT": "Niftify", @@ -11762,6 +11854,7 @@ "NOHAT": "DogWifNoHat", "NOIA": "Syntropy", "NOICE": "noice", + "NOIRSHARES": "NoirShares", "NOIS": "Nois Network", "NOIZ": "NOIZ", "NOKA": "Noka Solana AI", @@ -11835,7 +11928,7 @@ "NRN": "Neuron", "NRO": "Neuro", "NRP": "Neural Protocol", - "NRS": "NoirShares", + "NRS": "Nereus", "NRV": "Nerve Finance", "NRVE": "Narrative", "NRX": "Neironix", @@ -12033,6 +12126,8 @@ "ODDZ": "Oddz", "ODE": "ODEM", "ODGN": "OrdiGen", + "ODIC": "ODIC Token", + "ODIK": "ODIK", "ODIN": "Odin Protocol", "ODMC": "ODMCoin", "ODN": "Obsidian", @@ -12221,12 +12316,15 @@ "OPENCHAT": "OpenChat", "OPENCUSTODY": "Open Custody Protocol", "OPENDAO": "OpenDAO", + "OPENECO": "OPEN Ticketing Ecosystem", + "OPENECOV1": "GET Protocol", "OPENGO": "OPEN Governance Token", "OPENON": "Opendoor Technologies (Ondo Tokenized)", "OPENP": "Open Platform", "OPENRI": "Open Rights Exchange", "OPENSOURCE": "Open Source Network", "OPENSWAP": "OpenSwap Optimism Token", + "OPENV": "OpenVPP", "OPENVC": "OpenVoiceCoin", "OPENW": "OpenWorld", "OPENX": "OpenxAI", @@ -12240,9 +12338,8 @@ "OPINU": "Optimus Inu", "OPIUM": "Opium", "OPMND": "Open Mind Network", - "OPN": "OPEN Ticketing Ecosystem", + "OPN": "OPINION", "OPNN": "Opennity", - "OPNV1": "GET Protocol", "OPP": "Opporty", "OPS": "Octopus Protocol", "OPSC": "OpenSourceCoin", @@ -12482,6 +12579,7 @@ "PANGEA": "PANGEA", "PANIC": "PanicSwap", "PANO": "PanoVerse", + "PANTH": "Panther AI", "PANTHER": "Panther Protocol", "PANTOS": "Pantos", "PAO": "South Pao", @@ -12628,7 +12726,7 @@ "PEAN": "Peanut the Squirrel (peanut-token.xyz)", "PEANIE": "Peanie", "PEANU": "PEANUT INU", - "PEANUT": "#1 Tiktok Squirrel", + "PEANUT": "Peanut", "PEAQ": "peaq", "PEAR": "Pear Swap", "PEARL": "Pearl Finance", @@ -12682,9 +12780,11 @@ "PENGYX": "PengyX", "PENIS": "PenisGrow", "PENJ": "Penjamin Blinkerton", + "PENNIES": "Penny", "PENP": "Penpie", "PENR": "Penrose Finance", "PENTA": "Penta", + "PENTAG": "Pentagon", "PEON": "Peon", "PEOPLE": "ConstitutionDAO", "PEOPLEFB": "PEOPLE", @@ -12740,6 +12840,7 @@ "PEPEPI": "PEPEPi", "PEPER": "Baby Pepe", "PEPERA": "PEPERA", + "PEPESDOG": "Pepes Dog", "PEPESOL": "PEPE SOL", "PEPESOLCTO": "Pepe (pepesolcto.vip)", "PEPESORA": "Pepe Sora AI", @@ -12784,6 +12885,7 @@ "PESOBIT": "PesoBit", "PESTO": "Pesto the Baby King Penguin", "PET": "Hello Pets", + "PETAH": "ピータさん", "PETE": "PETE", "PETERTODD": "Peter Todd", "PETF": "PEPE ETF", @@ -12899,6 +13001,7 @@ "PIKE": "Pike Token", "PIKO": "Pinnako", "PIKZ": "PIKZ", + "PILL": "life changing pill", "PILLAR": "PillarFi", "PILOT": "Unipilot", "PIM": "PIM", @@ -12929,6 +13032,7 @@ "PIPO": "Pipo", "PIPONHL": "PiP", "PIPPIN": "pippin", + "PIPPKIN": "Pippkin The Horse", "PIPT": "Power Index Pool Token", "PIRATE": "Pirate Nation", "PIRATECASH": "PirateCash", @@ -13070,6 +13174,7 @@ "PMR": "Pomerium Utility Token", "PMT": "Public Masterpiece Token", "PMTN": "Peer Mountain", + "PMUSD": "Precious Metals USD", "PMX": "Phillip Morris xStock", "PNB": "Pink BNB", "PNC": "PlatiniumCoin", @@ -13440,8 +13545,9 @@ "PUMPTRUMP": "PUMP TRUMP", "PUMPY": "WOW MOON LAMBO PUMPPPPPPY", "PUN": "Punkko", - "PUNCH": "PUNCHWORD", + "PUNCH": "パンチ (Punch) (punchonsolana.fun)", "PUNCHI": "Punchimals", + "PUNCHWORD": "PUNCHWORD (punchword.com)", "PUNDIAI": "Pundi AI", "PUNDIX": "Pundi X", "PUNDU": "Pundu", @@ -13450,7 +13556,7 @@ "PUNK": "PunkCity", "PUNKAI": "PunkAI", "PUNKV": "Punk Vault (NFTX)", - "PUP": "Puppy Coin", + "PUP": "PUP", "PUPA": "PupaCoin", "PUPPER": "Pupper", "PUPPET": "Puppet", @@ -13596,6 +13702,7 @@ "QQBC": "QQBC IPFS BLOCKCHAIN", "QQQ": "Poseidon Network", "QQQF": "Standard Crypto Fund", + "QQQON": "Invesco QQQ (Ondo Tokenized)", "QQQX": "Nasdaq xStock", "QR": "Qrolli", "QRK": "QuarkCoin", @@ -13670,6 +13777,7 @@ "QWT": "QoWatt", "QXC": "QuantumXC", "R1": "Recast1", + "R2": "R2", "R2R": "CitiOs", "R34P": "R34P", "R3FI": "r3fi.finance", @@ -13708,6 +13816,7 @@ "RAILS": "Rails Token", "RAIN": "Rain", "RAINBOW": "Rainbow Token", + "RAINBOWTOKEN": "Rainbow Token", "RAINC": "RainCheck", "RAINCO": "Rain Coin", "RAINI": "Rainicorn", @@ -13780,7 +13889,7 @@ "RBXDEFI": "RBX", "RBXS": "RBXSamurai", "RBY": "RubyCoin", - "RC": "Russiacoin", + "RC": "Rebel Cars", "RC20": "RoboCalls", "RCADE": "RCADE", "RCC": "Reality Clash", @@ -13880,6 +13989,7 @@ "REFUND": "Refund", "REG": "RealToken Ecosystem Governance", "REGALCOIN": "Regalcoin", + "REGARISK": "REGA Risk Sharing Token", "REGE": "Regent of the North Winds", "REGEN": "Regen Network", "REGENT": "REGENT COIN", @@ -13943,7 +14053,8 @@ "RETH": "Rocket Pool ETH", "RETH2": "rETH2", "RETIK": "Retik Finance", - "RETIRE": "Retire Token", + "RETIRE": "The Last Play", + "RETIRETOKEN": "Retire Token", "RETSA": "Retsa Coin", "REU": "REUCOIN", "REUNI": "Reunit Wallet", @@ -13996,6 +14107,7 @@ "RHOC": "RChain", "RHP": "Rhypton Club", "RHUB": "ROLLHUB", + "RHYPURR": "rHYPURR", "RIA": "aRIA Currency", "RIB": "Ribus", "RIBB": "Ribbit", @@ -14004,7 +14116,7 @@ "RICE": "RICE AI", "RICECOIN": "RiceCoin", "RICEFARM": "RiceFarm", - "RICH": "GET RICH QUICK", + "RICH": "Ostrich", "RICHCOIN": "RICHCOIN", "RICHIE": "Richie2.0", "RICHIEV1": "Richie", @@ -14096,7 +14208,7 @@ "RMV": "Reality Metaverse", "RNAPEPE": "RNA PEPE", "RNB": "Rentible", - "RNBW": "Rainbow Token", + "RNBW": "Rainbow", "RNC": "ReturnCoin", "RND": "The RandomDAO", "RNDR": "Render Token", @@ -14110,15 +14222,16 @@ "ROA": "ROA CORE", "ROAD": "ROAD", "ROAM": "Roam Token", - "ROAR": "Alpha DEX", + "ROAR": "Roaring Kitty", "ROARINGCAT": "Roaring Kitty", "ROB": "ROB", "ROBET": "RoBet", "ROBI": "Robin Rug", "ROBIN": "Robin of Da Hood", "ROBINH": "ROBIN HOOD", - "ROBO": "RoboHero", + "ROBO": "Robo Token", "ROBOCOIN": "First Bitcoin ATM", + "ROBOHERO": "RoboHero", "ROBOTA": "TAXI", "ROBOTAXI": "ROBOTAXI", "ROC": "Rasputin Online Coin", @@ -14176,6 +14289,7 @@ "ROSX": "Roseon", "ROT": "Rotten", "ROTTY": "ROTTYCOIN", + "ROU": "ROUTINE COIN", "ROUGE": "Rouge Studio", "ROUND": "RoundCoin", "ROUP": "Roup (Ordinals)", @@ -14227,7 +14341,7 @@ "RSRV": "Reserve", "RSRV1": "Reserve Rights v1", "RSS3": "RSS3", - "RST": "REGA Risk Sharing Token", + "RST": "Runesoul", "RSTK": "Restake Finance", "RSUN": "RisingSun", "RSUSHI": "Sushi (Rainbow Bridge)", @@ -14244,6 +14358,7 @@ "RTH": "Rotharium", "RTK": "RetaFi", "RTM": "Raptoreum", + "RTP": "Return to Player", "RTR": "Restore The Republic", "RTT": "Restore Truth Token", "RTX": "RateX", @@ -14283,6 +14398,7 @@ "RUSH": "RUSH COIN", "RUSHCMC": "RUSHCMC", "RUSSELL": "Russell", + "RUSSIACOIN": "Russiacoin", "RUST": "RustCoin", "RUSTBITS": "Rustbits", "RUTH": "RUTH", @@ -14332,7 +14448,7 @@ "RYOSHI": "Ryoshis Vision", "RYS": "RefundYourSOL", "RYT": "Real Yield Token", - "RYU": "The Blue Dragon", + "RYU": "RyuJin", "RYZ": "Anryze", "RZR": "Rezor", "RZTO": "RZTO Token", @@ -14611,7 +14727,7 @@ "SECT": "SECTBOT", "SECTO": "Sector Finance", "SEDA": "SEDA Protocol", - "SEED": "Superbloom", + "SEED": "SEED", "SEEDS": "SeedShares", "SEEDV": "Seed Venture", "SEEDX": "SEEDx", @@ -14739,6 +14855,7 @@ "SHAMAN": "Shaman King Inu", "SHAN": "Shanum", "SHANG": "Shanghai Inu", + "SHAPE": "Shape", "SHAR": "Shark Cat", "SHARBI": "SHARBI", "SHARDS": "WorldShards", @@ -14931,7 +15048,8 @@ "SILV": "Silver Surfer Solana", "SILV2": "Escrowed Illuvium 2", "SILVA": "Silva Token", - "SILVER": "SILVER", + "SILVER": "silver coin", + "SILVERETHCLUB": "SILVER (silvereth.club)", "SILVERKRC": "Silver KRC-20", "SILVERNOV": "Silvernova Token", "SILVERSTAND": "Silver Standard", @@ -15155,6 +15273,7 @@ "SMURFCATSOL": "Real Smurf Cat", "SMX": "Snapmuse.io", "SN": "SpaceN", + "SN3": "Supernova Nebula3", "SNA": "SUKUYANA", "SNAC": "SnackboxAI", "SNACK": "Crypto Snack", @@ -15279,6 +15398,7 @@ "SOLAREU": "Solareum", "SOLARFARM": "SolarFarm", "SOLARIX": "SOLARIX", + "SOLARX": "SolarX", "SOLAV": "SOLAV TOKEN", "SOLBANK": "Solbank", "SOLBET": "SOL STREET BETS", @@ -15287,7 +15407,8 @@ "SOLBULL": "SOLBULL", "SOLC": "SolCard", "SOLCASH": "SOLCash", - "SOLCAT": "SOLCAT", + "SOLCAT": "CatSolHat", + "SOLCATMEME": "SOLCAT", "SOLCEX": "SolCex", "SOLCHICKSSHARDS": "SolChicks Shards", "SOLE": "SoleCoin", @@ -15336,7 +15457,7 @@ "SOLVE": "SOLVE", "SOLVEX": "SOLVEX", "SOLWIF": "Solwif", - "SOLX": "SolarX", + "SOLX": "Solaxy", "SOLXD": "Solxdex", "SOLY": "Solamander", "SOLYMPICS": "Solympics", @@ -15736,8 +15857,8 @@ "STOGE": "Stoner Doge Finance", "STOIC": "stoicDAO", "STON": "STON", - "STONE": "Stone Token", "STONEDE": "Stone DeFi", + "STONETOKEN": "Stone Token", "STONK": "STONK", "STONKS": "STONKS", "STOP": "LETSTOP", @@ -15850,6 +15971,7 @@ "SUMMIT": "Summit", "SUMMITTHE": "SUMMIT", "SUMO": "Sumokoin", + "SUMR": "SummerToken", "SUN": "Sun Token", "SUNC": "Sunrise", "SUNCAT": "Suncat", @@ -15904,6 +16026,7 @@ "SUSDA": "sUSDa", "SUSDE": "Ethena Staked USDe", "SUSDS": "Savings USDS", + "SUSDT": "SkyTrade Pro", "SUSDX": "Staked USDX", "SUSHI": "Sushi", "SUSX": "Savings USX", @@ -16095,6 +16218,7 @@ "TAP": "TAP FANTASY", "TAPC": "Tap Coin", "TAPCOIN": "TAP FANTASY", + "TAPP": "TAPP", "TAPPINGCOIN": "TappingCoin", "TAPROOT": "Taproot Exchange", "TAPS": "TapSwap", @@ -16225,6 +16349,7 @@ "TEMP": "Tempus", "TEMPLE": "TempleDAO", "TEN": "TEN", + "TENCENTAI": "Tencent AI", "TEND": "Tendies", "TENDIE": "TendieSwap", "TENET": "TENET", @@ -16259,6 +16384,7 @@ "TESOURO": "Etherfuse TESOURO", "TEST": "Test", "TESTA": "Testa", + "TESTICLE": "Testicle", "TET": "Tectum", "TETH": "Treehouse ETH", "TETHYS": "Tethys", @@ -16298,6 +16424,7 @@ "THEAICOIN": "AI", "THEB": "The Boys Club", "THEBLOX": "The Blox Project", + "THEBLUEDRAGON": "The Blue Dragon", "THEC": "The CocktailBar", "THECA": "Theca", "THECAT": "THECAT", @@ -16327,6 +16454,7 @@ "THETAN": "Thetan Coin", "THETRANSFERTOKEN": "The Transfer Token", "THETRIBE": "The Tribe", + "THEWHALE": "The Whale killer", "THEX": "Thore Exchange", "THG": "Thetan Arena", "THIK": "ThikDik", @@ -16384,6 +16512,7 @@ "TIKI": "Tiki Token", "TIKTOK": "Tiktok", "TIKTOKEN": "TikToken", + "TILECOIN": "TileCoin", "TIM": "TIMTIM GAMES", "TIME": "Chrono.tech", "TIMEFUN": "timefun", @@ -16710,6 +16839,7 @@ "TRR": "Terran Coin", "TRSCT": "Transactra Finance", "TRST": "TrustCoin", + "TRT": "TRUST AI", "TRTL": "TurtleCoin", "TRTT": "Trittium", "TRU": "TrueFi", @@ -16866,6 +16996,7 @@ "TUTC": "TUTUT COIN", "TUTELLUS": "Tutellus", "TUTTER": "Tutter", + "TUURNT": "TuurnT", "TUX": "Tux The Penguin", "TUZKI": "Tuzki", "TUZLA": "Tuzlaspor Token", @@ -17180,6 +17311,7 @@ "USDCSO": "USD Coin (Portal from Solana)", "USDCV": "USD CoinVertible", "USDD": "USDD", + "USDDD": "USDDD", "USDDV1": "USDD v1", "USDE": "Ethena USDe", "USDEBT": "USDEBT", @@ -17188,6 +17320,7 @@ "USDFL": "USDFreeLiquidity", "USDG": "Global Dollar", "USDGLOBI": "Globiance USD Stablecoin", + "USDGO": "USDGO", "USDGV1": "USDG v1", "USDGV2": "USDG", "USDH": "USDH", @@ -17212,6 +17345,7 @@ "USDS": "Sky Dollar", "USDSB": "USDSB", "USDSTABLY": "StableUSD", + "USDSUI": "USDsui", "USDT": "Tether", "USDT0": "USDT0", "USDT1": "USDT1", @@ -17314,6 +17448,7 @@ "VALENTINE": "Valentine", "VALI": "VALIMARKET", "VALID": "Validator Token", + "VALLEYDAO": "ValleyDAO Token", "VALOR": "Valor Token", "VALORBIT": "Valorbit", "VALU": "Value", @@ -17384,6 +17519,7 @@ "VEE": "BLOCKv", "VEED": "VEED", "VEEN": "LIVEEN", + "VEETOKEN": "Vee Token", "VEG": "BitVegan", "VEGA": "Vega Protocol", "VEGAS": "Vegas", @@ -17401,6 +17537,7 @@ "VELODV1": "Velodrome v1", "VELOX": "Velox", "VELOXPROJECT": "Velox", + "VELT": "VELTRIXA", "VELVET": "Velvet", "VEMP": "vEmpire DDAO", "VEN": "VeChain Old", @@ -17463,6 +17600,7 @@ "VICA": "ViCA Token", "VICE": "VICE Token", "VICEX": "ViceToken", + "VICPAY": "VICTORUM", "VICS": "RoboF", "VICT": "Victory Impact Coin", "VICTORIUM": "Victorium", @@ -17498,6 +17636,7 @@ "VIRTUALMINING": "VirtualMining Coin", "VIRTUM": "VIRTUMATE", "VIS": "Vigorus", + "VISAON": "Visa (Ondo Tokenized)", "VISIO": "Visio", "VISION": "VisionGame", "VISIONCITY": "Vision City", @@ -17868,6 +18007,7 @@ "WEFI": "WeFi", "WEGEN": "WeGen Platform", "WEGI": "Wegie", + "WEGL": "White Eagle", "WEGLD": "Wrapped EGLD", "WEHMND": "Wrapped eHMND", "WEHODL": "HODL", @@ -18081,6 +18221,7 @@ "WMXWOM": "Wombex WOM", "WNCG": "Wrapped NCG", "WND": "WonderHero", + "WNDGAME": "Wizards And Dragons", "WNDR": "Wonderman Nation", "WNE": "Winee3", "WNEAR": "Wrapped Near", @@ -18149,6 +18290,7 @@ "WORLDLIBERTYICU": "World Liberty Financial", "WORLDLIBERTYSOL": "World Liberty Financial", "WORLDOFD": "World of Defish", + "WORLDW": "World War 3", "WORM": "HealthyWorm", "WORX": "Worx", "WOS": "Wolf Of Solana", @@ -18360,6 +18502,7 @@ "XCPO": "Copico", "XCR": "Crypti", "XCRE": "Creatio", + "XCREDI": "xCREDI", "XCRX": "xCRX", "XCT": "C-Bits", "XCUR": "Curate", @@ -18443,6 +18586,7 @@ "XIL": "Xillion", "XIN": "Mixin", "XING": "Xing Xing", + "XINGXING": "星星", "XINU": "XINU", "XIO": "Blockzero Labs", "XION": "XION", @@ -18612,7 +18756,7 @@ "XT3": "Xt3ch", "XTAG": "xHashtag", "XTAL": "XTAL", - "XTC": "TileCoin", + "XTC": "Xitcoin", "XTECH": "X-TECH", "XTER": "Xterio", "XTK": "xToken", @@ -18748,6 +18892,7 @@ "YFL": "YF Link", "YFO": "YFIONE", "YFPRO": "YFPRO Finance", + "YFSX": "YFSX", "YFTE": "YFTether", "YFV": "YFValue", "YFX": "Your Futures Exchange", @@ -18952,6 +19097,7 @@ "ZFL": "Zuflo Coin", "ZFLOKI": "zkFloki", "ZFM": "ZFMCOIN", + "ZGC": "Z Generation Coin", "ZGD": "ZambesiGold", "ZGEM": "GemSwap", "ZHC": "ZHC : Zero Hour Cash", @@ -19129,11 +19275,13 @@ "分红狗头": "分红狗头", "哭哭马": "哭哭马", "安": "安", + "小龙虾": "币安小龙虾", "币安人生": "币安人生", "恶俗企鹅": "恶俗企鹅", "我踏马来了": "我踏马来了", "狗屎": "狗屎", "老子": "老子", "雪球": "雪球", - "黑马": "黑马" + "黑马": "黑马", + "龙虾": "龙虾" } From 5f232c741c7da06ed999b8cf679f0e9c58841581 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 2 Apr 2026 19:45:13 +0200 Subject: [PATCH 126/138] Task/eliminate OnDestroy lifecycle hook in subscription interstitial dialog component (#6654) Eliminate OnDestroy lifecycle hook --- ...subscription-interstitial-dialog.component.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts b/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts index 0d616b92e..d10be10bd 100644 --- a/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts +++ b/apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.component.ts @@ -7,9 +7,11 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, + DestroyRef, Inject, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, @@ -21,8 +23,8 @@ import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { arrowForwardOutline, checkmarkCircleOutline } from 'ionicons/icons'; import ms from 'ms'; -import { interval, Subject } from 'rxjs'; -import { take, takeUntil, tap } from 'rxjs/operators'; +import { interval } from 'rxjs'; +import { take, tap } from 'rxjs/operators'; import { SubscriptionInterstitialDialogParams } from './interfaces/interfaces'; @@ -51,11 +53,10 @@ export class GfSubscriptionInterstitialDialogComponent implements OnInit { public routerLinkPricing = publicRoutes.pricing.routerLink; public variantIndex: number; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, @Inject(MAT_DIALOG_DATA) public data: SubscriptionInterstitialDialogParams, + private destroyRef: DestroyRef, public dialogRef: MatDialogRef ) { this.variantIndex = Math.floor( @@ -76,7 +77,7 @@ export class GfSubscriptionInterstitialDialogComponent implements OnInit { this.changeDetectorRef.markForCheck(); }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(); } @@ -84,9 +85,4 @@ export class GfSubscriptionInterstitialDialogComponent implements OnInit { public closeDialog() { this.dialogRef.close({}); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 6da77e6417a3f85eb6dd533c5f2ce72ad2a40c02 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 2 Apr 2026 19:45:53 +0200 Subject: [PATCH 127/138] Task/eliminate OnDestroy lifecycle hook in pricing page component (#6657) Eliminate OnDestroy lifecycle hook --- .../pages/pricing/pricing-page.component.ts | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/apps/client/src/app/pages/pricing/pricing-page.component.ts b/apps/client/src/app/pages/pricing/pricing-page.component.ts index 831f0809c..08c561fc8 100644 --- a/apps/client/src/app/pages/pricing/pricing-page.component.ts +++ b/apps/client/src/app/pages/pricing/pricing-page.component.ts @@ -12,9 +12,10 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatTooltipModule } from '@angular/material/tooltip'; @@ -27,8 +28,8 @@ import { informationCircleOutline } from 'ionicons/icons'; import { StringValue } from 'ms'; -import { EMPTY, Subject } from 'rxjs'; -import { catchError, takeUntil } from 'rxjs/operators'; +import { EMPTY } from 'rxjs'; +import { catchError } from 'rxjs/operators'; @Component({ host: { class: 'page' }, @@ -46,7 +47,7 @@ import { catchError, takeUntil } from 'rxjs/operators'; styleUrls: ['./pricing-page.scss'], templateUrl: './pricing-page.html' }) -export class GfPricingPageComponent implements OnDestroy, OnInit { +export class GfPricingPageComponent implements OnInit { public baseCurrency: string; public coupon: number; public couponId: string; @@ -92,11 +93,10 @@ export class GfPricingPageComponent implements OnDestroy, OnInit { public routerLinkRegister = publicRoutes.register.routerLink; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private notificationService: NotificationService, private userService: UserService ) { @@ -124,7 +124,7 @@ export class GfPricingPageComponent implements OnDestroy, OnInit { this.price = subscriptionOffer?.price; this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -161,15 +161,10 @@ export class GfPricingPageComponent implements OnDestroy, OnInit { return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(({ sessionUrl }) => { window.location.href = sessionUrl; }); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From c9499408e35cf74860d0a1f306088d980e4d54a5 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 2 Apr 2026 19:46:45 +0200 Subject: [PATCH 128/138] Task/eliminate OnDestroy lifecycle hook in user account membership component (#6655) Eliminate OnDestroy lifecycle hook --- .../user-account-membership.component.ts | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts index 92fd0d590..b13a983fc 100644 --- a/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts +++ b/apps/client/src/app/components/user-account-membership/user-account-membership.component.ts @@ -14,15 +14,16 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, - OnDestroy + DestroyRef } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatSnackBar } from '@angular/material/snack-bar'; import { RouterModule } from '@angular/router'; import ms, { StringValue } from 'ms'; -import { EMPTY, Subject } from 'rxjs'; -import { catchError, takeUntil } from 'rxjs/operators'; +import { EMPTY } from 'rxjs'; +import { catchError } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -38,7 +39,7 @@ import { catchError, takeUntil } from 'rxjs/operators'; styleUrls: ['./user-account-membership.scss'], templateUrl: './user-account-membership.html' }) -export class GfUserAccountMembershipComponent implements OnDestroy { +export class GfUserAccountMembershipComponent { public baseCurrency: string; public coupon: number; public couponId: string; @@ -54,11 +55,10 @@ export class GfUserAccountMembershipComponent implements OnDestroy { '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; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private notificationService: NotificationService, private snackBar: MatSnackBar, private userService: UserService @@ -73,7 +73,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy { ); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -118,7 +118,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy { return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(({ sessionUrl }) => { window.location.href = sessionUrl; @@ -142,7 +142,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy { return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(({ apiKey }) => { this.notificationService.alert({ @@ -180,7 +180,7 @@ export class GfUserAccountMembershipComponent implements OnDestroy { return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(() => { const snackBarRef = this.snackBar.open( @@ -193,14 +193,14 @@ export class GfUserAccountMembershipComponent implements OnDestroy { snackBarRef .afterDismissed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { window.location.reload(); }); snackBarRef .onAction() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { window.location.reload(); }); @@ -210,9 +210,4 @@ export class GfUserAccountMembershipComponent implements OnDestroy { title: $localize`Please enter your coupon code.` }); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From e934cc4224a4ef8025705c2ab203db57e51ba636 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 2 Apr 2026 19:49:26 +0200 Subject: [PATCH 129/138] Release 2.252.0 (#6658) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aabb98610..d3984ca7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.252.0 - 2026-03-02 ### Added diff --git a/package-lock.json b/package-lock.json index 1f4295a6a..49974055d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.251.0", + "version": "2.252.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.251.0", + "version": "2.252.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index b7f9bc2e7..cf5787a4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.251.0", + "version": "2.252.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From 3ad4428604e395a4d2b480c5763f675e044f8df5 Mon Sep 17 00:00:00 2001 From: Trevin Chow Date: Thu, 2 Apr 2026 23:49:14 -0700 Subject: [PATCH 130/138] Feature/eliminate OnDestroy lifecycle hook from markets page component (#6653) Eliminate OnDestroy lifecycle hook --- .../src/app/pages/markets/markets-page.component.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/client/src/app/pages/markets/markets-page.component.ts b/apps/client/src/app/pages/markets/markets-page.component.ts index 1ab97c3e0..c70cb8120 100644 --- a/apps/client/src/app/pages/markets/markets-page.component.ts +++ b/apps/client/src/app/pages/markets/markets-page.component.ts @@ -1,7 +1,6 @@ import { GfHomeMarketComponent } from '@ghostfolio/client/components/home-market/home-market.component'; -import { Component, OnDestroy } from '@angular/core'; -import { Subject } from 'rxjs'; +import { Component } from '@angular/core'; @Component({ host: { class: 'page' }, @@ -10,11 +9,4 @@ import { Subject } from 'rxjs'; styleUrls: ['./markets-page.scss'], templateUrl: './markets-page.html' }) -export class GfMarketsPageComponent implements OnDestroy { - private unsubscribeSubject = new Subject(); - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } -} +export class GfMarketsPageComponent {} From 2d2259a0f5a942d41b7ca1a6fec14681ca56fc74 Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 3 Apr 2026 08:50:58 +0200 Subject: [PATCH 131/138] Task/eliminate OnDestroy lifecycle hook from home watchlist component (#6659) Eliminate OnDestroy lifecycle hook --- .../home-watchlist.component.ts | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts b/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts index 4adb4e54f..e6f366351 100644 --- a/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts +++ b/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts @@ -15,9 +15,10 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router, RouterModule } from '@angular/router'; @@ -25,8 +26,6 @@ import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { addOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; import { GfCreateWatchlistItemDialogComponent } from './create-watchlist-item-dialog/create-watchlist-item-dialog.component'; import { CreateWatchlistItemDialogParams } from './create-watchlist-item-dialog/interfaces/interfaces'; @@ -45,7 +44,7 @@ import { CreateWatchlistItemDialogParams } from './create-watchlist-item-dialog/ styleUrls: ['./home-watchlist.scss'], templateUrl: './home-watchlist.html' }) -export class GfHomeWatchlistComponent implements OnDestroy, OnInit { +export class GfHomeWatchlistComponent implements OnInit { public deviceType: string; public hasImpersonationId: boolean; public hasPermissionToCreateWatchlistItem: boolean; @@ -53,11 +52,10 @@ export class GfHomeWatchlistComponent implements OnDestroy, OnInit { public user: User; public watchlist: Benchmark[]; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private dialog: MatDialog, private impersonationStorageService: ImpersonationStorageService, @@ -69,13 +67,13 @@ export class GfHomeWatchlistComponent implements OnDestroy, OnInit { this.impersonationStorageService .onChangeHasImpersonation() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { this.hasImpersonationId = !!impersonationId; }); this.route.queryParams - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((params) => { if (params['createWatchlistItemDialog']) { this.openCreateWatchlistItemDialog(); @@ -83,7 +81,7 @@ export class GfHomeWatchlistComponent implements OnDestroy, OnInit { }); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -118,7 +116,7 @@ export class GfHomeWatchlistComponent implements OnDestroy, OnInit { }: AssetProfileIdentifier) { this.dataService .deleteWatchlistItem({ dataSource, symbol }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe({ next: () => { return this.loadWatchlistData(); @@ -126,15 +124,10 @@ export class GfHomeWatchlistComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private loadWatchlistData() { this.dataService .fetchWatchlist() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ watchlist }) => { this.watchlist = watchlist; @@ -145,7 +138,7 @@ export class GfHomeWatchlistComponent implements OnDestroy, OnInit { private openCreateWatchlistItemDialog() { this.userService .get() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -163,12 +156,12 @@ export class GfHomeWatchlistComponent implements OnDestroy, OnInit { dialogRef .afterClosed() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ dataSource, symbol } = {}) => { if (dataSource && symbol) { this.dataService .postWatchlistItem({ dataSource, symbol }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe({ next: () => this.loadWatchlistData() }); From 33ff0403ea457a34983845d21743b03f1535ca7d Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 3 Apr 2026 08:52:50 +0200 Subject: [PATCH 132/138] Task/eliminate OnDestroy lifecycle hook from user account settings component (#6661) Eliminate OnDestroy lifecycle hook --- .../user-account-settings.component.ts | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts index 0cf18df36..72bbfc2c6 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -18,9 +18,10 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormBuilder, FormsModule, @@ -43,8 +44,8 @@ import { format, parseISO } from 'date-fns'; import { addIcons } from 'ionicons'; import { eyeOffOutline, eyeOutline } from 'ionicons/icons'; import ms from 'ms'; -import { EMPTY, Subject, throwError } from 'rxjs'; -import { catchError, takeUntil } from 'rxjs/operators'; +import { EMPTY, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -65,7 +66,7 @@ import { catchError, takeUntil } from 'rxjs/operators'; styleUrls: ['./user-account-settings.scss'], templateUrl: './user-account-settings.html' }) -export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { +export class GfUserAccountSettingsComponent implements OnInit { public appearancePlaceholder = $localize`Auto`; public baseCurrency: string; public currencies: string[] = []; @@ -98,11 +99,10 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { ]; public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private formBuilder: FormBuilder, private notificationService: NotificationService, private settingsStorageService: SettingsStorageService, @@ -116,7 +116,7 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { this.currencies = currencies; this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -157,11 +157,11 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { public onChangeUserSetting(aKey: string, aValue: string) { this.dataService .putUserSetting({ [aKey]: aValue }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -193,7 +193,7 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(() => { this.userService.signOut(); @@ -209,11 +209,11 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { public onExperimentalFeaturesChange(aEvent: MatSlideToggleChange) { this.dataService .putUserSetting({ isExperimentalFeatures: aEvent.checked }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -225,7 +225,7 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { public onExport() { this.dataService .fetchExport() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((data) => { for (const activity of data.activities) { delete activity.id; @@ -245,11 +245,11 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { public onRestrictedViewChange(aEvent: MatSlideToggleChange) { this.dataService .putUserSetting({ isRestrictedView: aEvent.checked }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -284,11 +284,11 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { public onViewModeChange(aEvent: MatSlideToggleChange) { this.dataService .putUserSetting({ viewMode: aEvent.checked === true ? 'ZEN' : 'DEFAULT' }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.userService .get(true) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((user) => { this.user = user; @@ -297,11 +297,6 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private deregisterDevice() { this.webAuthnService .deregister() @@ -311,7 +306,7 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(() => { this.update(); @@ -341,7 +336,7 @@ export class GfUserAccountSettingsComponent implements OnDestroy, OnInit { return error; }); }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe({ next: () => { From ebae16c36b1e457e3339a7c27e98476cd1fc8d4a Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 3 Apr 2026 08:55:14 +0200 Subject: [PATCH 133/138] Task/eliminate OnDestroy lifecycle hook from user account access component (#6660) Eliminate OnDestroy lifecycle hook --- ...reate-or-update-access-dialog.component.ts | 21 +++++---------- .../user-account-access.component.ts | 27 ++++++++----------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts b/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts index 5c87b2f63..a4fadeecf 100644 --- a/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts +++ b/apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts @@ -7,10 +7,11 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, Inject, - OnDestroy, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormBuilder, FormGroup, @@ -28,7 +29,7 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { StatusCodes } from 'http-status-codes'; -import { EMPTY, Subject, catchError, takeUntil } from 'rxjs'; +import { EMPTY, catchError } from 'rxjs'; import { CreateOrUpdateAccessDialogParams } from './interfaces/interfaces'; @@ -48,19 +49,16 @@ import { CreateOrUpdateAccessDialogParams } from './interfaces/interfaces'; styleUrls: ['./create-or-update-access-dialog.scss'], templateUrl: 'create-or-update-access-dialog.html' }) -export class GfCreateOrUpdateAccessDialogComponent - implements OnDestroy, OnInit -{ +export class GfCreateOrUpdateAccessDialogComponent implements OnInit { public accessForm: FormGroup; public mode: 'create' | 'update'; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, @Inject(MAT_DIALOG_DATA) private data: CreateOrUpdateAccessDialogParams, public dialogRef: MatDialogRef, private dataService: DataService, + private destroyRef: DestroyRef, private formBuilder: FormBuilder, private notificationService: NotificationService ) { @@ -113,11 +111,6 @@ export class GfCreateOrUpdateAccessDialogComponent } } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private async createAccess() { const access: CreateAccessDto = { alias: this.accessForm.get('alias').value, @@ -144,7 +137,7 @@ export class GfCreateOrUpdateAccessDialogComponent return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(() => { this.dialogRef.close(access); @@ -181,7 +174,7 @@ export class GfCreateOrUpdateAccessDialogComponent return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(() => { this.dialogRef.close(access); diff --git a/apps/client/src/app/components/user-account-access/user-account-access.component.ts b/apps/client/src/app/components/user-account-access/user-account-access.component.ts index 4f744a087..4ca088775 100644 --- a/apps/client/src/app/components/user-account-access/user-account-access.component.ts +++ b/apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -13,9 +13,10 @@ import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, - OnDestroy, + DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; @@ -26,8 +27,8 @@ import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { addOutline, eyeOffOutline, eyeOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; -import { EMPTY, Subject } from 'rxjs'; -import { catchError, takeUntil } from 'rxjs/operators'; +import { EMPTY } from 'rxjs'; +import { catchError } from 'rxjs/operators'; import { GfCreateOrUpdateAccessDialogComponent } from './create-or-update-access-dialog/create-or-update-access-dialog.component'; import { CreateOrUpdateAccessDialogParams } from './create-or-update-access-dialog/interfaces/interfaces'; @@ -51,7 +52,7 @@ import { CreateOrUpdateAccessDialogParams } from './create-or-update-access-dial styleUrls: ['./user-account-access.scss'], templateUrl: './user-account-access.html' }) -export class GfUserAccountAccessComponent implements OnDestroy, OnInit { +export class GfUserAccountAccessComponent implements OnInit { public accessesGet: Access[]; public accessesGive: Access[]; public deviceType: string; @@ -64,11 +65,10 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { }); public user: User; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, private deviceService: DeviceDetectorService, private dialog: MatDialog, private formBuilder: FormBuilder, @@ -85,7 +85,7 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { ); this.userService.stateChanged - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((state) => { if (state?.user) { this.user = state.user; @@ -110,7 +110,7 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { }); this.route.queryParams - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((params) => { if (params['createDialog']) { this.openCreateAccessDialog(); @@ -131,7 +131,7 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { public onDeleteAccess(aId: string) { this.dataService .deleteAccess(aId) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe({ next: () => { this.update(); @@ -154,7 +154,7 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { return EMPTY; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ) .subscribe(({ accessToken }) => { this.notificationService.alert({ @@ -179,11 +179,6 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private openCreateAccessDialog() { const dialogRef = this.dialog.open< GfCreateOrUpdateAccessDialogComponent, @@ -261,7 +256,7 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { this.dataService .fetchAccesses() - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((accesses) => { this.accessesGive = accesses; From 6f86505c8feb63d6bd3d8981ccb500689c476b50 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:41:24 +0200 Subject: [PATCH 134/138] Task/eliminate OnDestroy lifecycle hook in API page component (#6656) Eliminate OnDestroy lifecycle hook --- .../src/app/pages/api/api-page.component.ts | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/apps/client/src/app/pages/api/api-page.component.ts b/apps/client/src/app/pages/api/api-page.component.ts index 353605380..357a08bbd 100644 --- a/apps/client/src/app/pages/api/api-page.component.ts +++ b/apps/client/src/app/pages/api/api-page.component.ts @@ -14,9 +14,10 @@ import { import { CommonModule } from '@angular/common'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { Component, OnInit } from '@angular/core'; +import { Component, DestroyRef, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { format, startOfYear } from 'date-fns'; -import { map, Observable, Subject, takeUntil } from 'rxjs'; +import { map, Observable } from 'rxjs'; @Component({ host: { class: 'page' }, @@ -35,9 +36,11 @@ export class GfApiPageComponent implements OnInit { public status$: Observable; private apiKey: string; - private unsubscribeSubject = new Subject(); - public constructor(private http: HttpClient) {} + public constructor( + private destroyRef: DestroyRef, + private http: HttpClient + ) {} public ngOnInit() { this.apiKey = prompt($localize`Please enter your Ghostfolio API key:`); @@ -51,18 +54,13 @@ export class GfApiPageComponent implements OnInit { this.status$ = this.fetchStatus(); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private fetchAssetProfile({ symbol }: { symbol: string }) { return this.http .get( `/api/v1/data-providers/ghostfolio/asset-profile/${symbol}`, { headers: this.getHeaders() } ) - .pipe(takeUntil(this.unsubscribeSubject)); + .pipe(takeUntilDestroyed(this.destroyRef)); } private fetchDividends({ symbol }: { symbol: string }) { @@ -82,7 +80,7 @@ export class GfApiPageComponent implements OnInit { map(({ dividends }) => { return dividends; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ); } @@ -103,7 +101,7 @@ export class GfApiPageComponent implements OnInit { map(({ historicalData }) => { return historicalData; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ); } @@ -129,7 +127,7 @@ export class GfApiPageComponent implements OnInit { map(({ items }) => { return items; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ); } @@ -145,7 +143,7 @@ export class GfApiPageComponent implements OnInit { map(({ quotes }) => { return quotes; }), - takeUntil(this.unsubscribeSubject) + takeUntilDestroyed(this.destroyRef) ); } @@ -155,7 +153,7 @@ export class GfApiPageComponent implements OnInit { '/api/v2/data-providers/ghostfolio/status', { headers: this.getHeaders() } ) - .pipe(takeUntil(this.unsubscribeSubject)); + .pipe(takeUntilDestroyed(this.destroyRef)); } private getHeaders() { From c311d835fadc3b34713095b4ad51a3a0167e0182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20TISON?= <13355624+Airthee@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:45:02 +0200 Subject: [PATCH 135/138] Feature/add type filter to activities table component (#6622) * Add type filter * Update changelog --------- Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> --- CHANGELOG.md | 6 + .../app/activities/activities.controller.ts | 7 +- .../src/app/activities/activities.service.ts | 2 +- apps/api/src/app/export/export.controller.ts | 5 + apps/api/src/app/export/export.service.ts | 5 +- .../activities/activities-page.component.ts | 18 ++- .../portfolio/activities/activities-page.html | 2 + .../activities-table.component.html | 134 +++++++++++------- .../activities-table.component.ts | 27 +++- libs/ui/src/lib/services/data.service.ts | 12 ++ .../migration.sql | 2 + prisma/schema.prisma | 1 + 12 files changed, 161 insertions(+), 60 deletions(-) create mode 100644 prisma/migrations/20260321200654_added_index_for_type_to_order/migration.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index d3984ca7f..53461fd8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Added support for filtering by activity type on the activities page (experimental) + ## 2.252.0 - 2026-03-02 ### Added diff --git a/apps/api/src/app/activities/activities.controller.ts b/apps/api/src/app/activities/activities.controller.ts index 141fd4c82..6b0440dc4 100644 --- a/apps/api/src/app/activities/activities.controller.ts +++ b/apps/api/src/app/activities/activities.controller.ts @@ -37,7 +37,7 @@ import { } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; -import { Order, Prisma } from '@prisma/client'; +import { Order, Prisma, Type as ActivityType } from '@prisma/client'; import { parseISO } from 'date-fns'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; @@ -112,6 +112,7 @@ export class ActivitiesController { public async getAllActivities( @Headers(HEADER_KEY_IMPERSONATION.toLowerCase()) impersonationId: string, @Query('accounts') filterByAccounts?: string, + @Query('activityTypes') filterByTypes?: string, @Query('assetClasses') filterByAssetClasses?: string, @Query('dataSource') filterByDataSource?: string, @Query('range') dateRange?: DateRange, @@ -139,6 +140,9 @@ export class ActivitiesController { const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); + + const types = (filterByTypes?.split(',') as ActivityType[]) ?? []; + const userCurrency = this.request.user.settings.settings.baseCurrency; const { activities, count } = await this.activitiesService.getActivities({ @@ -147,6 +151,7 @@ export class ActivitiesController { sortColumn, sortDirection, startDate, + types, userCurrency, includeDrafts: true, skip: isNaN(skip) ? undefined : skip, diff --git a/apps/api/src/app/activities/activities.service.ts b/apps/api/src/app/activities/activities.service.ts index 89b9468f8..58b9c11a4 100644 --- a/apps/api/src/app/activities/activities.service.ts +++ b/apps/api/src/app/activities/activities.service.ts @@ -629,7 +629,7 @@ export class ActivitiesService { orderBy = [{ [sortColumn]: sortDirection }]; } - if (types) { + if (types?.length > 0) { where.type = { in: types }; } diff --git a/apps/api/src/app/export/export.controller.ts b/apps/api/src/app/export/export.controller.ts index 6fda8f17f..4f4f4e6dd 100644 --- a/apps/api/src/app/export/export.controller.ts +++ b/apps/api/src/app/export/export.controller.ts @@ -15,6 +15,7 @@ import { } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; +import { Type as ActivityType } from '@prisma/client'; import { ExportService } from './export.service'; @@ -33,12 +34,15 @@ export class ExportController { public async export( @Query('accounts') filterByAccounts?: string, @Query('activityIds') filterByActivityIds?: string, + @Query('activityTypes') filterByTypes?: string, @Query('assetClasses') filterByAssetClasses?: string, @Query('dataSource') filterByDataSource?: string, @Query('symbol') filterBySymbol?: string, @Query('tags') filterByTags?: string ): Promise { const activityIds = filterByActivityIds?.split(',') ?? []; + const activityTypes = (filterByTypes?.split(',') as ActivityType[]) ?? []; + const filters = this.apiService.buildFiltersFromQueryParams({ filterByAccounts, filterByAssetClasses, @@ -49,6 +53,7 @@ export class ExportController { return this.exportService.export({ activityIds, + activityTypes, filters, userId: this.request.user.id, userSettings: this.request.user.settings.settings diff --git a/apps/api/src/app/export/export.service.ts b/apps/api/src/app/export/export.service.ts index 4f2fb3309..4da942cd7 100644 --- a/apps/api/src/app/export/export.service.ts +++ b/apps/api/src/app/export/export.service.ts @@ -10,7 +10,7 @@ import { } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; -import { Platform, Prisma } from '@prisma/client'; +import { Platform, Prisma, Type as ActivityType } from '@prisma/client'; import { groupBy, uniqBy } from 'lodash'; @Injectable() @@ -24,11 +24,13 @@ export class ExportService { public async export({ activityIds, + activityTypes, filters, userId, userSettings }: { activityIds?: string[]; + activityTypes?: ActivityType[]; filters?: Filter[]; userId: string; userSettings: UserSettings; @@ -44,6 +46,7 @@ export class ExportService { includeDrafts: true, sortColumn: 'date', sortDirection: 'asc', + types: activityTypes, userCurrency: userSettings?.baseCurrency, withExcludedAccountsAndActivities: true }); diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts index b9dc9077c..faadef54f 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts @@ -54,6 +54,7 @@ import { ImportActivitiesDialogParams } from './import-activities-dialog/interfa templateUrl: './activities-page.html' }) export class GfActivitiesPageComponent implements OnInit { + public activityTypesFilter: string[] = []; public dataSource: MatTableDataSource; public deviceType: string; public hasImpersonationId: boolean; @@ -141,6 +142,9 @@ export class GfActivitiesPageComponent implements OnInit { this.dataService .fetchActivities({ range, + activityTypes: this.activityTypesFilter.length + ? this.activityTypesFilter + : undefined, filters: this.userService.getFilters(), skip: this.pageIndex * this.pageSize, sortColumn: this.sortColumn, @@ -217,7 +221,12 @@ export class GfActivitiesPageComponent implements OnInit { let fetchExportParams: any = { activityIds }; if (!activityIds) { - fetchExportParams = { filters: this.userService.getFilters() }; + fetchExportParams = { + activityTypes: this.activityTypesFilter.length + ? this.activityTypesFilter + : undefined, + filters: this.userService.getFilters() + }; } this.dataService @@ -318,6 +327,13 @@ export class GfActivitiesPageComponent implements OnInit { this.fetchActivities(); } + public onTypesFilterChanged(aTypes: string[]) { + this.activityTypesFilter = aTypes; + this.pageIndex = 0; + + this.fetchActivities(); + } + public onUpdateActivity(aActivity: Activity) { this.router.navigate([], { queryParams: { activityId: aActivity.id, editDialog: true } diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.html b/apps/client/src/app/pages/portfolio/activities/activities-page.html index 80ad71b79..2a72dcfd2 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.html +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.html @@ -10,6 +10,7 @@ [hasPermissionToCreateActivity]="hasPermissionToCreateActivity" [hasPermissionToDeleteActivity]="hasPermissionToDeleteActivity" [hasPermissionToExportActivities]="!hasImpersonationId" + [hasPermissionToFilterByType]="user?.settings?.isExperimentalFeatures" [locale]="user?.settings?.locale" [pageIndex]="pageIndex" [pageSize]="pageSize" @@ -32,6 +33,7 @@ (importDividends)="onImportDividends()" (pageChanged)="onChangePage($event)" (sortChanged)="onSortChanged($event)" + (typesFilterChanged)="onTypesFilterChanged($event)" />
diff --git a/libs/ui/src/lib/activities-table/activities-table.component.html b/libs/ui/src/lib/activities-table/activities-table.component.html index bdb1e6373..b8fe962d7 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -1,77 +1,101 @@ -@if (hasPermissionToCreateActivity) { -
- - @if (hasPermissionToExportActivities) { - +
+
+ @if (hasPermissionToFilterByType) { + + Type + + @for ( + activityType of activityTypesTranslationMap | keyvalue; + track activityType.key + ) { + + {{ activityType.value }} + + } + + } - +
+ + @if (hasPermissionToCreateActivity) { +
@if (hasPermissionToExportActivities) { + } + + - } - @if (hasPermissionToExportActivities) { + @if (hasPermissionToExportActivities) { + + } + @if (hasPermissionToExportActivities) { + + } +
- } -
- -
-
-} + +
+ } +
(); @Output() selectedActivities = new EventEmitter(); @Output() sortChanged = new EventEmitter(); + @Output() typesFilterChanged = new EventEmitter(); @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; + public activityTypesTranslationMap = new Map(); public hasDrafts = false; public hasErrors = false; public isUUID = isUUID; public selectedRows = new SelectionModel(true, []); + public typesFilter = new FormControl([]); public readonly dataSource = input.required< MatTableDataSource | undefined @@ -189,6 +201,13 @@ export class GfActivitiesTableComponent private readonly unsubscribeSubject = new Subject(); public constructor() { + for (const type of Object.keys(ActivityType) as ActivityType[]) { + this.activityTypesTranslationMap.set( + ActivityType[type], + translate(ActivityType[type]) + ); + } + addIcons({ alertCircleOutline, calendarClearOutline, @@ -214,6 +233,12 @@ export class GfActivitiesTableComponent this.selectedActivities.emit(selectedRows.source.selected); }); } + + this.typesFilter.valueChanges + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe((types) => { + this.typesFilterChanged.emit(types ?? []); + }); } public ngAfterViewInit() { diff --git a/libs/ui/src/lib/services/data.service.ts b/libs/ui/src/lib/services/data.service.ts index f3e3fb81f..7f2dac0b1 100644 --- a/libs/ui/src/lib/services/data.service.ts +++ b/libs/ui/src/lib/services/data.service.ts @@ -209,6 +209,7 @@ export class DataService { } public fetchActivities({ + activityTypes, filters, range, skip, @@ -216,6 +217,7 @@ export class DataService { sortDirection, take }: { + activityTypes?: string[]; filters?: Filter[]; range?: DateRange; skip?: number; @@ -225,6 +227,10 @@ export class DataService { }): Observable { let params = this.buildFiltersAsQueryParams({ filters }); + if (activityTypes?.length) { + params = params.append('activityTypes', activityTypes.join(',')); + } + if (range) { params = params.append('range', range); } @@ -411,9 +417,11 @@ export class DataService { public fetchExport({ activityIds, + activityTypes, filters }: { activityIds?: string[]; + activityTypes?: string[]; filters?: Filter[]; } = {}) { let params = this.buildFiltersAsQueryParams({ filters }); @@ -422,6 +430,10 @@ export class DataService { params = params.append('activityIds', activityIds.join(',')); } + if (activityTypes?.length) { + params = params.append('activityTypes', activityTypes.join(',')); + } + return this.http.get('/api/v1/export', { params }); diff --git a/prisma/migrations/20260321200654_added_index_for_type_to_order/migration.sql b/prisma/migrations/20260321200654_added_index_for_type_to_order/migration.sql new file mode 100644 index 000000000..ba4d1b1ff --- /dev/null +++ b/prisma/migrations/20260321200654_added_index_for_type_to_order/migration.sql @@ -0,0 +1,2 @@ +-- CreateIndex +CREATE INDEX "Order_type_idx" ON "Order"("type"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 232dde9ca..50aac91fb 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -158,6 +158,7 @@ model Order { @@index([accountId]) @@index([date]) @@index([isDraft]) + @@index([type]) @@index([userId]) } From 1b26b6ced04b5eaa50317b087163e9dbeaf34d04 Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 3 Apr 2026 16:57:19 +0200 Subject: [PATCH 136/138] Task/eliminate OnDestroy lifecycle hook from activities table page (#6672) Eliminate OnDestroy lifecycle hook --- .../activities-table.component.ts | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/libs/ui/src/lib/activities-table/activities-table.component.ts b/libs/ui/src/lib/activities-table/activities-table.component.ts index 4d88960b9..ffc07f09c 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.ts +++ b/libs/ui/src/lib/activities-table/activities-table.component.ts @@ -20,9 +20,9 @@ import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, + DestroyRef, EventEmitter, Input, - OnDestroy, OnInit, Output, ViewChild, @@ -30,6 +30,7 @@ import { inject, input } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; @@ -68,7 +69,6 @@ import { trashOutline } from 'ionicons/icons'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; -import { Subject, takeUntil } from 'rxjs'; import { GfActivityTypeComponent } from '../activity-type/activity-type.component'; import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component'; @@ -102,9 +102,7 @@ import { GfValueComponent } from '../value/value.component'; styleUrls: ['./activities-table.component.scss'], templateUrl: './activities-table.component.html' }) -export class GfActivitiesTableComponent - implements AfterViewInit, OnDestroy, OnInit -{ +export class GfActivitiesTableComponent implements AfterViewInit, OnInit { @Input() baseCurrency: string; @Input() deviceType: string; @Input() hasActivities: boolean; @@ -198,9 +196,8 @@ export class GfActivitiesTableComponent }); private readonly notificationService = inject(NotificationService); - private readonly unsubscribeSubject = new Subject(); - public constructor() { + public constructor(private destroyRef: DestroyRef) { for (const type of Object.keys(ActivityType) as ActivityType[]) { this.activityTypesTranslationMap.set( ActivityType[type], @@ -228,14 +225,14 @@ export class GfActivitiesTableComponent if (this.showCheckbox()) { this.toggleAllRows(); this.selectedRows.changed - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((selectedRows) => { this.selectedActivities.emit(selectedRows.source.selected); }); } this.typesFilter.valueChanges - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((types) => { this.typesFilterChanged.emit(types ?? []); }); @@ -367,9 +364,4 @@ export class GfActivitiesTableComponent this.selectedActivities.emit(this.selectedRows.selected); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 875f173c34ecdec91d632389dfbeac0ae17779b3 Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:01:51 +0200 Subject: [PATCH 137/138] Task/eliminate OnDestroy lifecycle hook from benchmark detail dialog component (#6675) Eliminate OnDestroy lifecycle hook --- .../benchmark-detail-dialog.component.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.component.ts b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.component.ts index 2f4c18288..0c75b5954 100644 --- a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.component.ts +++ b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.component.ts @@ -12,18 +12,17 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + DestroyRef, Inject, - OnDestroy, OnInit } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { format } from 'date-fns'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; import { GfLineChartComponent } from '../../line-chart/line-chart.component'; import { GfValueComponent } from '../../value/value.component'; @@ -44,16 +43,15 @@ import { BenchmarkDetailDialogParams } from './interfaces/interfaces'; styleUrls: ['./benchmark-detail-dialog.component.scss'], templateUrl: 'benchmark-detail-dialog.html' }) -export class GfBenchmarkDetailDialogComponent implements OnDestroy, OnInit { +export class GfBenchmarkDetailDialogComponent implements OnInit { public assetProfile: AdminMarketDataDetails['assetProfile']; public historicalDataItems: LineChartItem[]; public value: number; - private unsubscribeSubject = new Subject(); - public constructor( private changeDetectorRef: ChangeDetectorRef, private dataService: DataService, + private destroyRef: DestroyRef, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: BenchmarkDetailDialogParams ) {} @@ -64,7 +62,7 @@ export class GfBenchmarkDetailDialogComponent implements OnDestroy, OnInit { dataSource: this.data.dataSource, symbol: this.data.symbol }) - .pipe(takeUntil(this.unsubscribeSubject)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ assetProfile, marketData }) => { this.assetProfile = assetProfile; @@ -88,9 +86,4 @@ export class GfBenchmarkDetailDialogComponent implements OnDestroy, OnInit { public onClose() { this.dialogRef.close(); } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } } From 2cdfeb84d6768523ea8994a31b922ace16831836 Mon Sep 17 00:00:00 2001 From: Erwin <111194281+Erwin-N@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:03:26 +0200 Subject: [PATCH 138/138] Task/eliminate OnDestroy lifecycle hook from create watchlist item dialog component (#6676) Eliminate OnDestroy lifecycle hook --- .../create-watchlist-item-dialog.component.ts | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.component.ts b/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.component.ts index 60d74be92..4669a827d 100644 --- a/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.component.ts +++ b/apps/client/src/app/components/home-watchlist/create-watchlist-item-dialog/create-watchlist-item-dialog.component.ts @@ -1,11 +1,6 @@ import { GfSymbolAutocompleteComponent } from '@ghostfolio/ui/symbol-autocomplete'; -import { - ChangeDetectionStrategy, - Component, - OnDestroy, - OnInit -} from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { AbstractControl, FormBuilder, @@ -19,7 +14,6 @@ import { import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; -import { Subject } from 'rxjs'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -36,11 +30,9 @@ import { Subject } from 'rxjs'; styleUrls: ['./create-watchlist-item-dialog.component.scss'], templateUrl: 'create-watchlist-item-dialog.html' }) -export class GfCreateWatchlistItemDialogComponent implements OnDestroy, OnInit { +export class GfCreateWatchlistItemDialogComponent implements OnInit { public createWatchlistItemForm: FormGroup; - private unsubscribeSubject = new Subject(); - public constructor( public readonly dialogRef: MatDialogRef, public readonly formBuilder: FormBuilder @@ -69,11 +61,6 @@ export class GfCreateWatchlistItemDialogComponent implements OnDestroy, OnInit { }); } - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } - private validator(control: AbstractControl): ValidationErrors { const searchSymbolControl = control.get('searchSymbol');