Skip to content

Commit 7537f9c

Browse files
committed
Improvement - VueUiXy - Add formatters for zoom labels and time tag
1 parent 62e98cd commit 7537f9c

File tree

6 files changed

+381
-46
lines changed

6 files changed

+381
-46
lines changed

TestingArena/ArenaVueUiXy.vue

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,18 @@ function createDs(n, m = 100) {
289289
return arr
290290
}
291291
292+
function generateDayTimestamps(length) {
293+
const result = [];
294+
const start = new Date();
295+
start.setHours(0, 0, 0, 0);
296+
297+
for (let i = 0; i < length; i += 1) {
298+
result.push(new Date(start.getTime() + i * 24 * 60 * 60 * 1000).getTime());
299+
}
300+
301+
return result;
302+
}
303+
292304
// const to = ref(null);
293305
// const raf = ref(null);
294306
// const ds = ref(createDs(12));
@@ -378,27 +390,27 @@ onMounted(() => {
378390
dataset.value = [
379391
{
380392
name: "Serie A",
381-
series: [60, 100, 112, 221, 119, 75, 199, -226, -243, 198, 156, 127, 120],
393+
series: createDs(100),
382394
type: "line",
383395
dataLabels: false,
384396
smooth: false
385397
},
386-
{
387-
name: "Serie B",
388-
series: [60, 75, 11, 20, 10, 8, null, 20, 22, 204, 146, 117, 55],
389-
type: "line",
390-
dataLabels: false,
391-
shape: 'triangle',
392-
// useArea: true,
393-
smooth: false,
394-
// useProgression: true
395-
},
396-
{
397-
name: "Serie C with a long name",
398-
series: [60, 75, 11, 20, 10, 8, null, 20, 22, 204, 146, 117, 55],
399-
type: "plot",
400-
dataLabels: false,
401-
},
398+
// {
399+
// name: "Serie B",
400+
// series: [60, 75, 11, 20, 10, 8, null, 20, 22, 204, 146, 117, 55],
401+
// type: "line",
402+
// dataLabels: false,
403+
// shape: 'triangle',
404+
// // useArea: true,
405+
// smooth: false,
406+
// // useProgression: true
407+
// },
408+
// {
409+
// name: "Serie C with a long name",
410+
// series: [60, 75, 11, 20, 10, 8, null, 20, 22, 204, 146, 117, 55],
411+
// type: "plot",
412+
// dataLabels: false,
413+
// },
402414
]
403415
}, 2000)
404416
})
@@ -592,6 +604,7 @@ function toggleProps() {
592604
const model = ref([
593605
{ key: 'debug', def: true, type: 'checkbox'},
594606
{ key: 'autoSize', def: false, type: 'checkbox'}, // v3 opt-in
607+
// { key: 'downsample.threshold', def: 100, type: 'number'},
595608
596609
{ key: 'locale', def: '', type: 'select', options: ['', 'en-US', 'en-GB', 'fr-FR', 'de-DE', 'ar-SA'] },
597610
{ key: 'responsive', def: false, type: 'checkbox' },
@@ -625,7 +638,7 @@ const model = ref([
625638
{ key: 'chart.zoom.enableRangeHandles', def: true, type: 'chexkbox' },
626639
{ key: 'chart.zoom.enableSelectionDrag', def: true, type: 'checkbox' },
627640
628-
{ key: 'chart.zoom.minimap.show', def: true, type: 'checkbox' },
641+
{ key: 'chart.zoom.minimap.show', def: false, type: 'checkbox' },
629642
{ key: 'chart.zoom.minimap.smooth', def: true, type: 'checkbox' },
630643
{ key: 'chart.zoom.minimap.selectedColor', def: '#1f77b4', type: 'color' },
631644
{ key: 'chart.zoom.minimap.selectedColorOpacity', def: 0.2, type: 'range', min: 0, max: 1, step: 0.01 },
@@ -1110,14 +1123,14 @@ const config = computed(() => {
11101123
},
11111124
xAxisLabels: {
11121125
...c.chart.grid.labels.xAxisLabels,
1113-
values: dates,
1126+
values: generateDayTimestamps(1000),
11141127
// values: new Array(13).fill(0).map((d,i) => {
11151128
// return `Some long name\nwith a value ${i}`
11161129
// }),
11171130
// rotation: -30,
11181131
datetimeFormatter: {
11191132
enable: true,
1120-
locale: 'en',
1133+
locale: 'fr',
11211134
useUTC: false,
11221135
januaryAsYear: true,
11231136
options: {
@@ -1132,11 +1145,20 @@ const config = computed(() => {
11321145
}
11331146
}
11341147
},
1148+
zoom: {
1149+
...c.chart.zoom,
1150+
useDefaultFormat: true,
1151+
// customFormat: ({ absoluteIndex }) => {
1152+
// return String(absoluteIndex) + 'TEST'
1153+
// }
1154+
},
11351155
timeTag: {
11361156
...c.chart.timeTag,
1137-
customFormat: ({ absoluteIndex }) => {
1138-
return absoluteIndex.toString();
1139-
}
1157+
useDefaultFormat: true,
1158+
timeFormat: 'yyyy-MM-dd HH:mm:ss',
1159+
// customFormat: ({ absoluteIndex }) => {
1160+
// return String(absoluteIndex) + 'TEST'
1161+
// }
11401162
}
11411163
}
11421164
}

src/atoms/SlicerPreview.vue

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, onUpdated,
33
import BaseIcon from './BaseIcon.vue';
44
import { useResponsive } from '../useResponsive';
55
import { throttle } from '../canvas-lib';
6-
import { XMLNS, adaptColorToBackground, createSmoothPath, createStraightPath, createUid } from '../lib';
6+
import { XMLNS, adaptColorToBackground, createSmoothPath, createStraightPath, createUid, isFunction } from '../lib';
77
88
const props = defineProps({
99
background: {
@@ -116,6 +116,22 @@ const props = defineProps({
116116
isPreview: {
117117
type: Boolean,
118118
default: false
119+
},
120+
preciseLabels: {
121+
type: Array,
122+
default() {
123+
return []
124+
}
125+
},
126+
usePreciseLabels: {
127+
type: Boolean,
128+
default: false
129+
},
130+
selectedSeries: {
131+
type: Object,
132+
},
133+
customFormat: {
134+
type: [Function, null]
119135
}
120136
});
121137
@@ -573,9 +589,42 @@ watch(() => props.labelRight, () => {
573589
nextTick(setTooltipRight);
574590
}, { deep: true });
575591
592+
const useCustomFormat = ref(false);
593+
576594
const labels = computed(() => {
577-
const left = props.timeLabels.find(t => t.absoluteIndex === startValue.value);
578-
const right = props.timeLabels.find(t => t.absoluteIndex === endValue.value - 1);
595+
let left = { text: '' }, right = { text: '' };
596+
useCustomFormat.value = false;
597+
598+
if (isFunction(props.customFormat)) {
599+
try {
600+
const customLeft = props.customFormat({
601+
absoluteIndex: startValue.value,
602+
seriesIndex: startValue.value,
603+
datapoint: props.selectedSeries
604+
});
605+
const customRight = props.customFormat({
606+
absoluteIndex: endValue.value - 1,
607+
seriesIndex: endValue.value - 1,
608+
datapoint: props.selectedSeries
609+
});
610+
if (typeof customLeft === 'string' && typeof customRight === 'string') {
611+
left.text = customLeft;
612+
right.text = customRight;
613+
useCustomFormat.value = true;
614+
}
615+
} catch (err) {
616+
console.warn('Custom format cannot be applied on zoom labels.');
617+
useCustomFormat.value = false;
618+
}
619+
}
620+
621+
if (!useCustomFormat.value) {
622+
left = props.usePreciseLabels ? props.preciseLabels.find(t => t.absoluteIndex === startValue.value) : props.timeLabels.find(t => t.absoluteIndex === startValue.value);
623+
624+
right = props.usePreciseLabels ? props.preciseLabels.find(t => t.absoluteIndex === endValue.value - 1) : props.timeLabels.find(t => t.absoluteIndex === endValue.value - 1);
625+
}
626+
627+
579628
return {
580629
left: left ? left.text : '',
581630
right: right ? right.text : ''

src/components/vue-ui-xy.cy.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@ import { testCommonFeatures } from "../../cypress/fixtures";
44

55
const { config, dataset } = components.find((c) => c.name === "VueUiXy");
66

7+
function generateDayTimestamps(length) {
8+
const result = [];
9+
const start = new Date(2026, 0, 1);
10+
start.setHours(0, 0, 0, 0);
11+
12+
for (let i = 0; i < length; i += 1) {
13+
result.push(new Date(start.getTime() + i * 24 * 60 * 60 * 1000).getTime());
14+
}
15+
16+
return result;
17+
}
18+
19+
function createDs(n, m = 100) {
20+
const arr = [];
21+
for (let i = 0; i < n; i += 1) {
22+
arr.push(Math.random() * m * - 1)
23+
}
24+
return arr
25+
}
26+
727
describe("<VueUiXy />", () => {
828
it("renders default", () => {
929
cy.mount(VueUiXy, {
@@ -213,4 +233,114 @@ describe("<VueUiXy />", () => {
213233
});
214234
});
215235
});
236+
237+
const config2 = {
238+
chart: {
239+
grid: {
240+
labels: {
241+
xAxisLabels: {
242+
datetimeFormatter: {
243+
enable: true
244+
},
245+
values: generateDayTimestamps(365)
246+
}
247+
}
248+
},
249+
timeTag: {
250+
show: true,
251+
useDefaultFormat: false
252+
}
253+
}
254+
}
255+
256+
const dataset2 = [
257+
{
258+
name: 'Series A',
259+
type: 'line',
260+
series: createDs(365)
261+
}
262+
]
263+
264+
it("uses zoom slicer (preview) with formatted labels", () => {
265+
cy.mount(VueUiXy, {
266+
props: {
267+
dataset: dataset2,
268+
config: {
269+
...config2,
270+
chart: {
271+
...config2.chart,
272+
zoom: {
273+
useDefaultFormat: false,
274+
}
275+
}
276+
},
277+
},
278+
}).then(() => {
279+
cy.get('[data-cy="slicer-handle-left"]').trigger('mousedown', { force: true });
280+
cy.get('[data-cy="slicer-label-left"]').contains('2026-01-01 00:00:00');
281+
cy.get('[data-cy="slicer-label-right"]').contains('2026-12-31 00:00:00');
282+
})
283+
})
284+
285+
it("uses zoom slicer (preview) with customFormat labels", () => {
286+
cy.mount(VueUiXy, {
287+
props: {
288+
dataset: dataset2,
289+
config: {
290+
...config2,
291+
chart: {
292+
...config2.chart,
293+
zoom: {
294+
customFormat: ({ absoluteIndex }) => {
295+
return String(absoluteIndex) + ' - CUSTOM'
296+
}
297+
}
298+
}
299+
},
300+
},
301+
}).then(() => {
302+
cy.get('[data-cy="slicer-handle-left"]').trigger('mousedown', { force: true });
303+
cy.get('[data-cy="slicer-label-left"]').contains('0 - CUSTOM');
304+
cy.get('[data-cy="slicer-label-right"]').contains('364 - CUSTOM');
305+
})
306+
})
307+
308+
it("displays time tag with time format", () => {
309+
cy.mount(VueUiXy, {
310+
props: {
311+
dataset: dataset2,
312+
config: {
313+
...config2,
314+
},
315+
},
316+
}).then(() => {
317+
cy.get('[data-cy="xy-svg"]').trigger('mouseenter', { force: true });
318+
cy.get('[data-cy="xy-svg"]').trigger('mousemove', { force: true });
319+
cy.get('[data-cy="time-tag"]').should('be.visible').and('contain', "2026-06-25 01:00:00")
320+
})
321+
})
322+
323+
it("displays time tag with customFormat", () => {
324+
cy.mount(VueUiXy, {
325+
props: {
326+
dataset: dataset2,
327+
config: {
328+
...config2,
329+
chart: {
330+
...config2.chart,
331+
timeTag: {
332+
show: true,
333+
customFormat: ({ absoluteIndex }) => {
334+
return String(absoluteIndex) + ' - CUSTOM';
335+
}
336+
}
337+
}
338+
},
339+
},
340+
}).then(() => {
341+
cy.get('[data-cy="xy-svg"]').trigger('mouseenter', { force: true });
342+
cy.get('[data-cy="xy-svg"]').trigger('mousemove', { force: true });
343+
cy.get('[data-cy="time-tag"]').should('be.visible').and('contain', "175 - CUSTOM")
344+
})
345+
})
216346
});

0 commit comments

Comments
 (0)