Skip to content

Commit 64a6928

Browse files
committed
VueUiHeatmap fixed viewBox size issues on small datasets; added tests
1 parent d489311 commit 64a6928

19 files changed

+178
-58
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,14 @@ Types are available in the 'vue-data-ui.d.ts' file under the types directory of
109109
[This repo contains a boilerplate implementation of the vue-data-ui package in Nuxt](https://github.com/graphieros/vue-data-ui-nuxt)
110110

111111
# Slots
112-
Most Vue Data UI chart components include a #svg slot you can use to introduce customized svg elements (shapes, text, etc).
112+
Most Vue Data UI chart components include a #svg slot you can use to introduce customized svg elements (shapes, text, etc).
113+
114+
# Config
115+
If for some reason you can't access the documentation website and need to get the default config object for a component:
116+
117+
```
118+
import { getVueDataUiConfig } from "vue-data-ui";
119+
120+
const defaultConfigXy = getVueDataUiConfig("vue_ui_xy");
121+
122+
```

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vue-data-ui",
33
"private": false,
4-
"version": "1.9.94",
4+
"version": "1.9.95",
55
"type": "module",
66
"description": "A user-empowering data visualization Vue components library",
77
"keywords": [
@@ -60,7 +60,7 @@
6060
"./style.css": "./dist/style.css"
6161
},
6262
"scripts": {
63-
"dev": "vite",
63+
"dev": "npm i && vite",
6464
"clean": "node cleanup.cjs",
6565
"build": "npm run clean && vite build --mode production && node copy-types.cjs && npm i",
6666
"prod": "npm run test && npx cypress run --component && npm run clean && vite build --mode production && node copy-types.cjs",

src/components/vue-ui-donut-evolution.cy.js

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,34 +23,26 @@ describe('<VueUiDonutEvolution />', () => {
2323
})
2424
});
2525

26-
function updateConfig(modifiedConfig) {
27-
cy.get('@fixture').then((fixture) => {
28-
const updatedFixture = { ...fixture, config: modifiedConfig };
29-
cy.wrap(updatedFixture).as('fixture');
30-
cy.mount(VueUiDonutEvolution, {
31-
props: {
32-
dataset: fixture.dataset,
33-
config: modifiedConfig
34-
}
35-
});
36-
});
37-
}
26+
it('shows zoomed donut on trap click', () => {
27+
cy.get('[data-cy-trap]').eq(0).click()
28+
cy.get('[data-cy-zoom]').should('be.visible')
29+
cy.get('[data-cy-zoom-donut]').should('be.visible')
30+
cy.get('[data-cy-close]').should('be.visible').click({ force: true})
31+
cy.get('[data-cy-zoom]').should('not.exist')
32+
})
3833

39-
it('renders donuts', () => {
40-
for(let i = 0; i < 12; i += 1) {
41-
cy.get(`[data-cy="donut-wrapper-${i}"]`).then(($wrapper) => {
42-
cy.wrap($wrapper).should('exist')
43-
})
44-
45-
cy.get(`[data-cy="trap-${i}"]`).then(($trap) => {
46-
cy.wrap($trap).trigger('mouseenter', { force: true })
47-
cy.wait(150)
48-
cy.wrap($trap).trigger('mouseleave')
49-
cy.wrap($trap).click();
50-
cy.wait(150)
51-
cy.get(`[data-cy="quit-dialog"]`).click()
52-
})
53-
}
34+
it('segregates series when selecting legend items', () => {
35+
cy.get('[data-cy-legend-item]').eq(0).click()
36+
cy.get(`[data-cy="arc_0"]`).should('have.length', 3)
37+
cy.get('[data-cy-legend-item]').eq(0).click()
38+
cy.get(`[data-cy="arc_0"]`).should('have.length', 4)
39+
})
40+
41+
it('shows donut hovered state', () => {
42+
cy.get('[data-cy-trap]').eq(0).trigger('mouseenter')
43+
cy.get('[data-cy="donut_hover_0"]').should('have.length', 4)
44+
cy.get('[data-cy-trap]').eq(0).trigger('mouseleave')
45+
cy.get('[data-cy="donut_hover_0"]').should('not.exist')
5446
})
5547

5648
it('opens user options and shows table', () => {

src/components/vue-ui-donut-evolution.vue

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ defineExpose({
536536
<g v-if="hoveredIndex !== null && hoveredIndex === i">
537537
<g v-for="arc in datapoint.donut">
538538
<path
539+
:data-cy="`donut_hover_${i}`"
539540
:d="calcNutArrowPath(arc, {x: arc.center.endX, y: arc.center.endY}, 12, 12, { x: datapoint.x, y: datapoint.y}, true)"
540541
:stroke="arc.color"
541542
stroke-width="1"
@@ -548,6 +549,7 @@ defineExpose({
548549
<g v-for="(arc, i) in datapoint.donut">
549550
<text
550551
:data-cy="`donut-datalabel-value-${i}`"
552+
data-cy-hover-label
551553
:text-anchor="calcMarkerOffsetX(arc, true, 0).anchor"
552554
:x="calcMarkerOffsetX(arc, true, 3).x"
553555
:y="calcMarkerOffsetY(arc)"
@@ -580,7 +582,8 @@ defineExpose({
580582
/>
581583
</g>
582584
<g v-else>
583-
<path
585+
<path
586+
:data-cy="`arc_${i}`"
584587
v-for="(arc, k) in datapoint.donut"
585588
:d="arc.arcSlice"
586589
:fill="`${arc.color}`"
@@ -629,6 +632,7 @@ defineExpose({
629632
<rect
630633
v-for="(datapoint, i) in drawableDataset"
631634
:data-cy="`trap-${i}`"
635+
data-cy-trap
632636
:x="padding.left + (i * slit)"
633637
:y="padding.top"
634638
:width="slit"
@@ -641,7 +645,7 @@ defineExpose({
641645
/>
642646
643647
<!-- DIALOG -->
644-
<g v-if="isFixed">
648+
<g v-if="isFixed" data-cy-zoom>
645649
<rect
646650
:rx="4"
647651
:x="padding.left"
@@ -672,7 +676,7 @@ defineExpose({
672676
stroke-width="1.5"
673677
/>
674678
<circle
675-
data-cy="quit-dialog"
679+
data-cy-close
676680
@click="unfixDatapoint"
677681
@keypress.enter="unfixDatapoint"
678682
:cx="svg.absoluteWidth - padding.right - svg.width / 40"
@@ -685,6 +689,7 @@ defineExpose({
685689
686690
<g v-for="arc in fixedDatapoint.donutFocus">
687691
<path
692+
data-cy-zoom-donut
688693
:d="calcNutArrowPath(arc, {x: svg.centerX, y: svg.centerY}, 12, 12, false, false, 1)"
689694
:stroke="arc.color"
690695
stroke-width="1"
@@ -764,7 +769,7 @@ defineExpose({
764769
@clickMarker="({legend}) => segregate(legend.uid)"
765770
>
766771
<template #item="{legend, index}">
767-
<div @click="segregate(legend.uid)" :style="`opacity:${segregated.includes(legend.uid) ? 0.5 : 1}`">
772+
<div data-cy-legend-item @click="segregate(legend.uid)" :style="`opacity:${segregated.includes(legend.uid) ? 0.5 : 1}`">
768773
{{ legend.name }} : {{ Number(legend.value.toFixed(donutEvolutionConfig.style.chart.legend.roundingValue)).toLocaleString() }}
769774
<span v-if="!segregated.includes(legend.uid)">
770775
({{ isNaN(legend.value / grandTotal) ? '-' : (legend.value / grandTotal * 100).toFixed(donutEvolutionConfig.style.chart.legend.roundingPercentage)}}%)

src/components/vue-ui-heatmap.vue

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const maxX = computed(() => {
8080
8181
const svg = computed(() => {
8282
const height = heatmapConfig.value.style.layout.padding.top + heatmapConfig.value.style.layout.padding.bottom + (props.dataset.length * heatmapConfig.value.style.layout.cells.height) + (mutableConfig.value.inside ? 92 : 0);
83-
const width= heatmapConfig.value.style.layout.padding.left + heatmapConfig.value.style.layout.padding.right + (maxX.value * heatmapConfig.value.style.layout.cells.height);
83+
const width= heatmapConfig.value.style.layout.padding.left + heatmapConfig.value.style.layout.padding.right + ((maxX.value < props.dataset.length ? props.dataset.length : maxX.value) * heatmapConfig.value.style.layout.cells.height);
8484
8585
return {
8686
height,
@@ -125,7 +125,7 @@ const average = computed(() => {
125125
const cellSize = computed(() => {
126126
return {
127127
width: (drawingArea.value.width / maxX.value),
128-
height: (drawingArea.value.width / maxX.value)
128+
height: (drawingArea.value.width / (maxX.value < props.dataset.length ? props.dataset.length : maxX.value))
129129
}
130130
});
131131
@@ -352,18 +352,18 @@ defineExpose({
352352
<g v-for="(cell, j) in serie.temperatures">
353353
<rect
354354
:x="drawingArea.left + cellSize.width * j"
355-
:y="drawingArea.top + cellSize.width * i"
355+
:y="drawingArea.top + cellSize.height * i"
356356
:width="cellSize.width - heatmapConfig.style.layout.cells.spacing"
357-
:height="cellSize.width - heatmapConfig.style.layout.cells.spacing"
357+
:height="cellSize.height - heatmapConfig.style.layout.cells.spacing"
358358
:fill="heatmapConfig.style.layout.cells.colors.underlayer"
359359
:stroke="heatmapConfig.style.backgroundColor"
360360
:stroke-width="heatmapConfig.style.layout.cells.spacing"
361361
/>
362362
<rect
363363
:x="drawingArea.left + cellSize.width * j"
364-
:y="drawingArea.top + cellSize.width * i"
364+
:y="drawingArea.top + cellSize.height * i"
365365
:width="cellSize.width - heatmapConfig.style.layout.cells.spacing"
366-
:height="cellSize.width - heatmapConfig.style.layout.cells.spacing"
366+
:height="cellSize.height - heatmapConfig.style.layout.cells.spacing"
367367
:fill="cell.color"
368368
:stroke="hoveredCell && hoveredCell === cell.id ? heatmapConfig.style.layout.cells.selected.color : heatmapConfig.style.backgroundColor"
369369
:stroke-width="heatmapConfig.style.layout.cells.spacing"
@@ -375,7 +375,7 @@ defineExpose({
375375
:font-weight="heatmapConfig.style.layout.cells.value.bold ? 'bold': 'normal'"
376376
:fill="adaptColorToBackground(cell.color)"
377377
:x="(drawingArea.left + cellSize.width * j) + (cellSize.width / 2)"
378-
:y="(drawingArea.top + cellSize.width * i) + (cellSize.width / 2) + heatmapConfig.style.layout.cells.value.fontSize / 3"
378+
:y="(drawingArea.top + cellSize.height * i) + (cellSize.height / 2) + heatmapConfig.style.layout.cells.value.fontSize / 3"
379379
>
380380
{{ Number(cell.value.toFixed(heatmapConfig.style.layout.cells.value.roundingValue)).toLocaleString() }}
381381
</text>
@@ -385,9 +385,9 @@ defineExpose({
385385
<rect
386386
:data-cy="`heatmap-trap-${i}-${j}`"
387387
:x="drawingArea.left + cellSize.width * j"
388-
:y="drawingArea.top + cellSize.width * i"
388+
:y="drawingArea.top + cellSize.height * i"
389389
:width="cellSize.width"
390-
:height="cellSize.width"
390+
:height="cellSize.height"
391391
fill="transparent"
392392
stroke="none"
393393
@mouseover="useTooltip(cell)"
@@ -399,7 +399,7 @@ defineExpose({
399399
:font-size="heatmapConfig.style.layout.dataLabels.yAxis.fontSize"
400400
:fill="heatmapConfig.style.layout.dataLabels.yAxis.color"
401401
:x="drawingArea.left + heatmapConfig.style.layout.dataLabels.yAxis.offsetX - 6"
402-
:y="drawingArea.top + (cellSize.width * i) + cellSize.width / 2 + heatmapConfig.style.layout.dataLabels.yAxis.fontSize / 3 + heatmapConfig.style.layout.dataLabels.yAxis.offsetY"
402+
:y="drawingArea.top + (cellSize.height * i) + cellSize.height / 2 + heatmapConfig.style.layout.dataLabels.yAxis.fontSize / 3 + heatmapConfig.style.layout.dataLabels.yAxis.offsetY"
403403
text-anchor="end"
404404
:font-weight="heatmapConfig.style.layout.dataLabels.yAxis.bold ? 'bold' : 'normal'"
405405
>

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ describe('<VueUiOnion />', () => {
1313
});
1414
}
1515

16+
it('segregates series when selecting legend items', () => {
17+
cy.get('@fixture').then((fixture) => {
18+
cy.mount(VueUiOnion, {
19+
props: {
20+
dataset: fixture.dataset,
21+
config: fixture.config
22+
}
23+
});
24+
25+
cy.get('[data-cy-legend-item]').eq(0).click()
26+
cy.get('[data-cy-trap]').should('have.length', 3)
27+
cy.get('[data-cy-legend-item]').eq(0).click()
28+
cy.get('[data-cy-trap]').should('have.length', 4)
29+
});
30+
})
31+
1632
it('renders with different config attributes', function () {
1733
cy.get('@fixture').then((fixture) => {
1834
cy.mount(VueUiOnion, {

src/components/vue-ui-onion.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ defineExpose({
397397
<!-- TOOLTIP TRAPS -->
398398
<circle
399399
v-for="(onion, i) in mutableDataset"
400+
data-cy-trap
400401
:data-cy="`onion-track-${i}`"
401402
:cx="drawableArea.centerX"
402403
:cy="drawableArea.centerY"
@@ -448,7 +449,7 @@ defineExpose({
448449
<foreignObject
449450
v-if="onionConfig.style.chart.legend.show && mutableConfig.inside && !isPrinting"
450451
:x="0"
451-
:y="drawableArea.bottom"
452+
:y="drawableArea.bottom + onionConfig.style.chart.legend.offsetY"
452453
width="100%"
453454
:height="svg.height - drawableArea.bottom"
454455
style="overflow:visible"
@@ -478,7 +479,7 @@ defineExpose({
478479
@clickMarker="({legend}) => segregate(legend.id)"
479480
>
480481
<template #item="{ legend }">
481-
<div @click="segregate(legend.id)" :style="`opacity:${segregated.includes(legend.id) ? 0.5 : 1}`">
482+
<div data-cy-legend-item @click="segregate(legend.id)" :style="`opacity:${segregated.includes(legend.id) ? 0.5 : 1}`">
482483
{{ legend.name }} : {{ legend.percentage.toFixed(onionConfig.style.chart.legend.roundingPercentage) }}%
483484
484485

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@ describe('<VueUiQuadrant />', () => {
77
cy.viewport(500, 650);
88
});
99

10+
it('segregates series when selecting legend items', () => {
11+
cy.get('@fixture').then((fixture) => {
12+
cy.mount(VueUiQuadrant, {
13+
props: {
14+
dataset: fixture.dataset,
15+
config: fixture.config
16+
},
17+
});
18+
19+
cy.get('[data-cy-legend-item]').eq(0).click()
20+
cy.get('[data-cy-quadrant-area]').should('have.length', 1)
21+
cy.get('[data-cy-legend-item]').eq(0).click()
22+
cy.get('[data-cy-quadrant-area]').should('have.length', 2)
23+
});
24+
})
25+
1026
it('renders', () => {
1127
cy.get('@fixture').then((fixture) => {
1228
cy.mount(VueUiQuadrant, {

src/components/vue-ui-quadrant.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,8 +798,9 @@ defineExpose({
798798
<!-- AREAS GIFT WRAPPING -->
799799
<g v-if="quadrantConfig.style.chart.layout.areas.show">
800800
<g v-for="(category, i) in drawableDataset">
801-
<polygon
801+
<polygon
802802
v-if="category.series.length > 2"
803+
data-cy-quadrant-area
803804
:fill="quadrantConfig.style.chart.layout.areas.useGradient ? `url(#quadrant_gradient_${uid}_${i})` : `${category.color}${opacity[quadrantConfig.style.chart.layout.areas.opacity]}`"
804805
:points="giftWrap(category)"
805806
/>
@@ -870,7 +871,7 @@ defineExpose({
870871
@clickMarker="({legend}) => segregate(legend.id)"
871872
>
872873
<template #item="{ legend }">
873-
<div @click="segregate(legend.id)" :style="`opacity:${segregated.includes(legend.id) ? 0.5 : 1}`">
874+
<div data-cy-legend-item @click="segregate(legend.id)" :style="`opacity:${segregated.includes(legend.id) ? 0.5 : 1}`">
874875
{{ legend.name }}
875876
</div>
876877
</template>

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@ describe('<VueUiRadar />', () => {
77
cy.viewport(500, 500);
88
});
99

10+
it('segregates series when selecting legend items', () => {
11+
cy.get('@fixture').then((fixture) => {
12+
cy.mount(VueUiRadar, {
13+
props: {
14+
dataset: fixture.dataset,
15+
config: fixture.config
16+
},
17+
});
18+
19+
cy.get('[data-cy-legend-item]').eq(0).click()
20+
cy.get('[data-cy-radar-path]').should('have.length', 2)
21+
cy.get('[data-cy-legend-item]').eq(0).click()
22+
cy.get('[data-cy-radar-path]').should('have.length', 3)
23+
});
24+
})
25+
1026
it('renders', () => {
1127
cy.get('@fixture').then((fixture) => {
1228
cy.mount(VueUiRadar, {

src/components/vue-ui-radar.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ defineExpose({
525525
<!-- PLOTS -->
526526
<g v-for="(d, i) in datasetCopy">
527527
<g v-if="!segregated.includes(i)">
528-
<path
528+
<path
529+
data-cy-radar-path
529530
:d="makePath(radar.map(r => r.plots[i]))"
530531
:stroke="d.color"
531532
:stroke-width="radarConfig.style.chart.layout.dataPolygon.strokeWidth"
@@ -578,7 +579,7 @@ defineExpose({
578579
@clickMarker="({i}) => segregate(i)"
579580
>
580581
<template #item="{ legend, index }">
581-
<div @click="segregate(index)" :style="`opacity:${segregated.includes(index) ? 0.5 : 1}`">
582+
<div data-cy-legend-item @click="segregate(index)" :style="`opacity:${segregated.includes(index) ? 0.5 : 1}`">
582583
{{ legend.name }} : {{ (legend.totalProportion * 100).toFixed(radarConfig.style.chart.legend.roundingPercentage) }}%
583584
</div>
584585
</template>

0 commit comments

Comments
 (0)