Skip to content

Commit 1e4b6d6

Browse files
committed
feat: implement timeline visualization for compliance evaluations with initial chart setup and styling
1 parent 1467cff commit 1e4b6d6

2 files changed

Lines changed: 96 additions & 49 deletions

File tree

frontend/src/app/compliance/compliance-evaluations-view/compliance-evaluations-view.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<ng-container *ngIf="evaluations">
22
<div class="container-fluid p-3">
33
<div echarts
4-
[options]="option"
4+
[options]="chartOption"
55
class="timeline-chart"
66
(chartInit)="onChartInit($event)">
77
</div>

frontend/src/app/compliance/compliance-evaluations-view/compliance-evaluations-view.component.ts

Lines changed: 95 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -55,49 +55,7 @@ export class ComplianceEvaluationsViewComponent implements OnInit, OnDestroy {
5555
destroy$: Subject<void> = new Subject<void>();
5656
showBack = false;
5757

58-
option = {
59-
tooltip: {
60-
trigger: 'item',
61-
formatter: params => {
62-
const e = params.data;
63-
return `
64-
<b>${e.dateFormatted}</b><br/>
65-
Status: <b>${e.status}</b>
66-
`;
67-
}
68-
},
69-
xAxis: {
70-
type: 'time',
71-
name: 'Evaluations over time'
72-
},
73-
yAxis: {
74-
show: false
75-
},
76-
dataZoom: [
77-
{
78-
type: 'slider',
79-
show: true,
80-
xAxisIndex: 0,
81-
filterMode: 'none',
82-
start: 0,
83-
end: 10
84-
},
85-
{
86-
type: 'inside',
87-
xAxisIndex: 0,
88-
filterMode: 'none',
89-
start: 0,
90-
end: 10
91-
}
92-
],
93-
series: [
94-
{
95-
type: 'scatter',
96-
symbolSize: 20, // ← importante para que se vea como punto
97-
data: [] // ← se llena después
98-
}
99-
]
100-
};
58+
chartOption: any = {};
10159

10260
constructor(private activeRoute: ActivatedRoute,
10361
// private cpReportsService: CpReportsService,
@@ -157,10 +115,95 @@ export class ComplianceEvaluationsViewComponent implements OnInit, OnDestroy {
157115
if (this.controlId) {
158116
this.cpControlConfigService.evaluationsByControl(this.controlId)
159117
.subscribe(response => {
160-
this.evaluations = response.body;
161-
console.log('Evaluations: ', this.evaluations);
162-
this.option.series[0].data = this.buildChartData();
163-
this.option = { ...this.option };
118+
this.evaluations = response.body.evaluations;
119+
this.chartOption = {
120+
tooltip: {
121+
trigger: 'item',
122+
formatter: params => {
123+
const e = params.data;
124+
return `
125+
<b>${e.dateFormatted}</b><br/>
126+
Status: <b>${e.status}</b>
127+
`;
128+
}
129+
},
130+
xAxis: {
131+
type: 'time',
132+
min: new Date(response.body.startDate).getTime(),
133+
max: new Date(response.body.endDate).getTime(),
134+
axisLabel: {
135+
formatter: value => {
136+
const d = new Date(value);
137+
return d.toLocaleString('en-US', {
138+
month: 'short',
139+
day: '2-digit',
140+
year: 'numeric',
141+
});
142+
}
143+
},
144+
axisTick: {
145+
alignWithLabel: true
146+
},
147+
splitLine: {
148+
show: true
149+
},
150+
interval: 1000 * 60 * 60 * 24
151+
},
152+
yAxis: { show: false },
153+
dataZoom: [
154+
{ type: 'slider', start: 0, end: 10 },
155+
{ type: 'inside', start: 0, end: 10 }
156+
],
157+
series: [
158+
{
159+
type: 'custom',
160+
renderItem: (params, api) => {
161+
const xValue = api.value(0);
162+
const x = api.coord([xValue, 0])[0];
163+
164+
const totalWidth = 40;
165+
const margin = 2;
166+
const width = totalWidth - margin * 2;
167+
168+
const yBottom = api.coord([xValue, 0])[1];
169+
const yTop = api.coord([xValue, 1])[1];
170+
const height = yBottom - yTop;
171+
172+
return {
173+
type: 'group',
174+
children: [
175+
{
176+
type: 'rect',
177+
shape: {
178+
x: x - totalWidth / 2 + margin,
179+
y: yTop,
180+
width,
181+
height
182+
},
183+
style: api.style(),
184+
// ⭐ Aquí viene la magia
185+
clipPath: {
186+
type: 'rect',
187+
shape: {
188+
x: x - totalWidth / 2 + margin,
189+
y: yTop,
190+
width,
191+
height,
192+
r: 5 // ⭐ radio de borde redondeado
193+
}
194+
}
195+
}
196+
]
197+
};
198+
},
199+
data: []
200+
}
201+
]
202+
203+
};
204+
205+
this.chartOption.series[0].data = this.buildChartData();
206+
this.chartOption = { ...this.chartOption };
164207
});
165208
}
166209
}
@@ -171,7 +214,11 @@ export class ComplianceEvaluationsViewComponent implements OnInit, OnDestroy {
171214
controlId: e.controlId,
172215
status: e.status,
173216
timestamp: e.timestamp,
174-
dateFormatted: new Date(e.timestamp).toLocaleString(),
217+
dateFormatted: new Date(e.timestamp).toLocaleString('en-US', {
218+
month: 'short',
219+
day: '2-digit',
220+
year: 'numeric'
221+
}),
175222
itemStyle: {
176223
color: e.status === 'COMPLIANT' ? '#4CAF50' : '#F44336'
177224
}

0 commit comments

Comments
 (0)