Skip to content

Commit 7a32c27

Browse files
committed
fix them
1 parent eeba54b commit 7a32c27

File tree

17 files changed

+263
-26
lines changed

17 files changed

+263
-26
lines changed

src/app/reports/run-report/chart/chart.component.html

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,27 @@
66
file, You can obtain one at http://mozilla.org/MPL/2.0/.
77
-->
88

9-
<div class="m-b-20 layout-align-end">
10-
<mat-button-toggle-group aria-label="Select Chart Type">
11-
<mat-button-toggle value="Bar" (click)="setBarChart(inputData)">{{
12-
'labels.buttons.Bar Chart' | translate
13-
}}</mat-button-toggle>
14-
<mat-button-toggle value="Pie" (click)="setPieChart(inputData)">{{
15-
'labels.buttons.Pie Chart' | translate
16-
}}</mat-button-toggle>
17-
</mat-button-toggle-group>
18-
</div>
9+
<div class="p-20 m-b-20">
10+
<div class="layout-align-end m-b-20">
11+
<mat-button-toggle-group
12+
[value]="selectedChartType"
13+
[disabled]="hideOutput"
14+
aria-label="{{ 'labels.buttons.Select Chart Type' | translate }}"
15+
(change)="selectChart($event.value)"
16+
>
17+
<mat-button-toggle value="Bar" (click)="refreshChartIfSameType('Bar')">{{
18+
'labels.buttons.Bar Chart' | translate
19+
}}</mat-button-toggle>
20+
<mat-button-toggle value="Pie" (click)="refreshChartIfSameType('Pie')">{{
21+
'labels.buttons.Pie Chart' | translate
22+
}}</mat-button-toggle>
23+
<mat-button-toggle value="Polar" (click)="refreshChartIfSameType('Polar')">{{
24+
'labels.buttons.Polar Area Chart' | translate
25+
}}</mat-button-toggle>
26+
</mat-button-toggle-group>
27+
</div>
1928

20-
<div [ngStyle]="{ display: hideOutput ? 'none' : 'block' }">
21-
<canvas id="output"></canvas>
29+
<div [ngStyle]="{ display: hideOutput ? 'none' : 'block' }" class="chart-output-container">
30+
<canvas id="output"></canvas>
31+
</div>
2232
</div>

src/app/reports/run-report/chart/chart.component.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,14 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
77
*/
8+
9+
.chart-output-container {
10+
position: relative;
11+
width: 100%;
12+
height: 500px;
13+
14+
canvas {
15+
width: 100% !important;
16+
height: 100% !important;
17+
}
18+
}

src/app/reports/run-report/chart/chart.component.ts

Lines changed: 203 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
*/
88

99
/** Angular Imports */
10-
import { Component, OnChanges, Input, inject } from '@angular/core';
10+
import { Component, OnChanges, OnInit, OnDestroy, Input, inject } from '@angular/core';
1111

1212
/** Custom Services */
1313
import { ReportsService } from '../../reports.service';
14+
import { ThemeStorageService } from 'app/shared/theme-picker/theme-storage.service';
1415

1516
/** Custom Models */
1617
import { ChartData } from '../../common-models/chart-data.model';
@@ -38,8 +39,11 @@ Chart.register(...registerables);
3839
NgStyle
3940
]
4041
})
41-
export class ChartComponent implements OnChanges {
42+
export class ChartComponent implements OnChanges, OnInit, OnDestroy {
4243
private reportsService = inject(ReportsService);
44+
private themeStorageService = inject(ThemeStorageService);
45+
private resizeTimeoutId: ReturnType<typeof setTimeout> | undefined;
46+
private initialRenderTimeoutId: ReturnType<typeof setTimeout> | undefined;
4347

4448
/** Run Report Data */
4549
@Input() dataObject: any;
@@ -50,6 +54,52 @@ export class ChartComponent implements OnChanges {
5054
hideOutput = true;
5155
/** Data object for witching charts in view. */
5256
inputData: ChartData;
57+
/** Tracks the currently selected chart type */
58+
selectedChartType: string = 'Pie';
59+
/** Resize listener */
60+
private readonly resizeListener = () => this.resizeChart();
61+
62+
/**
63+
* Initialize component and add resize listener.
64+
*/
65+
ngOnInit() {
66+
window.addEventListener('resize', this.resizeListener);
67+
}
68+
69+
/**
70+
* Clean up on component destroy.
71+
*/
72+
ngOnDestroy() {
73+
window.removeEventListener('resize', this.resizeListener);
74+
if (this.resizeTimeoutId !== undefined) {
75+
clearTimeout(this.resizeTimeoutId);
76+
this.resizeTimeoutId = undefined;
77+
}
78+
if (this.initialRenderTimeoutId !== undefined) {
79+
clearTimeout(this.initialRenderTimeoutId);
80+
this.initialRenderTimeoutId = undefined;
81+
}
82+
if (this.chart) {
83+
this.chart.destroy();
84+
this.chart = undefined;
85+
}
86+
}
87+
88+
/**
89+
* Resize and redraw chart when window size changes.
90+
*/
91+
resizeChart() {
92+
if (this.chart) {
93+
if (this.resizeTimeoutId !== undefined) {
94+
clearTimeout(this.resizeTimeoutId);
95+
}
96+
// Debounce resize calls to avoid queuing multiple chart operations.
97+
this.resizeTimeoutId = setTimeout(() => {
98+
this.chart?.resize();
99+
this.resizeTimeoutId = undefined;
100+
}, 100);
101+
}
102+
}
53103

54104
/**
55105
* Fetches run report data post changes in run report form.
@@ -63,19 +113,59 @@ export class ChartComponent implements OnChanges {
63113
.getChartRunReportData(this.dataObject.report.name, this.dataObject.formData)
64114
.subscribe((response: ChartData) => {
65115
this.inputData = response;
66-
this.setPieChart(this.inputData);
116+
this.selectedChartType = 'Pie';
67117
this.hideOutput = false;
118+
if (this.initialRenderTimeoutId !== undefined) {
119+
clearTimeout(this.initialRenderTimeoutId);
120+
}
121+
this.initialRenderTimeoutId = setTimeout(() => {
122+
this.setPieChart(response);
123+
this.initialRenderTimeoutId = undefined;
124+
});
68125
});
69126
}
70127

128+
/**
129+
* Handles chart type selection and renders the selected chart.
130+
* @param {string} chartType The type of chart to display
131+
*/
132+
selectChart(chartType: string) {
133+
if (!this.inputData) {
134+
return;
135+
}
136+
const chartColors = this.randomColorArray(this.inputData.values.length);
137+
this.selectedChartType = chartType;
138+
switch (chartType) {
139+
case 'Bar':
140+
this.setBarChart(this.inputData, chartColors);
141+
break;
142+
case 'Pie':
143+
this.setPieChart(this.inputData, chartColors);
144+
break;
145+
case 'Polar':
146+
this.setPolarAreaChart(this.inputData, chartColors);
147+
break;
148+
}
149+
}
150+
151+
/**
152+
* Refreshes colors when user clicks the currently selected toggle.
153+
*/
154+
refreshChartIfSameType(chartType: string) {
155+
if (chartType === this.selectedChartType) {
156+
this.selectChart(chartType);
157+
}
158+
}
159+
71160
/**
72161
* Creates instance of chart.js pie chart.
73162
* Refer: https://www.chartjs.org/docs/latest/charts/doughnut.html for configuration details.
74163
*/
75-
setPieChart(inputData: ChartData) {
164+
setPieChart(inputData: ChartData, chartColors?: string[]) {
76165
if (this.chart) {
77166
this.chart.destroy();
78167
}
168+
const colors = chartColors ?? this.randomColorArray(inputData.values.length);
79169
this.chart = new Chart('output', {
80170
type: 'pie',
81171
data: {
@@ -84,11 +174,13 @@ export class ChartComponent implements OnChanges {
84174
{
85175
label: inputData.valuesLabel,
86176
data: inputData.values,
87-
backgroundColor: this.randomColorArray(inputData.values.length)
177+
backgroundColor: colors
88178
}
89179
]
90180
},
91181
options: {
182+
responsive: true,
183+
maintainAspectRatio: false,
92184
plugins: {
93185
title: {
94186
display: true,
@@ -103,10 +195,11 @@ export class ChartComponent implements OnChanges {
103195
* Creates instance of chart.js bar chart.
104196
* Refer: https://www.chartjs.org/docs/latest/charts/bar.html for configuration details.
105197
*/
106-
setBarChart(inputData: ChartData) {
198+
setBarChart(inputData: ChartData, chartColors?: string[]) {
107199
if (this.chart) {
108200
this.chart.destroy();
109201
}
202+
const colors = chartColors ?? this.randomColorArray(inputData.values.length);
110203
this.chart = new Chart('output', {
111204
type: 'bar',
112205
data: {
@@ -115,11 +208,13 @@ export class ChartComponent implements OnChanges {
115208
{
116209
label: inputData.valuesLabel,
117210
data: inputData.values,
118-
backgroundColor: this.randomColorArray(inputData.values.length)
211+
backgroundColor: colors
119212
}
120213
]
121214
},
122215
options: {
216+
responsive: true,
217+
maintainAspectRatio: false,
123218
plugins: {
124219
legend: { display: false }
125220
},
@@ -138,12 +233,53 @@ export class ChartComponent implements OnChanges {
138233
});
139234
}
140235

236+
/**
237+
* Creates instance of chart.js polar area chart.
238+
* Refer: https://www.chartjs.org/docs/latest/charts/polar.html for configuration details.
239+
*/
240+
setPolarAreaChart(inputData: ChartData, chartColors?: string[]) {
241+
if (this.chart) {
242+
this.chart.destroy();
243+
}
244+
const colors = chartColors ?? this.randomColorArray(inputData.values.length);
245+
this.chart = new Chart('output', {
246+
type: 'polarArea',
247+
data: {
248+
labels: inputData.keys,
249+
datasets: [
250+
{
251+
label: inputData.valuesLabel,
252+
data: inputData.values,
253+
backgroundColor: colors,
254+
borderColor: colors
255+
}
256+
]
257+
},
258+
options: {
259+
responsive: true,
260+
maintainAspectRatio: false,
261+
plugins: {
262+
title: {
263+
display: true,
264+
text: inputData.keysLabel
265+
},
266+
legend: { display: true }
267+
},
268+
scales: {
269+
r: {
270+
min: 0
271+
}
272+
}
273+
}
274+
});
275+
}
276+
141277
/**
142278
* Generates bar/pie-slice colors array for dynamic charts.
143279
* @param {number} length Length of dataset array.
144280
*/
145281
randomColorArray(length: number) {
146-
const colorArray: any[] = [];
282+
const colorArray: string[] = [];
147283
while (length--) {
148284
const color = this.randomColor();
149285
colorArray.push(color);
@@ -152,12 +288,66 @@ export class ChartComponent implements OnChanges {
152288
}
153289

154290
/**
155-
* Returns a random rgb color.
291+
* Returns a semi-random color based on the active theme palette.
156292
*/
157293
randomColor() {
158-
const r = Math.floor(Math.random() * 255);
159-
const g = Math.floor(Math.random() * 255);
160-
const b = Math.floor(Math.random() * 255);
161-
return `rgb(${r},${g},${b},0.6)`;
294+
const baseColors = this.getThemeBaseColors();
295+
const baseColor = baseColors[Math.floor(Math.random() * baseColors.length)];
296+
const variation = Math.floor(Math.random() * 61) - 30;
297+
const [
298+
r,
299+
g,
300+
b
301+
] = this.hexToRgb(baseColor).map((channel) => this.clamp(channel + variation));
302+
return `rgba(${r},${g},${b},0.6)`;
303+
}
304+
305+
/**
306+
* Derives chart base colors from the user's selected theme and current dark mode.
307+
*/
308+
private getThemeBaseColors(): string[] {
309+
const savedTheme = this.themeStorageService.getTheme();
310+
const primary = savedTheme?.primary || '#1074B9';
311+
const accent = savedTheme?.accent || '#B4D575';
312+
const isDark = document.body.classList.contains('dark-theme');
313+
314+
if (isDark) {
315+
return [
316+
primary,
317+
accent,
318+
'#5BA2EC',
319+
'#83A447',
320+
'#C4C6D0'
321+
];
322+
}
323+
324+
return [
325+
primary,
326+
accent,
327+
'#004989',
328+
'#E7FFA5',
329+
'#6E8A3B'
330+
];
331+
}
332+
333+
private hexToRgb(hexColor: string): number[] {
334+
const hex = hexColor.replace('#', '');
335+
const normalized =
336+
hex.length === 3
337+
? hex
338+
.split('')
339+
.map((char) => char + char)
340+
.join('')
341+
: hex;
342+
const numeric = parseInt(normalized, 16);
343+
return [
344+
(numeric >> 16) & 255,
345+
(numeric >> 8) & 255,
346+
numeric & 255
347+
];
348+
}
349+
350+
private clamp(value: number): number {
351+
return Math.max(0, Math.min(255, value));
162352
}
163353
}

src/app/reports/run-report/run-report.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119

120120
<div class="container output" *ngIf="isCollapsed">
121121
<mat-card>
122-
<div class="m-b-20">
122+
<div class="m-b-20 p-20">
123123
<button mat-raised-button color="primary" (click)="isCollapsed = false">
124124
{{ 'labels.buttons.Parameters' | translate }}
125125
</button>

src/assets/translations/cs-CS.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@
524524
"Payments": "Platby",
525525
"Permissions": "Oprávnění",
526526
"Pie Chart": "Koláčový graf",
527+
"Polar Area Chart": "Polární plošný graf",
527528
"Post Dividend": "Vyplácet dividendu",
528529
"Previous": "Předchozí",
529530
"Preview": "Náhled",
@@ -562,6 +563,7 @@
562563
"Setup Products": "Nastavení produktů",
563564
"Setup System": "Systém nastavení",
564565
"Select All": "Vybrat vše",
566+
"Select Chart Type": "Vybrat typ grafu",
565567
"Show more": "Zobrazit více",
566568
"Show less": "Ukaž méně",
567569
"Signing in...": "Přihlašování",

0 commit comments

Comments
 (0)