@visionaris-bruno/vs-echarts 7.2.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { provideEchartsCore, NgxEchartsDirective } from 'ngx-echarts';
|
|
2
2
|
import * as echarts from 'echarts/core';
|
|
3
3
|
import { BarChart, PieChart, LineChart, ScatterChart, FunnelChart, SunburstChart } from 'echarts/charts';
|
|
4
|
-
import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GraphicComponent, ToolboxComponent, PolarComponent } from 'echarts/components';
|
|
4
|
+
import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GraphicComponent, ToolboxComponent, PolarComponent, DatasetComponent } from 'echarts/components';
|
|
5
5
|
import { CanvasRenderer, SVGRenderer } from 'echarts/renderers';
|
|
6
6
|
import * as i0 from '@angular/core';
|
|
7
7
|
import { EventEmitter, Output, Input, ViewChild, Directive, Component } from '@angular/core';
|
|
@@ -75,6 +75,7 @@ function initializeEcharts() {
|
|
|
75
75
|
GraphicComponent,
|
|
76
76
|
ToolboxComponent,
|
|
77
77
|
PolarComponent,
|
|
78
|
+
DatasetComponent,
|
|
78
79
|
]);
|
|
79
80
|
initialized = true;
|
|
80
81
|
}
|
|
@@ -175,7 +176,7 @@ function defaultOptionsOverrides() {
|
|
|
175
176
|
class BaseEchartsComponent {
|
|
176
177
|
chartContainer;
|
|
177
178
|
/** Datos normalizados para graficar */
|
|
178
|
-
data = {
|
|
179
|
+
data = { dimensions: [], source: [] };
|
|
179
180
|
optionsOverrides = defaultOptionsOverrides();
|
|
180
181
|
/** Paleta de colores básica */
|
|
181
182
|
palette;
|
|
@@ -406,12 +407,12 @@ function getLegendOptions(overrides) {
|
|
|
406
407
|
return merge({}, defaults, overrides);
|
|
407
408
|
}
|
|
408
409
|
function getCategoryAxisOptions(overrides) {
|
|
409
|
-
const categories =
|
|
410
|
-
const autoRotate = categories.length > 10 ? 45 : 0;
|
|
410
|
+
const categories = overrides?.data ? overrides.data.map(c => typeof c === 'string' ? c : (c?.name || String(c))) : undefined;
|
|
411
|
+
const autoRotate = categories && categories.length > 10 ? 45 : 0;
|
|
411
412
|
const defaults = {
|
|
412
413
|
type: 'category',
|
|
413
414
|
triggerEvent: true,
|
|
414
|
-
data: categories,
|
|
415
|
+
...(categories ? { data: categories } : {}),
|
|
415
416
|
axisLabel: {
|
|
416
417
|
rotate: autoRotate,
|
|
417
418
|
interval: 0,
|
|
@@ -429,7 +430,7 @@ function getCategoryAxisOptions(overrides) {
|
|
|
429
430
|
}
|
|
430
431
|
}
|
|
431
432
|
};
|
|
432
|
-
return merge({}, defaults,
|
|
433
|
+
return merge({}, defaults, overrides);
|
|
433
434
|
}
|
|
434
435
|
function getValueAxisOptions(overrides) {
|
|
435
436
|
const defaults = {
|
|
@@ -598,12 +599,11 @@ function applyLineSelectionStyle(series, selectedCategoryIndex, selectedSeriesIn
|
|
|
598
599
|
/**
|
|
599
600
|
* Resolves the unique key of a category safely.
|
|
600
601
|
*/
|
|
601
|
-
function getCategoryKey(
|
|
602
|
-
if (!
|
|
602
|
+
function getCategoryKey(dimensions, index) {
|
|
603
|
+
if (!dimensions || !dimensions[index]) {
|
|
603
604
|
return String(index);
|
|
604
605
|
}
|
|
605
|
-
|
|
606
|
-
return node.key || node.name || String(index);
|
|
606
|
+
return dimensions[index].name;
|
|
607
607
|
}
|
|
608
608
|
/**
|
|
609
609
|
* Resolves the numeric value from a series data point.
|
|
@@ -613,126 +613,35 @@ function getCellValue(val) {
|
|
|
613
613
|
return 0;
|
|
614
614
|
return val;
|
|
615
615
|
}
|
|
616
|
-
function flattenCategoriesToFirstLevel(categories) {
|
|
617
|
-
if (!categories)
|
|
618
|
-
return [];
|
|
619
|
-
return categories.map(cat => ({
|
|
620
|
-
name: cat.name,
|
|
621
|
-
key: cat.key
|
|
622
|
-
}));
|
|
623
|
-
}
|
|
624
|
-
function getLeafIndicesMap(categories) {
|
|
625
|
-
let leafCount = 0;
|
|
626
|
-
const topLevelLeaves = [];
|
|
627
|
-
const countLeaves = (node) => {
|
|
628
|
-
if (!node.children || node.children.length === 0) {
|
|
629
|
-
return 1;
|
|
630
|
-
}
|
|
631
|
-
let sum = 0;
|
|
632
|
-
for (const child of node.children) {
|
|
633
|
-
sum += countLeaves(child);
|
|
634
|
-
}
|
|
635
|
-
return sum;
|
|
636
|
-
};
|
|
637
|
-
for (const cat of categories) {
|
|
638
|
-
const leavesUnderCat = countLeaves(cat);
|
|
639
|
-
topLevelLeaves.push({
|
|
640
|
-
start: leafCount,
|
|
641
|
-
end: leafCount + leavesUnderCat
|
|
642
|
-
});
|
|
643
|
-
leafCount += leavesUnderCat;
|
|
644
|
-
}
|
|
645
|
-
return {
|
|
646
|
-
topLevelLeaves,
|
|
647
|
-
totalLeaves: leafCount
|
|
648
|
-
};
|
|
649
|
-
}
|
|
650
|
-
function collectLeafSeries(nodes, parentNamePath = []) {
|
|
651
|
-
const leaves = [];
|
|
652
|
-
for (const node of nodes) {
|
|
653
|
-
const currentPath = [...parentNamePath, node.name];
|
|
654
|
-
if (node.children && node.children.length > 0) {
|
|
655
|
-
leaves.push(...collectLeafSeries(node.children, currentPath));
|
|
656
|
-
}
|
|
657
|
-
else {
|
|
658
|
-
const combinedName = currentPath.join(' ');
|
|
659
|
-
leaves.push({
|
|
660
|
-
...node,
|
|
661
|
-
name: combinedName
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
return leaves;
|
|
666
|
-
}
|
|
667
|
-
function flattenEChartData(data) {
|
|
668
|
-
if (!data)
|
|
669
|
-
return { categories: [], series: [] };
|
|
670
|
-
const categories = data.categories || [];
|
|
671
|
-
const series = data.series || [];
|
|
672
|
-
const topLevelCategories = flattenCategoriesToFirstLevel(categories);
|
|
673
|
-
const { topLevelLeaves } = getLeafIndicesMap(categories);
|
|
674
|
-
const flatSeries = collectLeafSeries(series).map(s => {
|
|
675
|
-
const aggregatedData = [];
|
|
676
|
-
for (const range of topLevelLeaves) {
|
|
677
|
-
let sum = 0;
|
|
678
|
-
for (let j = range.start; j < range.end; j++) {
|
|
679
|
-
sum += s.data[j] ?? 0;
|
|
680
|
-
}
|
|
681
|
-
aggregatedData.push(sum);
|
|
682
|
-
}
|
|
683
|
-
return {
|
|
684
|
-
...s,
|
|
685
|
-
data: aggregatedData
|
|
686
|
-
};
|
|
687
|
-
});
|
|
688
|
-
return {
|
|
689
|
-
categories: topLevelCategories,
|
|
690
|
-
series: flatSeries
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
/**
|
|
694
|
-
* Normalizes category nodes into an array of string names for category axes.
|
|
695
|
-
*/
|
|
696
|
-
function resolveCategoryNames(categories) {
|
|
697
|
-
if (!categories)
|
|
698
|
-
return [];
|
|
699
|
-
return categories.map(c => {
|
|
700
|
-
if (!c)
|
|
701
|
-
return '';
|
|
702
|
-
if (typeof c === 'string')
|
|
703
|
-
return c;
|
|
704
|
-
if (typeof c === 'object' && 'name' in c)
|
|
705
|
-
return c.name;
|
|
706
|
-
return String(c);
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* Maps categories and series data into a flat array of objects suitable for Pie/Ring/Funnel charts.
|
|
711
|
-
*/
|
|
712
|
-
function mapToChartItems(categories, seriesNode) {
|
|
713
|
-
if (!categories || !seriesNode || !seriesNode.data)
|
|
714
|
-
return [];
|
|
715
|
-
return categories.map((catNode, catIndex) => ({
|
|
716
|
-
name: catNode.name,
|
|
717
|
-
value: getCellValue(seriesNode.data[catIndex]),
|
|
718
|
-
originalMeassureKey: seriesNode.originalKey || getCategoryKey(categories, catIndex)
|
|
719
|
-
}));
|
|
720
|
-
}
|
|
721
616
|
/**
|
|
722
617
|
* Formatter generator for 'item' trigger strategy in tooltips.
|
|
723
618
|
*/
|
|
724
619
|
function getItemTooltipFormatter(data, formatCellValue, opts) {
|
|
725
|
-
const totalSeries = data.series.length;
|
|
726
620
|
return (params) => {
|
|
621
|
+
let title = '', subtitle = '', valFormatted = '', auxVal = '';
|
|
727
622
|
const showSerieName = opts?.showSerieName ?? true;
|
|
728
|
-
const
|
|
729
|
-
const
|
|
730
|
-
const
|
|
623
|
+
const row = params.value;
|
|
624
|
+
const dimension = data.dimensions[params.seriesIndex + 1];
|
|
625
|
+
const dimensionName = dimension ? dimension.name : '';
|
|
626
|
+
if (!dimensionName)
|
|
627
|
+
return '';
|
|
628
|
+
const rawValue = (row && typeof row === 'object') ? row[dimensionName] : params.value;
|
|
731
629
|
const serieName = showSerieName ? `${params.marker} ${params.seriesName}<br/ >` : '';
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
630
|
+
title = params.name || (row && typeof row === 'object' ? row.category : '');
|
|
631
|
+
subtitle = (params.percent !== undefined && data.dimensions.length <= 2) ? '' : serieName;
|
|
632
|
+
valFormatted = formatCellValue(Number(rawValue ?? 0), dimensionName);
|
|
633
|
+
auxVal = params.percent !== undefined ? ` (${params.percent}%)` : '';
|
|
634
|
+
// sunburst treemap
|
|
635
|
+
if (params.treePathInfo) {
|
|
636
|
+
const lastLevelIndex = params.treePathInfo.length - 1, parentNodeIndex = lastLevelIndex - 1;
|
|
637
|
+
const parentNode = params.treePathInfo[parentNodeIndex];
|
|
638
|
+
const oldParentNode = params.treePathInfo[1];
|
|
639
|
+
if (parentNode.name) {
|
|
640
|
+
title = `${parentNode.name}->${params.name}`;
|
|
641
|
+
subtitle = `${params.marker} ${oldParentNode.name}<br/ >`;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return `<div style="text-align: center;"><b>${title}</b><br/>${subtitle}<b>${valFormatted}</b>${auxVal}</div>`;
|
|
736
645
|
};
|
|
737
646
|
}
|
|
738
647
|
/**
|
|
@@ -746,13 +655,17 @@ function getAxisTooltipFormatter(data, formatCellValue, opts) {
|
|
|
746
655
|
if (items.length === 0)
|
|
747
656
|
return '';
|
|
748
657
|
const firstItem = items[0];
|
|
749
|
-
|
|
658
|
+
const row = firstItem.value;
|
|
659
|
+
const title = firstItem.name || (row && typeof row === 'object' ? row.category : '');
|
|
660
|
+
let html = `<b>${title}</b><br/>`;
|
|
750
661
|
for (const item of items) {
|
|
751
|
-
const
|
|
752
|
-
|
|
662
|
+
const dimension = data.dimensions[item.seriesIndex + 1];
|
|
663
|
+
const dimensionName = dimension ? dimension.name : '';
|
|
664
|
+
if (!dimensionName)
|
|
753
665
|
continue;
|
|
754
|
-
const
|
|
755
|
-
const
|
|
666
|
+
const itemRow = item.value;
|
|
667
|
+
const rawValue = (itemRow && typeof itemRow === 'object') ? itemRow[dimensionName] : item.value;
|
|
668
|
+
const valFormatted = formatCellValue(Number(rawValue ?? 0), dimensionName);
|
|
756
669
|
html += `${item.marker} ${item.seriesName}: <b>${valFormatted}</b><br/>`;
|
|
757
670
|
}
|
|
758
671
|
return html;
|
|
@@ -786,63 +699,43 @@ function getCommons(opts) {
|
|
|
786
699
|
return common;
|
|
787
700
|
}
|
|
788
701
|
/**
|
|
789
|
-
* Maps hierarchical category nodes and
|
|
790
|
-
* suitable for Sunburst/Treemap charts.
|
|
791
|
-
* The categories form the levels closest to the center, and the series form the leaf level.
|
|
702
|
+
* Maps hierarchical category nodes and their measures into a nested structure
|
|
703
|
+
* suitable for Sunburst/Treemap charts from the IEChartDataNode children.
|
|
792
704
|
*/
|
|
793
|
-
function mapHierarchicalData(
|
|
794
|
-
if (!
|
|
705
|
+
function mapHierarchicalData(source, dimensions) {
|
|
706
|
+
if (!source) {
|
|
795
707
|
return [];
|
|
796
708
|
}
|
|
797
|
-
|
|
798
|
-
function mapSeriesTree(seriesNodes, index) {
|
|
799
|
-
if (!seriesNodes) {
|
|
800
|
-
return [];
|
|
801
|
-
}
|
|
802
|
-
return seriesNodes.map(s => {
|
|
803
|
-
const node = {
|
|
804
|
-
name: s.name,
|
|
805
|
-
};
|
|
806
|
-
if (s.children && s.children.length > 0) {
|
|
807
|
-
node.children = mapSeriesTree(s.children, index);
|
|
808
|
-
}
|
|
809
|
-
else {
|
|
810
|
-
// Leaf series node: extract value from s.data[index]
|
|
811
|
-
const dataVal = s.data?.[index];
|
|
812
|
-
if (dataVal !== undefined && dataVal !== null) {
|
|
813
|
-
const value = typeof dataVal === 'object' && 'value' in dataVal ? dataVal.value : dataVal;
|
|
814
|
-
node.value = getCellValue(value);
|
|
815
|
-
}
|
|
816
|
-
else {
|
|
817
|
-
node.value = 0;
|
|
818
|
-
}
|
|
819
|
-
node.originalMeassureKey = s.originalKey;
|
|
820
|
-
}
|
|
821
|
-
return node;
|
|
822
|
-
});
|
|
823
|
-
}
|
|
709
|
+
const measureDims = dimensions.filter(d => d.name !== 'category');
|
|
824
710
|
function traverse(nodes) {
|
|
825
|
-
return nodes.map(
|
|
826
|
-
const
|
|
827
|
-
name:
|
|
711
|
+
return nodes.map(node => {
|
|
712
|
+
const item = {
|
|
713
|
+
name: node.category,
|
|
828
714
|
};
|
|
829
|
-
if (
|
|
830
|
-
|
|
715
|
+
if (node.children && node.children.length > 0) {
|
|
716
|
+
item.children = traverse(node.children);
|
|
831
717
|
}
|
|
832
718
|
else {
|
|
833
|
-
// Leaf category node: append the series
|
|
834
|
-
if (
|
|
835
|
-
|
|
719
|
+
// Leaf category node: append the series (measures) as the final level of children
|
|
720
|
+
if (measureDims.length > 0) {
|
|
721
|
+
item.children = measureDims.map(dim => {
|
|
722
|
+
const rawValue = node[dim.name];
|
|
723
|
+
const value = typeof rawValue === 'object' && rawValue !== null && 'value' in rawValue ? rawValue.value : rawValue;
|
|
724
|
+
return {
|
|
725
|
+
name: dim.displayName || dim.name,
|
|
726
|
+
value: getCellValue(Number(value ?? 0)),
|
|
727
|
+
originalMeassureKey: dim.name
|
|
728
|
+
};
|
|
729
|
+
});
|
|
836
730
|
}
|
|
837
731
|
else {
|
|
838
|
-
|
|
732
|
+
item.value = 0;
|
|
839
733
|
}
|
|
840
|
-
leafIndex++;
|
|
841
734
|
}
|
|
842
|
-
return
|
|
735
|
+
return item;
|
|
843
736
|
});
|
|
844
737
|
}
|
|
845
|
-
return traverse(
|
|
738
|
+
return traverse(source);
|
|
846
739
|
}
|
|
847
740
|
/**
|
|
848
741
|
* Calculates the maximum depth of a tree structure.
|
|
@@ -889,10 +782,14 @@ class RingBuilder {
|
|
|
889
782
|
merge(this.result, common);
|
|
890
783
|
}
|
|
891
784
|
addSeries(data, overrides) {
|
|
892
|
-
|
|
893
|
-
if (!flatData || !flatData.series.length)
|
|
785
|
+
if (!data || !data.dimensions || !data.source || data.source.length === 0)
|
|
894
786
|
return;
|
|
895
|
-
|
|
787
|
+
this.result.dataset = {
|
|
788
|
+
dimensions: data.dimensions,
|
|
789
|
+
source: data.source
|
|
790
|
+
};
|
|
791
|
+
const measureDims = data.dimensions.filter(d => d.name !== 'category');
|
|
792
|
+
const totalRings = measureDims.length; // Cada serie es un anillo
|
|
896
793
|
// Configuración dinámica de radios y márgenes
|
|
897
794
|
const margin = totalRings > 1 ? Math.max(0.5, 2.5 - (totalRings * 0.1)) : 0;
|
|
898
795
|
const minInnerRadius = totalRings === 1 ? 45 : (totalRings > 5 ? Math.max(15, 40 - (totalRings * 1.2)) : 40);
|
|
@@ -901,12 +798,14 @@ class RingBuilder {
|
|
|
901
798
|
const thickness = availableSpan / totalRings;
|
|
902
799
|
const borderRadius = totalRings === 1 ? 10 : Math.max(2, Math.min(10, thickness * 0.8));
|
|
903
800
|
const borderWidth = totalRings === 1 ? 2 : Math.max(0.5, Math.min(2, thickness * 0.15));
|
|
904
|
-
const series =
|
|
801
|
+
const series = measureDims.map((dim, ringIndex) => {
|
|
802
|
+
const dimKey = dim.name;
|
|
803
|
+
const friendlyName = dim.displayName || dim.name;
|
|
905
804
|
const inner = minInnerRadius + (ringIndex * (thickness + margin));
|
|
906
805
|
const outer = inner + thickness;
|
|
907
|
-
const pieData = mapToChartItems(flatData.categories, s);
|
|
908
806
|
const dynamicRingSeriesOptions = {
|
|
909
|
-
name:
|
|
807
|
+
name: friendlyName,
|
|
808
|
+
type: 'pie',
|
|
910
809
|
radius: [`${inner}%`, `${outer}%`],
|
|
911
810
|
itemStyle: {
|
|
912
811
|
borderRadius: borderRadius,
|
|
@@ -922,7 +821,10 @@ class RingBuilder {
|
|
|
922
821
|
borderWidth: borderWidth,
|
|
923
822
|
},
|
|
924
823
|
},
|
|
925
|
-
|
|
824
|
+
encode: {
|
|
825
|
+
itemName: 'category',
|
|
826
|
+
value: dimKey
|
|
827
|
+
},
|
|
926
828
|
id: `ring_${ringIndex}`,
|
|
927
829
|
};
|
|
928
830
|
const seriesOption = merge(dynamicRingSeriesOptions, overrides);
|
|
@@ -958,9 +860,8 @@ class RingBuilder {
|
|
|
958
860
|
}];
|
|
959
861
|
}
|
|
960
862
|
addTooltip(data, overrides) {
|
|
961
|
-
const flatData = flattenEChartData(data);
|
|
962
863
|
merge(overrides, {
|
|
963
|
-
formatter: getTooltipFormatter(overrides.trigger,
|
|
864
|
+
formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
|
|
964
865
|
});
|
|
965
866
|
const tooltip = getTooltipOptions(overrides);
|
|
966
867
|
this.result.tooltip = tooltip;
|
|
@@ -1022,7 +923,8 @@ class VSECDirector {
|
|
|
1022
923
|
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
1023
924
|
// chart components
|
|
1024
925
|
this.builder.addCommons();
|
|
1025
|
-
|
|
926
|
+
const layoutOpts = { axisTypes };
|
|
927
|
+
this.builder.addSeries(data, seriesOverrides, layoutOpts);
|
|
1026
928
|
this.builder.addXAxis(data, overrides.axis, axisTypes.x);
|
|
1027
929
|
this.builder.addYAxis(data, overrides.axis, axisTypes.y);
|
|
1028
930
|
this.builder.addTooltip(data, overrides.tooltip);
|
|
@@ -1044,7 +946,8 @@ class VSECDirector {
|
|
|
1044
946
|
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
1045
947
|
// chart components
|
|
1046
948
|
this.builder.addCommons();
|
|
1047
|
-
|
|
949
|
+
const layoutOpts = { axisTypes, coordinateSystem: 'polar' };
|
|
950
|
+
this.builder.addSeries(data, seriesOverrides, layoutOpts);
|
|
1048
951
|
this.builder.addPolar();
|
|
1049
952
|
this.builder.addAngleAxis(data, overrides['axis']);
|
|
1050
953
|
this.builder.addRadiusAxis(data, overrides['axis']);
|
|
@@ -1067,7 +970,8 @@ class VSECDirector {
|
|
|
1067
970
|
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
1068
971
|
// chart components
|
|
1069
972
|
this.builder.addCommons();
|
|
1070
|
-
|
|
973
|
+
const layoutOpts = { axisTypes };
|
|
974
|
+
this.builder.addSeries(data, seriesOverrides, layoutOpts);
|
|
1071
975
|
this.builder.addXAxis(data, overrides.axis, axisTypes.x);
|
|
1072
976
|
this.builder.addYAxis(data, overrides.axis, axisTypes.y);
|
|
1073
977
|
this.builder.addTooltip(data, overrides.tooltip);
|
|
@@ -1087,7 +991,8 @@ class VSECDirector {
|
|
|
1087
991
|
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
1088
992
|
// chart components
|
|
1089
993
|
this.builder.addCommons();
|
|
1090
|
-
|
|
994
|
+
const layoutOpts = { axisTypes };
|
|
995
|
+
this.builder.addSeries(data, seriesOverrides, layoutOpts);
|
|
1091
996
|
this.builder.addXAxis(data, overrides.axis, axisTypes.x);
|
|
1092
997
|
this.builder.addYAxis(data, overrides.axis, axisTypes.y);
|
|
1093
998
|
this.builder.addTooltip(data, overrides.tooltip);
|
|
@@ -1104,7 +1009,8 @@ class VSECDirector {
|
|
|
1104
1009
|
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
1105
1010
|
// chart components
|
|
1106
1011
|
this.builder.addCommons();
|
|
1107
|
-
|
|
1012
|
+
const layoutOpts = {};
|
|
1013
|
+
this.builder.addSeries(data, seriesOverrides, layoutOpts);
|
|
1108
1014
|
this.builder.addGraphic();
|
|
1109
1015
|
this.builder.addTooltip(data, overrides.tooltip);
|
|
1110
1016
|
this.builder.addLegend();
|
|
@@ -1120,7 +1026,8 @@ class VSECDirector {
|
|
|
1120
1026
|
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
1121
1027
|
// chart components
|
|
1122
1028
|
this.builder.addCommons();
|
|
1123
|
-
|
|
1029
|
+
const layoutOpts = {};
|
|
1030
|
+
this.builder.addSeries(data, seriesOverrides, layoutOpts);
|
|
1124
1031
|
this.builder.addTooltip(data, overrides.tooltip);
|
|
1125
1032
|
this.builder.addLegend();
|
|
1126
1033
|
}
|
|
@@ -1135,7 +1042,8 @@ class VSECDirector {
|
|
|
1135
1042
|
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
1136
1043
|
// chart components
|
|
1137
1044
|
this.builder.addCommons();
|
|
1138
|
-
|
|
1045
|
+
const layoutOpts = {};
|
|
1046
|
+
this.builder.addSeries(data, seriesOverrides, layoutOpts);
|
|
1139
1047
|
this.builder.addTooltip(data, overrides.tooltip);
|
|
1140
1048
|
this.builder.addLegend();
|
|
1141
1049
|
}
|
|
@@ -1150,7 +1058,8 @@ class VSECDirector {
|
|
|
1150
1058
|
const seriesOverrides = merge$1({}, product.baseOptions.series, overrides[product.chartKey].series);
|
|
1151
1059
|
// chart components
|
|
1152
1060
|
this.builder.addCommons();
|
|
1153
|
-
|
|
1061
|
+
const layoutOpts = {};
|
|
1062
|
+
this.builder.addSeries(data, seriesOverrides, layoutOpts);
|
|
1154
1063
|
this.builder.addTooltip(data, overrides.tooltip);
|
|
1155
1064
|
// this.builder.addLegend();
|
|
1156
1065
|
}
|
|
@@ -1316,18 +1225,26 @@ class PieBuilder {
|
|
|
1316
1225
|
merge(this.result, common);
|
|
1317
1226
|
}
|
|
1318
1227
|
addSeries(data, overrides) {
|
|
1319
|
-
|
|
1320
|
-
if (!flatData || !flatData.series.length)
|
|
1228
|
+
if (!data || !data.dimensions || !data.source || data.source.length === 0)
|
|
1321
1229
|
return;
|
|
1322
|
-
|
|
1230
|
+
this.result.dataset = {
|
|
1231
|
+
dimensions: data.dimensions,
|
|
1232
|
+
source: data.source
|
|
1233
|
+
};
|
|
1234
|
+
const measureDims = data.dimensions.filter(d => d.name !== 'category');
|
|
1235
|
+
const totalSeries = measureDims.length;
|
|
1323
1236
|
let series = [];
|
|
1324
1237
|
if (totalSeries === 1) {
|
|
1325
|
-
const
|
|
1326
|
-
const
|
|
1238
|
+
const dim = measureDims[0];
|
|
1239
|
+
const dimKey = dim.name;
|
|
1240
|
+
const friendlyName = dim.displayName || dim.name;
|
|
1327
1241
|
const dynamicPieSeriesOptions = {
|
|
1328
|
-
name:
|
|
1242
|
+
name: friendlyName,
|
|
1329
1243
|
type: 'pie',
|
|
1330
|
-
|
|
1244
|
+
encode: {
|
|
1245
|
+
itemName: 'category',
|
|
1246
|
+
value: dimKey
|
|
1247
|
+
},
|
|
1331
1248
|
id: `pie_0`,
|
|
1332
1249
|
radius: [0, '50%'],
|
|
1333
1250
|
label: {
|
|
@@ -1352,8 +1269,9 @@ class PieBuilder {
|
|
|
1352
1269
|
const numRings = totalSeries - 1;
|
|
1353
1270
|
const availableSpan = maxOuterRadius - (centerPieRadius + margin) - (margin * (numRings - 1));
|
|
1354
1271
|
const thickness = availableSpan / numRings;
|
|
1355
|
-
series =
|
|
1356
|
-
const
|
|
1272
|
+
series = measureDims.map((dim, idx) => {
|
|
1273
|
+
const dimKey = dim.name;
|
|
1274
|
+
const friendlyName = dim.displayName || dim.name;
|
|
1357
1275
|
let radius;
|
|
1358
1276
|
let labelPosition;
|
|
1359
1277
|
let labelLineShow;
|
|
@@ -1374,7 +1292,7 @@ class PieBuilder {
|
|
|
1374
1292
|
labelLineShow = true;
|
|
1375
1293
|
}
|
|
1376
1294
|
const dynamicPieSeriesOptions = {
|
|
1377
|
-
name:
|
|
1295
|
+
name: friendlyName,
|
|
1378
1296
|
type: 'pie',
|
|
1379
1297
|
radius: radius,
|
|
1380
1298
|
label: {
|
|
@@ -1384,7 +1302,10 @@ class PieBuilder {
|
|
|
1384
1302
|
labelLine: {
|
|
1385
1303
|
show: labelLineShow
|
|
1386
1304
|
},
|
|
1387
|
-
|
|
1305
|
+
encode: {
|
|
1306
|
+
itemName: 'category',
|
|
1307
|
+
value: dimKey
|
|
1308
|
+
},
|
|
1388
1309
|
id: `pie_${idx}`,
|
|
1389
1310
|
};
|
|
1390
1311
|
const seriesOption = merge(dynamicPieSeriesOptions, overrides);
|
|
@@ -1398,9 +1319,8 @@ class PieBuilder {
|
|
|
1398
1319
|
this.result.series = series;
|
|
1399
1320
|
}
|
|
1400
1321
|
addTooltip(data, overrides) {
|
|
1401
|
-
const flatData = flattenEChartData(data);
|
|
1402
1322
|
merge(overrides, {
|
|
1403
|
-
formatter: getTooltipFormatter(overrides.trigger,
|
|
1323
|
+
formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
|
|
1404
1324
|
});
|
|
1405
1325
|
const tooltip = getTooltipOptions(overrides);
|
|
1406
1326
|
this.result.tooltip = tooltip;
|
|
@@ -1524,39 +1444,45 @@ class FunnelBuilder {
|
|
|
1524
1444
|
merge(this.result, common);
|
|
1525
1445
|
}
|
|
1526
1446
|
addSeries(data, overrides) {
|
|
1527
|
-
|
|
1528
|
-
if (!flatData || !flatData.series.length)
|
|
1447
|
+
if (!data || !data.dimensions || !data.source || data.source.length === 0)
|
|
1529
1448
|
return;
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1449
|
+
this.result.dataset = {
|
|
1450
|
+
dimensions: data.dimensions,
|
|
1451
|
+
source: data.source
|
|
1452
|
+
};
|
|
1453
|
+
const measureDims = data.dimensions.filter(d => d.name !== 'category');
|
|
1454
|
+
if (measureDims.length === 0)
|
|
1455
|
+
return;
|
|
1456
|
+
const dim = measureDims[0];
|
|
1457
|
+
const dimKey = dim.name;
|
|
1458
|
+
const friendlyName = dim.displayName || dim.name;
|
|
1459
|
+
// Obtener los valores para min/max
|
|
1460
|
+
const seriesValues = data.source.map(row => Number(row[dimKey] ?? 0));
|
|
1461
|
+
const minVal = seriesValues.length > 0 ? Math.min(...seriesValues) : 0;
|
|
1462
|
+
const maxVal = seriesValues.length > 0 ? Math.max(...seriesValues) : 100;
|
|
1463
|
+
const dynamicFunnelSeriesOptions = {
|
|
1464
|
+
name: friendlyName,
|
|
1465
|
+
type: 'funnel',
|
|
1466
|
+
left: '10%',
|
|
1467
|
+
width: '80%',
|
|
1468
|
+
min: minVal,
|
|
1469
|
+
max: maxVal,
|
|
1470
|
+
encode: {
|
|
1471
|
+
itemName: 'category',
|
|
1472
|
+
value: dimKey
|
|
1473
|
+
},
|
|
1474
|
+
id: `funnel_0`
|
|
1475
|
+
};
|
|
1476
|
+
const seriesOption = merge({}, overrides, dynamicFunnelSeriesOptions);
|
|
1477
|
+
// Inject color resolver if provided
|
|
1478
|
+
if (this.colorResolver && seriesOption.itemStyle) {
|
|
1479
|
+
seriesOption.itemStyle.color = this.colorResolver;
|
|
1480
|
+
}
|
|
1481
|
+
this.result.series = seriesOption;
|
|
1555
1482
|
}
|
|
1556
1483
|
addTooltip(data, overrides) {
|
|
1557
|
-
const flatData = flattenEChartData(data);
|
|
1558
1484
|
merge(overrides, {
|
|
1559
|
-
formatter: getTooltipFormatter(overrides.trigger,
|
|
1485
|
+
formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
|
|
1560
1486
|
});
|
|
1561
1487
|
const tooltip = getTooltipOptions(overrides);
|
|
1562
1488
|
this.result.tooltip = tooltip;
|
|
@@ -1700,18 +1626,43 @@ class EChartBuilder {
|
|
|
1700
1626
|
* @param overrides
|
|
1701
1627
|
* @returns
|
|
1702
1628
|
*/
|
|
1703
|
-
addSeries(data, overrides) {
|
|
1704
|
-
|
|
1705
|
-
if (!flatData || !flatData.series.length)
|
|
1629
|
+
addSeries(data, overrides, opts) {
|
|
1630
|
+
if (!data || !data.dimensions || !data.source || data.source.length === 0)
|
|
1706
1631
|
return;
|
|
1707
|
-
|
|
1632
|
+
this.result.dataset = {
|
|
1633
|
+
dimensions: data.dimensions,
|
|
1634
|
+
source: data.source
|
|
1635
|
+
};
|
|
1636
|
+
const measureDims = data.dimensions.filter(d => d.name !== 'category');
|
|
1637
|
+
const isPolar = opts?.coordinateSystem === 'polar';
|
|
1638
|
+
const isHorizontal = opts?.axisTypes?.x === 'value' && opts?.axisTypes?.y === 'category';
|
|
1639
|
+
const series = measureDims.map((dim) => {
|
|
1640
|
+
const friendlyName = dim.displayName || dim.name;
|
|
1641
|
+
const dimKey = dim.name;
|
|
1642
|
+
let encode = {
|
|
1643
|
+
x: 'category',
|
|
1644
|
+
y: dimKey
|
|
1645
|
+
};
|
|
1646
|
+
if (isPolar) {
|
|
1647
|
+
encode = {
|
|
1648
|
+
angle: 'category',
|
|
1649
|
+
radius: dimKey
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
else if (isHorizontal) {
|
|
1653
|
+
encode = {
|
|
1654
|
+
x: dimKey,
|
|
1655
|
+
y: 'category'
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1708
1658
|
const dynamicOverrides = {
|
|
1709
|
-
name:
|
|
1710
|
-
|
|
1659
|
+
name: friendlyName,
|
|
1660
|
+
encode,
|
|
1711
1661
|
label: {
|
|
1712
1662
|
formatter: (params) => {
|
|
1713
|
-
const
|
|
1714
|
-
|
|
1663
|
+
const row = params.value;
|
|
1664
|
+
const rawValue = (row && typeof row === 'object') ? row[dimKey] : params.value;
|
|
1665
|
+
return this.formatCellValue(Number(rawValue ?? 0), dimKey);
|
|
1715
1666
|
}
|
|
1716
1667
|
}
|
|
1717
1668
|
};
|
|
@@ -1731,9 +1682,8 @@ class EChartBuilder {
|
|
|
1731
1682
|
*/
|
|
1732
1683
|
addTooltip(data, overrides) {
|
|
1733
1684
|
// inyecto formateador a overrides de tooltip
|
|
1734
|
-
const flatData = flattenEChartData(data);
|
|
1735
1685
|
merge$1(overrides, {
|
|
1736
|
-
formatter: getTooltipFormatter(overrides.trigger,
|
|
1686
|
+
formatter: getTooltipFormatter(overrides.trigger, data, this.formatCellValue.bind(this)),
|
|
1737
1687
|
});
|
|
1738
1688
|
const tooltip = getTooltipOptions(overrides);
|
|
1739
1689
|
this.result.tooltip = tooltip;
|
|
@@ -1850,10 +1800,9 @@ class EChartBuilder {
|
|
|
1850
1800
|
}
|
|
1851
1801
|
// Utils
|
|
1852
1802
|
getCategoryAxisOptions(data, overrides) {
|
|
1853
|
-
|
|
1803
|
+
// No explicit data needed on category axis when using ECharts dataset
|
|
1854
1804
|
const categoryAxisOptionsOverrides = {
|
|
1855
|
-
...overrides.categoryAxis[0]
|
|
1856
|
-
data: resolveCategoryNames(flatCategories),
|
|
1805
|
+
...overrides.categoryAxis[0]
|
|
1857
1806
|
};
|
|
1858
1807
|
const categoryAxisOptions = getCategoryAxisOptions(categoryAxisOptionsOverrides);
|
|
1859
1808
|
return categoryAxisOptions;
|
|
@@ -2282,10 +2231,10 @@ class SunburstBuilder {
|
|
|
2282
2231
|
this.result = {};
|
|
2283
2232
|
}
|
|
2284
2233
|
addSeries(data, overrides) {
|
|
2285
|
-
if (!data || !data.
|
|
2234
|
+
if (!data || !data.source || data.source.length === 0) {
|
|
2286
2235
|
return;
|
|
2287
2236
|
}
|
|
2288
|
-
const sunburstData = mapHierarchicalData(data.
|
|
2237
|
+
const sunburstData = mapHierarchicalData(data.source, data.dimensions);
|
|
2289
2238
|
const depth = getTreeDepth(sunburstData);
|
|
2290
2239
|
const levels = [];
|
|
2291
2240
|
for (let i = 0; i <= depth; i++) {
|