Merge branch 'main' of github.com:ghostfolio/ghostfolio
All checks were successful
Docker image CD / build_and_push (push) Successful in 29m55s
All checks were successful
Docker image CD / build_and_push (push) Successful in 29m55s
This commit is contained in:
commit
2413244bf1
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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'],
|
||||
|
@ -175,6 +175,9 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
|
||||
]
|
||||
});
|
||||
}),
|
||||
switchMap(() => {
|
||||
return this.userService.get(true);
|
||||
}),
|
||||
takeUntil(this.unsubscribeSubject)
|
||||
)
|
||||
.subscribe();
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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'
|
||||
|
@ -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,
|
||||
|
@ -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'
|
||||
|
@ -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,
|
||||
|
@ -1,9 +1,16 @@
|
||||
<small class="text-muted">
|
||||
<ng-container i18n>Market data provided by</ng-container> <ng-container
|
||||
*ngFor="let dataProviderInfo of dataProviderInfos; let last = last"
|
||||
><a target="_blank" [href]="dataProviderInfo.url">{{
|
||||
<ng-container i18n>Market data provided by</ng-container>
|
||||
@for (
|
||||
dataProviderInfo of dataProviderInfos;
|
||||
track dataProviderInfo;
|
||||
let last = $last
|
||||
) {
|
||||
<a target="_blank" [href]="dataProviderInfo.url">{{
|
||||
dataProviderInfo.name
|
||||
}}</a
|
||||
><ng-container *ngIf="!last">, </ng-container></ng-container
|
||||
>.
|
||||
}}</a>
|
||||
@if (!last) {
|
||||
,
|
||||
}
|
||||
}
|
||||
.
|
||||
</small>
|
||||
|
@ -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'],
|
||||
|
@ -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,
|
||||
|
392
libs/ui/src/lib/treemap-chart/treemap-chart.component.stories.ts
Normal file
392
libs/ui/src/lib/treemap-chart/treemap-chart.component.stories.ts
Normal file
@ -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<GfTreemapChartComponent>;
|
||||
|
||||
type Story = StoryObj<GfTreemapChartComponent>;
|
||||
|
||||
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'
|
||||
}
|
||||
};
|
@ -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: () => {
|
||||
|
@ -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'],
|
||||
|
Loading…
x
Reference in New Issue
Block a user