From 3ec4a73b35416103f00772711e134203cbcf5506 Mon Sep 17 00:00:00 2001
From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
Date: Sat, 2 Oct 2021 20:38:41 +0200
Subject: [PATCH] Feature/improve tooltips (#403)
* Improve tooltips
* Update changelog
---
CHANGELOG.md | 1 +
.../world-map-chart.component.ts | 17 +++++++-
.../allocations/allocations-page.component.ts | 40 +++++++++++++++----
.../allocations/allocations-page.html | 17 ++++----
.../portfolio-proportion-chart.component.ts | 37 ++++++++++++-----
5 files changed, 87 insertions(+), 25 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a551c83..f273bc66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Improved the symbol conversion for _Yahoo Finance_: Support for _Solana USD_ (`SOL1-USD`)
+- Improved the tooltips of the allocations page
- Upgraded `envalid` from version `7.1.0` to `7.2.1`
## 1.57.0 - 29.09.2021
diff --git a/apps/client/src/app/components/world-map-chart/world-map-chart.component.ts b/apps/client/src/app/components/world-map-chart/world-map-chart.component.ts
index 85f5bc69..3b2f3b72 100644
--- a/apps/client/src/app/components/world-map-chart/world-map-chart.component.ts
+++ b/apps/client/src/app/components/world-map-chart/world-map-chart.component.ts
@@ -18,6 +18,7 @@ import svgMap from 'svgmap';
export class WorldMapChartComponent implements OnChanges, OnDestroy, OnInit {
@Input() baseCurrency: string;
@Input() countries: { [code: string]: { name: string; value: number } };
+ @Input() isInPercent = false;
public isLoading = true;
public svgMapElement;
@@ -41,6 +42,20 @@ export class WorldMapChartComponent implements OnChanges, OnDestroy, OnInit {
}
private initialize() {
+ if (this.isInPercent) {
+ // Convert value of countries to percentage
+ let sum = 0;
+ Object.keys(this.countries).map((country) => {
+ sum += this.countries[country].value;
+ });
+
+ Object.keys(this.countries).map((country) => {
+ this.countries[country].value = Number(
+ ((this.countries[country].value * 100) / sum).toFixed(2)
+ );
+ });
+ }
+
this.svgMapElement = new svgMap({
colorMax: '#22bdb9',
colorMin: '#c3f1f0',
@@ -49,7 +64,7 @@ export class WorldMapChartComponent implements OnChanges, OnDestroy, OnInit {
applyData: 'value',
data: {
value: {
- format: `{0} ${this.baseCurrency}`
+ format: this.isInPercent ? `{0}%` : `{0} ${this.baseCurrency}`
}
},
values: this.countries
diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
index dd9ef0c1..de29311a 100644
--- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
+++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
@@ -37,13 +37,23 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
{ label: 'Current', value: 'current' }
];
public portfolioDetails: PortfolioDetails;
- public positions: { [symbol: string]: any };
+ public positions: {
+ [symbol: string]: Pick<
+ PortfolioPosition,
+ | 'assetClass'
+ | 'assetSubClass'
+ | 'currency'
+ | 'exchange'
+ | 'name'
+ | 'value'
+ >;
+ };
public positionsArray: PortfolioPosition[];
public sectors: {
[name: string]: { name: string; value: number };
};
public symbols: {
- [name: string]: { name: string; value: number };
+ [name: string]: { name: string; symbol: string; value: number };
};
public user: User;
@@ -121,6 +131,7 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
this.symbols = {
[UNKNOWN_KEY]: {
name: UNKNOWN_KEY,
+ symbol: UNKNOWN_KEY,
value: 0
}
};
@@ -137,15 +148,29 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
for (const [symbol, position] of Object.entries(
this.portfolioDetails.holdings
)) {
+ let value = 0;
+
+ if (aPeriod === 'original') {
+ if (this.hasImpersonationId) {
+ value = position.allocationInvestment;
+ } else {
+ value = position.investment;
+ }
+ } else {
+ if (this.hasImpersonationId) {
+ value = position.allocationCurrent;
+ } else {
+ value = position.value;
+ }
+ }
+
this.positions[symbol] = {
+ value,
assetClass: position.assetClass,
assetSubClass: position.assetSubClass,
currency: position.currency,
exchange: position.exchange,
- value:
- aPeriod === 'original'
- ? position.allocationInvestment
- : position.allocationCurrent
+ name: position.name
};
this.positionsArray.push(position);
@@ -221,7 +246,8 @@ export class AllocationsPageComponent implements OnDestroy, OnInit {
if (position.assetClass === AssetClass.EQUITY) {
this.symbols[symbol] = {
- name: symbol,
+ symbol,
+ name: position.name,
value: aPeriod === 'original' ? position.investment : position.value
};
}
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 eee9081d..eb8a4a71 100644
--- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.html
+++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.html
@@ -19,7 +19,7 @@
diff --git a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts
index 917a1fe6..cf65e44f 100644
--- a/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts
+++ b/libs/ui/src/lib/portfolio-proportion-chart/portfolio-proportion-chart.component.ts
@@ -35,7 +35,10 @@ export class PortfolioProportionChartComponent
@Input() maxItems?: number;
@Input() showLabels = false;
@Input() positions: {
- [symbol: string]: Pick & { value: number };
+ [symbol: string]: Pick & {
+ name: string;
+ value: number;
+ };
} = {};
@ViewChild('chartCanvas') chartCanvas: ElementRef;
@@ -80,6 +83,7 @@ export class PortfolioProportionChartComponent
const chartData: {
[symbol: string]: {
color?: string;
+ name: string;
subCategory: { [symbol: string]: { value: number } };
value: number;
};
@@ -106,6 +110,7 @@ export class PortfolioProportionChartComponent
}
} else {
chartData[this.positions[symbol][this.keys[0]]] = {
+ name: this.positions[symbol].name,
subCategory: {},
value: this.positions[symbol].value
};
@@ -123,6 +128,7 @@ export class PortfolioProportionChartComponent
chartData[UNKNOWN_KEY].value += this.positions[symbol].value;
} else {
chartData[UNKNOWN_KEY] = {
+ name: this.positions[symbol].name,
subCategory: this.keys[1]
? { [this.keys[1]]: { value: 0 } }
: undefined,
@@ -152,7 +158,7 @@ export class PortfolioProportionChartComponent
if (!unknownItem) {
const index = chartDataSorted.push([
UNKNOWN_KEY,
- { subCategory: {}, value: 0 }
+ { name: UNKNOWN_KEY, subCategory: {}, value: 0 }
]);
unknownItem = chartDataSorted[index];
}
@@ -160,6 +166,7 @@ export class PortfolioProportionChartComponent
rest.forEach((restItem) => {
if (unknownItem?.[1]) {
unknownItem[1] = {
+ name: UNKNOWN_KEY,
subCategory: {},
value: unknownItem[1].value + restItem[1].value
};
@@ -278,17 +285,29 @@ export class PortfolioProportionChartComponent
const labelIndex =
(data.datasets[context.datasetIndex - 1]?.data?.length ??
0) + context.dataIndex;
- const label = context.chart.data.labels?.[labelIndex] ?? '';
+ const symbol =
+ context.chart.data.labels?.[labelIndex] ?? '';
+
+ const name = this.positions[symbol]?.name;
+
+ let sum = 0;
+ context.dataset.data.map((item) => {
+ sum += item;
+ });
+
+ const percentage = (context.parsed * 100) / sum;
if (this.isInPercent) {
- const value = 100 * context.raw;
- return `${label} (${value.toFixed(2)}%)`;
+ return `${name ?? symbol} (${percentage.toFixed(2)}%)`;
} else {
const value = context.raw;
- return `${label} (${value.toLocaleString(this.locale, {
- maximumFractionDigits: 2,
- minimumFractionDigits: 2
- })} ${this.baseCurrency})`;
+ return `${name ?? symbol}: ${value.toLocaleString(
+ this.locale,
+ {
+ maximumFractionDigits: 2,
+ minimumFractionDigits: 2
+ }
+ )} ${this.baseCurrency} (${percentage.toFixed(2)}%)`;
}
}
}