Skip to content

Commit 07a4e12

Browse files
authored
Merge pull request #1806 from Kobzol/fraction-chart-ext
Switch fraction chart back to absolute values and improve its legend
2 parents 6fd05ce + cf26f96 commit 07a4e12

File tree

1 file changed

+127
-62
lines changed

1 file changed

+127
-62
lines changed

site/frontend/src/pages/compare/compile/table/sections-chart.vue

Lines changed: 127 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ const afterTotalWidth = computed(() => {
1818
return calculateTotalSectionsDuration(props.after);
1919
});
2020
21+
const maxTotalWidth = computed(() => {
22+
return Math.max(beforeTotalWidth.value, afterTotalWidth.value);
23+
});
24+
2125
const SECTIONS_PALETTE = [
2226
"#7768AE",
2327
"#FFCf96",
@@ -35,35 +39,61 @@ function calculate_width(value: number, totalDuration: number): string {
3539
return `${(fraction * 100).toFixed(2)}%`;
3640
}
3741
42+
function getSectionByName(
43+
sections: CompilationSections,
44+
name: string
45+
): CompilationSection | null {
46+
const values = sections.sections.filter((s) => s.name === name);
47+
if (values.length === 0) {
48+
return null;
49+
}
50+
return values[0];
51+
}
52+
3853
function formatPercent(
3954
sections: CompilationSections,
4055
sectionName: string
4156
): string {
42-
const values = sections.sections.filter((s) => s.name === sectionName);
43-
if (values.length === 0) return "??";
44-
const value = values[0].value;
57+
const section = getSectionByName(sections, sectionName);
58+
if (section === null) return "??";
59+
const value = section.value;
4560
const total = calculateTotalSectionsDuration(sections);
4661
const percent = (value / total) * 100;
4762
return `${percent.toFixed(2)}%`;
4863
}
4964
65+
function getRowWidth(): number {
66+
return maxTotalWidth.value;
67+
}
68+
5069
const chartRows: ComputedRef<Array<[string, CompilationSections]>> = computed(
5170
() => [
5271
["Before", props.before],
5372
["After", props.after],
5473
]
5574
);
5675
const legendItems: ComputedRef<
57-
Array<{section: CompilationSection; label: string; color: string}>
76+
Array<{
77+
section: CompilationSection;
78+
color: string;
79+
beforePercent: string;
80+
beforeAbsolute: string;
81+
afterPercent: string;
82+
afterAbsolute: string;
83+
}>
5884
> = computed(() => {
5985
const items = [];
6086
for (const section of props.before.sections) {
6187
items.push({
6288
section,
63-
label: `${section.name} (${formatPercent(
64-
props.before,
65-
section.name
66-
)} -> ${formatPercent(props.after, section.name)})`,
89+
beforePercent: formatPercent(props.before, section.name),
90+
beforeAbsolute:
91+
getSectionByName(props.before, section.name)?.value?.toLocaleString() ??
92+
"??",
93+
afterPercent: formatPercent(props.after, section.name),
94+
afterAbsolute:
95+
getSectionByName(props.after, section.name)?.value?.toLocaleString() ??
96+
"??",
6797
color: getSectionColor(items.length),
6898
});
6999
}
@@ -81,52 +111,81 @@ function deactivate() {
81111
</script>
82112

83113
<template>
84-
<div class="wrapper">
85-
<div class="chart-wrapper">
86-
<div class="chart" v-for="([label, sections], rowIndex) in chartRows">
87-
<span class="label">{{ label }}</span>
88-
<div class="section-wrapper">
89-
<div
90-
v-for="(section, index) in sections.sections"
91-
:class="{section: true, active: activeSection === section.name}"
92-
@mouseenter="activate(section.name)"
93-
@mouseleave="deactivate"
94-
:style="{
95-
width: calculate_width(
96-
section.value,
97-
rowIndex == 0 ? beforeTotalWidth : afterTotalWidth
98-
),
99-
backgroundColor: getSectionColor(index),
100-
}"
101-
>
114+
<div>
115+
<div class="wrapper">
116+
<div class="chart-wrapper">
117+
<div class="chart" v-for="([label, sections], rowIndex) in chartRows">
118+
<span class="label">{{ label }}</span>
119+
<div class="section-wrapper">
102120
<div
103-
class="description"
104-
v-if="rowIndex == 1 && activeSection === section.name"
121+
v-for="(section, index) in sections.sections"
122+
:class="{section: true, active: activeSection === section.name}"
123+
@mouseenter="activate(section.name)"
124+
@mouseleave="deactivate"
125+
:style="{
126+
width: calculate_width(section.value, getRowWidth()),
127+
backgroundColor: getSectionColor(index),
128+
}"
105129
>
106-
<div>
107-
<b>{{ section.name }}</b>
108-
</div>
109-
<div>
110-
{{ formatPercent(props.before, section.name) }} ->
111-
{{ formatPercent(props.after, section.name) }}
130+
<div
131+
class="description"
132+
v-if="rowIndex == 1 && activeSection === section.name"
133+
>
134+
<div>
135+
<b>{{ section.name }}</b>
136+
</div>
137+
<div>
138+
<div>
139+
{{ formatPercent(props.before, section.name) }} ->
140+
{{ formatPercent(props.after, section.name) }}
141+
</div>
142+
<div>
143+
{{
144+
getSectionByName(
145+
props.before,
146+
section.name
147+
)?.value?.toLocaleString() ?? "??"
148+
}}
149+
->
150+
{{
151+
getSectionByName(
152+
props.after,
153+
section.name
154+
)?.value.toLocaleString() ?? "??"
155+
}}
156+
</div>
157+
</div>
112158
</div>
113159
</div>
114160
</div>
115161
</div>
116162
</div>
117-
</div>
118-
<div class="legend">
119-
<div
120-
class="item"
121-
v-for="item in legendItems"
122-
@mouseenter="activate(item.section.name)"
123-
@mouseleave="deactivate"
124-
>
125-
<div
126-
:class="{color: true, active: activeSection === item.section.name}"
127-
:style="{backgroundColor: item.color}"
128-
></div>
129-
<div class="name">{{ item.label }}</div>
163+
<div class="legend">
164+
<table>
165+
<thead>
166+
<tr>
167+
<th></th>
168+
<th>Section</th>
169+
<th>Relative change</th>
170+
<th>Absolute change</th>
171+
</tr>
172+
</thead>
173+
<tbody>
174+
<tr
175+
v-for="item in legendItems"
176+
@mouseenter="activate(item.section.name)"
177+
@mouseleave="deactivate"
178+
:class="{active: activeSection === item.section.name}"
179+
>
180+
<td>
181+
<div class="color" :style="{backgroundColor: item.color}"></div>
182+
</td>
183+
<td class="name">{{ item.section.name }}</td>
184+
<td>{{ item.beforePercent }} -> {{ item.afterPercent }}</td>
185+
<td>{{ item.beforeAbsolute }} -> {{ item.afterAbsolute }}</td>
186+
</tr>
187+
</tbody>
188+
</table>
130189
</div>
131190
</div>
132191
</div>
@@ -135,11 +194,12 @@ function deactivate() {
135194
<style scoped lang="scss">
136195
.wrapper {
137196
display: flex;
197+
align-items: center;
138198
}
139199
.chart {
140200
display: flex;
141201
justify-content: flex-end;
142-
width: 600px;
202+
width: 500px;
143203
144204
&:first-child {
145205
margin-bottom: 10px;
@@ -173,10 +233,6 @@ function deactivate() {
173233
}
174234
}
175235
176-
.active {
177-
box-shadow: inset 0 0 1px 2px #000;
178-
}
179-
180236
.section:first-child {
181237
border-radius: 5px 0 0 5px;
182238
}
@@ -187,17 +243,26 @@ function deactivate() {
187243
.legend {
188244
margin-left: 40px;
189245
190-
.item {
191-
display: flex;
192-
margin-bottom: 5px;
193-
194-
.color {
195-
width: 15px;
196-
height: 15px;
197-
}
198-
.name {
199-
margin-left: 5px;
246+
table {
247+
td,
248+
th {
249+
padding: 5px;
200250
}
201251
}
252+
.color {
253+
width: 15px;
254+
height: 15px;
255+
}
256+
.active {
257+
font-weight: bold;
258+
}
259+
.name {
260+
margin-left: 5px;
261+
}
262+
}
263+
264+
.active .color,
265+
.active.section {
266+
box-shadow: inset 0 0 1px 2px #000;
202267
}
203268
</style>

0 commit comments

Comments
 (0)