Skip to content

Commit 6a3f4e3

Browse files
committed
Move the interactive legends out of the chart and display them below as toggleable buttons
1 parent 34abca8 commit 6a3f4e3

File tree

1 file changed

+167
-22
lines changed

1 file changed

+167
-22
lines changed

reporting/html_templates/lorust_perf_report.html

Lines changed: 167 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,43 @@
3434
margin: 0;
3535
}
3636

37+
.brand-link {
38+
margin-top: 6px;
39+
font-size: 12px;
40+
letter-spacing: 0.08em;
41+
}
42+
43+
.brand-link a {
44+
color: #7f28ff;
45+
text-decoration: none;
46+
}
47+
48+
.brand-link a:hover,
49+
.brand-link a:focus {
50+
text-decoration: underline;
51+
}
52+
3753
.info-grid {
3854
display: grid;
39-
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
40-
gap: 16px;
55+
grid-template-columns: repeat(6, minmax(0, 1fr));
56+
gap: 12px;
4157
margin-bottom: 32px;
4258
}
4359

4460
.info-card {
45-
background: linear-gradient(135deg, #7f28ff 0%, #c084fc 100%);
46-
border-radius: 12px;
47-
padding: 18px 20px;
48-
color: #ffffff;
49-
box-shadow: 0 6px 16px rgba(127, 40, 255, 0.2);
61+
background: #f7f5ff;
62+
border: 1px solid #d7caff;
63+
border-radius: 10px;
64+
padding: 16px 18px;
65+
color: #1a0a2e;
66+
box-shadow: 0 4px 10px rgba(127, 40, 255, 0.08);
5067
}
5168

5269
.info-label {
5370
font-size: 12px;
5471
letter-spacing: 0.06em;
5572
text-transform: uppercase;
56-
color: #e9d5ff;
73+
color: #6b5b95;
5774
}
5875

5976
.info-value {
@@ -74,7 +91,7 @@
7491

7592
.summary-grid {
7693
display: grid;
77-
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
94+
grid-template-columns: repeat(5, minmax(0, 1fr));
7895
gap: 16px;
7996
margin-bottom: 32px;
8097
}
@@ -132,6 +149,36 @@
132149
height: 340px;
133150
}
134151

152+
.chart-legend {
153+
display: flex;
154+
flex-wrap: wrap;
155+
gap: 8px;
156+
margin-top: 12px;
157+
}
158+
159+
.chart-legend button {
160+
border: 1px solid #d7caff;
161+
border-radius: 16px;
162+
padding: 6px 12px;
163+
background: #f7f5ff;
164+
color: #4b3f6b;
165+
font-size: 12px;
166+
cursor: pointer;
167+
transition: all 0.2s ease;
168+
}
169+
170+
.chart-legend button.active {
171+
background: #7f28ff;
172+
color: #ffffff;
173+
border-color: #7f28ff;
174+
box-shadow: 0 2px 6px rgba(127, 40, 255, 0.25);
175+
}
176+
177+
.chart-legend button:hover,
178+
.chart-legend button:focus {
179+
border-color: #7f28ff;
180+
}
181+
135182
.table-section {
136183
margin-bottom: 40px;
137184
}
@@ -220,6 +267,15 @@
220267
margin-bottom: 4px;
221268
}
222269

270+
@media (max-width: 1400px) {
271+
.info-grid {
272+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
273+
}
274+
.summary-grid {
275+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
276+
}
277+
}
278+
223279
@media print {
224280
body {
225281
background: white;
@@ -256,6 +312,9 @@
256312
<div class="header">
257313
<img src="https://zeuz.ai/_next/image?url=%2Fold-assets%2FLogo.svg&w=384&q=75" alt="ZeuZ Logo">
258314
<h1>Performance Test Report</h1>
315+
<div class="brand-link">
316+
<a href="https://zeuz.ai" target="_blank" rel="noopener">zeuz.ai</a>
317+
</div>
259318
</div>
260319

261320
<div class="info-grid">
@@ -334,42 +393,51 @@ <h2>Overall Summary</h2>
334393
<div class="charts-grid">
335394
<div class="chart-card">
336395
<div class="chart-title">Requests Per Second (Total)</div>
337-
<div id="overall_requests" class="chart-container"></div>
396+
<div id="overall_requests" class="chart-container" data-legend-target="legend-overall_requests"></div>
397+
<div class="chart-legend" id="legend-overall_requests"></div>
338398
</div>
339399
<div class="chart-card">
340400
<div class="chart-title">Active Users (Estimated Concurrency)</div>
341-
<div id="overall_concurrency" class="chart-container"></div>
401+
<div id="overall_concurrency" class="chart-container" data-legend-target="legend-overall_concurrency"></div>
402+
<div class="chart-legend" id="legend-overall_concurrency"></div>
342403
</div>
343404
<div class="chart-card">
344405
<div class="chart-title">Total Data Transferred Per Second</div>
345-
<div id="overall_throughput" class="chart-container"></div>
406+
<div id="overall_throughput" class="chart-container" data-legend-target="legend-overall_throughput"></div>
407+
<div class="chart-legend" id="legend-overall_throughput"></div>
346408
</div>
347409
<div class="chart-card">
348410
<div class="chart-title">Error Rate (%) Per Second</div>
349-
<div id="overall_error_rate" class="chart-container"></div>
411+
<div id="overall_error_rate" class="chart-container" data-legend-target="legend-overall_error_rate"></div>
412+
<div class="chart-legend" id="legend-overall_error_rate"></div>
350413
</div>
351414
</div>
352415

353416
<div class="charts-grid">
354417
<div class="chart-card">
355418
<div class="chart-title">Average Response Time (Overall)</div>
356-
<div id="overall_avg_response" class="chart-container"></div>
419+
<div id="overall_avg_response" class="chart-container" data-legend-target="legend-overall_avg_response"></div>
420+
<div class="chart-legend" id="legend-overall_avg_response"></div>
357421
</div>
358422
<div class="chart-card">
359423
<div class="chart-title">Latency Percentiles (Overall)</div>
360-
<div id="overall_percentiles" class="chart-container"></div>
424+
<div id="overall_percentiles" class="chart-container" data-legend-target="legend-overall_percentiles"></div>
425+
<div class="chart-legend" id="legend-overall_percentiles"></div>
361426
</div>
362427
<div class="chart-card">
363428
<div class="chart-title">Response Time vs Time (Per Endpoint)</div>
364-
<div id="endpoint_response_time" class="chart-container"></div>
429+
<div id="endpoint_response_time" class="chart-container" data-legend-target="legend-endpoint_response_time"></div>
430+
<div class="chart-legend" id="legend-endpoint_response_time"></div>
365431
</div>
366432
<div class="chart-card">
367433
<div class="chart-title">Requests Per Second (Per Endpoint)</div>
368-
<div id="endpoint_requests" class="chart-container"></div>
434+
<div id="endpoint_requests" class="chart-container" data-legend-target="legend-endpoint_requests"></div>
435+
<div class="chart-legend" id="legend-endpoint_requests"></div>
369436
</div>
370437
<div class="chart-card">
371438
<div class="chart-title">Average Content Size Per Second (Per Endpoint)</div>
372-
<div id="endpoint_throughput" class="chart-container"></div>
439+
<div id="endpoint_throughput" class="chart-container" data-legend-target="legend-endpoint_throughput"></div>
440+
<div class="chart-legend" id="legend-endpoint_throughput"></div>
373441
</div>
374442
</div>
375443

@@ -588,27 +656,104 @@ <h2>Endpoint Highlights</h2>
588656
if (element.previousElementSibling && element.previousElementSibling.classList.contains('chart-title')) {
589657
element.previousElementSibling.textContent = title;
590658
}
659+
const legendTargetId = element.dataset.legendTarget;
660+
const legendContainer = legendTargetId ? document.getElementById(legendTargetId) : null;
661+
const legendNames = Array.from(new Set(series.map(item => item.name).filter(Boolean)));
662+
const legendSelected = {};
663+
legendNames.forEach(name => {
664+
legendSelected[name] = true;
665+
});
666+
591667
const chart = echarts.init(element, 'light');
592668
const baseOptions = {
593669
color: ['#7f28ff', '#f50384', '#c084fc', '#c49cff', '#e9d5ff', '#10b981', '#f59e0b'],
594670
tooltip: { trigger: 'axis' },
595-
legend: { type: 'scroll' },
671+
legend: {
672+
show: false,
673+
data: legendNames,
674+
selected: legendSelected
675+
},
596676
toolbox: { feature: { saveAsImage: {} } },
597-
xAxis: { type: 'time' },
677+
xAxis: {
678+
type: 'time',
679+
axisLabel: { hideOverlap: true, rotate: 25, color: '#4b3f6b', fontSize: 11 },
680+
axisTick: { alignWithLabel: true },
681+
splitLine: { show: false }
682+
},
598683
yAxis: {
599684
type: 'value',
600685
name: yAxisName,
601686
axisLine: { symbol: 'arrow' },
602687
splitLine: { show: true, lineStyle: { color: '#ede3ff' } }
603688
},
604-
grid: { top: 24, left: 60, right: 30, bottom: 50 },
689+
grid: { top: 40, left: 60, right: 30, bottom: 60 },
605690
series: series
606691
};
607-
chart.setOption(Object.assign(baseOptions, options));
692+
const mergedOptions = Object.assign({}, baseOptions, options);
693+
if (options.legend) {
694+
mergedOptions.legend = Object.assign({}, baseOptions.legend, options.legend);
695+
}
696+
if (options.xAxis) {
697+
mergedOptions.xAxis = Object.assign({}, baseOptions.xAxis, options.xAxis);
698+
}
699+
if (options.yAxis) {
700+
mergedOptions.yAxis = Object.assign({}, baseOptions.yAxis, options.yAxis);
701+
}
702+
if (options.grid) {
703+
mergedOptions.grid = Object.assign({}, baseOptions.grid, options.grid);
704+
}
705+
chart.setOption(mergedOptions);
706+
if (legendContainer) {
707+
renderExternalLegend(chart, legendContainer, legendNames);
708+
}
608709
charts.push(chart);
609710
return chart;
610711
}
611712

713+
function renderExternalLegend(chart, container, legendNames) {
714+
if (!container) {
715+
return;
716+
}
717+
container.innerHTML = '';
718+
const buttons = {};
719+
720+
legendNames.forEach(name => {
721+
const button = document.createElement('button');
722+
button.type = 'button';
723+
button.textContent = name;
724+
button.addEventListener('click', () => {
725+
chart.dispatchAction({
726+
type: 'legendToggleSelect',
727+
name: name,
728+
});
729+
updateState();
730+
});
731+
container.appendChild(button);
732+
buttons[name] = button;
733+
});
734+
735+
chart.on('legendselectchanged', updateState);
736+
chart.on('restore', updateState);
737+
updateState();
738+
739+
function updateState() {
740+
const option = chart.getOption();
741+
const legend = Array.isArray(option.legend) ? option.legend[0] : option.legend;
742+
const selected = (legend && legend.selected) || {};
743+
legendNames.forEach(name => {
744+
const button = buttons[name];
745+
if (!button) {
746+
return;
747+
}
748+
if (selected[name] === false) {
749+
button.classList.remove('active');
750+
} else {
751+
button.classList.add('active');
752+
}
753+
});
754+
}
755+
}
756+
612757
createLineChart('overall_requests', 'Requests Per Second (Total)', [{
613758
name: 'Requests',
614759
type: 'line',

0 commit comments

Comments
 (0)