Skip to content

Commit 5fedcd5

Browse files
alinelariguetjhonyeduardo
authored andcommitted
fix(chart): corrige animação em loop em series com valores zerados
Os gráficos circulares ignoram as series com valor zero na renderização do chart, porém mantém a exibição na legenda. Fixes DTHFUI-2210
1 parent 3b45ccb commit 5fedcd5

File tree

5 files changed

+98
-18
lines changed

5 files changed

+98
-18
lines changed

projects/ui/src/lib/components/po-chart/po-chart-types/po-chart-circular/po-chart-circular-series.interface.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ export interface PoCircularChartSeries {
66
/** Define o valor do objeto. */
77
value: number;
88

9+
color?: string;
10+
911
}

projects/ui/src/lib/components/po-chart/po-chart-types/po-chart-circular/po-chart-circular.spec.ts

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ describe('PoChartCircular:', () => {
106106

107107
spyOn(PoChartCircular, <any>'calculateEndAngle').and.returnValues(...itemsEndAngle);
108108

109-
component['series'] = [ { value: 1 }, { value: 2 }, { value: 3 }, { value: 4 } ];
109+
component.colors = PoChartColors[3];
110+
component['series'] = [
111+
{ category: '1', value: 1 }, { category: '2', value: 2 }, { category: '3', value: 3 }, { category: '4', value: 4 }
112+
];
110113

111114
component['calculateAngleRadians']();
112115

@@ -117,7 +120,10 @@ describe('PoChartCircular:', () => {
117120
spyOn(PoChartCircular, <any>'calculateEndAngle');
118121
component['totalValue'] = 24;
119122

120-
component['series'] = [ { value: 1 }, { value: 2 }, { value: 3 }, { value: 4 } ];
123+
component.colors = PoChartColors[3];
124+
component['series'] = [
125+
{ category: '1', value: 1 }, { category: '2', value: 2 }, { category: '3', value: 3 }, { category: '4', value: 4 }
126+
];
121127

122128
component['calculateAngleRadians']();
123129

@@ -196,7 +202,7 @@ describe('PoChartCircular:', () => {
196202
spyOn(component['renderer'], 'setAttribute');
197203
spyOn(component['renderer'], 'appendChild');
198204

199-
component['createPath'](index, serie, svgPathsWrapper);
205+
component['createPath'](serie, svgPathsWrapper);
200206

201207
expect(component['renderer'].setAttribute).toHaveBeenCalledTimes(5);
202208
expect(component['renderer'].appendChild).toHaveBeenCalledTimes(1);
@@ -216,7 +222,7 @@ describe('PoChartCircular:', () => {
216222
spyOn(component['renderer'], 'appendChild');
217223
spyOn(component, <any> 'setTooltipAttributes');
218224

219-
component['createPath'](index, serie, svgPathsWrapper);
225+
component['createPath'](serie, svgPathsWrapper);
220226

221227
expect(component['setTooltipAttributes']).toHaveBeenCalledWith(svgPath, serie);
222228
});
@@ -385,6 +391,7 @@ describe('PoChartCircular:', () => {
385391
});
386392

387393
it('createPaths: should call `renderer.createElement` and call `createPath`', () => {
394+
component.colors = PoChartColors[2];
388395
component['series'] = [{ value: 10, category: 'First'}, { value: 20, category: 'Second' }];
389396

390397
spyOn(component['renderer'], 'createElement');
@@ -398,9 +405,12 @@ describe('PoChartCircular:', () => {
398405
expect(component['createPath']).toHaveBeenCalled();
399406
});
400407

401-
it('createSVGElements: should create svgElement and call `createPaths`, append svgElement in svgContainer and setAttributes', () => {
402-
408+
it(`createSVGElements: should create svgElement and call 'createPaths', 'createTexts',
409+
append svgElement in svgContainer and setAttributes`, () => {
410+
component.colors = PoChartColors[0];
411+
component.series = [{ category: 'po', value: 1 }];
403412
spyOn(component, <any> 'createPaths');
413+
spyOn(component, <any> 'createTexts');
404414
spyOn(component['renderer'], <any> 'createElement').and.callThrough();
405415
spyOn(component['renderer'], <any> 'setAttribute');
406416
spyOn(component['svgContainer'].nativeElement, <any> 'appendChild');
@@ -409,6 +419,7 @@ describe('PoChartCircular:', () => {
409419

410420
expect(component.svgElement).toBeDefined();
411421
expect(component['createPaths']).toHaveBeenCalled();
422+
expect(component['createTexts']).toHaveBeenCalled();
412423
expect(component['renderer'].createElement).toHaveBeenCalledWith('svg:svg', 'svg');
413424
expect(component['renderer'].setAttribute).toHaveBeenCalledTimes(5);
414425
expect(component['svgContainer'].nativeElement.appendChild).toHaveBeenCalledWith(component.svgElement);
@@ -611,6 +622,7 @@ describe('PoChartCircular:', () => {
611622
{ value: 20, category: 'Second' }
612623
];
613624

625+
component.colors = PoChartColors[mockSeries.length];
614626
component['series'] = mockSeries;
615627
component.type = PoChartType.Donut;
616628

@@ -627,6 +639,7 @@ describe('PoChartCircular:', () => {
627639
{ value: 20, category: 'Second' }
628640
];
629641

642+
component.colors = PoChartColors[mockSeries.length];
630643
component['series'] = mockSeries;
631644
component.type = PoChartType.Donut;
632645

@@ -638,7 +651,6 @@ describe('PoChartCircular:', () => {
638651
});
639652

640653
it('createText: should create a svg text element with some attributes and add it into `svgTextElementsList`', () => {
641-
const index = 0;
642654
const serie: PoDonutChartSeries = { category: 'po', value: 2 };
643655

644656
component.colors = PoChartColors[0];
@@ -652,7 +664,7 @@ describe('PoChartCircular:', () => {
652664
spyOn(component['renderer'], 'setAttribute');
653665
spyOn(component['renderer'], 'appendChild');
654666

655-
component['createText'](index, serie);
667+
component['createText'](serie);
656668

657669
expect(component['getFontSize']).toHaveBeenCalled();
658670
expect(component['getTextColor']).toHaveBeenCalled();
@@ -661,7 +673,7 @@ describe('PoChartCircular:', () => {
661673

662674
expect(component['renderer'].createElement).toHaveBeenCalledTimes(2);
663675
expect(component['renderer'].setAttribute).toHaveBeenCalledTimes(4);
664-
expect(component['renderer'].appendChild).toHaveBeenCalledTimes(1);
676+
expect(component['renderer'].appendChild).toHaveBeenCalledTimes(2);
665677

666678
expect(component['svgTextElementsList'].length).toEqual(1);
667679
});
@@ -736,6 +748,35 @@ describe('PoChartCircular:', () => {
736748
expect(component.innerRadius).toBe(expectedValue);
737749
});
738750

751+
it('getSeriesWithValue: should return only series with value and color attr', () => {
752+
const invalidSeries = [{ category: 'Valor 0', value: 0 }];
753+
const series = [{ category: 'Valor 2', value: 2 }, { category: 'Valor 3', value: 3 }];
754+
const seriesParam = [...series, ...invalidSeries];
755+
756+
component.colors = PoChartColors[seriesParam.length];
757+
758+
const validSeries = component['getSeriesWithValue'](seriesParam);
759+
760+
expect(validSeries.length).toEqual(series.length);
761+
expect(validSeries.every(serie => !!serie.color)).toBe(true);
762+
});
763+
764+
it('getSeriesWithValue: should return empty array if series has value 0', () => {
765+
const invalidSeries = [{ category: 'Valor 0', value: 0 }];
766+
767+
const validSeries = component['getSeriesWithValue'](invalidSeries);
768+
769+
expect(validSeries).toEqual([]);
770+
});
771+
772+
it('getSeriesWithValue: should return empty array if series has value -1', () => {
773+
const invalidSeries = [{ category: 'Valor -1', value: -1 }];
774+
775+
const validSeries = component['getSeriesWithValue'](invalidSeries);
776+
777+
expect(validSeries).toEqual([]);
778+
});
779+
739780
});
740781

741782
});

projects/ui/src/lib/components/po-chart/po-chart-types/po-chart-circular/po-chart-circular.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,23 @@ const poChartWhiteColor = '#ffffff';
1818

1919
export class PoChartCircular extends PoChartDynamicTypeComponent implements OnDestroy, OnInit {
2020

21+
private _series: Array<PoPieChartSeries | PoDonutChartSeries>;
22+
2123
private animationRunning: boolean;
2224
private chartItemEndAngle: number;
2325
private chartItemStartAngle: number;
2426
private chartItemsEndAngleList: Array<number> = [];
2527
private svgPathElementsList: Array<string> = [];
2628
private svgTextElementsList: Array<string> = [];
2729

30+
set series(value: Array<PoPieChartSeries | PoDonutChartSeries>) {
31+
this._series = this.getSeriesWithValue(value);
32+
}
33+
34+
get series() {
35+
return this._series;
36+
}
37+
2838
private static calculateEndAngle(value: number, totalValue: number): number {
2939
return value / totalValue * (Math.PI * 2);
3040
}
@@ -97,11 +107,11 @@ export class PoChartCircular extends PoChartDynamicTypeComponent implements OnDe
97107
return poPageContent.length ? poPageContent[0] : window;
98108
}
99109

100-
private createPath(index: number, serie: PoCircularChartSeries, svgPathsWrapper: any) {
110+
private createPath(serie: PoCircularChartSeries, svgPathsWrapper: any) {
101111
const svgPath = this.renderer.createElement('svg:path', 'svg');
102112

103113
this.renderer.setAttribute(svgPath, 'class', 'po-path-item');
104-
this.renderer.setAttribute(svgPath, 'fill', this.colors[index]);
114+
this.renderer.setAttribute(svgPath, 'fill', serie.color);
105115

106116
this.setTooltipAttributes(svgPath, serie);
107117

@@ -115,17 +125,17 @@ export class PoChartCircular extends PoChartDynamicTypeComponent implements OnDe
115125
private createPaths() {
116126
const svgPathsWrapper = this.renderer.createElement('svg:g', 'svg');
117127

118-
this.series.forEach((serie, index) => this.createPath(index, serie, svgPathsWrapper));
128+
this.series.forEach(serie => this.createPath(serie, svgPathsWrapper));
119129
}
120130

121-
private createText(index: number, serie: PoCircularChartSeries) {
131+
private createText(serie: PoCircularChartSeries) {
122132
const { value } = serie;
123133

124134
const svgG = this.renderer.createElement('svg:g', 'svg');
125135
const svgText = this.renderer.createElement('svg:text', 'svg');
126136

127137
const fontSize = this.getFontSize();
128-
const textColor = this.getTextColor(this.colors[index]);
138+
const textColor = this.getTextColor(serie.color);
129139

130140
svgText.textContent = this.getPercentValue(value, this.totalValue) + '%' ;
131141

@@ -136,14 +146,15 @@ export class PoChartCircular extends PoChartDynamicTypeComponent implements OnDe
136146

137147
this.setTooltipAttributes(svgText, serie);
138148

139-
svgG.appendChild(svgText);
149+
this.renderer.appendChild(svgG, svgText);
150+
140151
this.renderer.appendChild(this.svgElement, svgG);
141152
this.svgTextElementsList.push(svgText);
142153
}
143154

144155
private createTexts() {
145156
if (this.type === PoChartType.Donut) {
146-
this.series.forEach((serie, index) => this.createText(index, serie));
157+
this.series.forEach(serie => this.createText(serie));
147158
}
148159
}
149160

@@ -160,6 +171,7 @@ export class PoChartCircular extends PoChartDynamicTypeComponent implements OnDe
160171

161172
this.createPaths();
162173
this.createTexts();
174+
163175
}
164176

165177
private drawPath(path, chartItemStartAngle, chartItemEndAngle) {
@@ -259,6 +271,18 @@ export class PoChartCircular extends PoChartDynamicTypeComponent implements OnDe
259271
return String(floatPercentValue).replace('.', ',');
260272
}
261273

274+
private getSeriesWithValue(series: Array<PoCircularChartSeries>) {
275+
const newSeries = [];
276+
277+
series.forEach((serie, index) => {
278+
if (serie.value > 0) {
279+
newSeries.push({ ...serie, color: this.colors[index] });
280+
}
281+
});
282+
283+
return newSeries;
284+
}
285+
262286
private getTextColor(color: string) {
263287
if (PoSeriesTextBlack.includes(color)) {
264288
return poChartBlackColor;

projects/ui/src/lib/components/po-chart/po-chart.component.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,19 @@ describe('PoChartComponent:', () => {
222222

223223
});
224224

225+
it('setChartProperties: should set `instance.colors` with empty array if `component.colors` is undefined', () => {
226+
const instance: any = {};
227+
228+
component['colors'] = undefined;
229+
component.chartHeader = {nativeElement: {offsetHeight: 200}};
230+
component.chartLegend = {nativeElement: {offsetHeight: 200}};
231+
component.chartWrapper = {nativeElement: {offsetWidth: 200}};
232+
233+
component['setChartProperties'](instance);
234+
235+
expect(instance.colors).toEqual([]);
236+
});
237+
225238
it('setClickSubscribe: should call `onSeriesClick` if onSerieClick emits an event', () => {
226239
const event = { data: 10 };
227240

projects/ui/src/lib/components/po-chart/po-chart.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class PoChartComponent extends PoChartBaseComponent implements AfterViewI
4747
[PoChartType.Donut]: PoChartDonutComponent
4848
};
4949

50-
colors: Array<string>;
50+
colors: Array<string> = [];
5151

5252
@ViewChild('chartContainer', { read: ViewContainerRef, static: true })
5353
chartContainer: ViewContainerRef;
@@ -172,7 +172,7 @@ export class PoChartComponent extends PoChartBaseComponent implements AfterViewI
172172
instance.chartHeader = this.chartHeader.nativeElement.offsetHeight;
173173
instance.chartLegend = this.chartLegend.nativeElement.offsetHeight;
174174
instance.chartWrapper = this.chartWrapper.nativeElement.offsetWidth;
175-
instance.colors = this.colors;
175+
instance.colors = Array.isArray(this.colors) ? [...this.colors] : [];
176176
instance.height = this.height;
177177
instance.series = this.series || [];
178178
instance.type = this.type;

0 commit comments

Comments
 (0)