From ef084b642a69ff012834e76e3917db2b148fc513 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 5 Aug 2026 17:37:51 +0200 Subject: [PATCH 1/8] Task/improve log of symbol lookup in Trackinsight data enhancer (#7543) Improve log level and message --- .../trackinsight/trackinsight.service.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts index 64a8bf4ef..29e4e5129 100644 --- a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts @@ -50,12 +50,10 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { response: Partial; symbol: string; }): Promise> { - if ( - !( - response.assetClass === 'EQUITY' && - ['ETF', 'MUTUALFUND'].includes(response.assetSubClass) - ) - ) { + if (!( + response.assetClass === 'EQUITY' && + ['ETF', 'MUTUALFUND'].includes(response.assetSubClass) + )) { return response; } @@ -214,8 +212,8 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { return undefined; }) .catch(({ message }) => { - this.logger.error( - `Failed to search Trackinsight symbol for ${symbol} (${message})` + this.logger.warn( + `Could not search Trackinsight symbol for "${symbol}": ${message}` ); return undefined; From ee7c3037715dc0199cdc8866311454661c0d97c9 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 5 Aug 2026 17:38:25 +0200 Subject: [PATCH 2/8] Bugfix/handle exception in country weightings parsing of FMP service (#7544) * Handle exception in country weightings parsing * Update changelog --- CHANGELOG.md | 4 ++++ .../financial-modeling-prep.service.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b541d5af..1ac12156e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Guarded the system tags against deletion and renaming in the tag management of the admin control panel +### Fixed + +- Handled an exception in the country weightings parsing of the _Financial Modeling Prep_ service + ## 3.42.0 - 2026-08-04 ### Changed diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index 05df65ad1..f7f2e7eb9 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -178,7 +178,7 @@ export class FinancialModelingPrepService aliases: FinancialModelingPrepService.countriesMapping, name: countryName }), - weight: parseFloat(weightPercentage.slice(0, -1)) / 100 + weight: parseFloat(`${weightPercentage}`) / 100 }; }); From 52f8068ab048cc25fd3b04bfc7cfa3e975eea7ac Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:31:18 +0200 Subject: [PATCH 3/8] Task/remove deprecated isExcluded attribute from import test files (#7547) Remove deprecated attribute --- test/import/ok/500-activities.json | 1 - test/import/ok/derived-currency.json | 1 - test/import/ok/sample.json | 1 - 3 files changed, 3 deletions(-) diff --git a/test/import/ok/500-activities.json b/test/import/ok/500-activities.json index 2793c695e..03aabca33 100644 --- a/test/import/ok/500-activities.json +++ b/test/import/ok/500-activities.json @@ -8,7 +8,6 @@ "balance": 2000, "currency": "USD", "id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "isExcluded": false, "name": "My Online Trading Account", "platformId": null } diff --git a/test/import/ok/derived-currency.json b/test/import/ok/derived-currency.json index 637ab21b6..4b7aa46c3 100644 --- a/test/import/ok/derived-currency.json +++ b/test/import/ok/derived-currency.json @@ -8,7 +8,6 @@ "balance": 2000, "currency": "USD", "id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "isExcluded": false, "name": "My Online Trading Account", "platformId": null } diff --git a/test/import/ok/sample.json b/test/import/ok/sample.json index be385812a..feca8a379 100644 --- a/test/import/ok/sample.json +++ b/test/import/ok/sample.json @@ -19,7 +19,6 @@ "comment": null, "currency": "USD", "id": "b2d3fe1d-d6a8-41a3-be39-07ef5e9480f0", - "isExcluded": false, "name": "My Online Trading Account", "platformId": "9da3a8a7-4795-43e3-a6db-ccb914189737" } From 9c78bc29a476719f5bd516234bf0c28c17b21a73 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 6 Aug 2026 07:41:19 +0200 Subject: [PATCH 4/8] Task/extract non-investment activity types constant (#7535) Extract non-investment activity type --- apps/api/src/app/activities/activities.service.ts | 7 ++++--- apps/api/src/app/import/import.service.ts | 3 ++- .../src/services/data-provider/data-provider.service.ts | 3 ++- apps/client/src/app/services/import-activities.service.ts | 3 ++- libs/common/src/lib/config.ts | 6 ++++++ 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/api/src/app/activities/activities.service.ts b/apps/api/src/app/activities/activities.service.ts index ef3839340..140726aeb 100644 --- a/apps/api/src/app/activities/activities.service.ts +++ b/apps/api/src/app/activities/activities.service.ts @@ -20,6 +20,7 @@ import { DATA_GATHERING_QUEUE_PRIORITY_HIGH, GATHER_ASSET_PROFILE_PROCESS_JOB_NAME, GATHER_ASSET_PROFILE_PROCESS_JOB_OPTIONS, + NON_INVESTMENT_ACTIVITY_TYPES, TAG_ID_EXCLUDE_FROM_ANALYSIS } from '@ghostfolio/common/config'; import { @@ -191,7 +192,7 @@ export class ActivitiesService { const userId = data.userId; if ( - ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) || + NON_INVESTMENT_ACTIVITY_TYPES.includes(data.type) || (data.SymbolProfile.connectOrCreate.create.dataSource === 'MANUAL' && data.type === 'BUY') ) { @@ -260,7 +261,7 @@ export class ActivitiesService { const orderData: Prisma.OrderCreateInput = data; - const isDraft = ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) + const isDraft = NON_INVESTMENT_ACTIVITY_TYPES.includes(data.type) ? false : isAfter(data.date as Date, endOfToday()); @@ -981,7 +982,7 @@ export class ActivitiesService { let isDraft = false; if ( - ['FEE', 'INTEREST', 'LIABILITY'].includes(data.type) || + NON_INVESTMENT_ACTIVITY_TYPES.includes(data.type) || (data.SymbolProfile.connect.dataSource_symbol.dataSource === 'MANUAL' && data.type === 'BUY') ) { diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index be511df44..96612522e 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -12,6 +12,7 @@ import { TagService } from '@ghostfolio/api/services/tag/tag.service'; import { DATA_GATHERING_QUEUE_PRIORITY_HIGH, ghostfolioPrefix, + NON_INVESTMENT_ACTIVITY_TYPES, TAG_ID_EXCLUDE_FROM_ANALYSIS } from '@ghostfolio/common/config'; import { CreateAssetProfileDto, CreateOrderDto } from '@ghostfolio/common/dtos'; @@ -217,7 +218,7 @@ export class ImportService { // createActivity() if needed. for (const [index, activity] of activitiesDto.entries()) { if (!activity.dataSource) { - if (['FEE', 'INTEREST', 'LIABILITY'].includes(activity.type)) { + if (NON_INVESTMENT_ACTIVITY_TYPES.includes(activity.type)) { activity.dataSource = DataSource.MANUAL; } else { activity.dataSource = diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index 6031a8e25..c5de3e4e5 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -9,6 +9,7 @@ import { PropertyService } from '@ghostfolio/api/services/property/property.serv import { DEFAULT_CURRENCY, DERIVED_CURRENCIES, + NON_INVESTMENT_ACTIVITY_TYPES, PROPERTY_API_KEY_GHOSTFOLIO, PROPERTY_DATA_SOURCE_MAPPING } from '@ghostfolio/common/config'; @@ -268,7 +269,7 @@ export class DataProviderService implements OnModuleInit { if (!assetProfiles[assetProfileIdentifier]) { if ( (dataSource === DataSource.MANUAL && type === 'BUY') || - ['FEE', 'INTEREST', 'LIABILITY'].includes(type) + NON_INVESTMENT_ACTIVITY_TYPES.includes(type) ) { const assetProfileInImport = assetProfilesWithMarketDataDto?.find( (assetProfile) => { diff --git a/apps/client/src/app/services/import-activities.service.ts b/apps/client/src/app/services/import-activities.service.ts index 503149a03..b73676252 100644 --- a/apps/client/src/app/services/import-activities.service.ts +++ b/apps/client/src/app/services/import-activities.service.ts @@ -1,3 +1,4 @@ +import { NON_INVESTMENT_ACTIVITY_TYPES } from '@ghostfolio/common/config'; import { CreateAccountWithBalancesDto, CreateAssetProfileWithMarketDataDto, @@ -70,7 +71,7 @@ export class ImportActivitiesService { let dataSource = this.parseDataSource({ item }); let symbol = this.parseSymbol({ content, index, item }); - if (!dataSource && ['FEE', 'INTEREST', 'LIABILITY'].includes(type)) { + if (!dataSource && NON_INVESTMENT_ACTIVITY_TYPES.includes(type)) { // Apply the same data source as the import service dataSource = DataSource.MANUAL; } diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index cbd77740a..08a6701dc 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -231,6 +231,12 @@ export const INVESTMENT_ACTIVITY_TYPES = [ Type.SELL ] as Type[]; +export const NON_INVESTMENT_ACTIVITY_TYPES = Object.values(Type).filter( + (type) => { + return !INVESTMENT_ACTIVITY_TYPES.includes(type); + } +); + export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME = 'PORTFOLIO'; export const PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS: JobOptions = { removeOnComplete: true From 0530e098fb0fbff08b79b5cac156f944d2205724 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 6 Aug 2026 07:45:03 +0200 Subject: [PATCH 5/8] Task/extend value component by isLoading attribute (#7540) * Introduce isLoading attribute * Update changelog --- CHANGELOG.md | 1 + .../account-detail-dialog.component.ts | 3 + .../account-detail-dialog.html | 7 ++ .../asset-profile-dialog.component.ts | 3 + .../asset-profile-dialog.html | 10 +- .../admin-overview/admin-overview.html | 3 + .../holding-detail-dialog.component.ts | 3 + .../holding-detail-dialog.html | 14 +++ .../portfolio-performance.component.html | 14 +-- .../portfolio-summary.component.html | 97 +++++++++++-------- .../user-account-settings.component.ts | 3 + .../user-account-settings.html | 1 + .../user-detail-dialog.html | 39 +++++--- .../allocations/allocations-page.html | 11 ++- .../portfolio/analysis/analysis-page.html | 69 +++++-------- .../app/pages/public/public-page.component.ts | 3 + .../src/app/pages/public/public-page.html | 12 +-- .../activities-table.component.html | 18 ++-- .../benchmark-detail-dialog.component.ts | 3 + .../benchmark-detail-dialog.html | 1 + .../holdings-table.component.html | 21 ++-- libs/ui/src/lib/value/value.component.html | 26 ++--- .../src/lib/value/value.component.stories.ts | 5 +- libs/ui/src/lib/value/value.component.ts | 4 +- 24 files changed, 214 insertions(+), 157 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac12156e..e1171d2fb 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 - Added the platform logo to the platform selector in the create or update account dialog - Added the platform logo to the account selector in the create or update activity dialog +- Extended the value component by an `isLoading` attribute to distinguish the loading state from redacted values ### Changed diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts index d1845222a..e81b8cf06 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts @@ -102,6 +102,7 @@ export class GfAccountDetailDialogComponent implements OnInit { protected holdings: PortfolioPosition[]; protected interestInBaseCurrency: number; protected interestInBaseCurrencyPrecision = 2; + protected isLoading = true; protected isLoadingChart: boolean; protected name: string | null; protected pageIndex = 0; @@ -302,6 +303,8 @@ export class GfAccountDetailDialogComponent implements OnInit { this.valueInBaseCurrency = valueInBaseCurrency; + this.isLoading = false; + this.changeDetectorRef.markForCheck(); } ); diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html index ff39f23b3..485af7500 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html @@ -12,6 +12,7 @@ @@ -108,6 +114,7 @@ PlatformSymbol @@ -191,6 +192,7 @@ - Currency @@ -231,6 +237,7 @@ i18n size="medium" [isDate]="assetProfile?.dateOfFirstActivity ? true : false" + [isLoading]="isLoading" [locale]="data.locale" [value]="assetProfile?.dateOfFirstActivity ?? '-'" >First ActivityActivitiesVersion @@ -19,6 +20,7 @@ Users; protected investmentInBaseCurrencyWithCurrencyEffect: number; protected investmentInBaseCurrencyWithCurrencyEffectPrecision = 2; + protected isLoading = true; protected readonly isUUID = isUUID; protected marketDataItems: MarketData[] = []; protected marketPrice: number; @@ -571,6 +572,8 @@ export class GfHoldingDetailDialogComponent implements OnInit { this.fetchMarketData(); } + this.isLoading = false; + this.changeDetectorRef.markForCheck(); } ); 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 c4f53497f..eccc62b4c 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 @@ -12,6 +12,7 @@ First Activity diff --git a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html index 7b9522956..d6339a5ff 100644 --- a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html +++ b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.html @@ -38,24 +38,18 @@
diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html index 9394d7624..520986c89 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -2,7 +2,11 @@
Time in Market
- +
@@ -46,10 +51,11 @@ @@ -62,14 +68,11 @@ @@ -79,12 +82,11 @@ @@ -97,10 +99,11 @@ @@ -113,12 +116,11 @@ @@ -136,13 +138,10 @@ class="justify-content-end" position="end" [colorizeSign]="true" + [isLoading]="isLoading" [isPercent]="true" [locale]="locale" - [value]=" - isLoading - ? undefined - : summary?.netPerformancePercentageWithCurrencyEffect - " + [value]="summary?.netPerformancePercentageWithCurrencyEffect" /> @@ -156,10 +155,11 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoading" [locale]="locale" [precision]="precision" [unit]="baseCurrency" - [value]="isLoading ? undefined : summary?.totalAssetsInBaseCurrency" + [value]="summary?.totalAssetsInBaseCurrency" /> @@ -188,10 +188,11 @@ ) { } @@ -200,10 +201,11 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoading" [locale]="locale" [precision]="precision" [unit]="baseCurrency" - [value]="isLoading ? undefined : holdingsInBaseCurrency" + [value]="holdingsInBaseCurrency" /> @@ -215,10 +217,11 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoading" [locale]="locale" [precision]="precision" [unit]="baseCurrency" - [value]="isLoading ? undefined : investmentsInBaseCurrency" + [value]="investmentsInBaseCurrency" /> @@ -229,10 +232,11 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoading" [locale]="locale" [precision]="precision" [unit]="baseCurrency" - [value]="isLoading ? undefined : summary?.emergencyFund?.assets" + [value]="summary?.emergencyFund?.assets" /> @@ -262,10 +266,11 @@ ) { } @@ -274,10 +279,11 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoading" [locale]="locale" [precision]="precision" [unit]="baseCurrency" - [value]="isLoading ? undefined : summary?.totalCashInBaseCurrency" + [value]="summary?.totalCashInBaseCurrency" /> @@ -289,10 +295,11 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoading" [locale]="locale" [precision]="precision" [unit]="baseCurrency" - [value]="isLoading ? undefined : summary?.cash" + [value]="summary?.cash" /> @@ -303,10 +310,11 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoading" [locale]="locale" [precision]="precision" [unit]="baseCurrency" - [value]="isLoading ? undefined : summary?.emergencyFund?.cash" + [value]="summary?.emergencyFund?.cash" /> @@ -321,20 +329,22 @@ ) { }
@@ -353,10 +363,11 @@ @@ -369,10 +380,11 @@ @@ -385,13 +397,10 @@ class="justify-content-end" position="end" [colorizeSign]="true" + [isLoading]="isLoading" [isPercent]="true" [locale]="locale" - [value]=" - isLoading - ? undefined - : summary?.annualizedPerformancePercentWithCurrencyEffect - " + [value]="summary?.annualizedPerformancePercentWithCurrencyEffect" /> @@ -408,10 +417,11 @@ ) { } @@ -443,10 +453,11 @@ @@ -456,10 +467,11 @@ @@ -469,10 +481,11 @@ 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 0a049a7ae..b48adf59d 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 @@ -87,6 +87,7 @@ export class GfUserAccountSettingsComponent implements OnInit { protected hasPermissionToUpdateUserSettings: boolean; protected isAccessTokenHidden = true; protected readonly isFingerprintSupported = this.doesBrowserSupportAuthn(); + protected isLoading = true; protected isWebAuthnEnabled: boolean; protected readonly language = document.documentElement.lang; protected locales = [ @@ -178,6 +179,8 @@ export class GfUserAccountSettingsComponent implements OnInit { this.locales = Array.from(new Set(this.locales)).sort(); + this.isLoading = false; + this.changeDetectorRef.markForCheck(); } }); diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.html b/apps/client/src/app/components/user-account-settings/user-account-settings.html index e77a89b24..57d3b54d7 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.html +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -273,6 +273,7 @@ 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 b77e0043e..efc4fe5b4 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 @@ -36,12 +36,17 @@ i18n size="medium" [enableCopyToClipboardButton]="true" - [value]="isLoading ? undefined : user.id" + [isLoading]="isLoading" + [value]="user?.id" >User ID
- Role
@@ -53,8 +58,9 @@ i18n size="medium" [isDate]="true" + [isLoading]="isLoading" [locale]="data.locale" - [value]="isLoading ? undefined : user.createdAt" + [value]="user?.createdAt" >Registration Date
@@ -62,8 +68,9 @@ Authentication @@ -75,10 +82,9 @@ Membership @@ -86,12 +92,9 @@ Country @@ -104,8 +107,9 @@ Accounts @@ -113,8 +117,9 @@ Activities @@ -126,9 +131,10 @@ Engagement per Day @@ -136,8 +142,9 @@ API Requests Today diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html index d5c765958..902d04cde 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html @@ -14,12 +14,9 @@ @@ -213,6 +210,7 @@ Developed MarketsEmerging MarketsOther Markets
No data available
Total amount
@@ -104,14 +101,11 @@ size="large" [colorizeSign]="true" [isCurrency]="true" + [isLoading]="isLoadingInvestmentChart" [locale]="user?.settings?.locale" [precision]="precision" [unit]="user?.settings?.baseCurrency" - [value]=" - isLoadingInvestmentChart - ? undefined - : performance?.netPerformanceWithCurrencyEffect - " + [value]="performance?.netPerformanceWithCurrencyEffect" >Change with currency effect
@@ -124,13 +118,10 @@ i18n size="large" [colorizeSign]="true" + [isLoading]="isLoadingInvestmentChart" [isPercent]="true" [locale]="user?.settings?.locale" - [value]=" - isLoadingInvestmentChart - ? undefined - : performance?.netPerformancePercentageWithCurrencyEffect - " + [value]="performance?.netPerformancePercentageWithCurrencyEffect" >Performance with currency effect
@@ -173,13 +164,10 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoadingInvestmentChart" [locale]="user?.settings?.locale" [unit]="user?.settings?.baseCurrency" - [value]=" - isLoadingInvestmentChart - ? undefined - : performance?.netPerformance - " + [value]="performance?.netPerformance" /> @@ -192,13 +180,10 @@ class="justify-content-end" position="end" [colorizeSign]="true" + [isLoading]="isLoadingInvestmentChart" [isPercent]="true" [locale]="user?.settings?.locale" - [value]=" - isLoadingInvestmentChart - ? undefined - : performance?.netPerformancePercentage - " + [value]="performance?.netPerformancePercentage" /> @@ -216,15 +201,14 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoadingInvestmentChart" [locale]="user?.settings?.locale" [unit]="user?.settings?.baseCurrency" [value]=" - isLoadingInvestmentChart - ? undefined - : performance?.netPerformance === null - ? null - : performance?.netPerformanceWithCurrencyEffect - - performance?.netPerformance + performance?.netPerformance === null + ? null + : performance?.netPerformanceWithCurrencyEffect - + performance?.netPerformance " /> @@ -238,15 +222,14 @@ class="justify-content-end" position="end" [colorizeSign]="true" + [isLoading]="isLoadingInvestmentChart" [isPercent]="true" [locale]="user?.settings?.locale" [value]=" - isLoadingInvestmentChart - ? undefined - : performance?.netPerformancePercentage === null - ? null - : performance?.netPerformancePercentageWithCurrencyEffect - - performance?.netPerformancePercentage + performance?.netPerformancePercentage === null + ? null + : performance?.netPerformancePercentageWithCurrencyEffect - + performance?.netPerformancePercentage " /> @@ -261,13 +244,10 @@ class="justify-content-end" position="end" [isCurrency]="true" + [isLoading]="isLoadingInvestmentChart" [locale]="user?.settings?.locale" [unit]="user?.settings?.baseCurrency" - [value]=" - isLoadingInvestmentChart - ? undefined - : performance?.netPerformanceWithCurrencyEffect - " + [value]="performance?.netPerformanceWithCurrencyEffect" /> @@ -280,12 +260,11 @@ class="justify-content-end" position="end" [colorizeSign]="true" + [isLoading]="isLoadingInvestmentChart" [isPercent]="true" [locale]="user?.settings?.locale" [value]=" - isLoadingInvestmentChart - ? undefined - : performance?.netPerformancePercentageWithCurrencyEffect + performance?.netPerformancePercentageWithCurrencyEffect " /> diff --git a/apps/client/src/app/pages/public/public-page.component.ts b/apps/client/src/app/pages/public/public-page.component.ts index 3b149cd08..e354f8a1b 100644 --- a/apps/client/src/app/pages/public/public-page.component.ts +++ b/apps/client/src/app/pages/public/public-page.component.ts @@ -69,6 +69,7 @@ export class GfPublicPageComponent implements OnInit { protected hasPermissionForSubscription: boolean; protected holdings: PublicPortfolioResponse['holdings'][string][]; protected info: InfoItem; + protected isLoading = true; protected latestActivitiesDataSource: MatTableDataSource< PublicPortfolioResponse['latestActivities'][0] >; @@ -138,6 +139,8 @@ export class GfPublicPageComponent implements OnInit { this.publicPortfolioDetails.latestActivities ); + this.isLoading = false; + this.changeDetectorRef.markForCheck(); }); } diff --git a/apps/client/src/app/pages/public/public-page.html b/apps/client/src/app/pages/public/public-page.html index 57bc1e95f..e0e855585 100644 --- a/apps/client/src/app/pages/public/public-page.html +++ b/apps/client/src/app/pages/public/public-page.html @@ -15,11 +15,11 @@ i18n size="large" [colorizeSign]="true" + [isLoading]="isLoading" [isPercent]="true" [precision]="2" [value]=" - publicPortfolioDetails?.performance?.['1d']?.relativeChange ?? - undefined + publicPortfolioDetails?.performance?.['1d']?.relativeChange " >Today
@@ -33,11 +33,11 @@ i18n size="large" [colorizeSign]="true" + [isLoading]="isLoading" [isPercent]="true" [precision]="2" [value]=" - publicPortfolioDetails?.performance?.['ytd']?.relativeChange ?? - undefined + publicPortfolioDetails?.performance?.['ytd']?.relativeChange " >This year
@@ -51,11 +51,11 @@ i18n size="large" [colorizeSign]="true" + [isLoading]="isLoading" [isPercent]="true" [precision]="2" [value]=" - publicPortfolioDetails?.performance?.['max']?.relativeChange ?? - undefined + publicPortfolioDetails?.performance?.['max']?.relativeChange " >From the beginning
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 ffcc77832..bf7fb2caf 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -210,8 +210,9 @@ @@ -234,8 +235,9 @@
@@ -258,8 +260,9 @@
@@ -282,8 +285,9 @@
@@ -305,8 +309,9 @@
@@ -337,8 +342,9 @@
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 0c75b5954..8a7e13156 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 @@ -46,6 +46,7 @@ import { BenchmarkDetailDialogParams } from './interfaces/interfaces'; export class GfBenchmarkDetailDialogComponent implements OnInit { public assetProfile: AdminMarketDataDetails['assetProfile']; public historicalDataItems: LineChartItem[]; + public isLoading = true; public value: number; public constructor( @@ -79,6 +80,8 @@ export class GfBenchmarkDetailDialogComponent implements OnInit { } ); + this.isLoading = false; + this.changeDetectorRef.markForCheck(); }); } diff --git a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.html b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.html index a8cf3730c..3ff7f03ab 100644 --- a/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.html +++ b/libs/ui/src/lib/benchmark/benchmark-detail-dialog/benchmark-detail-dialog.html @@ -11,6 +11,7 @@
@@ -105,8 +106,9 @@
@@ -125,9 +127,10 @@
@@ -147,10 +150,9 @@ @@ -170,13 +172,10 @@
diff --git a/libs/ui/src/lib/value/value.component.html b/libs/ui/src/lib/value/value.component.html index 14ac7154a..3ab711f7e 100644 --- a/libs/ui/src/lib/value/value.component.html +++ b/libs/ui/src/lib/value/value.component.html @@ -27,7 +27,20 @@ } - @if (value || value === 0 || value === null) { + + @if (isLoading() || value === undefined) { + + } @else if (value || value === 0 || value === null) {
} - @if (value === undefined) { - - } - @if (size === 'large') {
diff --git a/libs/ui/src/lib/value/value.component.stories.ts b/libs/ui/src/lib/value/value.component.stories.ts index a5971b252..19139e266 100644 --- a/libs/ui/src/lib/value/value.component.stories.ts +++ b/libs/ui/src/lib/value/value.component.stories.ts @@ -30,6 +30,9 @@ export default { enableCopyToClipboardButton: { control: 'boolean' }, + isLoading: { + control: 'boolean' + }, size: { control: 'select', options: ['small', 'medium', 'large'] @@ -41,7 +44,7 @@ type Story = StoryObj; export const Loading: Story = { args: { - value: undefined + isLoading: true } }; diff --git a/libs/ui/src/lib/value/value.component.ts b/libs/ui/src/lib/value/value.component.ts index 494f7a347..cc08e5a24 100644 --- a/libs/ui/src/lib/value/value.component.ts +++ b/libs/ui/src/lib/value/value.component.ts @@ -62,6 +62,8 @@ export class GfValueComponent implements AfterViewInit, OnChanges, OnDestroy { public readonly copiedTitle = $localize`The value has been copied to the clipboard`; public readonly copyToClipboardTitle = $localize`Copy to clipboard`; + public readonly isLoading = input(false); + public readonly precision = input(); public constructor( private changeDetectorRef: ChangeDetectorRef, @@ -74,8 +76,6 @@ export class GfValueComponent implements AfterViewInit, OnChanges, OnDestroy { }); } - public readonly precision = input(); - private copyToClipboardTimeout: ReturnType; private readonly formatOptions = computed(() => { From 154da3782b1e561770309792e49af7b22b87fcfe Mon Sep 17 00:00:00 2001 From: Sebastian Legarraga <64795732+slegarraga@users.noreply.github.com> Date: Thu, 6 Aug 2026 01:48:16 -0400 Subject: [PATCH 6/8] Task/improve language localization for ES (20260806) (#7549) * Update translations * Update changelog --- CHANGELOG.md | 1 + apps/client/src/locales/messages.es.xlf | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1171d2fb..b926d2c52 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 - Guarded the system tags against deletion and renaming in the tag management of the admin control panel +- Improved the language localization for Spanish (`es`) ### Fixed diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index ab4e4eb3e..866dac527 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -356,7 +356,7 @@ Unknown - Unknown + Desconocido libs/ui/src/lib/i18n.ts 88 @@ -440,7 +440,7 @@ Splits - Splits + Desdoblamientos apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 512 @@ -840,7 +840,7 @@ Split Ratio - Split Ratio + Relación de desdoblamiento apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 526 @@ -1776,7 +1776,7 @@ Invalid API key - Invalid API key + Clave de API no válida apps/client/src/app/components/admin-settings/admin-settings.component.html 112 @@ -3056,7 +3056,7 @@ Export - Export + Exportar libs/ui/src/lib/activities-table/activities-table.component.html 68 @@ -4168,7 +4168,7 @@ Cache has been flushed. - Cache has been flushed. + Caché vaciada. apps/client/src/app/components/admin-overview/admin-overview.component.ts 281 @@ -4324,7 +4324,7 @@ Shares After - Shares After + Acciones después apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 584 @@ -5292,7 +5292,7 @@ Do you really want to delete these activities? - Do you really want to delete these activities? + ¿De verdad quieres eliminar estas actividades? libs/ui/src/lib/activities-table/activities-table.component.ts 334 @@ -5758,7 +5758,7 @@ Data gathering has been started. - Data gathering has been started. + La recopilación de datos ha comenzado. apps/client/src/app/components/admin-market-data/admin-market-data.component.ts 413 @@ -7367,7 +7367,7 @@ Shares Before - Shares Before + Acciones antes apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 597 @@ -8170,7 +8170,7 @@ {VAR_PLURAL, plural, =1 {Activity} other {Activities}} - {VAR_PLURAL, plural, =1 {Activity} other {Activities}} + {VAR_PLURAL, plural, =1 {Actividad} other {Actividades}} libs/ui/src/lib/activities-table/activities-table.component.html 69 From 911e12358937f585602b094ab7ab36c38fcdac8b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 6 Aug 2026 07:50:37 +0200 Subject: [PATCH 7/8] Release 3.43.0 (#7552) --- 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 b926d2c52..be20727bd 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 +## 3.43.0 - 2026-08-06 ### Added diff --git a/package-lock.json b/package-lock.json index 06b0efda2..ce97c403b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "3.42.0", + "version": "3.43.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "3.42.0", + "version": "3.43.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 4bbda525e..b13aeab4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "3.42.0", + "version": "3.43.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From c90bb1dfe5b94bb5482b8278e2908c047cea9237 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 6 Aug 2026 20:10:46 +0200 Subject: [PATCH 8/8] Task/refactor abstract Material form field component to directive (#7555) * Migrate to directive * Update changelog --- CHANGELOG.md | 6 ++++++ libs/ui/src/lib/shared/abstract-mat-form-field.ts | 7 ++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be20727bd..736c708e2 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 + +- Migrated the abstract _Material_ form field from a component to a directive + ## 3.43.0 - 2026-08-06 ### Added diff --git a/libs/ui/src/lib/shared/abstract-mat-form-field.ts b/libs/ui/src/lib/shared/abstract-mat-form-field.ts index 0d547af4e..a6ef16175 100644 --- a/libs/ui/src/lib/shared/abstract-mat-form-field.ts +++ b/libs/ui/src/lib/shared/abstract-mat-form-field.ts @@ -1,7 +1,7 @@ import { FocusMonitor } from '@angular/cdk/a11y'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { - Component, + Directive, DoCheck, ElementRef, HostBinding, @@ -13,10 +13,7 @@ import { ControlValueAccessor, NgControl, Validators } from '@angular/forms'; import { MatFormFieldControl } from '@angular/material/form-field'; import { Subject } from 'rxjs'; -@Component({ - template: '', - standalone: false -}) +@Directive() export abstract class AbstractMatFormField implements ControlValueAccessor, DoCheck, MatFormFieldControl, OnDestroy {