diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5fa0fd7..8861b138 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
+### Changed
+
+- Reloaded the available tags after creating a custom tag in the holding detail dialog (experimental)
+- Migrated the `@ghostfolio/client` components to control flow
+- Migrated the `@ghostfolio/ui` components to control flow
+
### Fixed
- Added missing assets in _Storybook_ setup
@@ -15,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
+- Extended the tooltip in the chart of the holdings tab on the home page by the allocation, change and performance
- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Asia-Pacific Markets)
- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Japan)
- Added support to create custom tags in the holding detail dialog (experimental)
diff --git a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts b/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts
index 8c290706..e42e6259 100644
--- a/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts
+++ b/apps/client/src/app/components/admin-settings/ghostfolio-premium-api-dialog/ghostfolio-premium-api-dialog.component.ts
@@ -3,7 +3,6 @@ import { DataService } from '@ghostfolio/client/services/data.service';
import { PROPERTY_API_KEY_GHOSTFOLIO } from '@ghostfolio/common/config';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
-import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import {
@@ -18,7 +17,6 @@ import { GhostfolioPremiumApiDialogParams } from './interfaces/interfaces';
@Component({
imports: [
- CommonModule,
GfDialogFooterModule,
GfDialogHeaderModule,
GfPremiumIndicatorComponent,
diff --git a/apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.ts b/apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.ts
index 5db86296..179193da 100644
--- a/apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.ts
+++ b/apps/client/src/app/components/asset-profile-icon/asset-profile-icon.component.ts
@@ -1,4 +1,3 @@
-import { CommonModule } from '@angular/common';
import {
CUSTOM_ELEMENTS_SCHEMA,
ChangeDetectionStrategy,
@@ -10,7 +9,6 @@ import { DataSource } from '@prisma/client';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
- imports: [CommonModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-asset-profile-icon',
styleUrls: ['./asset-profile-icon.component.scss'],
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 69322b21..25317e0c 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
@@ -175,6 +175,9 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
]
});
}),
+ switchMap(() => {
+ return this.userService.get(true);
+ }),
takeUntil(this.unsubscribeSubject)
)
.subscribe();
diff --git a/apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts b/apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts
index 7ee9c66c..b57bcb0f 100644
--- a/apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts
+++ b/apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.component.ts
@@ -1,6 +1,5 @@
import { XRayRulesSettings } from '@ghostfolio/common/interfaces';
-import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
@@ -14,13 +13,7 @@ import { MatSliderModule } from '@angular/material/slider';
import { IRuleSettingsDialogParams } from './interfaces/interfaces';
@Component({
- imports: [
- CommonModule,
- FormsModule,
- MatButtonModule,
- MatDialogModule,
- MatSliderModule
- ],
+ imports: [FormsModule, MatButtonModule, MatDialogModule, MatSliderModule],
selector: 'gf-rule-settings-dialog',
styleUrls: ['./rule-settings-dialog.scss'],
templateUrl: './rule-settings-dialog.html'
diff --git a/apps/client/src/app/core/notification/alert-dialog/alert-dialog.component.ts b/apps/client/src/app/core/notification/alert-dialog/alert-dialog.component.ts
index 8aefe84c..98b6043e 100644
--- a/apps/client/src/app/core/notification/alert-dialog/alert-dialog.component.ts
+++ b/apps/client/src/app/core/notification/alert-dialog/alert-dialog.component.ts
@@ -1,4 +1,3 @@
-import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
@@ -6,7 +5,7 @@ import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { IAlertDialogParams } from './interfaces/interfaces';
@Component({
- imports: [CommonModule, MatButtonModule, MatDialogModule],
+ imports: [MatButtonModule, MatDialogModule],
selector: 'gf-alert-dialog',
styleUrls: ['./alert-dialog.scss'],
templateUrl: './alert-dialog.html'
diff --git a/apps/client/src/app/core/notification/confirmation-dialog/confirmation-dialog.component.ts b/apps/client/src/app/core/notification/confirmation-dialog/confirmation-dialog.component.ts
index 9aced99c..88e5113d 100644
--- a/apps/client/src/app/core/notification/confirmation-dialog/confirmation-dialog.component.ts
+++ b/apps/client/src/app/core/notification/confirmation-dialog/confirmation-dialog.component.ts
@@ -1,4 +1,3 @@
-import { CommonModule } from '@angular/common';
import { Component, HostListener } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
@@ -7,7 +6,7 @@ import { ConfirmationDialogType } from './confirmation-dialog.type';
import { IConfirmDialogParams } from './interfaces/interfaces';
@Component({
- imports: [CommonModule, MatButtonModule, MatDialogModule],
+ imports: [MatButtonModule, MatDialogModule],
selector: 'gf-confirmation-dialog',
styleUrls: ['./confirmation-dialog.scss'],
templateUrl: './confirmation-dialog.html'
diff --git a/apps/client/src/app/core/notification/prompt-dialog/prompt-dialog.component.ts b/apps/client/src/app/core/notification/prompt-dialog/prompt-dialog.component.ts
index 4ec634da..6c8af419 100644
--- a/apps/client/src/app/core/notification/prompt-dialog/prompt-dialog.component.ts
+++ b/apps/client/src/app/core/notification/prompt-dialog/prompt-dialog.component.ts
@@ -1,4 +1,3 @@
-import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
@@ -8,7 +7,6 @@ import { MatInputModule } from '@angular/material/input';
@Component({
imports: [
- CommonModule,
FormsModule,
MatButtonModule,
MatDialogModule,
diff --git a/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts b/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
index 3a0ec4ff..6a8543e7 100644
--- a/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
+++ b/apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts
@@ -3,14 +3,13 @@ import { Product } from '@ghostfolio/common/interfaces';
import { personalFinanceTools } from '@ghostfolio/common/personal-finance-tools';
import { translate } from '@ghostfolio/ui/i18n';
-import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { ActivatedRoute, RouterModule } from '@angular/router';
@Component({
host: { class: 'page' },
- imports: [CommonModule, MatButtonModule, RouterModule],
+ imports: [MatButtonModule, RouterModule],
selector: 'gf-product-page',
styleUrls: ['./product-page.scss'],
templateUrl: './product-page.html'
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 38c6252a..96dc6800 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
@@ -8,7 +8,6 @@ import {
} from '@ghostfolio/common/interfaces';
import { GfLineChartComponent } from '@ghostfolio/ui/line-chart';
-import { CommonModule } from '@angular/common';
import {
CUSTOM_ELEMENTS_SCHEMA,
ChangeDetectionStrategy,
@@ -33,7 +32,6 @@ import { BenchmarkDetailDialogParams } from './interfaces/interfaces';
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'd-flex flex-column h-100' },
imports: [
- CommonModule,
GfDialogFooterModule,
GfDialogHeaderModule,
GfLineChartComponent,
diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html
index fb9f2c13..92143362 100644
--- a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html
+++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html
@@ -1,9 +1,16 @@
- Market data provided by {{
+ Market data provided by
+ @for (
+ dataProviderInfo of dataProviderInfos;
+ track dataProviderInfo;
+ let last = $last
+ ) {
+ {{
dataProviderInfo.name
- }}, .
+ }}
+ @if (!last) {
+ ,
+ }
+ }
+ .
diff --git a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts
index 9be034e6..2d455c0d 100644
--- a/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts
+++ b/libs/ui/src/lib/data-provider-credits/data-provider-credits.component.ts
@@ -1,6 +1,5 @@
import { DataProviderInfo } from '@ghostfolio/common/interfaces';
-import { CommonModule } from '@angular/common';
import {
CUSTOM_ELEMENTS_SCHEMA,
ChangeDetectionStrategy,
@@ -10,7 +9,6 @@ import {
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
- imports: [CommonModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-data-provider-credits',
styleUrls: ['./data-provider-credits.component.scss'],
diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts
index 710cb402..73f382c5 100644
--- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts
+++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts
@@ -1,7 +1,6 @@
import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service';
-import { CommonModule } from '@angular/common';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
@@ -29,7 +28,6 @@ import { HistoricalMarketDataEditorDialogParams } from './interfaces/interfaces'
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'h-100' },
imports: [
- CommonModule,
FormsModule,
MatButtonModule,
MatDatepickerModule,
diff --git a/libs/ui/src/lib/treemap-chart/treemap-chart.component.stories.ts b/libs/ui/src/lib/treemap-chart/treemap-chart.component.stories.ts
new file mode 100644
index 00000000..2000b4f9
--- /dev/null
+++ b/libs/ui/src/lib/treemap-chart/treemap-chart.component.stories.ts
@@ -0,0 +1,392 @@
+import { CommonModule } from '@angular/common';
+import '@angular/localize/init';
+import { moduleMetadata } from '@storybook/angular';
+import type { Meta, StoryObj } from '@storybook/angular';
+import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
+
+import { GfTreemapChartComponent } from './treemap-chart.component';
+
+export default {
+ title: 'Treemap Chart',
+ component: GfTreemapChartComponent,
+ decorators: [
+ moduleMetadata({
+ imports: [CommonModule, NgxSkeletonLoaderModule]
+ })
+ ],
+ argTypes: {
+ colorScheme: {
+ control: {
+ type: 'select'
+ },
+ options: ['DARK', 'LIGHT']
+ },
+ cursor: {
+ control: {
+ type: 'select'
+ },
+ options: ['', 'pointer']
+ }
+ }
+} as Meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ baseCurrency: 'USD',
+ colorScheme: 'LIGHT',
+ cursor: undefined,
+ dateRange: 'mtd',
+ holdings: [
+ {
+ allocationInPercentage: 0.042990776363386086,
+ assetClass: 'EQUITY',
+ assetSubClass: 'STOCK',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'YAHOO',
+ dateOfFirstActivity: new Date('2021-12-01T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 3856,
+ grossPerformancePercent: 0.46047289228564603,
+ grossPerformancePercentWithCurrencyEffect: 0.46047289228564603,
+ grossPerformanceWithCurrencyEffect: 3856,
+ holdings: [],
+ investment: 8374,
+ marketPrice: 244.6,
+ name: 'Apple Inc',
+ netPerformance: 3855,
+ netPerformancePercent: 0.460353475041796,
+ netPerformancePercentWithCurrencyEffect: 0.036440677966101696,
+ netPerformanceWithCurrencyEffect: 430,
+ quantity: 50,
+ sectors: [],
+ symbol: 'AAPL',
+ tags: [],
+ transactionCount: 1,
+ url: 'https://www.apple.com',
+ valueInBaseCurrency: 12230
+ },
+ {
+ allocationInPercentage: 0.02377401948293552,
+ assetClass: 'EQUITY',
+ assetSubClass: 'STOCK',
+ countries: [],
+ currency: 'EUR',
+ dataSource: 'YAHOO',
+ dateOfFirstActivity: new Date('2021-04-23T00:00:00.000Z'),
+ dividend: 192,
+ grossPerformance: 2226.700251889169,
+ grossPerformancePercent: 0.49083842309827874,
+ grossPerformancePercentWithCurrencyEffect: 0.29306136948826367,
+ grossPerformanceWithCurrencyEffect: 1532.8272791336772,
+ holdings: [],
+ investment: 4536.523929471033,
+ marketPrice: 322.2,
+ name: 'Allianz SE',
+ netPerformance: 2222.2921914357685,
+ netPerformancePercent: 0.48986674069961134,
+ netPerformancePercentWithCurrencyEffect: 0.034489367670592026,
+ netPerformanceWithCurrencyEffect: 225.48257403052068,
+ quantity: 20,
+ sectors: [],
+ symbol: 'ALV.DE',
+ tags: [],
+ transactionCount: 2,
+ url: 'https://www.allianz.com',
+ valueInBaseCurrency: 6763.224181360202
+ },
+ {
+ allocationInPercentage: 0.08038536990007467,
+ assetClass: 'EQUITY',
+ assetSubClass: 'STOCK',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'YAHOO',
+ dateOfFirstActivity: new Date('2018-10-01T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 12758.05,
+ grossPerformancePercent: 1.2619300787837724,
+ grossPerformancePercentWithCurrencyEffect: 1.2619300787837724,
+ grossPerformanceWithCurrencyEffect: 12758.05,
+ holdings: [],
+ investment: 10109.95,
+ marketPrice: 228.68,
+ name: 'Amazon.com, Inc.',
+ netPerformance: 12677.26,
+ netPerformancePercent: 1.253938941339967,
+ netPerformancePercentWithCurrencyEffect: -0.037866008722316276,
+ netPerformanceWithCurrencyEffect: -899.99926757812,
+ quantity: 100,
+ sectors: [],
+ symbol: 'AMZN',
+ tags: [],
+ transactionCount: 1,
+ url: 'https://www.aboutamazon.com',
+ valueInBaseCurrency: 22868
+ },
+ {
+ allocationInPercentage: 0.19216416482928922,
+ assetClass: 'LIQUIDITY',
+ assetSubClass: 'CRYPTOCURRENCY',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'COINGECKO',
+ dateOfFirstActivity: new Date('2017-08-16T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 52666.7898248,
+ grossPerformancePercent: 26.333394912400003,
+ grossPerformancePercentWithCurrencyEffect: 26.333394912400003,
+ grossPerformanceWithCurrencyEffect: 52666.7898248,
+ holdings: [],
+ investment: 1999.9999999999998,
+ marketPrice: 97364,
+ name: 'Bitcoin',
+ netPerformance: 52636.8898248,
+ netPerformancePercent: 26.3184449124,
+ netPerformancePercentWithCurrencyEffect: -0.04760906442310894,
+ netPerformanceWithCurrencyEffect: -2732.737808972287,
+ quantity: 0.5614682,
+ sectors: [],
+ symbol: 'bitcoin',
+ tags: [],
+ transactionCount: 1,
+ url: null,
+ valueInBaseCurrency: 54666.7898248
+ },
+ {
+ allocationInPercentage: 0.007378652850073097,
+ assetClass: 'FIXED_INCOME',
+ assetSubClass: 'BOND',
+ countries: [],
+ currency: 'EUR',
+ dataSource: 'MANUAL',
+ dateOfFirstActivity: new Date('2021-02-01T00:00:00.000Z'),
+ dividend: 11.45,
+ grossPerformance: 0,
+ grossPerformancePercent: 0,
+ grossPerformancePercentWithCurrencyEffect: -0.1247202380342517,
+ grossPerformanceWithCurrencyEffect: -258.2576430160448,
+ holdings: [],
+ investment: 2099.0764063811926,
+ marketPrice: 1,
+ name: 'Bondora Go & Grow',
+ netPerformance: 0,
+ netPerformancePercent: 0,
+ netPerformancePercentWithCurrencyEffect: 0.009445843828715519,
+ netPerformanceWithCurrencyEffect: 19.6420125363184,
+ quantity: 2000,
+ sectors: [],
+ symbol: 'BONDORA_GO_AND_GROW',
+ tags: [],
+ transactionCount: 5,
+ url: null,
+ valueInBaseCurrency: 2099.0764063811926
+ },
+ {
+ allocationInPercentage: 0.07787531695543741,
+ assetClass: 'EQUITY',
+ assetSubClass: 'ETF',
+ countries: [],
+ currency: 'CHF',
+ dataSource: 'MANUAL',
+ dateOfFirstActivity: new Date('2021-04-01T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 4550.843985045582,
+ grossPerformancePercent: 0.3631417324494093,
+ grossPerformancePercentWithCurrencyEffect: 0.42037247857285137,
+ grossPerformanceWithCurrencyEffect: 5107.057936556927,
+ holdings: [],
+ investment: 17603.097090932337,
+ marketPrice: 188.22,
+ name: 'frankly Extreme 95 Index',
+ netPerformance: 4550.843985045582,
+ netPerformancePercent: 0.3631417324494093,
+ netPerformancePercentWithCurrencyEffect: 0.026190604904358043,
+ netPerformanceWithCurrencyEffect: 565.4165171873152,
+ quantity: 105.87328656807,
+ sectors: [],
+ symbol: 'FRANKLY95P',
+ tags: [],
+ transactionCount: 6,
+ url: 'https://www.frankly.ch',
+ valueInBaseCurrency: 22153.941075977917
+ },
+ {
+ allocationInPercentage: 0.04307127421937313,
+ assetClass: 'EQUITY',
+ assetSubClass: 'STOCK',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'YAHOO',
+ dateOfFirstActivity: new Date('2023-01-03T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 5065.5,
+ grossPerformancePercent: 0.7047750229568411,
+ grossPerformancePercentWithCurrencyEffect: 0.7047750229568411,
+ grossPerformanceWithCurrencyEffect: 5065.5,
+ holdings: [],
+ investment: 7187.4,
+ marketPrice: 408.43,
+ name: 'Microsoft Corporation',
+ netPerformance: 5065.5,
+ netPerformancePercent: 0.7047750229568411,
+ netPerformancePercentWithCurrencyEffect: -0.015973588391056275,
+ netPerformanceWithCurrencyEffect: -198.899926757814,
+ quantity: 30,
+ sectors: [],
+ symbol: 'MSFT',
+ tags: [],
+ transactionCount: 1,
+ url: 'https://www.microsoft.com',
+ valueInBaseCurrency: 12252.9
+ },
+ {
+ allocationInPercentage: 0.18762679306394897,
+ assetClass: 'EQUITY',
+ assetSubClass: 'STOCK',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'YAHOO',
+ dateOfFirstActivity: new Date('2017-01-03T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 51227.500000005,
+ grossPerformancePercent: 23.843379101756675,
+ grossPerformancePercentWithCurrencyEffect: 23.843379101756675,
+ grossPerformanceWithCurrencyEffect: 51227.500000005,
+ holdings: [],
+ investment: 2148.499999995,
+ marketPrice: 355.84,
+ name: 'Tesla, Inc.',
+ netPerformance: 51197.500000005,
+ netPerformancePercent: 23.829415871596066,
+ netPerformancePercentWithCurrencyEffect: -0.12051410125545206,
+ netPerformanceWithCurrencyEffect: -7314.00091552734,
+ quantity: 150,
+ sectors: [],
+ symbol: 'TSLA',
+ tags: [],
+ transactionCount: 1,
+ url: 'https://www.tesla.com',
+ valueInBaseCurrency: 53376
+ },
+ {
+ allocationInPercentage: 0.053051250766657634,
+ assetClass: 'EQUITY',
+ assetSubClass: 'ETF',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'YAHOO',
+ dateOfFirstActivity: new Date('2019-03-01T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 6845.8,
+ grossPerformancePercent: 1.0164758094605268,
+ grossPerformancePercentWithCurrencyEffect: 1.0164758094605268,
+ grossPerformanceWithCurrencyEffect: 6845.8,
+ holdings: [],
+ investment: 8246.2,
+ marketPrice: 301.84,
+ name: 'Vanguard Total Stock Market Index Fund ETF Shares',
+ netPerformance: 6746.3,
+ netPerformancePercent: 1.0017018833976383,
+ netPerformancePercentWithCurrencyEffect: 0.01085061564051406,
+ netPerformanceWithCurrencyEffect: 161.99969482422,
+ quantity: 50,
+ sectors: [],
+ symbol: 'VTI',
+ tags: [],
+ transactionCount: 5,
+ url: 'https://www.vanguard.com',
+ valueInBaseCurrency: 15092
+ },
+ {
+ allocationInPercentage: 0.0836576192450555,
+ assetClass: 'EQUITY',
+ assetSubClass: 'ETF',
+ countries: [],
+ currency: 'CHF',
+ dataSource: 'YAHOO',
+ dateOfFirstActivity: new Date('2018-03-01T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 6462.42356864925,
+ grossPerformancePercent: 0.5463044783973836,
+ grossPerformancePercentWithCurrencyEffect: 0.6282343505275325,
+ grossPerformanceWithCurrencyEffect: 7121.935580698947,
+ holdings: [],
+ investment: 17336.464702612564,
+ marketPrice: 129.74,
+ name: 'Vanguard FTSE All-World UCITS ETF',
+ netPerformance: 6373.040578098944,
+ netPerformancePercent: 0.5387484388540966,
+ netPerformancePercentWithCurrencyEffect: 0.008409682389650015,
+ netPerformanceWithCurrencyEffect: 198.47200506226807,
+ quantity: 165,
+ sectors: [],
+ symbol: 'VWRL.SW',
+ tags: [],
+ transactionCount: 5,
+ url: 'https://www.vanguard.com',
+ valueInBaseCurrency: 23798.888271261814
+ },
+ {
+ allocationInPercentage: 0.03265192235898284,
+ assetClass: 'EQUITY',
+ assetSubClass: 'ETF',
+ countries: [],
+ currency: 'EUR',
+ dataSource: 'YAHOO',
+ dateOfFirstActivity: new Date('2021-08-19T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 3112.7991183879094,
+ grossPerformancePercent: 0.5040147846036197,
+ grossPerformancePercentWithCurrencyEffect: 0.3516875105542396,
+ grossPerformanceWithCurrencyEffect: 2416.799201046856,
+ holdings: [],
+ investment: 6176.007556675063,
+ marketPrice: 118.005,
+ name: 'Xtrackers MSCI World UCITS ETF 1C',
+ netPerformance: 3081.4179261125105,
+ netPerformancePercent: 0.4989336392216841,
+ netPerformancePercentWithCurrencyEffect: 0.006460676966633529,
+ netPerformanceWithCurrencyEffect: 59.626750161726044,
+ quantity: 75,
+ sectors: [],
+ symbol: 'XDWD.DE',
+ tags: [],
+ transactionCount: 1,
+ url: null,
+ valueInBaseCurrency: 9288.806675062973
+ },
+ {
+ allocationInPercentage: 0.17537283996478595,
+ assetClass: 'LIQUIDITY',
+ assetSubClass: 'CASH',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'MANUAL',
+ dateOfFirstActivity: new Date('2021-04-01T00:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 0,
+ grossPerformancePercent: 0,
+ grossPerformancePercentWithCurrencyEffect: 0,
+ grossPerformanceWithCurrencyEffect: 0,
+ holdings: [],
+ investment: 49890,
+ marketPrice: 0,
+ name: 'USD',
+ netPerformance: 0,
+ netPerformancePercent: 0,
+ netPerformancePercentWithCurrencyEffect: 0,
+ netPerformanceWithCurrencyEffect: 0,
+ quantity: 0,
+ sectors: [],
+ symbol: 'USD',
+ tags: [],
+ transactionCount: 0,
+ valueInBaseCurrency: 49890
+ }
+ ],
+ locale: 'en-US'
+ }
+};
diff --git a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
index 4c3167c9..8c5ee94d 100644
--- a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
+++ b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
@@ -342,24 +342,42 @@ export class GfTreemapChartComponent
}),
callbacks: {
label: (context) => {
+ const allocationInPercentage = `${((context.raw._data.allocationInPercentage as number) * 100).toFixed(2)}%`;
const name = context.raw._data.name;
+ const sign =
+ context.raw._data.netPerformancePercentWithCurrencyEffect > 0
+ ? '+'
+ : '';
const symbol = context.raw._data.symbol;
+ const netPerformanceInPercentageWithSign = `${sign}${(context.raw._data.netPerformancePercentWithCurrencyEffect * 100).toFixed(2)}%`;
+
if (context.raw._data.valueInBaseCurrency !== null) {
const value = context.raw._data.valueInBaseCurrency as number;
return [
- `${name ?? symbol}`,
+ `${name ?? symbol} (${allocationInPercentage})`,
`${value.toLocaleString(this.locale, {
maximumFractionDigits: 2,
minimumFractionDigits: 2
- })} ${this.baseCurrency}`
+ })} ${this.baseCurrency}`,
+ '',
+ $localize`Change` + ' (' + $localize`Performance` + ')',
+ `${sign}${context.raw._data.netPerformanceWithCurrencyEffect.toLocaleString(
+ this.locale,
+ {
+ maximumFractionDigits: 2,
+ minimumFractionDigits: 2
+ }
+ )} ${this.baseCurrency} (${netPerformanceInPercentageWithSign})`
];
} else {
- const percentage =
- (context.raw._data.allocationInPercentage as number) * 100;
-
- return [`${name ?? symbol}`, `${percentage.toFixed(2)}%`];
+ return [
+ `${name ?? symbol} (${allocationInPercentage})`,
+ '',
+ $localize`Performance`,
+ netPerformanceInPercentageWithSign
+ ];
}
},
title: () => {
diff --git a/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts b/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts
index e44c41aa..efb48c98 100644
--- a/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts
+++ b/libs/ui/src/lib/trend-indicator/trend-indicator.component.ts
@@ -1,6 +1,5 @@
import { DateRange, MarketState } from '@ghostfolio/common/types';
-import { CommonModule } from '@angular/common';
import {
CUSTOM_ELEMENTS_SCHEMA,
ChangeDetectionStrategy,
@@ -11,7 +10,7 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
- imports: [CommonModule, NgxSkeletonLoaderModule],
+ imports: [NgxSkeletonLoaderModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-trend-indicator',
styleUrls: ['./trend-indicator.component.scss'],