Skip to content

Commit 34df9ce

Browse files
committed
Improvement - Add time-label scoped slot and @selectTimeLabel emit
1 parent 4c35bc9 commit 34df9ce

File tree

2 files changed

+169
-51
lines changed

2 files changed

+169
-51
lines changed

src/components/vue-ui-stackbar.vue

Lines changed: 92 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const props = defineProps({
5757
},
5858
});
5959
60-
const emit = defineEmits(['selectDatapoint', 'selectLegend']);
60+
const emit = defineEmits(['selectDatapoint', 'selectLegend', 'selectTimeLabel']);
6161
6262
const isDataset = computed({
6363
get() {
@@ -400,8 +400,14 @@ const yLabels = computed(() => {
400400
});
401401
402402
const timeLabels = computed(() => {
403-
return FINAL_CONFIG.value.style.chart.grid.x.timeLabels.values
404-
.slice(slicer.value.start, slicer.value.end);
403+
const labels = [];
404+
for (let i = 0; i < maxSeries.value; i += 1) {
405+
labels.push({
406+
text: FINAL_CONFIG.value.style.chart.grid.x.timeLabels.values[i] || String(i),
407+
absoluteIndex: i
408+
})
409+
}
410+
return labels.slice(slicer.value.start, slicer.value.end);
405411
});
406412
407413
const formattedDataset = computed(() => {
@@ -617,8 +623,8 @@ function useTooltip(seriesIndex) {
617623
618624
let html = "";
619625
620-
if (timeLabels.value[seriesIndex]) {
621-
html += `<div style="width:100%;text-align:center;border-bottom:1px solid ${borderColor};padding-bottom:6px;margin-bottom:3px;">${timeLabels.value[seriesIndex]}</div>`;
626+
if (timeLabels.value[seriesIndex] && timeLabels.value[seriesIndex].text && FINAL_CONFIG.value.style.chart.tooltip.showTimeLabel) {
627+
html += `<div style="width:100%;text-align:center;border-bottom:1px solid ${borderColor};padding-bottom:6px;margin-bottom:3px;">${timeLabels.value[seriesIndex].text}</div>`;
622628
}
623629
624630
const parenthesis = [
@@ -772,6 +778,24 @@ function toggleAnnotator() {
772778
isAnnotator.value = !isAnnotator.value;
773779
}
774780
781+
function selectTimeLabel(label, relativeIndex) {
782+
const datapoint = JSON.parse(JSON.stringify(formattedDataset.value)).map(fd => {
783+
return {
784+
name: fd.name,
785+
value: fd.series[relativeIndex] === 0 ? 0 : (fd.signedSeries[relativeIndex] === -1 ? (fd.series[relativeIndex] >= 0 ? -fd.series[relativeIndex] : fd.series[relativeIndex]) : fd.series[relativeIndex]) || null,
786+
proportion: fd.proportions[relativeIndex] || null,
787+
color: fd.color,
788+
id: fd.id
789+
}
790+
});
791+
792+
emit('selectTimeLabel', {
793+
datapoint,
794+
absoluteIndex: label.absoluteIndex,
795+
label: label.text
796+
});
797+
}
798+
775799
defineExpose({
776800
getData,
777801
generatePdf,
@@ -1166,31 +1190,73 @@ defineExpose({
11661190
11671191
<!-- TIME LABELS VERTICAL-->
11681192
<template v-if="FINAL_CONFIG.style.chart.grid.x.timeLabels.show && FINAL_CONFIG.orientation === 'vertical'">
1169-
<text
1170-
v-for="(timeLabel, i) in timeLabels"
1171-
:text-anchor="FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation > 0 ? 'start' : FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation < 0 ? 'end' : 'middle'"
1172-
:font-size="FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize"
1173-
:font-weight="FINAL_CONFIG.style.chart.grid.x.timeLabels.bold ? 'bold': 'normal'"
1174-
:fill="FINAL_CONFIG.style.chart.grid.x.timeLabels.color"
1175-
:transform="`translate(${drawingArea.left + (barSlot * i) + barSlot / 2}, ${drawingArea.bottom + FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize * 1.3 + FINAL_CONFIG.style.chart.grid.x.timeLabels.offsetY}), rotate(${FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation})`"
1176-
>
1177-
{{ timeLabel }}
1178-
</text>
1193+
<g v-if="$slots['time-label']">
1194+
<g v-for="(timeLabel, i) in timeLabels">
1195+
<slot name="time-label" v-bind="{
1196+
x: drawingArea.left + (barSlot * i) + barSlot / 2,
1197+
y: drawingArea.bottom + FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize * 1.3 + FINAL_CONFIG.style.chart.grid.x.timeLabels.offsetY,
1198+
fontSize: FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize,
1199+
fill: FINAL_CONFIG.style.chart.grid.x.timeLabels.color,
1200+
transform: `translate(${drawingArea.left + (barSlot * i) + barSlot / 2}, ${drawingArea.bottom + FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize * 1.3 + FINAL_CONFIG.style.chart.grid.x.timeLabels.offsetY}), rotate(${FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation})`,
1201+
absoluteIndex: timeLabel.absoluteIndex,
1202+
content: timeLabel.text,
1203+
textAnchor: FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation > 0 ? 'start' : FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation < 0 ? 'end' : 'middle',
1204+
show: true
1205+
}"/>
1206+
</g>
1207+
</g>
1208+
<g v-else>
1209+
<text
1210+
v-for="(timeLabel, i) in timeLabels"
1211+
:text-anchor="FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation > 0 ? 'start' : FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation < 0 ? 'end' : 'middle'"
1212+
:font-size="FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize"
1213+
:font-weight="FINAL_CONFIG.style.chart.grid.x.timeLabels.bold ? 'bold': 'normal'"
1214+
:fill="FINAL_CONFIG.style.chart.grid.x.timeLabels.color"
1215+
:transform="`translate(${drawingArea.left + (barSlot * i) + barSlot / 2}, ${drawingArea.bottom + FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize * 1.3 + FINAL_CONFIG.style.chart.grid.x.timeLabels.offsetY}), rotate(${FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation})`"
1216+
:style="{
1217+
cursor: 'pointer'
1218+
}"
1219+
@click="() => selectTimeLabel(timeLabel, i)"
1220+
>
1221+
{{ timeLabel.text }}
1222+
</text>
1223+
</g>
11791224
</template>
11801225
11811226
<!-- TIME LABELS HORIZONTAL -->
11821227
<template v-if="FINAL_CONFIG.style.chart.grid.x.timeLabels.show && FINAL_CONFIG.orientation === 'horizontal'">
1183-
<text
1184-
v-for="(timeLabel, i) in timeLabels"
1185-
text-anchor="end"
1186-
:font-size="FINAL_CONFIG.style.chart.grid.y.axisLabels.fontSize"
1187-
:font-weight="FINAL_CONFIG.style.chart.grid.y.axisLabels.bold ? 'bold' : 'normal'"
1188-
:fill="FINAL_CONFIG.style.chart.grid.y.axisLabels.color"
1189-
:x="drawingArea.left - 8"
1190-
:y="drawingArea.top + (barSlot * i ) + (barSlot / 2) + FINAL_CONFIG.style.chart.grid.y.axisLabels.fontSize / 3"
1191-
>
1192-
{{ timeLabel }}
1193-
</text>
1228+
<g v-if="$slots['time-label']">
1229+
<g v-for="(timeLabel, i) in timeLabels">
1230+
<slot name="time-label" v-bind="{
1231+
x: drawingArea.left - 8,
1232+
y: drawingArea.top + (barSlot * i ) + (barSlot / 2) + FINAL_CONFIG.style.chart.grid.y.axisLabels.fontSize / 3,
1233+
fontSize: FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize,
1234+
fill: FINAL_CONFIG.style.chart.grid.x.timeLabels.color,
1235+
transform: null,
1236+
absoluteIndex: timeLabel.absoluteIndex,
1237+
content: timeLabel.text,
1238+
textAnchor: 'end',
1239+
show: true
1240+
}" />
1241+
</g>
1242+
</g>
1243+
<g v-else>
1244+
<text
1245+
v-for="(timeLabel, i) in timeLabels"
1246+
text-anchor="end"
1247+
:font-size="FINAL_CONFIG.style.chart.grid.y.axisLabels.fontSize"
1248+
:font-weight="FINAL_CONFIG.style.chart.grid.y.axisLabels.bold ? 'bold' : 'normal'"
1249+
:fill="FINAL_CONFIG.style.chart.grid.y.axisLabels.color"
1250+
:x="drawingArea.left - 8"
1251+
:y="drawingArea.top + (barSlot * i ) + (barSlot / 2) + FINAL_CONFIG.style.chart.grid.y.axisLabels.fontSize / 3"
1252+
:style="{
1253+
cursor: 'pointer'
1254+
}"
1255+
@click="() => selectTimeLabel(timeLabel, i)"
1256+
>
1257+
{{ timeLabel.text }}
1258+
</text>
1259+
</g>
11941260
</template>
11951261
11961262
<!-- TOOLTIP TRAPS (vertical mode) -->

src/components/vue-ui-xy.vue

Lines changed: 77 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -950,24 +950,47 @@
950950

951951
<!-- TIME LABELS -->
952952
<g v-if="FINAL_CONFIG.chart.grid.labels.xAxisLabels.show">
953-
<g v-for="(label, i) in timeLabels" :key="`time_label_${i}`">
954-
955-
<text
956-
:data-cy="`xy-time-label-${i}`"
957-
v-if="
958-
(label && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
959-
(label && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && (i === 0 || i === timeLabels.length -1) && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
960-
(label && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && selectedSerieIndex === i && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
961-
(label && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo && (i % Math.floor((this.slicer.end - this.slicer.start) / FINAL_CONFIG.chart.grid.labels.xAxisLabels.modulo) === 0))
962-
"
963-
:text-anchor="FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation > 0 ? 'start' : FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation < 0 ? 'end' : 'middle'"
964-
:font-size="fontSizes.xAxis"
965-
:fill="FINAL_CONFIG.chart.grid.labels.xAxisLabels.color"
966-
:transform="`translate(${drawingArea.left + (drawingArea.width / maxSeries) * i + (drawingArea.width / maxSeries / 2)}, ${drawingArea.bottom + fontSizes.xAxis * 1.3 + FINAL_CONFIG.chart.grid.labels.xAxisLabels.yOffset}), rotate(${FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation})`"
967-
>
968-
{{ label || "" }}
969-
</text>
970-
</g>
953+
<template v-if="$slots['time-label']">
954+
<g v-for="(label, i) in timeLabels" :key="`time_label_${i}`">
955+
<slot name="time-label" v-bind="{
956+
x: drawingArea.left + (drawingArea.width / maxSeries) * i + (drawingArea.width / maxSeries / 2),
957+
y: drawingArea.bottom + fontSizes.xAxis * 1.3 + FINAL_CONFIG.chart.grid.labels.xAxisLabels.yOffset,
958+
fontSize: fontSizes.xAxis,
959+
fill: FINAL_CONFIG.chart.grid.labels.xAxisLabels.color,
960+
transform: `translate(${drawingArea.left + (drawingArea.width / maxSeries) * i + (drawingArea.width / maxSeries / 2)}, ${drawingArea.bottom + fontSizes.xAxis * 1.3 + FINAL_CONFIG.chart.grid.labels.xAxisLabels.yOffset}), rotate(${FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation})`,
961+
absoluteIndex: label.absoluteIndex,
962+
content: label.text,
963+
textAnchor: FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation > 0 ? 'start' : FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation < 0 ? 'end' : 'middle',
964+
show: (label && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
965+
(label && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && (i === 0 || i === timeLabels.length -1) && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
966+
(label && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && selectedSerieIndex === i && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
967+
(label && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo && (i % Math.floor((this.slicer.end - this.slicer.start) / FINAL_CONFIG.chart.grid.labels.xAxisLabels.modulo) === 0))
968+
}" />
969+
</g>
970+
</template>
971+
<template v-else>
972+
<g v-for="(label, i) in timeLabels" :key="`time_label_${i}`">
973+
<text
974+
:data-cy="`xy-time-label-${i}`"
975+
v-if="
976+
(label && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
977+
(label && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && (i === 0 || i === timeLabels.length -1) && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
978+
(label && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && selectedSerieIndex === i && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo) ||
979+
(label && !FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyFirstAndLast && FINAL_CONFIG.chart.grid.labels.xAxisLabels.showOnlyAtModulo && (i % Math.floor((this.slicer.end - this.slicer.start) / FINAL_CONFIG.chart.grid.labels.xAxisLabels.modulo) === 0))
980+
"
981+
:text-anchor="FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation > 0 ? 'start' : FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation < 0 ? 'end' : 'middle'"
982+
:font-size="fontSizes.xAxis"
983+
:fill="FINAL_CONFIG.chart.grid.labels.xAxisLabels.color"
984+
:transform="`translate(${drawingArea.left + (drawingArea.width / maxSeries) * i + (drawingArea.width / maxSeries / 2)}, ${drawingArea.bottom + fontSizes.xAxis * 1.3 + FINAL_CONFIG.chart.grid.labels.xAxisLabels.yOffset}), rotate(${FINAL_CONFIG.chart.grid.labels.xAxisLabels.rotation})`"
985+
:style="{
986+
cursor: 'pointer'
987+
}"
988+
@click="() => selectTimeLabel(label, i)"
989+
>
990+
{{ label.text || "" }}
991+
</text>
992+
</g>
993+
</template>
971994
</g>
972995

973996
<!-- TOOLTIP TRAPS -->
@@ -998,7 +1021,7 @@
9981021
style="overflow: visible !important;"
9991022
>
10001023
<div class="vue-ui-xy-time-tag" :style="`width: fit-content;margin: 0 auto;text-align:center;padding:3px 12px;background:${FINAL_CONFIG.chart.timeTag.backgroundColor};color:${FINAL_CONFIG.chart.timeTag.color};font-size:${FINAL_CONFIG.chart.timeTag.fontSize}px`">
1001-
{{ timeLabels[(selectedSerieIndex !== null ? selectedSerieIndex : 0) || (selectedMinimapIndex !== null ? selectedMinimapIndex : 0)] || ((selectedSerieIndex !== null ? selectedSerieIndex : 0) || (selectedMinimapIndex !== null ? selectedMinimapIndex : 0)) }}
1024+
{{ timeLabels[(selectedSerieIndex !== null ? selectedSerieIndex : 0) || (selectedMinimapIndex !== null ? selectedMinimapIndex : 0)].text || ((selectedSerieIndex !== null ? selectedSerieIndex : 0) || (selectedMinimapIndex !== null ? selectedMinimapIndex : 0)) }}
10021025
</div>
10031026
</foreignObject>
10041027
<circle
@@ -1984,7 +2007,17 @@ export default {
19842007
return this.slicer.end - this.slicer.start;
19852008
},
19862009
timeLabels() {
1987-
return this.FINAL_CONFIG.chart.grid.labels.xAxisLabels.values.slice(this.slicer.start, this.slicer.end);
2010+
const max = Math.max(...this.dataset.map(datapoint => this.largestTriangleThreeBucketsArray({data:datapoint.series, threshold: this.FINAL_CONFIG.downsample.threshold}).length));
2011+
const labels = [];
2012+
2013+
for (let i = 0; i < max; i += 1) {
2014+
labels.push({
2015+
text: this.FINAL_CONFIG.chart.grid.labels.xAxisLabels.values[i] || String(i),
2016+
absoluteIndex: i
2017+
})
2018+
}
2019+
2020+
return labels.slice(this.slicer.start, this.slicer.end);
19882021
},
19892022
slot() {
19902023
return {
@@ -2017,7 +2050,7 @@ export default {
20172050
const body = [];
20182051
20192052
this.timeLabels.forEach((t, i) => {
2020-
const row = [t];
2053+
const row = [t.text];
20212054
this.relativeDataset.forEach(s => {
20222055
row.push(this.canShowValue(s.absoluteValues[i]) ? Number(s.absoluteValues[i].toFixed(this.FINAL_CONFIG.table.rounding)) : '')
20232056
});
@@ -2041,7 +2074,7 @@ export default {
20412074
}).reduce((a, b) => a + b, 0)
20422075
20432076
body.push([
2044-
this.timeLabels[i] ?? '-']
2077+
this.timeLabels[i].text ?? '-']
20452078
.concat(this.relativeDataset
20462079
.map(ds => {
20472080
return this.applyDataLabel(
@@ -2130,8 +2163,8 @@ export default {
21302163
config: this.FINAL_CONFIG
21312164
})
21322165
} else {
2133-
if(time) {
2134-
html += `<div style="padding-bottom: 6px; margin-bottom: 4px; border-bottom: 1px solid ${this.FINAL_CONFIG.chart.tooltip.borderColor}; width:100%">${time}</div>`;
2166+
if(time && time.text && this.FINAL_CONFIG.chart.tooltip.showTimeLabel) {
2167+
html += `<div style="padding-bottom: 6px; margin-bottom: 4px; border-bottom: 1px solid ${this.FINAL_CONFIG.chart.tooltip.borderColor}; width:100%">${time.text}</div>`;
21352168
}
21362169
this.selectedSeries.forEach(s => {
21372170
if(this.isSafeValue(s.value)) {
@@ -2285,7 +2318,26 @@ export default {
22852318
useNestedProp,
22862319
toggleAnnotator() {
22872320
this.isAnnotator = !this.isAnnotator;
2288-
},
2321+
},
2322+
selectTimeLabel(label, relativeIndex) {
2323+
const datapoint = this.relativeDataset.map(datapoint => {
2324+
return {
2325+
shape: datapoint.shape || null,
2326+
name: datapoint.name,
2327+
color: datapoint.color,
2328+
type: datapoint.type,
2329+
value: datapoint.absoluteValues.find((_s,i) => i === relativeIndex),
2330+
comments: datapoint.comments || [],
2331+
prefix: datapoint.prefix || this.FINAL_CONFIG.chart.labels.prefix,
2332+
suffix: datapoint.suffix || this.FINAL_CONFIG.chart.labels.suffix,
2333+
}
2334+
})
2335+
this.$emit('selectTimeLabel', {
2336+
datapoint,
2337+
absoluteIndex: label.absoluteIndex,
2338+
label: label.text
2339+
})
2340+
},
22892341
getHighlightAreaPosition(area) {
22902342
const x = this.drawingArea.left + (this.drawingArea.width / this.maxSeries) * (area.from - this.slicer.start);
22912343

0 commit comments

Comments
 (0)