From b2698fccbd4ff1f90f9ae554da6c0dd15eaf6005 Mon Sep 17 00:00:00 2001
From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
Date: Wed, 19 Feb 2025 17:25:54 +0100
Subject: [PATCH 01/14] Feature/improve validation of currency management in
admin control panel (#4334)
* Improve validation of currency management
* Update changelog
---
CHANGELOG.md | 1 +
.../market-data/market-data.controller.ts | 5 ++--
.../create-asset-profile-dialog.component.ts | 29 ++++++++++++-------
.../admin-overview.component.ts | 19 ------------
.../admin-overview/admin-overview.html | 10 -------
.../faq/self-hosting/self-hosting-page.html | 5 ++++
6 files changed, 27 insertions(+), 42 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5af20d2f..d6580eb33 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
- Reloaded the available tags after creating a custom tag in the holding detail dialog (experimental)
+- Improved the validation of the currency management in the admin control panel
- Migrated the `@ghostfolio/client` components to control flow
- Migrated the `@ghostfolio/ui` components to control flow
diff --git a/apps/api/src/app/endpoints/market-data/market-data.controller.ts b/apps/api/src/app/endpoints/market-data/market-data.controller.ts
index b4aef807a..933e70e9d 100644
--- a/apps/api/src/app/endpoints/market-data/market-data.controller.ts
+++ b/apps/api/src/app/endpoints/market-data/market-data.controller.ts
@@ -1,6 +1,7 @@
import { AdminService } from '@ghostfolio/api/app/admin/admin.service';
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
+import { getCurrencyFromSymbol, isCurrency } from '@ghostfolio/common/helper';
import { MarketDataDetailsResponse } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { RequestWithUser } from '@ghostfolio/common/types';
@@ -42,7 +43,7 @@ export class MarketDataController {
{ dataSource, symbol }
]);
- if (!assetProfile) {
+ if (!assetProfile && !isCurrency(getCurrencyFromSymbol(symbol))) {
throw new HttpException(
getReasonPhrase(StatusCodes.NOT_FOUND),
StatusCodes.NOT_FOUND
@@ -55,7 +56,7 @@ export class MarketDataController {
);
const canReadOwnAssetProfile =
- assetProfile.userId === this.request.user.id &&
+ assetProfile?.userId === this.request.user.id &&
hasPermission(
this.request.user.permissions,
permissions.readMarketDataOfOwnAssetProfile
diff --git a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts
index fa5e33f10..b0f69fa5c 100644
--- a/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts
+++ b/apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.component.ts
@@ -15,9 +15,11 @@ import {
FormControl,
FormGroup,
ValidationErrors,
+ ValidatorFn,
Validators
} from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
+import { isISO4217CurrencyCode } from 'class-validator';
import { uniq } from 'lodash';
import { Subject, takeUntil } from 'rxjs';
@@ -52,9 +54,7 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy {
this.createAssetProfileForm = this.formBuilder.group(
{
addCurrency: new FormControl(null, [
- Validators.maxLength(3),
- Validators.minLength(3),
- Validators.required
+ this.iso4217CurrencyCodeValidator()
]),
addSymbol: new FormControl(null, [Validators.required]),
searchSymbol: new FormControl(null, [Validators.required])
@@ -83,11 +83,11 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy {
symbol: this.createAssetProfileForm.get('searchSymbol').value.symbol
});
} else if (this.mode === 'currency') {
- const currency = this.createAssetProfileForm
- .get('addCurrency')
- .value.toUpperCase();
+ const currency = (
+ this.createAssetProfileForm.get('addCurrency').value as string
+ ).toUpperCase();
- const currencies = uniq([...this.customCurrencies, currency]);
+ const currencies = uniq([...this.customCurrencies, currency]).sort();
this.dataService
.putAdminSetting(PROPERTY_CURRENCIES, {
@@ -109,10 +109,7 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy {
const addCurrencyFormControl =
this.createAssetProfileForm.get('addCurrency');
- if (
- addCurrencyFormControl.hasError('maxlength') ||
- addCurrencyFormControl.hasError('minlength')
- ) {
+ if (addCurrencyFormControl.hasError('invalidCurrency')) {
return true;
}
@@ -161,4 +158,14 @@ export class CreateAssetProfileDialog implements OnInit, OnDestroy {
this.changeDetectorRef.markForCheck();
});
}
+
+ private iso4217CurrencyCodeValidator(): ValidatorFn {
+ return (control: AbstractControl): ValidationErrors | null => {
+ if (!isISO4217CurrencyCode(control.value?.toUpperCase())) {
+ return { invalidCurrency: true };
+ }
+
+ return null;
+ };
+ }
}
diff --git a/apps/client/src/app/components/admin-overview/admin-overview.component.ts b/apps/client/src/app/components/admin-overview/admin-overview.component.ts
index d217f871d..f54af4174 100644
--- a/apps/client/src/app/components/admin-overview/admin-overview.component.ts
+++ b/apps/client/src/app/components/admin-overview/admin-overview.component.ts
@@ -28,7 +28,6 @@ import {
formatDistanceToNowStrict,
parseISO
} from 'date-fns';
-import { uniq } from 'lodash';
import { StringValue } from 'ms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@@ -122,24 +121,6 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
this.putAdminSetting({ key: PROPERTY_COUPONS, value: coupons });
}
- public onAddCurrency() {
- const currency = prompt($localize`Please add a currency:`);
-
- if (currency) {
- if (currency.length === 3) {
- const currencies = uniq([
- ...this.customCurrencies,
- currency.toUpperCase()
- ]);
- this.putAdminSetting({ key: PROPERTY_CURRENCIES, value: currencies });
- } else {
- this.notificationService.alert({
- title: $localize`${currency} is an invalid currency!`
- });
- }
- }
- }
-
public onChangeCouponDuration(aCouponDuration: StringValue) {
this.couponDuration = aCouponDuration;
}
diff --git a/apps/client/src/app/components/admin-overview/admin-overview.html b/apps/client/src/app/components/admin-overview/admin-overview.html
index ba8545d16..a85c32d43 100644
--- a/apps/client/src/app/components/admin-overview/admin-overview.html
+++ b/apps/client/src/app/components/admin-overview/admin-overview.html
@@ -95,16 +95,6 @@
}
-
-
-
diff --git a/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html b/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html
index 7538678c3..3b2f6f605 100644
--- a/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html
+++ b/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html
@@ -56,6 +56,11 @@
Click on the + button
Switch to Add Currency
Insert e.g. EUR
for Euro
+ Select Filter by Currencies
+ Find the entry USDEUR
+
+ Click the menu item Gather Historical Data in the dialog
+
From 46878ea5a87a49299118dae41c99c0f0dca2e520 Mon Sep 17 00:00:00 2001
From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
Date: Thu, 20 Feb 2025 17:46:10 +0100
Subject: [PATCH 02/14] Bugfix/improve error handling in http response
interceptor (#4338)
* Improve error handling
* Update changelog
---
CHANGELOG.md | 1 +
apps/client/src/app/core/http-response.interceptor.ts | 10 ++++++----
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d6580eb33..b8020def5 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
### Fixed
+- Improved the error handling in the `HttpResponseInterceptor`
- Added missing assets in _Storybook_ setup
## 2.139.1 - 2025-02-15
diff --git a/apps/client/src/app/core/http-response.interceptor.ts b/apps/client/src/app/core/http-response.interceptor.ts
index 018e441fc..62c3540f7 100644
--- a/apps/client/src/app/core/http-response.interceptor.ts
+++ b/apps/client/src/app/core/http-response.interceptor.ts
@@ -108,10 +108,12 @@ export class HttpResponseInterceptor implements HttpInterceptor {
});
}
} else if (error.status === StatusCodes.UNAUTHORIZED) {
- if (this.webAuthnService.isEnabled()) {
- this.router.navigate(['/webauthn']);
- } else if (!error.url.includes('/data-providers/ghostfolio/status')) {
- this.tokenStorageService.signOut();
+ if (!error.url.includes('/data-providers/ghostfolio/status')) {
+ if (this.webAuthnService.isEnabled()) {
+ this.router.navigate(['/webauthn']);
+ } else {
+ this.tokenStorageService.signOut();
+ }
}
}
From 69a0de28cd9afe11e6c0412fff979ee7dce1f84f Mon Sep 17 00:00:00 2001
From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
Date: Thu, 20 Feb 2025 19:40:27 +0100
Subject: [PATCH 03/14] Bugfix/fix issue with symbol profile overrides in
historical market data table of admin control panel (#4339)
* Respect symbol profile overrides in market data controller (GET)
* Update changelog
---
CHANGELOG.md | 1 +
apps/api/src/app/admin/admin.service.ts | 40 ++++++++++++++++---
.../symbol-profile/symbol-profile.service.ts | 11 +++--
3 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8020def5..ed9e778f6 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
### Fixed
- Improved the error handling in the `HttpResponseInterceptor`
+- Fixed an issue while using symbol profile overrides in the historical market data table of the admin control panel
- Added missing assets in _Storybook_ setup
## 2.139.1 - 2025-02-15
diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts
index 142109725..ee79059f9 100644
--- a/apps/api/src/app/admin/admin.service.ts
+++ b/apps/api/src/app/admin/admin.service.ts
@@ -30,6 +30,7 @@ import {
EnhancedSymbolProfile,
Filter
} from '@ghostfolio/common/interfaces';
+import { Sector } from '@ghostfolio/common/interfaces/sector.interface';
import { MarketDataPreset } from '@ghostfolio/common/types';
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
@@ -259,7 +260,8 @@ export class AdminService {
},
scraperConfiguration: true,
sectors: true,
- symbol: true
+ symbol: true,
+ SymbolProfileOverrides: true
}
}),
this.prismaService.symbolProfile.count({ where })
@@ -313,11 +315,10 @@ export class AdminService {
name,
Order,
sectors,
- symbol
+ symbol,
+ SymbolProfileOverrides
}) => {
- const countriesCount = countries
- ? Object.keys(countries).length
- : 0;
+ let countriesCount = countries ? Object.keys(countries).length : 0;
const lastMarketPrice = lastMarketPriceMap.get(
getAssetProfileIdentifier({ dataSource, symbol })
@@ -331,7 +332,34 @@ export class AdminService {
);
})?._count ?? 0;
- const sectorsCount = sectors ? Object.keys(sectors).length : 0;
+ let sectorsCount = sectors ? Object.keys(sectors).length : 0;
+
+ if (SymbolProfileOverrides) {
+ assetClass = SymbolProfileOverrides.assetClass ?? assetClass;
+ assetSubClass =
+ SymbolProfileOverrides.assetSubClass ?? assetSubClass;
+
+ if (
+ (
+ SymbolProfileOverrides.countries as unknown as Prisma.JsonArray
+ )?.length > 0
+ ) {
+ countriesCount = (
+ SymbolProfileOverrides.countries as unknown as Prisma.JsonArray
+ ).length;
+ }
+
+ name = SymbolProfileOverrides.name ?? name;
+
+ if (
+ (SymbolProfileOverrides.sectors as unknown as Sector[])
+ ?.length > 0
+ ) {
+ sectorsCount = (
+ SymbolProfileOverrides.sectors as unknown as Prisma.JsonArray
+ ).length;
+ }
+ }
return {
assetClass,
diff --git a/apps/api/src/services/symbol-profile/symbol-profile.service.ts b/apps/api/src/services/symbol-profile/symbol-profile.service.ts
index df0526d9f..0dae63311 100644
--- a/apps/api/src/services/symbol-profile/symbol-profile.service.ts
+++ b/apps/api/src/services/symbol-profile/symbol-profile.service.ts
@@ -204,8 +204,7 @@ export class SymbolProfileService {
?.length > 0
) {
item.countries = this.getCountries(
- item.SymbolProfileOverrides
- ?.countries as unknown as Prisma.JsonArray
+ item.SymbolProfileOverrides.countries as unknown as Prisma.JsonArray
);
}
@@ -214,22 +213,22 @@ export class SymbolProfileService {
?.length > 0
) {
item.holdings = this.getHoldings(
- item.SymbolProfileOverrides?.holdings as unknown as Prisma.JsonArray
+ item.SymbolProfileOverrides.holdings as unknown as Prisma.JsonArray
);
}
- item.name = item.SymbolProfileOverrides?.name ?? item.name;
+ item.name = item.SymbolProfileOverrides.name ?? item.name;
if (
(item.SymbolProfileOverrides.sectors as unknown as Sector[])?.length >
0
) {
item.sectors = this.getSectors(
- item.SymbolProfileOverrides?.sectors as unknown as Prisma.JsonArray
+ item.SymbolProfileOverrides.sectors as unknown as Prisma.JsonArray
);
}
- item.url = item.SymbolProfileOverrides?.url ?? item.url;
+ item.url = item.SymbolProfileOverrides.url ?? item.url;
delete item.SymbolProfileOverrides;
}
From f1acff1c7656d9b3383d94e32a5e41af2503687f Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 20 Feb 2025 20:51:17 +0100
Subject: [PATCH 04/14] Feature/update locales (#4333)
* Update translations
* Update changelog
---------
Co-authored-by: github-actions[bot]
Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
---
CHANGELOG.md | 1 +
apps/client/src/locales/messages.ca.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.de.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.es.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.fr.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.it.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.nl.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.pl.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.pt.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.tr.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.uk.xlf | 114 ++++++++++++------------
apps/client/src/locales/messages.xlf | 110 +++++++++++------------
apps/client/src/locales/messages.zh.xlf | 114 ++++++++++++------------
13 files changed, 683 insertions(+), 682 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed9e778f6..b0a5b23e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the validation of the currency management in the admin control panel
- Migrated the `@ghostfolio/client` components to control flow
- Migrated the `@ghostfolio/ui` components to control flow
+- Improved the language localization for German (`de`)
### Fixed
diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf
index d70c773e6..a36fb152f 100644
--- a/apps/client/src/locales/messages.ca.xlf
+++ b/apps/client/src/locales/messages.ca.xlf
@@ -447,7 +447,7 @@
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 23
+ 22
@@ -583,7 +583,7 @@
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 24
+ 23
@@ -803,7 +803,7 @@
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 26
+ 25
@@ -1219,7 +1219,7 @@
apps/client/src/app/components/admin-overview/admin-overview.html
- 206
+ 196
apps/client/src/app/components/admin-platform/admin-platform.component.html
@@ -1958,28 +1958,12 @@
124
-
- Please add a currency:
- Si us plau, afegiu una divisa:
-
- apps/client/src/app/components/admin-overview/admin-overview.component.ts
- 126
-
-
-
- is an invalid currency!
- no és una divisa vàlida!
-
- apps/client/src/app/components/admin-overview/admin-overview.component.ts
- 137
-
-
Do you really want to delete this coupon?
Està segur qeu vol eliminar aquest cupó?
apps/client/src/app/components/admin-overview/admin-overview.component.ts
- 156
+ 137
@@ -1987,7 +1971,7 @@
Està segur que vol eliminar aquesta divisa?
apps/client/src/app/components/admin-overview/admin-overview.component.ts
- 169
+ 150
@@ -1995,7 +1979,7 @@
Està segur que vol eliminar aquest missatge del sistema?
apps/client/src/app/components/admin-overview/admin-overview.component.ts
- 182
+ 163
@@ -2003,7 +1987,7 @@
Està segur que vol depurar el cache?
apps/client/src/app/components/admin-overview/admin-overview.component.ts
- 206
+ 187
@@ -2011,7 +1995,7 @@
Si us plau, afegeixi el seu missatge del sistema:
apps/client/src/app/components/admin-overview/admin-overview.component.ts
- 226
+ 207
@@ -2061,17 +2045,13 @@
apps/client/src/app/components/admin-market-data/create-asset-profile-dialog/create-asset-profile-dialog.html
22
-
- apps/client/src/app/components/admin-overview/admin-overview.html
- 105
-
User Signup
Registrar Usuari
apps/client/src/app/components/admin-overview/admin-overview.html
- 111
+ 101
@@ -2079,7 +2059,7 @@
Mode Només Lecutra
apps/client/src/app/components/admin-overview/admin-overview.html
- 125
+ 115
@@ -2087,7 +2067,7 @@
Recollida de Dades
apps/client/src/app/components/admin-overview/admin-overview.html
- 137
+ 127
@@ -2095,7 +2075,7 @@
Missatge del Sistema
apps/client/src/app/components/admin-overview/admin-overview.html
- 149
+ 139
@@ -2103,7 +2083,7 @@
Estableix el Missatge
apps/client/src/app/components/admin-overview/admin-overview.html
- 171
+ 161
@@ -2111,7 +2091,7 @@
Coupons
apps/client/src/app/components/admin-overview/admin-overview.html
- 179
+ 169
@@ -2119,7 +2099,7 @@
Afegir
apps/client/src/app/components/admin-overview/admin-overview.html
- 239
+ 229
libs/ui/src/lib/account-balances/account-balances.component.html
@@ -2131,7 +2111,7 @@
Ordre
apps/client/src/app/components/admin-overview/admin-overview.html
- 247
+ 237
@@ -2139,7 +2119,7 @@
Depurar el Cache
apps/client/src/app/components/admin-overview/admin-overview.html
- 251
+ 241
@@ -2355,7 +2335,7 @@
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 94
+ 93
@@ -5095,7 +5075,7 @@
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 88
+ 87
@@ -5611,7 +5591,7 @@
Switzerland
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 59
+ 58
libs/ui/src/lib/i18n.ts
@@ -5623,7 +5603,7 @@
Global
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 60
+ 59
libs/ui/src/lib/i18n.ts
@@ -6775,7 +6755,7 @@
Alternative
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 82
+ 81
@@ -6783,7 +6763,7 @@
App
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 83
+ 82
@@ -6791,7 +6771,7 @@
Budgeting
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 84
+ 83
@@ -6799,7 +6779,7 @@
Community
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 85
+ 84
@@ -6807,7 +6787,7 @@
Family Office
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 86
+ 85
@@ -6815,7 +6795,7 @@
Investor
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 89
+ 88
@@ -6823,7 +6803,7 @@
Open Source
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 90
+ 89
@@ -6831,7 +6811,7 @@
Personal Finance
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 92
+ 91
@@ -6839,7 +6819,7 @@
Privacy
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 93
+ 92
@@ -6847,7 +6827,7 @@
Software
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 95
+ 94
@@ -6855,7 +6835,7 @@
Tool
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 96
+ 95
@@ -6863,7 +6843,7 @@
User Experience
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 97
+ 96
@@ -6871,7 +6851,7 @@
Wealth
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 98
+ 97
@@ -6879,7 +6859,7 @@
Wealth Management
apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
- 99
+ 98
@@ -7633,7 +7613,7 @@
Please enter your Ghostfolio API key.
apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts
- 59
+ 57
@@ -7764,6 +7744,26 @@
374
+
+ Change
+ Change
+
+ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
+ 365
+
+
+
+ Performance
+ Performance
+
+ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
+ 365
+
+
+ libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
+ 378
+
+