diff --git a/CHANGELOG.md b/CHANGELOG.md index 58dd3fdbc..0d6ba5d26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added a tooltip to the chart of the holdings tab on the home page (experimental) - Extended the _Public API_ with the health check endpoint (experimental) ### Changed diff --git a/apps/client/src/app/components/home-holdings/home-holdings.html b/apps/client/src/app/components/home-holdings/home-holdings.html index 01afe31a2..f1c4e7e88 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.html +++ b/apps/client/src/app/components/home-holdings/home-holdings.html @@ -38,8 +38,11 @@ } 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 8915707fa..b278180ea 100644 --- a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts +++ b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -2,11 +2,13 @@ import { getAnnualizedPerformancePercent, getIntervalFromDateRange } from '@ghostfolio/common/calculation-helper'; +import { getTooltipOptions } from '@ghostfolio/common/chart-helper'; +import { getLocale } from '@ghostfolio/common/helper'; import { AssetProfileIdentifier, PortfolioPosition } from '@ghostfolio/common/interfaces'; -import { DateRange } from '@ghostfolio/common/types'; +import { ColorScheme, DateRange } from '@ghostfolio/common/types'; import { CommonModule } from '@angular/common'; import { @@ -25,7 +27,7 @@ import { DataSource } from '@prisma/client'; import { Big } from 'big.js'; import { ChartConfiguration } from 'chart.js'; import { LinearScale } from 'chart.js'; -import { Chart } from 'chart.js'; +import { Chart, Tooltip } from 'chart.js'; import { TreemapController, TreemapElement } from 'chartjs-chart-treemap'; import { differenceInDays, max } from 'date-fns'; import { orderBy } from 'lodash'; @@ -44,9 +46,12 @@ const { gray, green, red } = require('open-color'); export class GfTreemapChartComponent implements AfterViewInit, OnChanges, OnDestroy { + @Input() baseCurrency: string; + @Input() colorScheme: ColorScheme; @Input() cursor: string; @Input() dateRange: DateRange; @Input() holdings: PortfolioPosition[]; + @Input() locale = getLocale(); @Output() treemapChartClicked = new EventEmitter(); @@ -58,7 +63,7 @@ export class GfTreemapChartComponent public isLoading = true; public constructor() { - Chart.register(LinearScale, TreemapController, TreemapElement); + Chart.register(LinearScale, Tooltip, TreemapController, TreemapElement); } public ngAfterViewInit() { @@ -168,6 +173,9 @@ export class GfTreemapChartComponent if (this.chartCanvas) { if (this.chart) { this.chart.data = data; + this.chart.options.plugins.tooltip = ( + this.getTooltipPluginConfiguration() + ); this.chart.update(); } else { this.chart = new Chart(this.chartCanvas.nativeElement, { @@ -199,9 +207,7 @@ export class GfTreemapChartComponent } }, plugins: { - tooltip: { - enabled: false - } + tooltip: this.getTooltipPluginConfiguration() } }, type: 'treemap' @@ -211,4 +217,34 @@ export class GfTreemapChartComponent this.isLoading = false; } + + private getTooltipPluginConfiguration() { + return { + ...getTooltipOptions({ + colorScheme: this.colorScheme, + currency: this.baseCurrency, + locale: this.locale + }), + callbacks: { + label: (context) => { + if (context.raw._data.valueInBaseCurrency !== null) { + const value = context.raw._data.valueInBaseCurrency; + return `${value.toLocaleString(this.locale, { + maximumFractionDigits: 2, + minimumFractionDigits: 2 + })} ${this.baseCurrency}`; + } else { + const percentage = + context.raw._data.allocationInPercentage * 100; + return `${percentage.toFixed(2)}%`; + } + }, + title: () => { + return ''; + } + }, + xAlign: 'center', + yAlign: 'center' + }; + } }