From f3d2de328660e3b79b9b4f308f2908af73e6a10e Mon Sep 17 00:00:00 2001
From: Thomas <4159106+dtslvr@users.noreply.github.com>
Date: Wed, 12 May 2021 21:58:22 +0200
Subject: [PATCH] Improve proportion charts

---
 CHANGELOG.md                                  |  6 ++
 .../portfolio-proportion-chart.component.ts   | 72 ++++++++++++-------
 package.json                                  |  2 +-
 yarn.lock                                     |  8 +--
 4 files changed, 59 insertions(+), 29 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb47651b7..ac499c9e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Changed
 
 - Harmonized the style of various tables
+- Keep the color per type when switching between _Initial_ and _Current_ in pie charts
+- Upgraded `chart.js` from version `3.0.2` to `3.2.1`
+
+### Fixed
+
+- Fixed the tooltips when switching between _Initial_ and _Current_ in pie charts
 
 ## 1.1.0 - 11.05.2021
 
diff --git a/apps/client/src/app/components/portfolio-proportion-chart/portfolio-proportion-chart.component.ts b/apps/client/src/app/components/portfolio-proportion-chart/portfolio-proportion-chart.component.ts
index d1cbd333e..6a4e808b1 100644
--- a/apps/client/src/app/components/portfolio-proportion-chart/portfolio-proportion-chart.component.ts
+++ b/apps/client/src/app/components/portfolio-proportion-chart/portfolio-proportion-chart.component.ts
@@ -36,6 +36,10 @@ export class PortfolioProportionChartComponent
   public chart: Chart;
   public isLoading = true;
 
+  private colorMap: {
+    [symbol: string]: string;
+  } = {};
+
   public constructor() {
     Chart.register(ArcElement, DoughnutController, LinearScale, Tooltip);
   }
@@ -48,37 +52,69 @@ export class PortfolioProportionChartComponent
     }
   }
 
+  public ngOnDestroy() {
+    this.chart?.destroy();
+  }
+
   private initialize() {
     this.isLoading = true;
-    const chartData: { [symbol: string]: number } = {};
+    const chartData: {
+      [symbol: string]: { color: string; value: number };
+    } = {};
 
     Object.keys(this.positions).forEach((symbol) => {
       if (this.positions[symbol][this.key]) {
         if (chartData[this.positions[symbol][this.key]]) {
-          chartData[this.positions[symbol][this.key]] += this.positions[
+          chartData[this.positions[symbol][this.key]].value += this.positions[
             symbol
           ].value;
         } else {
-          chartData[this.positions[symbol][this.key]] = this.positions[
-            symbol
-          ].value;
+          chartData[this.positions[symbol][this.key]] = {
+            color: 'red',
+            value: this.positions[symbol].value
+          };
+        }
+      } else {
+        if (chartData['Other']) {
+          chartData['Other'].value += this.positions[symbol].value;
+        } else {
+          chartData['Other'] = {
+            color: 'red',
+            value: this.positions[symbol].value
+          };
         }
       }
     });
 
     const chartDataSorted = Object.entries(chartData)
       .sort((a, b) => {
-        return a[1] - b[1];
+        return a[1].value - b[1].value;
       })
       .reverse();
 
+    chartDataSorted.forEach(([symbol, item], index) => {
+      if (this.colorMap[symbol]) {
+        // Reuse color
+        item.color = this.colorMap[symbol];
+      } else {
+        const color = this.getColorPalette()[index];
+
+        // Store color for reuse
+        this.colorMap[symbol] = color;
+
+        item.color = color;
+      }
+    });
+
     const data = {
       datasets: [
         {
-          backgroundColor: this.getColorPalette(),
+          backgroundColor: chartDataSorted.map(([, item]) => {
+            return item.color;
+          }),
           borderWidth: 0,
-          data: chartDataSorted.map(([, value]) => {
-            return value;
+          data: chartDataSorted.map(([, item]) => {
+            return item.value;
           })
         }
       ],
@@ -100,21 +136,13 @@ export class PortfolioProportionChartComponent
               tooltip: {
                 callbacks: {
                   label: (context) => {
-                    const label = data.labels[context.dataIndex];
+                    const label = context.label;
 
                     if (this.isInPercent) {
-                      const value =
-                        100 *
-                        data.datasets[context.datasetIndex].data[
-                          context.dataIndex
-                        ];
+                      const value = 100 * <number>context.raw;
                       return `${label} (${value.toFixed(2)}%)`;
                     } else {
-                      const value =
-                        data.datasets[context.datasetIndex].data[
-                          context.dataIndex
-                        ];
-
+                      const value = <number>context.raw;
                       return `${label} (${value.toLocaleString(this.locale, {
                         maximumFractionDigits: 2,
                         minimumFractionDigits: 2
@@ -153,8 +181,4 @@ export class PortfolioProportionChartComponent
       '#cc5de8' // grape 5
     ];
   }
-
-  public ngOnDestroy() {
-    this.chart?.destroy();
-  }
 }
diff --git a/package.json b/package.json
index ed8f36650..3add8b483 100644
--- a/package.json
+++ b/package.json
@@ -71,7 +71,7 @@
     "bootstrap": "4.6.0",
     "cache-manager": "3.4.3",
     "cache-manager-redis-store": "2.0.0",
-    "chart.js": "3.0.2",
+    "chart.js": "3.2.1",
     "chartjs-adapter-date-fns": "1.1.0-beta.1",
     "chartjs-chart-timeline": "0.4.0",
     "cheerio": "1.0.0-rc.6",
diff --git a/yarn.lock b/yarn.lock
index 24031cfe0..a7d688a64 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4066,10 +4066,10 @@ chardet@^0.7.0:
   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
 
-chart.js@3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.0.2.tgz#5893b0548714445b5190cbda9ac307357a56a0c7"
-  integrity sha512-DR0GmFSlxcFJp/w//ZmbxSduAkH/AqwxoiZxK97KHnWZf6gvsKWS3160WvNMMHYvzW9OXqGWjPjVh1Qu+xDabg==
+chart.js@3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.2.1.tgz#1a17d6a88cef324ef711949e227eb51d6c4c26d3"
+  integrity sha512-XsNDf3854RGZkLCt+5vWAXGAtUdKP2nhfikLGZqud6G4CvRE2ts64TIxTTfspOin2kEZvPgomE29E6oU02dYjQ==
 
 chartjs-adapter-date-fns@1.1.0-beta.1:
   version "1.1.0-beta.1"