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] 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 @@
@@ -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 MarketsNo data availableTotal 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(() => {