|
|
@ -22,11 +22,16 @@ import { |
|
|
} from '@angular/core'; |
|
|
} from '@angular/core'; |
|
|
import { DataSource } from '@prisma/client'; |
|
|
import { DataSource } from '@prisma/client'; |
|
|
import { Big } from 'big.js'; |
|
|
import { Big } from 'big.js'; |
|
|
import { ChartConfiguration, Tooltip } from 'chart.js'; |
|
|
import { |
|
|
import { LinearScale } from 'chart.js'; |
|
|
ArcElement, |
|
|
import { ArcElement } from 'chart.js'; |
|
|
Chart, |
|
|
import { DoughnutController } from 'chart.js'; |
|
|
type ChartData, |
|
|
import { Chart } from 'chart.js'; |
|
|
type ChartDataset, |
|
|
|
|
|
DoughnutController, |
|
|
|
|
|
LinearScale, |
|
|
|
|
|
Tooltip, |
|
|
|
|
|
type TooltipOptions |
|
|
|
|
|
} from 'chart.js'; |
|
|
import ChartDataLabels from 'chartjs-plugin-datalabels'; |
|
|
import ChartDataLabels from 'chartjs-plugin-datalabels'; |
|
|
import { isUUID } from 'class-validator'; |
|
|
import { isUUID } from 'class-validator'; |
|
|
import Color from 'color'; |
|
|
import Color from 'color'; |
|
|
@ -286,7 +291,7 @@ export class GfPortfolioProportionChartComponent |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
const datasets: ChartConfiguration<'doughnut'>['data']['datasets'] = [ |
|
|
const datasets: ChartDataset<'doughnut'>[] = [ |
|
|
{ |
|
|
{ |
|
|
backgroundColor: chartDataSorted.map(([, item]) => { |
|
|
backgroundColor: chartDataSorted.map(([, item]) => { |
|
|
return item.color; |
|
|
return item.color; |
|
|
@ -324,7 +329,7 @@ export class GfPortfolioProportionChartComponent |
|
|
datasets[1].data[1] = Number.MAX_SAFE_INTEGER; |
|
|
datasets[1].data[1] = Number.MAX_SAFE_INTEGER; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const data: ChartConfiguration<'doughnut'>['data'] = { |
|
|
const data: ChartData<'doughnut'> = { |
|
|
datasets, |
|
|
datasets, |
|
|
labels |
|
|
labels |
|
|
}; |
|
|
}; |
|
|
@ -332,9 +337,9 @@ export class GfPortfolioProportionChartComponent |
|
|
if (this.chartCanvas) { |
|
|
if (this.chartCanvas) { |
|
|
if (this.chart) { |
|
|
if (this.chart) { |
|
|
this.chart.data = data; |
|
|
this.chart.data = data; |
|
|
this.chart.options.plugins.tooltip = this.getTooltipPluginConfiguration( |
|
|
this.chart.options.plugins ??= {}; |
|
|
data |
|
|
this.chart.options.plugins.tooltip = |
|
|
) as unknown; |
|
|
this.getTooltipPluginConfiguration(data); |
|
|
this.chart.update(); |
|
|
this.chart.update(); |
|
|
} else { |
|
|
} else { |
|
|
this.chart = new Chart<'doughnut'>(this.chartCanvas.nativeElement, { |
|
|
this.chart = new Chart<'doughnut'>(this.chartCanvas.nativeElement, { |
|
|
@ -345,21 +350,22 @@ export class GfPortfolioProportionChartComponent |
|
|
layout: { |
|
|
layout: { |
|
|
padding: this.showLabels === true ? 100 : 0 |
|
|
padding: this.showLabels === true ? 100 : 0 |
|
|
}, |
|
|
}, |
|
|
onClick: (event, activeElements) => { |
|
|
onClick: (_, activeElements, chart) => { |
|
|
try { |
|
|
try { |
|
|
const dataIndex = activeElements[0].index; |
|
|
const dataIndex = activeElements[0].index; |
|
|
const symbol: string = event.chart.data.labels[dataIndex]; |
|
|
const symbol = chart.data.labels?.[dataIndex] as string; |
|
|
|
|
|
|
|
|
const dataSource = this.data[symbol]?.dataSource; |
|
|
const dataSource = this.data[symbol].dataSource; |
|
|
|
|
|
|
|
|
this.proportionChartClicked.emit({ dataSource, symbol }); |
|
|
if (dataSource) { |
|
|
|
|
|
this.proportionChartClicked.emit({ dataSource, symbol }); |
|
|
|
|
|
} |
|
|
} catch {} |
|
|
} catch {} |
|
|
}, |
|
|
}, |
|
|
onHover: (event, chartElement) => { |
|
|
onHover: (event, chartElement) => { |
|
|
if (this.cursor) { |
|
|
if (this.cursor) { |
|
|
event.native.target.style.cursor = chartElement[0] |
|
|
(event.native?.target as HTMLElement).style.cursor = |
|
|
? this.cursor |
|
|
chartElement[0] ? this.cursor : 'default'; |
|
|
: 'default'; |
|
|
|
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
plugins: { |
|
|
plugins: { |
|
|
@ -392,7 +398,7 @@ export class GfPortfolioProportionChartComponent |
|
|
legend: { display: false }, |
|
|
legend: { display: false }, |
|
|
tooltip: this.getTooltipPluginConfiguration(data) |
|
|
tooltip: this.getTooltipPluginConfiguration(data) |
|
|
} |
|
|
} |
|
|
} as unknown, |
|
|
}, |
|
|
plugins: [ChartDataLabels], |
|
|
plugins: [ChartDataLabels], |
|
|
type: 'doughnut' |
|
|
type: 'doughnut' |
|
|
}); |
|
|
}); |
|
|
@ -419,19 +425,23 @@ export class GfPortfolioProportionChartComponent |
|
|
]; |
|
|
]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private getTooltipPluginConfiguration(data: ChartConfiguration['data']) { |
|
|
private getTooltipPluginConfiguration( |
|
|
|
|
|
data: ChartData<'doughnut'> |
|
|
|
|
|
): Partial<TooltipOptions<'doughnut'>> { |
|
|
return { |
|
|
return { |
|
|
...getTooltipOptions({ |
|
|
...getTooltipOptions({ |
|
|
colorScheme: this.colorScheme, |
|
|
colorScheme: this.colorScheme, |
|
|
currency: this.baseCurrency, |
|
|
currency: this.baseCurrency, |
|
|
locale: this.locale |
|
|
locale: this.locale |
|
|
}), |
|
|
}), |
|
|
|
|
|
// @ts-expect-error: no need to set all attributes in callbacks.
|
|
|
callbacks: { |
|
|
callbacks: { |
|
|
label: (context) => { |
|
|
label: (context) => { |
|
|
const labelIndex = |
|
|
const labelIndex = |
|
|
(data.datasets[context.datasetIndex - 1]?.data?.length ?? 0) + |
|
|
(data.datasets[context.datasetIndex - 1]?.data?.length ?? 0) + |
|
|
context.dataIndex; |
|
|
context.dataIndex; |
|
|
let symbol = context.chart.data.labels?.[labelIndex] ?? ''; |
|
|
let symbol = |
|
|
|
|
|
(context.chart.data.labels?.[labelIndex] as string) ?? ''; |
|
|
|
|
|
|
|
|
if (symbol === this.OTHER_KEY) { |
|
|
if (symbol === this.OTHER_KEY) { |
|
|
symbol = $localize`Other`; |
|
|
symbol = $localize`Other`; |
|
|
@ -439,7 +449,7 @@ export class GfPortfolioProportionChartComponent |
|
|
symbol = $localize`No data available`; |
|
|
symbol = $localize`No data available`; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const name = translate(this.data[symbol as string]?.name); |
|
|
const name = translate(this.data[symbol]?.name); |
|
|
|
|
|
|
|
|
let sum = 0; |
|
|
let sum = 0; |
|
|
for (const item of context.dataset.data) { |
|
|
for (const item of context.dataset.data) { |
|
|
|