@@ -13,6 +13,7 @@ import {
13
13
createCsvContent ,
14
14
createUid ,
15
15
dataLabel ,
16
+ deepEmptyObjectToNull ,
16
17
downloadCsv ,
17
18
error ,
18
19
getMissingDatasetAttributes ,
@@ -41,6 +42,8 @@ import PackageVersion from "../atoms/PackageVersion.vue";
41
42
import PenAndPaper from " ../atoms/PenAndPaper.vue" ;
42
43
import { useUserOptionState } from " ../useUserOptionState" ;
43
44
import { useChartAccessibility } from " ../useChartAccessibility" ;
45
+ import BaseDraggableDialog from " ../atoms/BaseDraggableDialog.vue" ;
46
+ import VueUiDonut from " ./vue-ui-donut.vue" ;
44
47
45
48
const { vue_ui_donut_evolution: DEFAULT_CONFIG } = useConfig ();
46
49
@@ -422,36 +425,29 @@ function displayArcPercentage(arc, stepBreakdown) {
422
425
}
423
426
424
427
function leave () {
425
- if (isFixed .value ) return ;
426
428
hoveredIndex .value = null ;
427
429
hoveredDatapoint .value = null ;
428
430
}
429
431
430
432
function enter (datapoint ) {
431
- if (isFixed .value ) return ;
432
433
hoveredIndex .value = datapoint .index ;
433
434
hoveredDatapoint .value = datapoint;
434
435
}
435
436
436
437
const fixedDatapointIndex = ref (null );
437
438
438
439
function fixDatapoint (datapoint , index ) {
439
- if (! datapoint .subtotal ) return ;
440
+ if (! datapoint .subtotal || ! FINAL_CONFIG . value . style . chart . dialog . show ) return ;
440
441
hoveredDatapoint .value = null ;
441
442
hoveredIndex .value = null ;
442
443
isFixed .value = true ;
443
444
fixedDatapoint .value = datapoint;
445
+ createDonutDatasetForDialog (datapoint);
444
446
if (! [null , undefined ].includes (index)) {
445
447
fixedDatapointIndex .value = index;
446
448
}
447
449
}
448
450
449
- function unfixDatapoint () {
450
- fixedDatapoint .value = null ;
451
- isFixed .value = false ;
452
- fixedDatapointIndex .value = null ;
453
- }
454
-
455
451
const legendSet = computed (() => {
456
452
return convertedDataset .value
457
453
.map ((serie , i ) => {
@@ -582,8 +578,27 @@ function toggleAnnotator() {
582
578
function isArcBigEnoughHover (arc ) {
583
579
return arc .proportion * 100 > FINAL_CONFIG .value .style .chart .donuts .hover .hideLabelsUnderValue ;
584
580
}
585
- function isArcBigEnoughZoom (arc ) {
586
- return arc .proportion * 100 > FINAL_CONFIG .value .style .chart .donuts .zoom .hideLabelsUnderValue ;
581
+
582
+ const donutDataset = ref ([]);
583
+ const donutConfig = ref ({});
584
+ const dialog = ref (null );
585
+
586
+ function createDonutDatasetForDialog (ds ) {
587
+ donutDataset .value = ds .donut .map (ds => {
588
+ return {
589
+ name: ds .name ,
590
+ values: [ds .value ],
591
+ color: ds .color
592
+ }
593
+ });
594
+
595
+ donutConfig .value = deepEmptyObjectToNull ({
596
+ ... FINAL_CONFIG .value .style .chart .dialog .donutChart ,
597
+ responsive: true ,
598
+ theme: FINAL_CONFIG .value .theme ,
599
+ });
600
+
601
+ dialog .value && dialog .value .open ();
587
602
}
588
603
589
604
defineExpose ({
@@ -692,7 +707,7 @@ defineExpose({
692
707
: class = " { 'vue-data-ui-fullscreen--on': isFullscreen, 'vue-data-ui-fulscreen--off': !isFullscreen }"
693
708
data- cy= " donut-evolution-svg"
694
709
: viewBox= " `0 0 ${svg.absoluteWidth} ${svg.absoluteHeight}`"
695
- : style= " `max-width:100%; overflow: visible; background:transparent;color:${FINAL_CONFIG.style.chart.color}`"
710
+ : style= " `max-width:100%; overflow: visible; background:transparent;color:${FINAL_CONFIG.style.chart.color}; `"
696
711
>
697
712
< PackageVersion / >
698
713
@@ -764,7 +779,7 @@ defineExpose({
764
779
< / g>
765
780
766
781
<!-- Y LABELS -->
767
- < g v- if = " FINAL_CONFIG.style.chart.layout.grid.yAxis.dataLabels.show" : class = " {'donut-opacity': true, 'donut-behind': hoveredIndex !== null || isFixed }" >
782
+ < g v- if = " FINAL_CONFIG.style.chart.layout.grid.yAxis.dataLabels.show" : class = " {'donut-opacity': true, 'donut-behind': hoveredIndex !== null}" >
768
783
< g v- for = " (yLabel, i) in yLabels" >
769
784
< line
770
785
data- cy= " axis-y-tick"
@@ -803,7 +818,7 @@ defineExpose({
803
818
< / g>
804
819
805
820
<!-- X LABELS -->
806
- < g v- if = " FINAL_CONFIG.style.chart.layout.grid.xAxis.dataLabels.show" : class = " {'donut-opacity': true, 'donut-behind': isFixed }" >
821
+ < g v- if = " FINAL_CONFIG.style.chart.layout.grid.xAxis.dataLabels.show" : class = " {'donut-opacity': true,}" >
807
822
< g v- for = " (_, i) in (slicer.end - slicer.start)" >
808
823
< text
809
824
data- cy= " axis-x-label"
@@ -822,7 +837,7 @@ defineExpose({
822
837
<!-- DATAPOINTS -->
823
838
< g v- for = " (datapoint, i ) in drawableDataset" >
824
839
< line
825
- : class = " {'donut-opacity': true, 'donut-behind': hoveredIndex !== null || isFixed }"
840
+ : class = " {'donut-opacity': true, 'donut-behind': hoveredIndex !== null}"
826
841
v- if = " FINAL_CONFIG.style.chart.layout.line.show && i < drawableDataset.length - 1 && ![datapoint.subtotal, drawableDataset[i + 1].subtotal].includes(null)"
827
842
: x1= " datapoint.x"
828
843
: y1= " datapoint.y"
@@ -844,7 +859,7 @@ defineExpose({
844
859
< / g>
845
860
< / g>
846
861
847
- < g v- for = " (datapoint, i ) in drawableDataset" : data- cy= " `donut-wrapper-${i}`" : class = " {'donut-opacity': true, 'donut-behind': (i !== hoveredIndex && hoveredIndex !== null) || isFixed }" >
862
+ < g v- for = " (datapoint, i ) in drawableDataset" : data- cy= " `donut-wrapper-${i}`" : class = " {'donut-opacity': true, 'donut-behind': (i !== hoveredIndex && hoveredIndex !== null)}" >
848
863
< g v- if = " datapoint.subtotal" >
849
864
< g v- if = " hoveredIndex !== null && hoveredIndex === i" >
850
865
< g v- for = " arc in datapoint.donutHover" >
@@ -886,7 +901,7 @@ defineExpose({
886
901
< / g>
887
902
< / g>
888
903
< / g>
889
- < g v- for = " (datapoint, i ) in drawableDataset" : class = " {'donut-opacity': true, 'donut-behind': (i !== hoveredIndex && hoveredIndex !== null) || isFixed }" >
904
+ < g v- for = " (datapoint, i ) in drawableDataset" : class = " {'donut-opacity': true, 'donut-behind': (i !== hoveredIndex && hoveredIndex !== null)}" >
890
905
< g v- if = " datapoint.subtotal !== null" >
891
906
< circle
892
907
v- if = " datapoint.subtotal === 0"
@@ -918,7 +933,7 @@ defineExpose({
918
933
< / g>
919
934
920
935
<!-- DATALABELS -->
921
- < g v- for = " (datapoint, i ) in drawableDataset" : class = " {'donut-opacity': true, 'donut-behind': (i !== hoveredIndex && hoveredIndex !== null) || isFixed}" >
936
+ < g v- for = " (datapoint, i ) in drawableDataset" : class = " {'donut-opacity': true, 'donut-behind': (i !== hoveredIndex && hoveredIndex !== null) || ( isFixed && i !== fixedDatapoint.index) }" >
922
937
< text
923
938
v- if = " datapoint.subtotal !== null && FINAL_CONFIG.style.chart.layout.dataLabels.show"
924
939
text- anchor= " middle"
@@ -936,12 +951,14 @@ defineExpose({
936
951
< rect
937
952
v- for = " (datapoint, i) in drawableDataset"
938
953
: x= " padding.left + (i * slit)"
939
- : y= " svg.absoluteHeight - padding.bottom - 10 "
954
+ : y= " padding.top "
940
955
: width= " slit"
941
- : height= " 10"
942
- : fill= " hoveredIndex === datapoint.index ? `url(#hover_${uid})` : 'transparent'"
943
- @click= " fixDatapoint(datapoint, i)"
944
- : class = " {'donut-hover': hoveredIndex === datapoint.index && datapoint.subtotal}"
956
+ : height= " svg.height"
957
+ : fill= " [hoveredIndex, fixedDatapointIndex].includes(datapoint.index) ? `url(#hover_${uid})` : 'transparent'"
958
+ : class = " {'donut-hover': datapoint.subtotal && [hoveredIndex, fixedDatapointIndex].includes(datapoint.index)}"
959
+ : style= " {
960
+ pointerEvents: 'none'
961
+ }"
945
962
/ >
946
963
< rect
947
964
v- for = " (datapoint, i) in drawableDataset"
@@ -957,124 +974,6 @@ defineExpose({
957
974
@click= " fixDatapoint(datapoint, i)"
958
975
: class = " {'donut-hover': hoveredIndex === datapoint.index && datapoint.subtotal}"
959
976
/ >
960
-
961
- <!-- DIALOG -->
962
- < g v- if = " isFixed" data- cy- zoom class = " vue-ui-donut-evolution-dialog" >
963
- < rect
964
- : rx= " 4"
965
- : x= " padding.left"
966
- : y= " padding.top"
967
- : width= " svg.width"
968
- : height= " svg.height"
969
- : fill= " FINAL_CONFIG.style.chart.backgroundColor"
970
- style= " filter:drop-shadow(0 12px 12px rgba(0,0,0,0.3))"
971
- / >
972
- < line
973
- data- dom- to- png- ignore
974
- : x1= " svg.absoluteWidth - padding.right - 15"
975
- : y1= " padding.top + 5"
976
- : x2= " svg.absoluteWidth - padding.right - 4"
977
- : y2= " padding.top + 15.5"
978
- stroke- linecap= " round"
979
- : stroke= " FINAL_CONFIG.style.chart.color"
980
- stroke- width= " 1.5"
981
- / >
982
- < line
983
- data- dom- to- png- ignore
984
- : x1= " svg.absoluteWidth - padding.right - 15"
985
- : y2= " padding.top + 5"
986
- : x2= " svg.absoluteWidth - padding.right - 4"
987
- : y1= " padding.top + 15.5"
988
- stroke- linecap= " round"
989
- : stroke= " FINAL_CONFIG.style.chart.color"
990
- stroke- width= " 1.5"
991
- / >
992
- < circle
993
- data- cy- close
994
- @click= " unfixDatapoint"
995
- @keypress .enter = " unfixDatapoint"
996
- : cx= " svg.absoluteWidth - padding.right - svg.width / 40"
997
- : cy= " padding.top + svg.height / 30"
998
- : r= " svg.height / 12"
999
- fill= " transparent"
1000
- style= " cursor:pointer"
1001
- tabindex= " 0"
1002
- / >
1003
-
1004
- < g v- for = " arc in fixedDatapoint.donutFocus" >
1005
- < path
1006
- v- if = " isArcBigEnoughZoom(arc)"
1007
- data- cy- zoom- donut
1008
- : d= " calcNutArrowPath(arc, {x: svg.centerX, y: svg.centerY}, 12, 12, false, false, 15)"
1009
- : stroke= " arc.color"
1010
- stroke- width= " 1"
1011
- stroke- linecap= " round"
1012
- stroke- linejoin= " round"
1013
- fill= " none"
1014
- class = " vue-ui-donut-evolution-focus"
1015
- / >
1016
- < / g>
1017
- < circle
1018
- : cx= " padding.left + svg.width / 2"
1019
- : cy= " padding.top + svg.height / 2"
1020
- : r= " svg.height / 7"
1021
- : fill= " FINAL_CONFIG.style.chart.backgroundColor"
1022
- / >
1023
- < path
1024
- v- for = " (arc, k) in fixedDatapoint.donutFocus"
1025
- : d= " arc.arcSlice"
1026
- : fill= " `${arc.color}`"
1027
- : stroke- width= " 1"
1028
- : stroke= " FINAL_CONFIG.style.chart.backgroundColor"
1029
- class = " vue-ui-donut-evolution-focus"
1030
- / >
1031
- < g v- for = " (arc, i) in fixedDatapoint.donutFocus" class = " vue-ui-donut-evolution-focus" >
1032
- < text
1033
- v- if = " isArcBigEnoughZoom(arc)"
1034
- : data- cy= " `donut-datalabel-value-${i}`"
1035
- : text- anchor= " calcMarkerOffsetX(arc, true, 20).anchor"
1036
- : x= " calcMarkerOffsetX(arc, true, 10).x"
1037
- : y= " calcMarkerOffsetY(arc)"
1038
- : fill= " FINAL_CONFIG.style.chart.layout.grid.yAxis.dataLabels.color"
1039
- : font- size= " 10"
1040
- : font- weight= " 'bold'"
1041
- >
1042
- {{ arc .name }}: {{ displayArcPercentage (arc, fixedDatapoint .donutFocus ) }} ({{ arc .value === null ? ' -' : labellizeValue (arc .value , arc, i) }})
1043
- < / text>
1044
- < / g>
1045
- < circle
1046
- : cx= " padding.left + (svg.width / 2)"
1047
- : cy= " padding.top + (svg.height / 2)"
1048
- : r= " svg.height / 3.8"
1049
- : fill= " `url(#focus_${uid})`"
1050
- / >
1051
- < circle
1052
- : cx= " padding.left + (svg.width / 2)"
1053
- : cy= " padding.top + (svg.height / 2)"
1054
- : r= " svg.height / 7.7"
1055
- : fill= " FINAL_CONFIG.style.chart.backgroundColor"
1056
- / >
1057
- < text
1058
- text- anchor= " middle"
1059
- : x= " padding.left + svg.width / 2"
1060
- : y= " padding.top + (svg.height / 2) + 14 / 3"
1061
- : font- size= " 14"
1062
- : font- weight= " 'bold'"
1063
- : fill= " FINAL_CONFIG.style.chart.layout.dataLabels.color"
1064
- class = " vue-ui-donut-evolution-focus"
1065
- >
1066
- {{ labellizeValue (fixedDatapoint .subtotal , fixedDatapoint, null ) }}
1067
- < / text>
1068
- < text
1069
- v- if = " FINAL_CONFIG.style.chart.layout.grid.xAxis.dataLabels.values[fixedDatapoint.index]"
1070
- : x= " padding.left + 6"
1071
- : y= " padding.top + FINAL_CONFIG.style.chart.layout.grid.xAxis.dataLabels.fontSize * 2"
1072
- : font- size= " FINAL_CONFIG.style.chart.layout.grid.xAxis.dataLabels.fontSize * 1.6"
1073
- : fill= " FINAL_CONFIG.style.chart.layout.dataLabels.color"
1074
- >
1075
- {{ FINAL_CONFIG .style .chart .layout .grid .xAxis .dataLabels .values [Number (fixedDatapoint .index ) + Number (slicer .start )] }}
1076
- < / text>
1077
- < / g>
1078
977
< slot name= " svg" : svg= " svg" / >
1079
978
< / svg>
1080
979
@@ -1209,6 +1108,24 @@ defineExpose({
1209
1108
< / DataTable>
1210
1109
< / template>
1211
1110
< / Accordion>
1111
+
1112
+ < BaseDraggableDialog
1113
+ v- if = " FINAL_CONFIG.style.chart.dialog.show"
1114
+ ref= " dialog"
1115
+ @close= " fixedDatapoint = null; isFixed = false"
1116
+ : backgroundColor= " FINAL_CONFIG.style.chart.dialog.backgroundColor"
1117
+ : color= " FINAL_CONFIG.style.chart.dialog.color"
1118
+ : headerBg= " FINAL_CONFIG.style.chart.dialog.header.backgroundColor"
1119
+ : headerColor= " FINAL_CONFIG.style.chart.dialog.header.color" >
1120
+ < template #title>
1121
+ {{ FINAL_CONFIG .style .chart .layout .grid .xAxis .dataLabels .values [Number (fixedDatapoint .index ) + Number (slicer .start )] }}
1122
+ < / template>
1123
+ < VueUiDonut
1124
+ v- if = " fixedDatapoint"
1125
+ : config= " donutConfig"
1126
+ : dataset= " donutDataset"
1127
+ / >
1128
+ < / BaseDraggableDialog>
1212
1129
< / div>
1213
1130
< / template>
1214
1131
0 commit comments