pace-chart-lib 1.0.2 → 1.0.4
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.
- package/dist/{components → Components}/Charts/ChartsWithAxis/ChartsWithAxisFunctions.d.ts +76 -38
- package/dist/{components → Components}/Charts/ChartsWithoutAxis/ChartsWithoutAxisTypes.types.d.ts +4 -2
- package/dist/{components → Components}/Charts/Core/CommonFunctions.d.ts +3 -1
- package/dist/{components → Components}/Charts/Core/DefaultProperties.types.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/pace-chart-lib.es.js +54619 -0
- package/dist/pace-chart-lib.umd.js +54622 -0
- package/dist/vite.svg +1 -0
- package/package.json +1 -1
- package/dist/Services/ErrorLog.js +0 -3
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/AreaChart.js +0 -496
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/LineChart.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/LineChart.js +0 -491
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/NormalizedStackAreaChart.js +0 -517
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/NormalizedStackLineChart.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/NormalizedStackLineChart.js +0 -553
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/StackAreaChart.js +0 -517
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/StackLineChart.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/AreaFamily/StackLineChart.js +0 -553
- package/dist/components/Charts/ChartsWithAxis/BarFamily/BarChart.d.ts +0 -12
- package/dist/components/Charts/ChartsWithAxis/BarFamily/BarChart.js +0 -9
- package/dist/components/Charts/ChartsWithAxis/ChartsWithAxisFunctions.js +0 -4909
- package/dist/components/Charts/ChartsWithAxis/ChartsWithAxisTypes.type.d.ts +0 -0
- package/dist/components/Charts/ChartsWithAxis/ChartsWithAxisTypes.type.js +0 -0
- package/dist/components/Charts/ChartsWithAxis/ChartsWithAxisTypes.types.js +0 -49
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/ColumnChart copy.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/ColumnChart copy.js +0 -486
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/ColumnChart.js +0 -497
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/ColumnHistogramChart.js +0 -418
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/CustomColumnChart.js +0 -1013
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/LayeredColumnChart.js +0 -478
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/LineChart.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/LineChart.js +0 -451
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/NormalizedStackColumnChart.js +0 -533
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/NormalizedStackLineChart.js +0 -512
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/StackColumnChart.js +0 -530
- package/dist/components/Charts/ChartsWithAxis/ColumnFamily/StackLineChart.js +0 -512
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/BarChart.d.ts +0 -12
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/BarChart.js +0 -9
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/HorizontalBarChart.js +0 -497
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/HorizontalHistogramChart.js +0 -497
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/LayeredColumnChart.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/LayeredColumnChart.js +0 -479
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/LayeredHorizontalBarChart.js +0 -478
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/NormalizedStackHorizontalBarChart.js +0 -473
- package/dist/components/Charts/ChartsWithAxis/HorizontalBarFamily/StackHorizontalBarChart.js +0 -465
- package/dist/components/Charts/ChartsWithAxis/LineFamily/100%StackLineChart.d.ts +0 -0
- package/dist/components/Charts/ChartsWithAxis/LineFamily/100%StackLineChart.js +0 -0
- package/dist/components/Charts/ChartsWithAxis/LineFamily/LineChart.js +0 -451
- package/dist/components/Charts/ChartsWithAxis/LineFamily/NormalisedStackLineChart.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/LineFamily/NormalisedStackLineChart.js +0 -554
- package/dist/components/Charts/ChartsWithAxis/LineFamily/NormalizedStackLineChart.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/LineFamily/NormalizedStackLineChart.js +0 -510
- package/dist/components/Charts/ChartsWithAxis/LineFamily/StackLineChart.d.ts +0 -4
- package/dist/components/Charts/ChartsWithAxis/LineFamily/StackLineChart.js +0 -507
- package/dist/components/Charts/ChartsWithAxis/MiscellaneousChartFamily/TornadoChart.js +0 -393
- package/dist/components/Charts/ChartsWithAxis/MiscellaneousChartFamily/WaterfallChart.js +0 -606
- package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxis.types.d.ts +0 -0
- package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxis.types.js +0 -0
- package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxisFunctions.js +0 -815
- package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxisTypes.type.d.ts +0 -0
- package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxisTypes.type.js +0 -0
- package/dist/components/Charts/ChartsWithoutAxis/ChartsWithoutAxisTypes.types.js +0 -32
- package/dist/components/Charts/ChartsWithoutAxis/Maps/Cordinates.js +0 -15021
- package/dist/components/Charts/ChartsWithoutAxis/Maps/Maps.js +0 -391
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/BubbleChart.js +0 -367
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/OrganizationChart.js +0 -570
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/ProgressChart.js +0 -212
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/PyramidChart.js +0 -401
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/RadialBarChart.js +0 -313
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/SankeyChart.js +0 -719
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/ScatterChart.js +0 -807
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/Speedometer.js +0 -514
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/VennChart.js +0 -282
- package/dist/components/Charts/ChartsWithoutAxis/OtherCharts/WordCloud.js +0 -207
- package/dist/components/Charts/ChartsWithoutAxis/PieFamily/DonutChart.js +0 -476
- package/dist/components/Charts/ChartsWithoutAxis/PieFamily/PieChart.js +0 -420
- package/dist/components/Charts/ChartsWithoutAxis/PieFamily/PieFamilyCommonFunctions.js +0 -106
- package/dist/components/Charts/ChartsWithoutAxis/PieFamily/PieofPieChart.js +0 -507
- package/dist/components/Charts/ChartsWithoutAxis/PieFamily/TreemapChart.js +0 -246
- package/dist/components/Charts/Core/Common.type.d.ts +0 -0
- package/dist/components/Charts/Core/Common.type.js +0 -0
- package/dist/components/Charts/Core/Common.types.js +0 -133
- package/dist/components/Charts/Core/CommonFunctions.js +0 -1782
- package/dist/components/Charts/Core/DefaultChartDataProperties.js +0 -64
- package/dist/components/Charts/Core/DefaultProperties.d.ts +0 -0
- package/dist/components/Charts/Core/DefaultProperties.js +0 -0
- package/dist/components/Charts/Core/DefaultProperties.type.d.ts +0 -586
- package/dist/components/Charts/Core/DefaultProperties.type.js +0 -585
- package/dist/components/Charts/Core/DefaultProperties.types.js +0 -592
- package/dist/index.js +0 -40
- /package/dist/{components → Components}/Charts/ChartsWithAxis/AreaFamily/AreaChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/AreaFamily/NormalizedStackAreaChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/AreaFamily/StackAreaChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/ChartsWithAxisTypes.types.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/ColumnChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/ColumnHistogramChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/CustomColumnChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/LayeredColumnChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/NormalizedStackColumnChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/ColumnFamily/StackColumnChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/HorizontalBarChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/HorizontalHistogramChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/LayeredHorizontalBarChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/NormalizedStackHorizontalBarChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/HorizontalBarFamily/StackHorizontalBarChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/LineFamily/LineChart.d.ts +0 -0
- /package/dist/{components/Charts/ChartsWithAxis/ColumnFamily → Components/Charts/ChartsWithAxis/LineFamily}/NormalizedStackLineChart.d.ts +0 -0
- /package/dist/{components/Charts/ChartsWithAxis/ColumnFamily → Components/Charts/ChartsWithAxis/LineFamily}/StackLineChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/MiscellaneousChartFamily/TornadoChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithAxis/MiscellaneousChartFamily/WaterfallChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/ChartsWithoutAxisFunctions.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/Maps/Cordinates.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/Maps/Maps.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/BubbleChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/OrganizationChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/ProgressChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/PyramidChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/RadialBarChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/SankeyChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/ScatterChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/Speedometer.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/VennChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/OtherCharts/WordCloud.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/DonutChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/PieChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/PieFamilyCommonFunctions.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/PieofPieChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/ChartsWithoutAxis/PieFamily/TreemapChart.d.ts +0 -0
- /package/dist/{components → Components}/Charts/Core/Common.types.d.ts +0 -0
- /package/dist/{components → Components}/Charts/Core/DefaultChartDataProperties.d.ts +0 -0
|
@@ -1,1782 +0,0 @@
|
|
|
1
|
-
import * as d3 from "d3";
|
|
2
|
-
import { calculateWidthHeightDynamically, getNumberWithFormat } from "../ChartsWithAxis/ChartsWithAxisFunctions";
|
|
3
|
-
import { actualChartTypes } from "../ChartsWithAxis/ChartsWithAxisTypes.types";
|
|
4
|
-
import { colorThemeTypes, fontStyleOptions, horizontalLegendAllignment, legendColorMode, staticLegendShape, staticLegendPosition, staticTotalAlignment, staticTotalPosition, verticalLegendAllignment } from "./Common.types";
|
|
5
|
-
import { defaultChartFormatOptions } from "./DefaultProperties.types";
|
|
6
|
-
import { logError } from "../../../Services/ErrorLog";
|
|
7
|
-
const fileName = "CommonFunctions.ts";
|
|
8
|
-
import { chartProperties } from "./DefaultChartDataProperties";
|
|
9
|
-
const chartsWithDataTableArray = [
|
|
10
|
-
actualChartTypes.bar,
|
|
11
|
-
actualChartTypes.stackColumn,
|
|
12
|
-
actualChartTypes.stackColumn100,
|
|
13
|
-
actualChartTypes.line,
|
|
14
|
-
actualChartTypes.stackLine,
|
|
15
|
-
actualChartTypes.stackLine100,
|
|
16
|
-
actualChartTypes.area,
|
|
17
|
-
actualChartTypes.stackArea,
|
|
18
|
-
actualChartTypes.stackArea100,
|
|
19
|
-
];
|
|
20
|
-
const chartsWithoutPlotArea = [
|
|
21
|
-
actualChartTypes.pie,
|
|
22
|
-
actualChartTypes.pieOfPie,
|
|
23
|
-
actualChartTypes.sunburst,
|
|
24
|
-
actualChartTypes.pyramidChart,
|
|
25
|
-
actualChartTypes.organizationalChart,
|
|
26
|
-
actualChartTypes.vennDiagramChart,
|
|
27
|
-
actualChartTypes.progressChart,
|
|
28
|
-
actualChartTypes.maps,
|
|
29
|
-
actualChartTypes.wordCloud,
|
|
30
|
-
actualChartTypes.sankey,
|
|
31
|
-
actualChartTypes.speedometerChart,
|
|
32
|
-
actualChartTypes.radialBarChart,
|
|
33
|
-
];
|
|
34
|
-
export const svgID = "scaling-svg-";
|
|
35
|
-
export function getRandomColor() {
|
|
36
|
-
try {
|
|
37
|
-
let letters = "0123456789ABCDEF";
|
|
38
|
-
let color = "#";
|
|
39
|
-
for (let i = 0; i < 6; i++) {
|
|
40
|
-
color += letters[Math.floor(Math.random() * 16)];
|
|
41
|
-
}
|
|
42
|
-
return { color };
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
logError(fileName, "getRandomColor", error);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Draws chart legends in the specified position with optional scroll behavior,
|
|
50
|
-
* using layout and format options defined in the configuration.
|
|
51
|
-
*
|
|
52
|
-
* @param {number} height - The total height of the chart container.
|
|
53
|
-
* @param {any} svg - The SVG element where the chart and legends are rendered.
|
|
54
|
-
* @param {number[]} maxLegendDimensions - Array with the maximum dimensions [width, height] of the legends.
|
|
55
|
-
* @param {number} chartTitleHeight - Height occupied by the chart title (used to offset legends).
|
|
56
|
-
* @param {number} width - The total width of the chart container.
|
|
57
|
-
* @param {number} legendMargin - Margin to be applied around the legend area.
|
|
58
|
-
* @param {TDefaultChartFormatOptionsType} formatOptions - Formatting options for the chart including legend settings.
|
|
59
|
-
* @param {TSeries[]} seriesData - Array of data series to be represented in the legend.
|
|
60
|
-
* @param {string} chartId - A unique identifier for the chart, used to bind legend elements.
|
|
61
|
-
* @param {string} legendShape - A shape for chart legends.
|
|
62
|
-
*
|
|
63
|
-
* @return {void} - This function does not return anything. It updates the SVG by rendering legends.
|
|
64
|
-
*/
|
|
65
|
-
export function drawLegends(height, svg, maxLegendDimensions, chartTitleHeight, width, legendMargin, formatOptions, seriesData, chartId, legendShape) {
|
|
66
|
-
try {
|
|
67
|
-
let position = formatOptions.legends.legendPosition;
|
|
68
|
-
let horizontalLegendAlignment = formatOptions.legends.legendAlignmentTopBottom;
|
|
69
|
-
let verticalLegendAlignment = formatOptions.legends.legendAlignment;
|
|
70
|
-
if (formatOptions.legends.legendVisibility) {
|
|
71
|
-
switch (position) {
|
|
72
|
-
case staticLegendPosition.none:
|
|
73
|
-
break;
|
|
74
|
-
case staticLegendPosition.right:
|
|
75
|
-
let heightRight = !formatOptions.plotArea.fitChart
|
|
76
|
-
? height - chartTitleHeight - 20
|
|
77
|
-
: height - chartTitleHeight - 10;
|
|
78
|
-
legendsWithScroll(svg, seriesData, width - maxLegendDimensions[0] - 30, chartTitleHeight + 5, legendMargin + 25, heightRight, position, verticalLegendAlignment, legendShape, formatOptions, chartId);
|
|
79
|
-
break;
|
|
80
|
-
case staticLegendPosition.top:
|
|
81
|
-
legendsWithScroll(svg, seriesData, 7, chartTitleHeight + 5, width - 10, 30, position, horizontalLegendAlignment, legendShape, formatOptions, chartId);
|
|
82
|
-
break;
|
|
83
|
-
case staticLegendPosition.left:
|
|
84
|
-
let heightLeft = !formatOptions.plotArea.fitChart
|
|
85
|
-
? height - chartTitleHeight - 20
|
|
86
|
-
: height - chartTitleHeight - 10;
|
|
87
|
-
legendsWithScroll(svg, seriesData, 7, chartTitleHeight + 5, legendMargin + 25, heightLeft, position, verticalLegendAlignment, legendShape, formatOptions, chartId);
|
|
88
|
-
break;
|
|
89
|
-
case staticLegendPosition.bottom:
|
|
90
|
-
legendsWithScroll(svg, seriesData, 7, height - 25, width - 10, 30, position, horizontalLegendAlignment, legendShape, formatOptions, chartId);
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
logError(fileName, "drawLegends", error);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
;
|
|
100
|
-
/**
|
|
101
|
-
* @param {string[]} list - Array of legend strings.
|
|
102
|
-
* @param {TDefaultChartFormatOptionsType} formatOptions - Chart formatting options including legend font size and family.
|
|
103
|
-
* @return {{width: number, height: number}} - The calculated width and height of the longest legend text.
|
|
104
|
-
*/
|
|
105
|
-
export function calculateMaxLegendWidth(list, formatOptions) {
|
|
106
|
-
try {
|
|
107
|
-
let maxLength = 0;
|
|
108
|
-
let maxLegend = list[0];
|
|
109
|
-
list.forEach(legend => {
|
|
110
|
-
//legend.includes("-") ? legend.split("-")[1] :
|
|
111
|
-
let splitedLegend = legend.includes("~$~") ? legend.split("~$~")[1] : legend.includes("-") ? legend.slice(legend.indexOf("-") + 1) : legend;
|
|
112
|
-
let splitedLegendLength = splitedLegend.length;
|
|
113
|
-
if (maxLength < splitedLegendLength) {
|
|
114
|
-
maxLength = splitedLegendLength;
|
|
115
|
-
maxLegend = splitedLegend;
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
return calculateWidthHeightDynamically(maxLegend, formatOptions.legends.legendFontSize, formatOptions.legends.legendFontFamily);
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
logError(fileName, "calculateMaxLegendWidth", error);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Renders markers for line or area chart series on the provided D3 selection.
|
|
126
|
-
* Binds marker shapes, sizes, colors, and handles visibility and interaction (tooltips).
|
|
127
|
-
*
|
|
128
|
-
* @param {d3.Selection<SVGGElement, unknown, null, undefined>} lines - The D3 selection (SVG group) where marker groups will be appended.
|
|
129
|
-
* @param {TSeries[]} chartData - The data array representing chart series, each with data points and properties.
|
|
130
|
-
* @param {string} type - The chart type (e.g., "CombiLine", "Area", "StackArea") affecting marker rendering logic.
|
|
131
|
-
* @param {Function} xScale - D3 scale function for x-axis, used to position markers horizontally.
|
|
132
|
-
* @param {Function} yScale - D3 scale function for y-axis, used to position markers vertically.
|
|
133
|
-
* @param {Function} yScaleRight - D3 scale function for secodary y-axis, used to position markers vertically.
|
|
134
|
-
* @param {Function} tooltipHandle - (Not used in current snippet but assumed) Function to manage tooltip display.
|
|
135
|
-
* @param {TDefaultChartFormatOptionsType} formatOptions - Configuration object for chart formatting and visibility settings.
|
|
136
|
-
* @param {TChartJSON} chartJSON - Object containing chart metadata, formatting info, and dimension mappings.
|
|
137
|
-
* @param {number} secondaryCustomYaxisMaxValue - Maximum value for secondary Y axis scale, used for visibility logic.
|
|
138
|
-
* @param {number} secondaryCustomYaxisMinValue - Minimum value for secondary Y axis scale, used for visibility logic.
|
|
139
|
-
* @param {number} customYaxisMinValue - Minimum value for primary Y axis scale, used for visibility logic.
|
|
140
|
-
* @param {number} customYaxisMaxValue - Maximum value for primary Y axis scale, used for visibility logic.
|
|
141
|
-
* @param {boolean} isNormalizedChart - 100% chart type validation.
|
|
142
|
-
*
|
|
143
|
-
* @returns {void} This function does not return a value; it appends and updates SVG marker elements in the DOM.
|
|
144
|
-
*/
|
|
145
|
-
export function lineMarkers(lines, chartData, type, xScale, yScale, yScaleRight, tooltipHandle, formatOptions, chartJSON, secondaryCustomYaxisMaxValue, secondaryCustomYaxisMinValue, customYaxisMinValue, customYaxisMaxValue, isNormalizedChart) {
|
|
146
|
-
try {
|
|
147
|
-
let hideZeroValues = formatOptions.plotArea.hideZeroValues;
|
|
148
|
-
formatOptions.plotArea.plotAreaHideLineAndMarkers === undefined ? formatOptions.plotArea.plotAreaHideLineAndMarkers = true : null;
|
|
149
|
-
chartData.forEach((d) => d.data.forEach((j) => {
|
|
150
|
-
j["markerShape"] = (type === "CombiLine" && !formatOptions.plotArea.plotAreaHideLineAndMarkers) ? "None" : d.properties.markerShape ? d.properties.markerShape : "Circle";
|
|
151
|
-
j["currentMeasure"] = d.properties.currentMeasure;
|
|
152
|
-
}));
|
|
153
|
-
chartData.forEach((d) => d.data.forEach((j) => (j["markerColor"] = d.properties.markerColor ? d.properties.markerColor : "Blue")));
|
|
154
|
-
chartData.forEach((d) => d.data.forEach((j) => (j["markerSize"] =
|
|
155
|
-
d.properties.markerShape != "None" && d.properties.markerSize && d.properties.markerShape != "None" ? type === "Area" ? formatOptions.plotArea.plotAreaHideLineAndMarkers ? d.properties.markerSize : 0 : d.properties.markerSize : 0)));
|
|
156
|
-
function Markershapes(Shape) {
|
|
157
|
-
return Shape == "Square"
|
|
158
|
-
? d3.symbolSquare
|
|
159
|
-
: Shape == "Circle"
|
|
160
|
-
? d3.symbolCircle
|
|
161
|
-
: Shape == "Cross"
|
|
162
|
-
? d3.symbolCross
|
|
163
|
-
: Shape == "Triangle"
|
|
164
|
-
? d3.symbolTriangle
|
|
165
|
-
: Shape == "Star"
|
|
166
|
-
? d3.symbolStar
|
|
167
|
-
: Shape == "Diamond"
|
|
168
|
-
? d3.symbolDiamond
|
|
169
|
-
: Shape == "Wye"
|
|
170
|
-
? d3.symbolWye
|
|
171
|
-
: d3.symbolCircle;
|
|
172
|
-
}
|
|
173
|
-
// JOIN: bind parent marker groups
|
|
174
|
-
let markerGroups = lines.selectAll(".parentGroup")
|
|
175
|
-
.data(chartData, d => d.legend);
|
|
176
|
-
// EXIT old groups
|
|
177
|
-
// markerGroups.exit().remove();
|
|
178
|
-
// ENTER new groups
|
|
179
|
-
let markerGroupsEnter = markerGroups.enter()
|
|
180
|
-
.append("g")
|
|
181
|
-
.attr("class", "parentGroup")
|
|
182
|
-
.attr("hoverId", d => {
|
|
183
|
-
if (Array.isArray(d.legend) && d.legend.length > 0) {
|
|
184
|
-
return d.legend.includes("~$~")
|
|
185
|
-
? d.legend.split("~$~")[1].replace(/ /g, "-")
|
|
186
|
-
: d.legend.replace(/ /g, "-");
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
return d.legend.replace(/ /g, "-");
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
// MERGE all groups
|
|
193
|
-
let mergedMarkerGroups = markerGroupsEnter.merge(markerGroups);
|
|
194
|
-
// FOR EACH group: bind marker data and render path elements
|
|
195
|
-
mergedMarkerGroups.each(function (groupData) {
|
|
196
|
-
const group = d3.select(this);
|
|
197
|
-
// JOIN markers to path elements
|
|
198
|
-
let markers = group.selectAll("path")
|
|
199
|
-
.data(groupData.data);
|
|
200
|
-
// EXIT old paths
|
|
201
|
-
// markers.exit().remove();
|
|
202
|
-
// ENTER new paths
|
|
203
|
-
let markersEnter = markers.enter()
|
|
204
|
-
.append("path")
|
|
205
|
-
.attr("fill", d => d.markerColor);
|
|
206
|
-
// ENTER + UPDATE merged paths
|
|
207
|
-
markersEnter.merge(markers)
|
|
208
|
-
.attr("d", d => {
|
|
209
|
-
return d3.symbol()
|
|
210
|
-
.type(Markershapes(d.markerShape))
|
|
211
|
-
.size(d.markerSize * 50)();
|
|
212
|
-
})
|
|
213
|
-
.attr("visibility", d => {
|
|
214
|
-
const hideByX = !xScale(d.dimension) && xScale(d.dimension) !== 0;
|
|
215
|
-
const visible = formatOptions.marker.markerVisibility
|
|
216
|
-
? checkVisibleConditions(chartData, d, type, hideZeroValues, secondaryCustomYaxisMaxValue, secondaryCustomYaxisMinValue, customYaxisMinValue, customYaxisMaxValue)
|
|
217
|
-
? "hidden"
|
|
218
|
-
: ([actualChartTypes.stackLine100, "CombiLine"].includes(type) ? "visible"
|
|
219
|
-
: ([actualChartTypes.stackArea, actualChartTypes.area, "CombiArea", "CombiStackArea"].includes(type)
|
|
220
|
-
? (formatOptions.plotArea.plotAreaHideLineAndMarkers ? "visible" : "hidden")
|
|
221
|
-
: "visible"))
|
|
222
|
-
: (type === "CombiLine" ? "visible"
|
|
223
|
-
: (["Area", "CombiArea"].includes(type)
|
|
224
|
-
? (formatOptions.plotArea.plotAreaHideLineAndMarkers ? "visible" : "hidden")
|
|
225
|
-
: "hidden"));
|
|
226
|
-
return hideByX ? "hidden" : visible;
|
|
227
|
-
})
|
|
228
|
-
.attr("transform", d => {
|
|
229
|
-
let requiredYScale = d.axis == "Primary" ? yScale : yScaleRight;
|
|
230
|
-
const x = xScale(d.dimension);
|
|
231
|
-
const y = [actualChartTypes.stackArea100, actualChartTypes.stackArea, actualChartTypes.stackLine, actualChartTypes.stackLine100, "CombiStackArea"].includes(type)
|
|
232
|
-
? (d[1] > 0 ? requiredYScale(d[1]) : requiredYScale(d[0]))
|
|
233
|
-
: requiredYScale(d.value);
|
|
234
|
-
return `translate(${x},${y})`;
|
|
235
|
-
})
|
|
236
|
-
.on("mousemove", (event, d) => {
|
|
237
|
-
showTooltipOnMouseMove([
|
|
238
|
-
{
|
|
239
|
-
key: formatOptions.xAxisTitle.xAxisTitleText,
|
|
240
|
-
value: chartJSON.formattedDimensionListMap.get(Array.isArray(d.dimension) ? d.dimension[0] : d.dimension)
|
|
241
|
-
},
|
|
242
|
-
{
|
|
243
|
-
key: formatOptions.yAxisTitle.yAxisTitleText || d.value,
|
|
244
|
-
value: getNumberWithFormat(
|
|
245
|
-
// (["combiStackArea", "StackArea", "StackLine"].includes(type) ? (d as TDataPoint).value : ["100StackLine"].includes(type) ? d[1] - d[0] : (d as TDataPoint).value),
|
|
246
|
-
([actualChartTypes.stackLine100, actualChartTypes.stackArea100, ""].includes(type) ? d[1] - d[0] : d.value), formatOptions.toolTip.toolTipDisplayUnits, formatOptions.toolTip.toolTipNumberFormat, formatOptions.toolTip.toolTipDecimalPrecision)
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
key: "Legend",
|
|
250
|
-
value: d.legend.includes("~$~") ? d.legend.split("~$~")[1] : d.legend
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
key: "Calculated Tooltip",
|
|
254
|
-
value: d.tooltip
|
|
255
|
-
}
|
|
256
|
-
], formatOptions, event);
|
|
257
|
-
})
|
|
258
|
-
.on("mouseout", () => {
|
|
259
|
-
hideTooltipOnMouseOut();
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
catch (error) {
|
|
264
|
-
logError(fileName, "lineMarkers", error);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Determines whether a data point should be hidden based on visibility rules, axis scales, and zero value hiding.
|
|
269
|
-
*
|
|
270
|
-
* @param {TSeries[]} chartData - Array of chart series data, used to check axis property of the first series.
|
|
271
|
-
* @param {any} d - Data point to check visibility for; expected to have properties like Measure, [0], and [1].
|
|
272
|
-
* @param {string} type - Chart type string (e.g., "StackArea"), influences visibility logic for stacked charts.
|
|
273
|
-
* @param {boolean} hideZeroValues - Flag indicating whether zero values should be hidden.
|
|
274
|
-
* @param {number} secondaryCustomYaxisMaxValue - Maximum allowed value on secondary Y axis.
|
|
275
|
-
* @param {number} secondaryCustomYaxisMinValue - Minimum allowed value on secondary Y axis.
|
|
276
|
-
* @param {number} customYaxisMinValue - Minimum allowed value on primary Y axis.
|
|
277
|
-
* @param {number} customYaxisMaxValue - Maximum allowed value on primary Y axis.
|
|
278
|
-
*
|
|
279
|
-
* @returns {boolean} True if the data point should be hidden based on the conditions; false otherwise.
|
|
280
|
-
*/
|
|
281
|
-
const checkVisibleConditions = (chartData, d, type, hideZeroValues, secondaryCustomYaxisMaxValue, secondaryCustomYaxisMinValue, customYaxisMinValue, customYaxisMaxValue) => {
|
|
282
|
-
try {
|
|
283
|
-
if (chartData[0].properties.axis && chartData[0].properties.axis === "Secondary") {
|
|
284
|
-
return (hideZeroValues && d.Measure == 0) || d.Measure > secondaryCustomYaxisMaxValue || d.Measure < secondaryCustomYaxisMinValue;
|
|
285
|
-
}
|
|
286
|
-
else if (type.includes("Stack")) {
|
|
287
|
-
return (d.Measure > 0) ? ((hideZeroValues && d[1] == 0) || d[1] < customYaxisMinValue || d[1] > customYaxisMaxValue) : ((hideZeroValues && d[0] == 0) || d[0] < customYaxisMinValue || d[0] > customYaxisMaxValue);
|
|
288
|
-
}
|
|
289
|
-
else
|
|
290
|
-
return (hideZeroValues && d.Measure == 0) || d.Measure < customYaxisMinValue || d.Measure > customYaxisMaxValue;
|
|
291
|
-
}
|
|
292
|
-
catch (error) {
|
|
293
|
-
logError(fileName, "checkVisibleConditions", error);
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
/**
|
|
297
|
-
* Attaches hover interactions to the area chart elements to show markers and tooltips
|
|
298
|
-
* when the user moves the mouse over the chart.
|
|
299
|
-
*
|
|
300
|
-
* @param {TDefaultChartFormatOptionsType} formatOptions - Configuration options for chart appearance and tooltip formatting.
|
|
301
|
-
* @param {any} areas - D3 selection representing the area paths of the chart.
|
|
302
|
-
* @param {any} focus - D3 selection representing the group or element used for showing the focus marker and tooltip.
|
|
303
|
-
* @param {string[]} filteredDimension - Array of dimension values representing the x-axis categories.
|
|
304
|
-
* @param {any[]} lineData - Array of data series objects containing values, marker properties, and metadata.
|
|
305
|
-
* @param {any} xScale - D3 scale function for the x-axis.
|
|
306
|
-
* @param {any} yScaleLeft - D3 scale function for the left y-axis.
|
|
307
|
-
* @param {string} chartType - The type of area chart (e.g., "stackArea", "stackArea100").
|
|
308
|
-
*
|
|
309
|
-
* @return {void} This function modifies the chart's behavior by adding interactivity but does not return a value.
|
|
310
|
-
*/
|
|
311
|
-
export function onHoverMarkerForAreaChartFamily(formatOptions, areas, focus, filteredDimension, lineData, xScale, yScaleLeft, chartType) {
|
|
312
|
-
try {
|
|
313
|
-
if (!formatOptions.plotArea.plotAreaHideLineAndMarkers) {
|
|
314
|
-
areas
|
|
315
|
-
.on("mouseover", function () {
|
|
316
|
-
focus.style("display", null);
|
|
317
|
-
})
|
|
318
|
-
.on("mousemove", mousemove)
|
|
319
|
-
.on("mouseout", function () {
|
|
320
|
-
focus.style("display", "none");
|
|
321
|
-
hideTooltipOnMouseOut();
|
|
322
|
-
//
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
// .on("mousemove", mouseout)
|
|
326
|
-
let demList = filteredDimension;
|
|
327
|
-
function mousemove(event) {
|
|
328
|
-
try {
|
|
329
|
-
let m = d3.pointer(event), lowDiff = 1e99, legendIndex, dimensionIndex = null;
|
|
330
|
-
for (let i = 0; i < demList.length; i++) {
|
|
331
|
-
let diff = Math.abs(m[0] - xScale(demList[i]));
|
|
332
|
-
if (diff < lowDiff) {
|
|
333
|
-
lowDiff = diff;
|
|
334
|
-
dimensionIndex = i;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
let mindiff = 1e99;
|
|
338
|
-
for (let k = 0; k < lineData.length; k++) {
|
|
339
|
-
let diff1 = Math.abs(m[1] - yScaleLeft(lineData[k].data[dimensionIndex].value));
|
|
340
|
-
if (diff1 < mindiff) {
|
|
341
|
-
mindiff = diff1;
|
|
342
|
-
legendIndex = k;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
focus
|
|
346
|
-
.attr("transform", getCoordinates(lineData[legendIndex], dimensionIndex, xScale, yScaleLeft))
|
|
347
|
-
.append("circle")
|
|
348
|
-
.attr("r", lineData[legendIndex].properties.markerSize * 2.5)
|
|
349
|
-
.attr("id", "tooltip")
|
|
350
|
-
// .attr("id", lineData[0].AxisDataList[dimensionIndex].Dimension)
|
|
351
|
-
.attr("fill", lineData[legendIndex].properties.markerColor)
|
|
352
|
-
.text(showTooltipOnMouseMove([
|
|
353
|
-
{ key: formatOptions.xAxisTitle.xAxisTitleText, value: lineData[legendIndex].data[dimensionIndex].dimension },
|
|
354
|
-
{
|
|
355
|
-
key: lineData[legendIndex].properties.currentMeasure ? lineData[legendIndex].properties.currentMeasure : this.basestyle.YAxisTitle.YAxisTitleText,
|
|
356
|
-
value: getNumberWithFormat((chartType === actualChartTypes.stackArea100) ? (legendIndex === 0 ? lineData[legendIndex].data[dimensionIndex].value : lineData[legendIndex].data[dimensionIndex].value - lineData[legendIndex - 1].data[dimensionIndex].value) : lineData[legendIndex].data[dimensionIndex].value, formatOptions.toolTip.toolTipDisplayUnits, formatOptions.toolTip.toolTipNumberFormat, formatOptions.toolTip.toolTipDecimalPrecision),
|
|
357
|
-
},
|
|
358
|
-
{ key: "Legend", value: lineData[legendIndex].data[dimensionIndex].legend.includes("~$~") ? lineData[legendIndex].data[dimensionIndex].legend.split("~$~")[1] : lineData[legendIndex].data[dimensionIndex].legend },
|
|
359
|
-
// { key: "Calculated Tooltip", value: lineData[legendIndex].data[dimensionIndex]. },
|
|
360
|
-
], formatOptions));
|
|
361
|
-
}
|
|
362
|
-
catch (error) {
|
|
363
|
-
logError(fileName, "onHoverMarkerForAreaChartFamily.mousemove", error);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
catch (error) {
|
|
368
|
-
logError(fileName, "onHoverMarkerForAreaChartFamily", error);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Calculates the SVG `transform` attribute value to position a marker
|
|
373
|
-
* at the correct (x, y) coordinate based on chart data and scales.
|
|
374
|
-
*
|
|
375
|
-
* @param {any} chartData - A single series object containing `data`, which holds dimension and value pairs.
|
|
376
|
-
* @param {number} pos - Index in the `chartData.data` array to locate the specific data point.
|
|
377
|
-
* @param {any} xScale - D3 scale function used to convert the dimension to an x-coordinate.
|
|
378
|
-
* @param {any} yScaleLeft - D3 scale function used to convert the value to a y-coordinate.
|
|
379
|
-
*
|
|
380
|
-
* @return {string} A `translate(x, y)` string used for SVG positioning.
|
|
381
|
-
*/
|
|
382
|
-
const getCoordinates = (chartData, pos, xScale, yScaleLeft) => {
|
|
383
|
-
try {
|
|
384
|
-
return `translate(${xScale(chartData.data[pos].dimension)},${yScaleLeft(chartData.data[pos].value)})`;
|
|
385
|
-
}
|
|
386
|
-
catch (error) {
|
|
387
|
-
logError(fileName, "getCoordinates", error);
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
/**
|
|
391
|
-
* Function to calculate actual height, width of content primarily used for margin calculations
|
|
392
|
-
* @returns { width: 0, height: 0, rotatedWidth: 0, rotatedHeight: 0 }
|
|
393
|
-
*/
|
|
394
|
-
export function preCalculateTextDimensions(content, fontSize, fontFamily, rotationDegree, fixedWidth) {
|
|
395
|
-
try {
|
|
396
|
-
const div = document.createElement('div');
|
|
397
|
-
Object.assign(div.style, {
|
|
398
|
-
position: 'absolute',
|
|
399
|
-
visibility: 'hidden',
|
|
400
|
-
top: '0',
|
|
401
|
-
left: '0',
|
|
402
|
-
margin: '0',
|
|
403
|
-
padding: '0',
|
|
404
|
-
border: 'none',
|
|
405
|
-
whiteSpace: 'nowrap',
|
|
406
|
-
overflowWrap: '',
|
|
407
|
-
transform: '',
|
|
408
|
-
});
|
|
409
|
-
document.body.appendChild(div);
|
|
410
|
-
div.style.transform = '';
|
|
411
|
-
div.style.width = '';
|
|
412
|
-
div.style.whiteSpace = 'nowrap';
|
|
413
|
-
div.style.overflowWrap = '';
|
|
414
|
-
if (fontSize != null)
|
|
415
|
-
div.style.fontSize = `${fontSize}px`;
|
|
416
|
-
if (fontFamily != null)
|
|
417
|
-
div.style.fontFamily = fontFamily;
|
|
418
|
-
if (fixedWidth != null) {
|
|
419
|
-
// to calculate height of content if width is restricted
|
|
420
|
-
div.style.width = `${fixedWidth}px`;
|
|
421
|
-
div.style.whiteSpace = 'normal';
|
|
422
|
-
div.style.overflowWrap = 'break-word';
|
|
423
|
-
}
|
|
424
|
-
// Set text and measure
|
|
425
|
-
div.textContent = content;
|
|
426
|
-
const baseRect = div.getBoundingClientRect();
|
|
427
|
-
const w = baseRect.width, h = baseRect.height;
|
|
428
|
-
// Optional rotation
|
|
429
|
-
if (rotationDegree && rotationDegree !== 0) {
|
|
430
|
-
div.style.transform = `rotate(${rotationDegree}deg)`;
|
|
431
|
-
const rotRect = div.getBoundingClientRect();
|
|
432
|
-
div.remove();
|
|
433
|
-
return { width: w, height: h, rotatedWidth: rotRect.width, rotatedHeight: rotRect.height };
|
|
434
|
-
}
|
|
435
|
-
div.remove();
|
|
436
|
-
return { width: w, height: h, rotatedWidth: 0, rotatedHeight: 0 };
|
|
437
|
-
}
|
|
438
|
-
catch (error) {
|
|
439
|
-
logError(fileName, "preCalculateTextDimensions", error);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* adds non defined properties from `defaults` to `target` to avoid further checks for undefined values
|
|
444
|
-
* @param defaults -> Object which contains default properties
|
|
445
|
-
* @param target -> Object which may contain some undefined properties
|
|
446
|
-
* @returns object with all properties from defaults
|
|
447
|
-
*/
|
|
448
|
-
export function addUndefinedDefaults(defaults, target) {
|
|
449
|
-
try {
|
|
450
|
-
if (typeof defaults !== 'object' || defaults === null) {
|
|
451
|
-
throw new TypeError('`defaults` must be a non-null object');
|
|
452
|
-
}
|
|
453
|
-
if (typeof target !== 'object' || target === null) {
|
|
454
|
-
throw new TypeError('`target` must be a non-null object');
|
|
455
|
-
}
|
|
456
|
-
Object.keys(defaults).forEach((key) => {
|
|
457
|
-
const defaultVal = defaults[key];
|
|
458
|
-
const targetHasKey = Object.prototype.hasOwnProperty.call(target, key);
|
|
459
|
-
const targetVal = target[key];
|
|
460
|
-
// If key is missing or explicitly undefined, adopt the default wholesale
|
|
461
|
-
if (!targetHasKey || targetVal === undefined) {
|
|
462
|
-
// Note: clone objects/arrays to avoid accidental shared references
|
|
463
|
-
target[key] = Array.isArray(defaultVal)
|
|
464
|
-
? [...defaultVal]
|
|
465
|
-
: (typeof defaultVal === 'object' && defaultVal !== null)
|
|
466
|
-
? { ...defaultVal }
|
|
467
|
-
: defaultVal;
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
// Both have the key and both values are plain objects → recurse
|
|
471
|
-
const isDefaultPlainObj = isPlainObject(defaultVal);
|
|
472
|
-
const isTargetPlainObj = isPlainObject(targetVal);
|
|
473
|
-
if (isDefaultPlainObj && isTargetPlainObj) {
|
|
474
|
-
addUndefinedDefaults(defaultVal, targetVal);
|
|
475
|
-
}
|
|
476
|
-
// Otherwise: target already has a concrete (non-object) value → leave it
|
|
477
|
-
});
|
|
478
|
-
return target;
|
|
479
|
-
}
|
|
480
|
-
catch (error) {
|
|
481
|
-
logError(fileName, "addUndefinedDefaults", error);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
/** Helper: is a value a plain (literal) object? */
|
|
485
|
-
function isPlainObject(val) {
|
|
486
|
-
try {
|
|
487
|
-
return Object.prototype.toString.call(val) === '[object Object]';
|
|
488
|
-
}
|
|
489
|
-
catch (error) {
|
|
490
|
-
logError(fileName, "isPlainObject", error);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Number formating function
|
|
495
|
-
* @returns function which takes number as input and return formatted number
|
|
496
|
-
*/
|
|
497
|
-
export function getNumberWithFormatFunction(displayUnits, numberFormat, decimalPrecision) {
|
|
498
|
-
try {
|
|
499
|
-
let Unit;
|
|
500
|
-
let displayUnitsPostFix = "";
|
|
501
|
-
let decimalValues = decimalPrecision;
|
|
502
|
-
let formatter;
|
|
503
|
-
return function (d) {
|
|
504
|
-
try {
|
|
505
|
-
if (displayUnits != "None") {
|
|
506
|
-
displayUnits == "Thousands"
|
|
507
|
-
? ((Unit = 1000), (displayUnitsPostFix = "K"))
|
|
508
|
-
: null;
|
|
509
|
-
displayUnits == "Millions"
|
|
510
|
-
? ((Unit = 1000000), (displayUnitsPostFix = "M"))
|
|
511
|
-
: null;
|
|
512
|
-
displayUnits == "Billions"
|
|
513
|
-
? ((Unit = 1000000000), (displayUnitsPostFix = "B"))
|
|
514
|
-
: null;
|
|
515
|
-
d = d / Unit;
|
|
516
|
-
}
|
|
517
|
-
switch (numberFormat) {
|
|
518
|
-
case ",.0%":
|
|
519
|
-
formatter = `.${decimalValues}%`;
|
|
520
|
-
return d3.format(formatter)(d);
|
|
521
|
-
case "":
|
|
522
|
-
formatter = `.${decimalValues}f`;
|
|
523
|
-
return d3.format(formatter)(d) + displayUnitsPostFix;
|
|
524
|
-
case ".2n":
|
|
525
|
-
formatter = `.${decimalValues == 0 ? 1 : (parseFloat(decimalValues) + 1).toString()}n`;
|
|
526
|
-
return d3.format(formatter)(d) + displayUnitsPostFix;
|
|
527
|
-
case ".2$":
|
|
528
|
-
formatter = `,.${decimalValues}f`;
|
|
529
|
-
return "$" + d3.format(formatter)(d) + displayUnitsPostFix;
|
|
530
|
-
case ".2c":
|
|
531
|
-
formatter = `,.${decimalValues}f`;
|
|
532
|
-
return "C$" + d3.format(formatter)(d) + displayUnitsPostFix;
|
|
533
|
-
case ".2ē":
|
|
534
|
-
formatter = `,.${decimalValues}f`;
|
|
535
|
-
return "€" + d3.format(formatter)(d) + displayUnitsPostFix;
|
|
536
|
-
case ".2ch":
|
|
537
|
-
formatter = `,.${decimalValues}f`;
|
|
538
|
-
return "CHF" + d3.format(formatter)(d) + displayUnitsPostFix;
|
|
539
|
-
case ".2£":
|
|
540
|
-
formatter = `,.${decimalValues}f`;
|
|
541
|
-
return "£" + d3.format(formatter)(d) + displayUnitsPostFix;
|
|
542
|
-
case ".2₹":
|
|
543
|
-
formatter = `,.${decimalValues}f`;
|
|
544
|
-
return "₹" + d3.format(formatter)(d) + displayUnitsPostFix;
|
|
545
|
-
case ",":
|
|
546
|
-
formatter = `,.${decimalValues}f`;
|
|
547
|
-
return d3.format(formatter)(d) + displayUnitsPostFix;
|
|
548
|
-
default:
|
|
549
|
-
formatter = `.${2}f`;
|
|
550
|
-
return d3.format(formatter)(d) + displayUnitsPostFix;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
catch (error) {
|
|
554
|
-
logError(fileName, "getNumberWithFormatFunction.inner", error);
|
|
555
|
-
}
|
|
556
|
-
};
|
|
557
|
-
}
|
|
558
|
-
catch (error) {
|
|
559
|
-
logError(fileName, "getNumberWithFormatFunction", error);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
/**
|
|
563
|
-
* @param elements -> array of key value pair which should be added to tooltip one after another;
|
|
564
|
-
* @param chartFormatOptions -> rightpane format options;
|
|
565
|
-
* @param event -> optional mouse event to track mouse;
|
|
566
|
-
*/
|
|
567
|
-
export function showTooltipOnMouseMove(elements, chartFormatOptions, event) {
|
|
568
|
-
try {
|
|
569
|
-
d3.selectAll(".chartTooltip").style("visibility", "hidden");
|
|
570
|
-
// Clear and create new tooltip container
|
|
571
|
-
let tooltip = d3
|
|
572
|
-
.select("#chartTooltipDiv")
|
|
573
|
-
.html("")
|
|
574
|
-
.append("div")
|
|
575
|
-
.attr("class", chartFormatOptions.toolTip.toolTipTheme == "Light"
|
|
576
|
-
? "tooltipParentLight chartTooltip"
|
|
577
|
-
: "tooltipParentDark chartTooltip");
|
|
578
|
-
// Use passed event or fallback
|
|
579
|
-
const e = event || window.event;
|
|
580
|
-
const mouseX = e.pageX;
|
|
581
|
-
const mouseY = e.pageY;
|
|
582
|
-
// Build content
|
|
583
|
-
const tooltipElements = elements.reduce((p, c) => {
|
|
584
|
-
p += `<label class="tooltipLabel">${c.value ? c.key : ""}</label>
|
|
585
|
-
<span class="tooltipValue">${c.value ? c.value : ""}</span>`;
|
|
586
|
-
return p;
|
|
587
|
-
}, ``);
|
|
588
|
-
tooltip.html(`<div class="arrow-placeholder"></div>
|
|
589
|
-
<div class="tooltipInner">${tooltipElements}</div>`);
|
|
590
|
-
// Get tooltip dimensions after it's in DOM
|
|
591
|
-
const tooltipNode = tooltip.node();
|
|
592
|
-
const tooltipWidth = tooltipNode.offsetWidth;
|
|
593
|
-
const tooltipHeight = tooltipNode.offsetHeight;
|
|
594
|
-
// Determine quadrant (screen is divided into 4 from center)
|
|
595
|
-
const halfWidth = window.innerWidth / 2;
|
|
596
|
-
const halfHeight = window.innerHeight / 2;
|
|
597
|
-
let left = 0;
|
|
598
|
-
let top = 0;
|
|
599
|
-
let arrow = "";
|
|
600
|
-
if (mouseX > halfWidth && mouseY < halfHeight) {
|
|
601
|
-
// Top-right
|
|
602
|
-
left = mouseX - tooltipWidth - 10;
|
|
603
|
-
top = mouseY - 10;
|
|
604
|
-
arrow = "right-top";
|
|
605
|
-
}
|
|
606
|
-
else if (mouseX < halfWidth && mouseY < halfHeight) {
|
|
607
|
-
// Top-left
|
|
608
|
-
left = mouseX + 20;
|
|
609
|
-
top = mouseY - 10;
|
|
610
|
-
arrow = "left-top";
|
|
611
|
-
}
|
|
612
|
-
else if (mouseX < halfWidth && mouseY >= halfHeight) {
|
|
613
|
-
// Bottom-left
|
|
614
|
-
left = mouseX + 20;
|
|
615
|
-
top = mouseY - tooltipHeight + 10;
|
|
616
|
-
arrow = "left-bottom";
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
// Bottom-right
|
|
620
|
-
left = mouseX - tooltipWidth - 10;
|
|
621
|
-
top = mouseY - tooltipHeight + 10;
|
|
622
|
-
arrow = "right-bottom";
|
|
623
|
-
}
|
|
624
|
-
// Set final position
|
|
625
|
-
tooltip
|
|
626
|
-
.style("left", `${left}px`)
|
|
627
|
-
.style("top", `${top}px`)
|
|
628
|
-
.style("visibility", chartFormatOptions.toolTip.toolTipVisibility ? "visible" : "hidden");
|
|
629
|
-
// Update arrow direction
|
|
630
|
-
tooltip.select(".arrow-placeholder").attr("class", `arrow-${arrow}`);
|
|
631
|
-
}
|
|
632
|
-
catch (error) {
|
|
633
|
-
logError(fileName, "showTooltipOnMouseMove", error);
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
export function hideTooltipOnMouseOut() {
|
|
637
|
-
try {
|
|
638
|
-
d3
|
|
639
|
-
.select("#chartTooltipDiv")
|
|
640
|
-
.html("")
|
|
641
|
-
.style("visibility", "hidden");
|
|
642
|
-
}
|
|
643
|
-
catch (error) {
|
|
644
|
-
logError(fileName, "hideTooltipOnMouseOut", error);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
/**
|
|
648
|
-
* Adds chart title to svg
|
|
649
|
-
* @param chartSvg -> svgRef from use ref hook;
|
|
650
|
-
* @param chartTitleHeight -> height of chart title;
|
|
651
|
-
* @param chartTitleWidth -> width of chart title;
|
|
652
|
-
* @param chartFormatOptions -> rightpane format options;
|
|
653
|
-
*/
|
|
654
|
-
export const drawChartTitle = (chartSvg, chartTitleHeight, chartTitleWidth, chartFormatOptions) => {
|
|
655
|
-
try {
|
|
656
|
-
let svg = d3.select(chartSvg.current);
|
|
657
|
-
let object = svg
|
|
658
|
-
.append("foreignObject")
|
|
659
|
-
.attr("visibility", chartFormatOptions.chartTitle.chartTitleVisibility
|
|
660
|
-
? "visible"
|
|
661
|
-
: "hidden")
|
|
662
|
-
.attr("transform", `translate(2,2)`)
|
|
663
|
-
.attr("class", "chartTitle")
|
|
664
|
-
.attr("width", chartTitleWidth)
|
|
665
|
-
.attr("height", chartTitleHeight + "px");
|
|
666
|
-
// if text set from editor except default chart title
|
|
667
|
-
if (chartFormatOptions.chartTitle.dynamicTitleText.length !== 0) {
|
|
668
|
-
object
|
|
669
|
-
.append("xhtml:div")
|
|
670
|
-
.style("color", "rgba(119,119,119)")
|
|
671
|
-
.attr("title", chartFormatOptions.chartTitle.chartTitleText)
|
|
672
|
-
.style("white-space", "pre")
|
|
673
|
-
.style("text-overflow", "ellipsis")
|
|
674
|
-
.html(chartFormatOptions.chartTitle.chartTitleHTML
|
|
675
|
-
? chartFormatOptions.chartTitle.chartTitleHTML
|
|
676
|
-
: chartFormatOptions.chartTitle.chartTitleText);
|
|
677
|
-
}
|
|
678
|
-
else {
|
|
679
|
-
object
|
|
680
|
-
.append("xhtml:div")
|
|
681
|
-
.style("white-space", "pre")
|
|
682
|
-
.style("user-select", "none")
|
|
683
|
-
.style("text-overflow", "ellipsis")
|
|
684
|
-
.style("overflow", "hidden")
|
|
685
|
-
.attr("class", "chartTiltle")
|
|
686
|
-
.attr("id", "chartTitleId")
|
|
687
|
-
.style("text-anchor", "start")
|
|
688
|
-
.style("color", "rgba(119,119,119)")
|
|
689
|
-
.style("font-size", "16px")
|
|
690
|
-
.style("font-family", chartFormatOptions.chartTitle.chartTitleFontFamily)
|
|
691
|
-
.attr("title", chartFormatOptions.chartTitle.chartTitleText)
|
|
692
|
-
.html(chartFormatOptions.chartTitle.chartTitleText);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
catch (error) {
|
|
696
|
-
logError(fileName, "drawChartTitle", error);
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
/**
|
|
700
|
-
* Finds the longest string from an array of strings or an array of objects.
|
|
701
|
-
* @param {Array<string | Object>} data -> The input array containing strings or objects.
|
|
702
|
-
* @param {string} [key] -> (Optional) If the array contains objects, specify the key to extract string values.
|
|
703
|
-
* @returns {string} The longest string found in the array.
|
|
704
|
-
*/
|
|
705
|
-
export const findStringWithLongestLength = (data, key) => {
|
|
706
|
-
try {
|
|
707
|
-
return data.reduce((longest, item) => {
|
|
708
|
-
const currentValue = typeof item === "string"
|
|
709
|
-
? item
|
|
710
|
-
: (key && typeof item === "object" && item[key]) || "";
|
|
711
|
-
return currentValue.length > longest.length ? currentValue : longest;
|
|
712
|
-
}, "");
|
|
713
|
-
}
|
|
714
|
-
catch (error) {
|
|
715
|
-
logError(fileName, "findStringWithLongestLength", error);
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
/**
|
|
719
|
-
* Renders chart legends within an SVG element with scroll support when needed.
|
|
720
|
-
* @param {SVGElement} svg - The D3 or SVG selection where the legends will be appended.
|
|
721
|
-
* @param {TSeries[]} seriesData - Array of data series passed to chart as props.
|
|
722
|
-
* @param {number} x - The x-coordinate for placing the legends container.
|
|
723
|
-
* @param {number} y - The y-coordinate for placing the legends container.
|
|
724
|
-
* @param {number} width - The width of the legend container.
|
|
725
|
-
* @param {number} height - The height of the legend container.
|
|
726
|
-
* @param {string} legendPosition - The position of the legend (e.g., 'top', 'bottom', 'left', 'right').
|
|
727
|
-
* @param {string} alignment - Alignment of the legends within the container ('start', 'center', 'end', 'Top','Mid','Bottom').
|
|
728
|
-
* @param {string} legendShape - Shape of the legend symbol (e.g., 'circle', 'rect', 'line', 'hollow circle').
|
|
729
|
-
* @param {TDefaultChartFormatOptionsType} chartFormatOptions - Configuration object for formatting styles and settings.
|
|
730
|
-
* @param {string} chartId - Unique ID for the chart, used to identify elements within the SVG.
|
|
731
|
-
*/
|
|
732
|
-
export const legendsWithScroll = (svg, seriesData, x, y, width, height, legendPosition, alignment, legendShape, chartFormatOptions, chartId, isVennChart = false) => {
|
|
733
|
-
try {
|
|
734
|
-
if (chartFormatOptions.legends.legendVisibility) {
|
|
735
|
-
let justifyContent = "";
|
|
736
|
-
let flexDirection = "";
|
|
737
|
-
if (legendPosition == staticLegendPosition.left || legendPosition == staticLegendPosition.right) {
|
|
738
|
-
flexDirection = "column";
|
|
739
|
-
justifyContent =
|
|
740
|
-
alignment == verticalLegendAllignment.top ? "start" : alignment == verticalLegendAllignment.middle ? "center" : "end";
|
|
741
|
-
}
|
|
742
|
-
else {
|
|
743
|
-
flexDirection = "row";
|
|
744
|
-
justifyContent =
|
|
745
|
-
alignment == horizontalLegendAllignment.start
|
|
746
|
-
? "start"
|
|
747
|
-
: alignment == horizontalLegendAllignment.middle
|
|
748
|
-
? "center"
|
|
749
|
-
: "end";
|
|
750
|
-
}
|
|
751
|
-
let object = svg
|
|
752
|
-
.append("foreignObject")
|
|
753
|
-
.attr("x", x)
|
|
754
|
-
.attr("y", y)
|
|
755
|
-
.style("pointer-events", "auto")
|
|
756
|
-
.attr("width", width + "px")
|
|
757
|
-
.attr("height", height + "px")
|
|
758
|
-
.style("user-select", "none");
|
|
759
|
-
var div = object
|
|
760
|
-
.append("xhtml:div")
|
|
761
|
-
.attr("id", "legendObject" + chartId)
|
|
762
|
-
.attr("class", "legendsBoxWrapper")
|
|
763
|
-
.style("width", width + "px")
|
|
764
|
-
.style("display", "flex")
|
|
765
|
-
.style("height", height - 1 + "px")
|
|
766
|
-
.style("overflow", "auto")
|
|
767
|
-
.style("pointer-events", "auto")
|
|
768
|
-
.style("justify-content", justifyContent)
|
|
769
|
-
.style("flex-direction", flexDirection)
|
|
770
|
-
.style("outline-offset", '-' + chartFormatOptions.legends.legendBorderThickness + "px")
|
|
771
|
-
.style("outline", chartFormatOptions.legends.legendBorder
|
|
772
|
-
? `${chartFormatOptions.legends.legendBorderThickness +
|
|
773
|
-
"px" +
|
|
774
|
-
" solid" +
|
|
775
|
-
chartFormatOptions.legends.legendBorderColor}`
|
|
776
|
-
: "none")
|
|
777
|
-
.append("div")
|
|
778
|
-
// .style("width", "100%")
|
|
779
|
-
.attr("class", "scrollbar")
|
|
780
|
-
.style("display", "flex")
|
|
781
|
-
.style("justify-content", justifyContent)
|
|
782
|
-
.style("flex-direction", flexDirection)
|
|
783
|
-
.style("flex-wrap", "nowrap")
|
|
784
|
-
.style("padding-left", "3px");
|
|
785
|
-
if (legendPosition == staticLegendPosition.top || legendPosition == staticLegendPosition.bottom)
|
|
786
|
-
div.style("flex-direction", "row");
|
|
787
|
-
seriesData.forEach((d, i) => {
|
|
788
|
-
let innerdiv = div
|
|
789
|
-
.append("div")
|
|
790
|
-
.style("display", "inline-flex")
|
|
791
|
-
.style("justify-content", "flex-start")
|
|
792
|
-
.style("align-items", "center")
|
|
793
|
-
.style("width", "fit-content")
|
|
794
|
-
.style("margin", "3px 0px")
|
|
795
|
-
.style("flex-wrap", "nowrap")
|
|
796
|
-
.style("white-space", "nowrap")
|
|
797
|
-
.on("mousemove", function (d) {
|
|
798
|
-
if (chartFormatOptions.legends.onHoverEffect) {
|
|
799
|
-
svg
|
|
800
|
-
.selectAll(".parentGroup")
|
|
801
|
-
.classed("highlight", false)
|
|
802
|
-
.classed("unhighlight", true);
|
|
803
|
-
svg
|
|
804
|
-
.selectAll('[hoverId="' + this.textContent.replace(/ /g, "-") + '"]')
|
|
805
|
-
.classed("highlight", true)
|
|
806
|
-
.classed("unhighlight", false);
|
|
807
|
-
}
|
|
808
|
-
})
|
|
809
|
-
.on("mouseout", function (d) {
|
|
810
|
-
if (chartFormatOptions.legends.onHoverEffect) {
|
|
811
|
-
svg
|
|
812
|
-
.selectAll(".parentGroup")
|
|
813
|
-
.classed("highlight", false)
|
|
814
|
-
.classed("unhighlight", false);
|
|
815
|
-
svg
|
|
816
|
-
.selectAll('[hoverId="' + this.textContent.replace(/ /g, "-") + '"]')
|
|
817
|
-
.classed("highlight", false)
|
|
818
|
-
.classed("unhighlight", false);
|
|
819
|
-
}
|
|
820
|
-
});
|
|
821
|
-
if (legendPosition == staticLegendPosition.top || legendPosition == staticLegendPosition.bottom) {
|
|
822
|
-
innerdiv.style("margin-right", isVennChart ? "0px" : "16px").style("white-space", "nowrap");
|
|
823
|
-
}
|
|
824
|
-
if (legendShape == staticLegendShape.circle) {
|
|
825
|
-
getCircleShape(d, innerdiv);
|
|
826
|
-
}
|
|
827
|
-
else if (legendShape == staticLegendShape.circle) {
|
|
828
|
-
getHollowCircleShape(d, innerdiv);
|
|
829
|
-
}
|
|
830
|
-
else if (legendShape == staticLegendShape.line) {
|
|
831
|
-
getLineShape(d, innerdiv, chartFormatOptions);
|
|
832
|
-
}
|
|
833
|
-
else if (legendShape == staticLegendShape.areaWithLine) {
|
|
834
|
-
getAreaShape(d, innerdiv, chartFormatOptions);
|
|
835
|
-
}
|
|
836
|
-
else if (legendShape == staticLegendShape.rectangle) {
|
|
837
|
-
getReactShape(d, innerdiv);
|
|
838
|
-
}
|
|
839
|
-
let vennSaparator = (isVennChart && (legendPosition == staticLegendPosition.bottom || legendPosition == staticLegendPosition.top)) ? (i != seriesData.length - 1 ? ' |' : '') : '';
|
|
840
|
-
let legendColor = isVennChart ? chartFormatOptions.legends.legendSelectedUnicolor :
|
|
841
|
-
(chartFormatOptions.legends.legendColorMode == legendColorMode.multiColor)
|
|
842
|
-
? d.properties.color
|
|
843
|
-
? d.properties.color
|
|
844
|
-
: "#000000"
|
|
845
|
-
: chartFormatOptions.legends.legendSelectedUnicolor;
|
|
846
|
-
innerdiv
|
|
847
|
-
.append("div")
|
|
848
|
-
.style("margin-left", "5px")
|
|
849
|
-
.style("color", legendColor)
|
|
850
|
-
.style("font-size", (!isVennChart ? d.properties.fontSize : chartFormatOptions.legends.legendFontSize) + "px")
|
|
851
|
-
.style("font-family", !isVennChart ? d.properties.fontFamily : chartFormatOptions.legends.legendFontFamily)
|
|
852
|
-
.style("font-style", () => {
|
|
853
|
-
let style = !isVennChart ? d.properties.fontStyle : chartFormatOptions.legends.legendFontStyle;
|
|
854
|
-
return style.includes(fontStyleOptions.italic) ? fontStyleOptions.italic : "";
|
|
855
|
-
})
|
|
856
|
-
.style("text-decoration", () => {
|
|
857
|
-
let style = !isVennChart ? d.properties.fontStyle : chartFormatOptions.legends.legendFontStyle;
|
|
858
|
-
return style.includes(fontStyleOptions.underline) ? fontStyleOptions.underline : "";
|
|
859
|
-
})
|
|
860
|
-
.style("font-weight", () => {
|
|
861
|
-
let style = !isVennChart ? d.properties.fontStyle : chartFormatOptions.legends.legendFontStyle;
|
|
862
|
-
return style.includes(fontStyleOptions.bold) ? fontStyleOptions.bold : "";
|
|
863
|
-
})
|
|
864
|
-
.style("white-space", "nowrap")
|
|
865
|
-
.attr("title", !isVennChart ? d.properties.alias : d.legendDisplay + ' : ' + d.actualValue)
|
|
866
|
-
.html(!isVennChart ? d.properties.alias : d.legendDisplay + ' : ' + d.actualValue + vennSaparator);
|
|
867
|
-
});
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
catch (error) {
|
|
871
|
-
logError(fileName, "legendsWithScroll", error);
|
|
872
|
-
}
|
|
873
|
-
};
|
|
874
|
-
// Functionality of legends without scroll bar but having buttons for scroll functionality
|
|
875
|
-
// On Hold, will resume after finishing with all charts
|
|
876
|
-
// export const legendsWithScroll = (
|
|
877
|
-
// svg: any,
|
|
878
|
-
// seriesData: TSeries[],
|
|
879
|
-
// x: number,
|
|
880
|
-
// y: number,
|
|
881
|
-
// width: number,
|
|
882
|
-
// height: number,
|
|
883
|
-
// legendPosition: string,
|
|
884
|
-
// alignment: string,
|
|
885
|
-
// legendShape: string,
|
|
886
|
-
// chartFormatOptions: TDefaultChartFormatOptionsType,
|
|
887
|
-
// chartId: string
|
|
888
|
-
// ) => {
|
|
889
|
-
// // 1. Flex and alignment logic
|
|
890
|
-
// let justifyContent = "";
|
|
891
|
-
// let flexDirection = "";
|
|
892
|
-
// if (legendPosition === "Left" || legendPosition === "Right") {
|
|
893
|
-
// flexDirection = "column";
|
|
894
|
-
// justifyContent =
|
|
895
|
-
// alignment === "Top" ? "flex-start" :
|
|
896
|
-
// alignment === "Middle" ? "center" : "flex-end";
|
|
897
|
-
// } else {
|
|
898
|
-
// flexDirection = "row";
|
|
899
|
-
// justifyContent =
|
|
900
|
-
// alignment === "Start" ? "flex-start" :
|
|
901
|
-
// alignment === "Middle" ? "center" : "flex-end";
|
|
902
|
-
// }
|
|
903
|
-
// // 2. Main container
|
|
904
|
-
// const foreignObject = svg
|
|
905
|
-
// .append("foreignObject")
|
|
906
|
-
// .attr("x", x)
|
|
907
|
-
// .attr("y", y)
|
|
908
|
-
// .attr("width", width)
|
|
909
|
-
// .attr("height", height)
|
|
910
|
-
// .style("pointer-events", "auto");
|
|
911
|
-
// // 3. Legend wrapper (for buttons and content)
|
|
912
|
-
// const legendWrapper = foreignObject
|
|
913
|
-
// .append("xhtml:div")
|
|
914
|
-
// .attr("id", "legendWrapper" + chartId)
|
|
915
|
-
// .style("position", "relative")
|
|
916
|
-
// .style("width", width + "px")
|
|
917
|
-
// .style("height", height + "px")
|
|
918
|
-
// .style("overflow", "hidden")
|
|
919
|
-
// .style("display", "flex")
|
|
920
|
-
// .style("align-items", "center")
|
|
921
|
-
// .style("justify-content", "center")
|
|
922
|
-
// .style("background", "transparent");
|
|
923
|
-
// // 4. Scrollable content area
|
|
924
|
-
// const content = legendWrapper
|
|
925
|
-
// .append("div")
|
|
926
|
-
// .attr("class", "legend-content")
|
|
927
|
-
// .style("display", "flex")
|
|
928
|
-
// .style("flex-direction", flexDirection)
|
|
929
|
-
// .style("justify-content", justifyContent)
|
|
930
|
-
// .style("align-items", "center")
|
|
931
|
-
// .style("height", flexDirection === "row" ? "100%" : "auto")
|
|
932
|
-
// .style("width", flexDirection === "row" ? "calc(100% - 40px)" : "100%")
|
|
933
|
-
// .style("overflow", "hidden")
|
|
934
|
-
// .style("scroll-behavior", "smooth")
|
|
935
|
-
// .style("margin", flexDirection === "row" ? "0 16px" : "30px 0");
|
|
936
|
-
// // 5. Add legend entries
|
|
937
|
-
// seriesData.forEach((d, i) => {
|
|
938
|
-
// const entry = content
|
|
939
|
-
// .append("div")
|
|
940
|
-
// .attr("class", "legend-entry")
|
|
941
|
-
// .style("display", "inline-flex")
|
|
942
|
-
// .style("align-items", "center")
|
|
943
|
-
// .style("margin", flexDirection === "row" ? "0 8px 0 0" : "0 0 8px 0")
|
|
944
|
-
// .style("white-space", "nowrap")
|
|
945
|
-
// .on("mousemove", function () {
|
|
946
|
-
// if (chartFormatOptions.legends.onHoverEffect) {
|
|
947
|
-
// svg.selectAll(".parentGroup")
|
|
948
|
-
// .classed("highlight", false)
|
|
949
|
-
// .classed("unhighlight", true);
|
|
950
|
-
// svg.selectAll('[hoverId="' + d.legend.replace(/ /g, "-") + '"]')
|
|
951
|
-
// .classed("highlight", true)
|
|
952
|
-
// .classed("unhighlight", false);
|
|
953
|
-
// }
|
|
954
|
-
// })
|
|
955
|
-
// .on("mouseout", function () {
|
|
956
|
-
// if (chartFormatOptions.legends.onHoverEffect) {
|
|
957
|
-
// svg.selectAll(".parentGroup")
|
|
958
|
-
// .classed("highlight", false)
|
|
959
|
-
// .classed("unhighlight", false);
|
|
960
|
-
// svg.selectAll('[hoverId="' + d.legend.replace(/ /g, "-") + '"]')
|
|
961
|
-
// .classed("highlight", false)
|
|
962
|
-
// .classed("unhighlight", false);
|
|
963
|
-
// }
|
|
964
|
-
// });
|
|
965
|
-
// // Add legend shape
|
|
966
|
-
// if (legendShape === staticLegendShape.circle) {
|
|
967
|
-
// getCircleShape(d, entry);
|
|
968
|
-
// } else if (legendShape === staticLegendShape.circle) {
|
|
969
|
-
// getHollowCircleShape(d, entry);
|
|
970
|
-
// } else if (legendShape === staticLegendShape.line) {
|
|
971
|
-
// getLineShape(d, entry);
|
|
972
|
-
// } else if (legendShape === staticLegendShape.areaWithLine) {
|
|
973
|
-
// getAreaShape(d, entry);
|
|
974
|
-
// } else if (legendShape === staticLegendShape.rectangle) {
|
|
975
|
-
// getReactShape(d, entry);
|
|
976
|
-
// }
|
|
977
|
-
// // Add legend text
|
|
978
|
-
// let legendColor =
|
|
979
|
-
// chartFormatOptions.legends.legendColorMode === 1
|
|
980
|
-
// ? d.properties.Color || "#000000"
|
|
981
|
-
// : chartFormatOptions.legends.legendSelectedUnicolor;
|
|
982
|
-
// entry.append("div")
|
|
983
|
-
// .style("margin-left", "5px")
|
|
984
|
-
// .style("color", legendColor)
|
|
985
|
-
// .style("font-size", d.properties.FontSize + "px")
|
|
986
|
-
// .style("font-family", d.properties.FontFamily)
|
|
987
|
-
// .style("font-style", d.properties.FontStyle.includes(fontStyleOptions.italic) ? fontStyleOptions.italic : "")
|
|
988
|
-
// .style("text-decoration", d.properties.FontStyle.includes(fontStyleOptions.underline) ? fontStyleOptions.underline : "")
|
|
989
|
-
// .style("font-weight", d.properties.FontStyle.includes(fontStyleOptions.bold) ? fontStyleOptions.bold : "")
|
|
990
|
-
// .style("white-space", "nowrap")
|
|
991
|
-
// .attr("title", d.legend)
|
|
992
|
-
// .html(d.legend);
|
|
993
|
-
// });
|
|
994
|
-
// // 6. Add scroll buttons
|
|
995
|
-
// const btnStyle = `
|
|
996
|
-
// position: absolute;
|
|
997
|
-
// background: rgba(250,250,250,0.85);
|
|
998
|
-
// border: unset;
|
|
999
|
-
// border-radius: 3px;
|
|
1000
|
-
// width: 15px;
|
|
1001
|
-
// height: 22px;
|
|
1002
|
-
// display: flex;
|
|
1003
|
-
// align-items: center;
|
|
1004
|
-
// justify-content: center;
|
|
1005
|
-
// cursor: pointer;
|
|
1006
|
-
// z-index: 10;
|
|
1007
|
-
// font-size: 12px;
|
|
1008
|
-
// box-shadow: 0 1px 4px rgba(0,0,0,0.08);
|
|
1009
|
-
// opacity: 0.85;
|
|
1010
|
-
// transition: opacity 0.2s;
|
|
1011
|
-
// color: grey;
|
|
1012
|
-
// outline: none;
|
|
1013
|
-
// padding: unset;
|
|
1014
|
-
// `;
|
|
1015
|
-
// // Left/Top button
|
|
1016
|
-
// const leftBtn = legendWrapper
|
|
1017
|
-
// .append("button")
|
|
1018
|
-
// .attr("type", "button")
|
|
1019
|
-
// .attr("tabindex", -1)
|
|
1020
|
-
// .attr("aria-label", flexDirection === "row" ? "Scroll left" : "Scroll up")
|
|
1021
|
-
// .style("display", "none")
|
|
1022
|
-
// .attr("style", btnStyle +
|
|
1023
|
-
// (flexDirection === "row"
|
|
1024
|
-
// ? "left:1px;top:50%;transform:translateY(-50%);"
|
|
1025
|
-
// : "top:0;left:50%;transform:translateX(-50%);"))
|
|
1026
|
-
// .text(flexDirection === "row" ? "◀" : "▲");
|
|
1027
|
-
// // Right/Bottom button
|
|
1028
|
-
// const rightBtn = legendWrapper
|
|
1029
|
-
// .append("button")
|
|
1030
|
-
// .attr("type", "button")
|
|
1031
|
-
// .attr("tabindex", -1)
|
|
1032
|
-
// .attr("aria-label", flexDirection === "row" ? "Scroll right" : "Scroll down")
|
|
1033
|
-
// .style("display", "none")
|
|
1034
|
-
// .attr("style", btnStyle +
|
|
1035
|
-
// (flexDirection === "row"
|
|
1036
|
-
// ? "right:1px;top:50%;transform:translateY(-50%);"
|
|
1037
|
-
// : "bottom:0;left:50%;transform:translateX(-50%);"))
|
|
1038
|
-
// .text(flexDirection === "row" ? "▶" : "▼");
|
|
1039
|
-
// // 7. Scrolling logic
|
|
1040
|
-
// function updateButtonVisibility() {
|
|
1041
|
-
// if (flexDirection == "row") {
|
|
1042
|
-
// if (content.node().clientWidth == content.node().scrollWidth) {
|
|
1043
|
-
// content.node().style.width = "100%";
|
|
1044
|
-
// content.node().style.margin = "10px 0";
|
|
1045
|
-
// leftBtn.remove();
|
|
1046
|
-
// rightBtn.remove();
|
|
1047
|
-
// }
|
|
1048
|
-
// }
|
|
1049
|
-
// }
|
|
1050
|
-
// function scrollContent(amount: number) {
|
|
1051
|
-
// const node = content.node() as HTMLElement;
|
|
1052
|
-
// if (!node) return;
|
|
1053
|
-
// if (flexDirection === "row") {
|
|
1054
|
-
// node.scrollBy({ left: amount, behavior: "smooth" });
|
|
1055
|
-
// } else {
|
|
1056
|
-
// node.scrollBy({ top: amount, behavior: "smooth" });
|
|
1057
|
-
// }
|
|
1058
|
-
// }
|
|
1059
|
-
// leftBtn.on("click", () => scrollContent(flexDirection === "row" ? -100 : -50));
|
|
1060
|
-
// rightBtn.on("click", () => scrollContent(flexDirection === "row" ? 100 : 50));
|
|
1061
|
-
// // Mouse wheel scrolling
|
|
1062
|
-
// content.on("wheel", function (event: any) {
|
|
1063
|
-
// const node = this as HTMLElement;
|
|
1064
|
-
// if (flexDirection === "row") {
|
|
1065
|
-
// node.scrollLeft += event.deltaY;
|
|
1066
|
-
// } else {
|
|
1067
|
-
// node.scrollTop += event.deltaY;
|
|
1068
|
-
// }
|
|
1069
|
-
// event.preventDefault();
|
|
1070
|
-
// });
|
|
1071
|
-
// updateButtonVisibility();
|
|
1072
|
-
// // Update buttons on scroll and resize
|
|
1073
|
-
// // content.on("scroll", updateButtonVisibility);
|
|
1074
|
-
// // setTimeout(updateButtonVisibility, 100); // Initial
|
|
1075
|
-
// // Optional: update on window resize
|
|
1076
|
-
// // window.addEventListener("resize", updateButtonVisibility);
|
|
1077
|
-
// };
|
|
1078
|
-
/**
|
|
1079
|
-
*
|
|
1080
|
-
* Appends a filled circle shape to the given legend container.
|
|
1081
|
-
* @param d - The data object containing legend properties (like color, size).
|
|
1082
|
-
* @param innerDiv - The D3 selection where the shape will be appended.
|
|
1083
|
-
*/
|
|
1084
|
-
export function getCircleShape(d, innerDiv) {
|
|
1085
|
-
try {
|
|
1086
|
-
innerDiv
|
|
1087
|
-
.append("div")
|
|
1088
|
-
.style("height", "12px")
|
|
1089
|
-
.style("width", "12px")
|
|
1090
|
-
.style("border-radius", "50%")
|
|
1091
|
-
.style("background", d.properties.color);
|
|
1092
|
-
}
|
|
1093
|
-
catch (error) {
|
|
1094
|
-
logError(fileName, "getCircleShape", error);
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
/**
|
|
1098
|
-
* Appends a hollow (outlined) circle shape to the given legend container.
|
|
1099
|
-
* @param d - The data object containing legend properties.
|
|
1100
|
-
* @param innerDiv - The D3 selection where the shape will be appended.
|
|
1101
|
-
*/
|
|
1102
|
-
export function getHollowCircleShape(d, innerDiv) {
|
|
1103
|
-
try {
|
|
1104
|
-
innerDiv
|
|
1105
|
-
.append("div")
|
|
1106
|
-
.style("height", "12px")
|
|
1107
|
-
.style("width", "12px")
|
|
1108
|
-
.style("border-radius", "50%")
|
|
1109
|
-
.style("border", `3px solid ${d.properties.Color}`);
|
|
1110
|
-
}
|
|
1111
|
-
catch (error) {
|
|
1112
|
-
logError(fileName, "getHollowCircleShape", error);
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
/**
|
|
1116
|
-
* @param {Object} d - Data object containing properties such as lineStyle, color, markerShape, and markerColor.
|
|
1117
|
-
* @param {Object} innerDiv - A D3 selection of a container element to append the line shape.
|
|
1118
|
-
* @param {TDefaultChartFormatOptionsType} formatOptions - Formatting options including marker visibility.
|
|
1119
|
-
* @return {void}
|
|
1120
|
-
*/
|
|
1121
|
-
export function getLineShape(d, innerDiv, formatOptions) {
|
|
1122
|
-
try {
|
|
1123
|
-
let shape = innerDiv
|
|
1124
|
-
.append("div")
|
|
1125
|
-
.style("height", "2px")
|
|
1126
|
-
.style("width", "20px")
|
|
1127
|
-
.style("background", d.properties.lineStyle == "solid" ? d.properties.color : "transparent")
|
|
1128
|
-
.style("position", "relative")
|
|
1129
|
-
.style("border-top", d.properties.lineStyle == "None" ? "unset" : d.properties.lineStyle == "dotted" ? "2px dotted " + d.properties.color : "2px dashed " + d.properties.color);
|
|
1130
|
-
if (formatOptions.marker.markerVisibility) {
|
|
1131
|
-
switch (d.properties.markerShape.toLowerCase()) {
|
|
1132
|
-
case "circle":
|
|
1133
|
-
shape
|
|
1134
|
-
.append("div")
|
|
1135
|
-
.append("svg")
|
|
1136
|
-
.style("position", "absolute")
|
|
1137
|
-
.style("left", "50%")
|
|
1138
|
-
.style("top", "50%")
|
|
1139
|
-
.attr("transform", "translate(-5,-6)")
|
|
1140
|
-
.attr("height", "10px")
|
|
1141
|
-
.attr("width", "10px")
|
|
1142
|
-
.append("circle")
|
|
1143
|
-
.attr("cx", "5")
|
|
1144
|
-
.attr("cy", "5")
|
|
1145
|
-
.attr("r", "4.5")
|
|
1146
|
-
.style("fill", d.properties.markerColor);
|
|
1147
|
-
break;
|
|
1148
|
-
case "square":
|
|
1149
|
-
shape
|
|
1150
|
-
.append("div")
|
|
1151
|
-
.style("position", "absolute")
|
|
1152
|
-
.style("left", "50%")
|
|
1153
|
-
.style("top", "50%")
|
|
1154
|
-
.style("transform", "translate(-2px, -7px)")
|
|
1155
|
-
.style("height", "8px")
|
|
1156
|
-
.style("width", "8px")
|
|
1157
|
-
.style("top", "2px")
|
|
1158
|
-
.style("left", "9px")
|
|
1159
|
-
.style("background", d.properties.markerColor);
|
|
1160
|
-
break;
|
|
1161
|
-
case "triangle":
|
|
1162
|
-
shape
|
|
1163
|
-
.append("div")
|
|
1164
|
-
.style("position", "absolute")
|
|
1165
|
-
.style("transform", "translate(5px, -6.5px)")
|
|
1166
|
-
.style("border-left", "6px solid transparent")
|
|
1167
|
-
.style("border-right", "6px solid transparent")
|
|
1168
|
-
.style("border-bottom", `10px solid ${d.properties.markerColor}`);
|
|
1169
|
-
break;
|
|
1170
|
-
case "cross":
|
|
1171
|
-
shape
|
|
1172
|
-
.append("div")
|
|
1173
|
-
.style("position", "absolute")
|
|
1174
|
-
.style("left", "50%")
|
|
1175
|
-
.style("top", "50%")
|
|
1176
|
-
.style("transform", "translate(-5px, -3px)")
|
|
1177
|
-
.style("height", "4px")
|
|
1178
|
-
.style("width", "10px")
|
|
1179
|
-
.style("background", d.properties.markerColor)
|
|
1180
|
-
.append("div")
|
|
1181
|
-
.style("height", "10px")
|
|
1182
|
-
.style("width", "4px")
|
|
1183
|
-
.style("background", d.properties.markerColor)
|
|
1184
|
-
.style("position", "relative")
|
|
1185
|
-
.style("top", "-3px")
|
|
1186
|
-
.style("left", "3px");
|
|
1187
|
-
break;
|
|
1188
|
-
case "diamond":
|
|
1189
|
-
shape
|
|
1190
|
-
.append("div")
|
|
1191
|
-
.style("height", "7px")
|
|
1192
|
-
.style("width", "7px")
|
|
1193
|
-
.style("background", d.properties.markerColor)
|
|
1194
|
-
.style("transform", "rotate(45deg)")
|
|
1195
|
-
.style("top", "-4px")
|
|
1196
|
-
.style("left", "7px")
|
|
1197
|
-
.style("position", "absolute");
|
|
1198
|
-
break;
|
|
1199
|
-
case "star":
|
|
1200
|
-
shape
|
|
1201
|
-
.append("div")
|
|
1202
|
-
.style("border-left", "4px solid transparent")
|
|
1203
|
-
.style("border-right", "4px solid transparent")
|
|
1204
|
-
.style("border-bottom", `8px solid ${d.properties.markerColor}`)
|
|
1205
|
-
.style("position", "absolute")
|
|
1206
|
-
.style("top", "-6.5px")
|
|
1207
|
-
.style("left", "7px")
|
|
1208
|
-
.style("transform", "rotate(0deg)")
|
|
1209
|
-
.append("div")
|
|
1210
|
-
.style("border-left", "4px solid transparent")
|
|
1211
|
-
.style("border-right", "4px solid transparent")
|
|
1212
|
-
.style("border-top", `8px solid ${d.properties.markerColor}`)
|
|
1213
|
-
.style("position", "absolute")
|
|
1214
|
-
.style("top", "2px")
|
|
1215
|
-
.style("left", "-4px")
|
|
1216
|
-
.style("transform", "rotate(360deg)");
|
|
1217
|
-
break;
|
|
1218
|
-
case "wye":
|
|
1219
|
-
shape
|
|
1220
|
-
.append("div")
|
|
1221
|
-
.style("height", "6.5px")
|
|
1222
|
-
.style("width", "3px")
|
|
1223
|
-
.style("background", d.properties.markerColor)
|
|
1224
|
-
.style("position", "absolute")
|
|
1225
|
-
.style("left", "10px")
|
|
1226
|
-
.style("top", "-3.5px")
|
|
1227
|
-
.append("div")
|
|
1228
|
-
.style("height", "5px")
|
|
1229
|
-
.style("width", "3px")
|
|
1230
|
-
.style("background", d.properties.markerColor)
|
|
1231
|
-
.style("transform", "rotate(-55deg)")
|
|
1232
|
-
.style("position", "relative")
|
|
1233
|
-
.style("top", "-2px")
|
|
1234
|
-
.style("left", "-2px")
|
|
1235
|
-
.append("div")
|
|
1236
|
-
.style("height", "5px")
|
|
1237
|
-
.style("width", "3px")
|
|
1238
|
-
.style("background", d.properties.markerColor)
|
|
1239
|
-
.style("transform", "rotate(108deg)")
|
|
1240
|
-
.style("position", "relative")
|
|
1241
|
-
.style("top", "3px")
|
|
1242
|
-
.style("left", "2px");
|
|
1243
|
-
break;
|
|
1244
|
-
case "none":
|
|
1245
|
-
shape;
|
|
1246
|
-
default:
|
|
1247
|
-
break;
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
catch (error) {
|
|
1252
|
-
logError(fileName, "getLineShape", error);
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
/**
|
|
1256
|
-
* @param {Object} d - Data object containing color, markerShape array, and properties including markerColor.
|
|
1257
|
-
* @param {Object} innerDiv - A D3 selection of a container element to append the area shape.
|
|
1258
|
-
* @param {TDefaultChartFormatOptionsType} formatOptions - Formatting options including marker visibility.
|
|
1259
|
-
* @return {void}
|
|
1260
|
-
*/
|
|
1261
|
-
export function getAreaShape(d, innerDiv, formatOptions) {
|
|
1262
|
-
try {
|
|
1263
|
-
let flexdiv = innerDiv
|
|
1264
|
-
.append("div")
|
|
1265
|
-
.style("height", "10px")
|
|
1266
|
-
.style("width", "15px")
|
|
1267
|
-
.style("background", d.properties.color)
|
|
1268
|
-
.style("display", "flex")
|
|
1269
|
-
.style("flex-direction", "column")
|
|
1270
|
-
.style("border-radius", "1px");
|
|
1271
|
-
if (formatOptions.marker.markerVisibility) {
|
|
1272
|
-
switch (d.properties.markerShape.toLowerCase()) {
|
|
1273
|
-
case "circle":
|
|
1274
|
-
flexdiv
|
|
1275
|
-
.append("div")
|
|
1276
|
-
.style("height", "20%")
|
|
1277
|
-
.style("width", "100%")
|
|
1278
|
-
.style("background", d.properties.color)
|
|
1279
|
-
.style("position", "relative")
|
|
1280
|
-
.append("svg")
|
|
1281
|
-
.style("position", "absolute")
|
|
1282
|
-
.style("left", "50%")
|
|
1283
|
-
.style("top", "50%")
|
|
1284
|
-
.attr("transform", "translate(-5,-5)")
|
|
1285
|
-
.attr("height", "10px")
|
|
1286
|
-
.attr("width", "10px")
|
|
1287
|
-
.append("circle")
|
|
1288
|
-
.attr("cx", "5")
|
|
1289
|
-
.attr("cy", "5")
|
|
1290
|
-
.attr("r", "2.5")
|
|
1291
|
-
.style("fill", d.properties.markerColor);
|
|
1292
|
-
break;
|
|
1293
|
-
case "square":
|
|
1294
|
-
flexdiv
|
|
1295
|
-
.append("div")
|
|
1296
|
-
.style("height", "20%")
|
|
1297
|
-
.style("width", "100%")
|
|
1298
|
-
.style("background", d.properties.markerColor)
|
|
1299
|
-
.style("position", "relative")
|
|
1300
|
-
.append("div")
|
|
1301
|
-
.style("position", "absolute")
|
|
1302
|
-
.style("left", "50%")
|
|
1303
|
-
.style("top", "50%")
|
|
1304
|
-
.style("transform", "translate(-4px, -3.5px)")
|
|
1305
|
-
.style("height", "5px")
|
|
1306
|
-
.style("width", "5px")
|
|
1307
|
-
.style("top", "2px")
|
|
1308
|
-
.style("left", "9px")
|
|
1309
|
-
.style("background", d.properties.markerColor)
|
|
1310
|
-
.style("border-radius", "1px");
|
|
1311
|
-
break;
|
|
1312
|
-
case "triangle":
|
|
1313
|
-
flexdiv
|
|
1314
|
-
.append("div")
|
|
1315
|
-
.style("height", "20%")
|
|
1316
|
-
.style("width", "100%")
|
|
1317
|
-
.style("background", d.properties.markerColor)
|
|
1318
|
-
.style("position", "relative")
|
|
1319
|
-
.append("div")
|
|
1320
|
-
.style("position", "absolute")
|
|
1321
|
-
.style("transform", "translate(5px, -3.5px)")
|
|
1322
|
-
.style("border-left", "3px solid transparent")
|
|
1323
|
-
.style("border-right", "3px solid transparent")
|
|
1324
|
-
.style("border-bottom", `7px solid ${d.properties.markerColor}`);
|
|
1325
|
-
break;
|
|
1326
|
-
case "cross":
|
|
1327
|
-
flexdiv
|
|
1328
|
-
.append("div")
|
|
1329
|
-
.style("height", "20%")
|
|
1330
|
-
.style("width", "100%")
|
|
1331
|
-
.style("background", d.properties.markerColor)
|
|
1332
|
-
.style("position", "relative")
|
|
1333
|
-
.append("div")
|
|
1334
|
-
.style("position", "absolute")
|
|
1335
|
-
.style("left", "50%")
|
|
1336
|
-
.style("top", "50%")
|
|
1337
|
-
.style("transform", "translate(-3px, -2px)")
|
|
1338
|
-
.style("height", "4px")
|
|
1339
|
-
.style("width", "7px")
|
|
1340
|
-
.style("background", d.properties.markerColor)
|
|
1341
|
-
.append("div")
|
|
1342
|
-
.style("height", "6px")
|
|
1343
|
-
.style("width", "3px")
|
|
1344
|
-
.style("background", d.properties.markerColor)
|
|
1345
|
-
.style("position", "relative")
|
|
1346
|
-
.style("top", "-1px")
|
|
1347
|
-
.style("left", "2px");
|
|
1348
|
-
break;
|
|
1349
|
-
case "diamond":
|
|
1350
|
-
flexdiv
|
|
1351
|
-
.append("div")
|
|
1352
|
-
.style("height", "20%")
|
|
1353
|
-
.style("width", "100%")
|
|
1354
|
-
.style("background", d.properties.markerColor)
|
|
1355
|
-
.style("position", "relative")
|
|
1356
|
-
.append("div")
|
|
1357
|
-
.style("height", "4px")
|
|
1358
|
-
.style("width", "4px")
|
|
1359
|
-
.style("background", d.properties.markerColor)
|
|
1360
|
-
.style("transform", "rotate(45deg)")
|
|
1361
|
-
.style("top", "-1px")
|
|
1362
|
-
.style("left", "5px")
|
|
1363
|
-
.style("position", "absolute");
|
|
1364
|
-
break;
|
|
1365
|
-
case "star":
|
|
1366
|
-
flexdiv
|
|
1367
|
-
.append("div")
|
|
1368
|
-
.style("height", "20%")
|
|
1369
|
-
.style("width", "100%")
|
|
1370
|
-
.style("background", d.properties.markerColor)
|
|
1371
|
-
.style("position", "relative")
|
|
1372
|
-
.append("div")
|
|
1373
|
-
.style("border-left", "2.5px solid transparent")
|
|
1374
|
-
.style("border-right", "2.5px solid transparent")
|
|
1375
|
-
.style("border-bottom", `6px solid ${d.properties.markerColor}`)
|
|
1376
|
-
.style("position", "absolute")
|
|
1377
|
-
.style("top", "-3px")
|
|
1378
|
-
.style("left", "6px")
|
|
1379
|
-
.style("transform", "rotate(0deg)")
|
|
1380
|
-
.append("div")
|
|
1381
|
-
.style("border-left", "2.5px solid transparent")
|
|
1382
|
-
.style("border-right", "2.5px solid transparent")
|
|
1383
|
-
.style("border-top", `6px solid ${d.properties.markerColor}`)
|
|
1384
|
-
.style("position", "absolute")
|
|
1385
|
-
.style("top", "0.5px")
|
|
1386
|
-
.style("left", "-2px")
|
|
1387
|
-
.style("transform", "rotate(360deg)");
|
|
1388
|
-
break;
|
|
1389
|
-
case "wye":
|
|
1390
|
-
flexdiv
|
|
1391
|
-
.append("div")
|
|
1392
|
-
.style("height", "20%")
|
|
1393
|
-
.style("width", "100%")
|
|
1394
|
-
.style("background", d.properties.markerColor)
|
|
1395
|
-
.style("position", "relative")
|
|
1396
|
-
.append("div")
|
|
1397
|
-
.style("height", "4.5px")
|
|
1398
|
-
.style("width", "2px")
|
|
1399
|
-
.style("background", d.properties.markerColor)
|
|
1400
|
-
.style("position", "absolute")
|
|
1401
|
-
.style("left", "6.5px")
|
|
1402
|
-
.style("top", "-0.5px")
|
|
1403
|
-
.append("div")
|
|
1404
|
-
.style("height", "3px")
|
|
1405
|
-
.style("width", "2px")
|
|
1406
|
-
.style("background", d.properties.markerColor)
|
|
1407
|
-
.style("transform", "rotate(-55deg)")
|
|
1408
|
-
.style("position", "relative")
|
|
1409
|
-
.style("top", "-2px")
|
|
1410
|
-
.style("left", "-2px")
|
|
1411
|
-
.append("div")
|
|
1412
|
-
.style("height", "3px")
|
|
1413
|
-
.style("width", "2px")
|
|
1414
|
-
.style("background", d.properties.markerColor)
|
|
1415
|
-
.style("transform", "rotate(108deg)")
|
|
1416
|
-
.style("position", "relative")
|
|
1417
|
-
.style("top", "3px")
|
|
1418
|
-
.style("left", "2px");
|
|
1419
|
-
break;
|
|
1420
|
-
case "none":
|
|
1421
|
-
flexdiv
|
|
1422
|
-
.append("div")
|
|
1423
|
-
.style("height", "20%")
|
|
1424
|
-
.style("width", "100%")
|
|
1425
|
-
.style("background", d.properties.markerColor);
|
|
1426
|
-
break;
|
|
1427
|
-
default:
|
|
1428
|
-
break;
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
flexdiv
|
|
1432
|
-
.append("div")
|
|
1433
|
-
.style("height", "20%")
|
|
1434
|
-
.style("width", "100%")
|
|
1435
|
-
.style("background", "white");
|
|
1436
|
-
flexdiv
|
|
1437
|
-
.append("div")
|
|
1438
|
-
.style("height", "60%")
|
|
1439
|
-
.style("width", "100%")
|
|
1440
|
-
.style("background", d.properties.color)
|
|
1441
|
-
.style("border-radius", "1px");
|
|
1442
|
-
}
|
|
1443
|
-
catch (error) {
|
|
1444
|
-
logError(fileName, "getAreaShape", error);
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1447
|
-
/**
|
|
1448
|
-
* Appends a rectangle shape to the given legend container.
|
|
1449
|
-
* @param d - The data object that includes styling for the rectangle (like color, border).
|
|
1450
|
-
* @param innerDiv - The D3 selection where the shape will be inserted.
|
|
1451
|
-
*/
|
|
1452
|
-
export function getReactShape(d, innerDiv) {
|
|
1453
|
-
try {
|
|
1454
|
-
innerDiv
|
|
1455
|
-
.append("div")
|
|
1456
|
-
.style("height", "10px")
|
|
1457
|
-
.style("width", "15px")
|
|
1458
|
-
.style("border-style", d)
|
|
1459
|
-
.style("border-width", d)
|
|
1460
|
-
.style("border-color", d)
|
|
1461
|
-
.style("background", d.properties.color)
|
|
1462
|
-
.style("border-radius", "1px");
|
|
1463
|
-
}
|
|
1464
|
-
catch (error) {
|
|
1465
|
-
logError(fileName, "getReactShape", error);
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
export function drawAnnotations(oldAnnotationList, newAnnotationList, chartFormatOptions) {
|
|
1469
|
-
try {
|
|
1470
|
-
// Implementation here if needed
|
|
1471
|
-
}
|
|
1472
|
-
catch (error) {
|
|
1473
|
-
logError(fileName, "drawAnnotations", error);
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
/**
|
|
1477
|
-
* Initializes the SVG element with the specified dimensions and chart format options.
|
|
1478
|
-
* @param svgRef - The reference to the SVG element.
|
|
1479
|
-
* @param width - The width of the SVG element.
|
|
1480
|
-
* @param height - The height of the SVG element.
|
|
1481
|
-
* @param chartFormatOptions - The format options for the chart, which may include properties like background color and border.
|
|
1482
|
-
*/
|
|
1483
|
-
export const initSvg = (svgRef, width, height, chartFormatOptions) => {
|
|
1484
|
-
try {
|
|
1485
|
-
let svgElement = svgRef.current;
|
|
1486
|
-
svgElement.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
1487
|
-
const { chartAreaColor, chartAreaBorder } = chartFormatOptions.chartArea;
|
|
1488
|
-
svgElement.style.backgroundColor = chartAreaColor;
|
|
1489
|
-
const isBorderEnable = chartAreaBorder;
|
|
1490
|
-
if (isBorderEnable) {
|
|
1491
|
-
let borderColor = chartFormatOptions.chartArea.chartAreaBorderColor;
|
|
1492
|
-
let borderWidth = chartFormatOptions.chartArea.chartAreaBorderThickness + "px";
|
|
1493
|
-
let borderStyle = convertStringToNumber(chartFormatOptions.chartArea.chartAreaBorderStyle);
|
|
1494
|
-
let border = borderStyle == 1 ? "solid" : borderStyle == 2 ? "dashed" : "dotted";
|
|
1495
|
-
svgElement.style.outline = `${borderWidth} ${border} ${borderColor}`;
|
|
1496
|
-
svgElement.style.outlineOffset = `-${borderWidth}`;
|
|
1497
|
-
}
|
|
1498
|
-
else {
|
|
1499
|
-
svgElement.style.outline = `unset`;
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
catch (error) {
|
|
1503
|
-
logError(fileName, "initSvg", error);
|
|
1504
|
-
}
|
|
1505
|
-
};
|
|
1506
|
-
/**
|
|
1507
|
-
* Initializes the chart area within the SVG element, applying margins and setting a default font color.
|
|
1508
|
-
* @param svg - The D3 selection of the SVG element.
|
|
1509
|
-
* @param margins - The margins to apply to the chart area.
|
|
1510
|
-
* @return {d3.Selection<SVGGElement, any, any, any>} - The D3 selection of the chart area group element.
|
|
1511
|
-
*/
|
|
1512
|
-
export const initChartArea = (svg, margins) => {
|
|
1513
|
-
try {
|
|
1514
|
-
return svg
|
|
1515
|
-
.append("g")
|
|
1516
|
-
.attr("transform", `translate(${margins.left},${margins.top})`)
|
|
1517
|
-
.attr("font-color", "#ccc");
|
|
1518
|
-
}
|
|
1519
|
-
catch (error) {
|
|
1520
|
-
logError(fileName, "initChartArea", error);
|
|
1521
|
-
}
|
|
1522
|
-
};
|
|
1523
|
-
/**
|
|
1524
|
-
* all common functions to do before draw chart .
|
|
1525
|
-
* @param svgRef - The reference to the SVG element.
|
|
1526
|
-
* @param formatOptions - The format options for the chart which may contains some undefined values.
|
|
1527
|
-
* @returns { chartFormatOptions: TDefaultChartFormatOptionsType } - The chart format options with defaults applied.
|
|
1528
|
-
* @returns { svg: d3.Selection<SVGSVGElement, any, any, any> } - The D3 selection of the SVG element.
|
|
1529
|
-
*
|
|
1530
|
-
*
|
|
1531
|
-
*/
|
|
1532
|
-
export const firstFunctionBeforeRender = (svgRef, formatOptions) => {
|
|
1533
|
-
try {
|
|
1534
|
-
let svg = d3.select(svgRef.current);
|
|
1535
|
-
svg.selectAll("*").remove();
|
|
1536
|
-
let chartFormatOptions = addUndefinedDefaults(defaultChartFormatOptions, formatOptions);
|
|
1537
|
-
let svgBounds = svgRef.current.getBoundingClientRect();
|
|
1538
|
-
let width = svgBounds.width;
|
|
1539
|
-
let height = svgBounds.height;
|
|
1540
|
-
return { chartFormatOptions, svg, width, height };
|
|
1541
|
-
}
|
|
1542
|
-
catch (error) {
|
|
1543
|
-
logError(fileName, "firstFunctionBeforeRender", error);
|
|
1544
|
-
}
|
|
1545
|
-
};
|
|
1546
|
-
export const marginCalculationsForChartsWithoutAxis = (chartFormatOptions, width, height, maxLegendDimensions, margins, isVennChart = false) => {
|
|
1547
|
-
try {
|
|
1548
|
-
let legendPosition = chartFormatOptions.legends.legendPosition;
|
|
1549
|
-
let width15Percent = width * 0.15 * 0.8;
|
|
1550
|
-
let legendListWidth = isVennChart ? maxLegendDimensions[0] :
|
|
1551
|
-
width15Percent < maxLegendDimensions[0] + 15
|
|
1552
|
-
? width15Percent
|
|
1553
|
-
: maxLegendDimensions[0] + 15;
|
|
1554
|
-
let chartTitleHeight = chartFormatOptions.chartTitle.chartTitleVisibility
|
|
1555
|
-
? chartFormatOptions.chartTitle.dynamicTitleText.length !== 0
|
|
1556
|
-
? preCalculateTextDimensions(chartFormatOptions.chartTitle.chartTitleHTML, undefined, undefined).height
|
|
1557
|
-
: preCalculateTextDimensions(chartFormatOptions.chartTitle.chartTitleText, 16, "Helvetica").height
|
|
1558
|
-
: 5;
|
|
1559
|
-
switch (legendPosition) {
|
|
1560
|
-
case staticLegendPosition.none:
|
|
1561
|
-
margins.top = chartTitleHeight + 20;
|
|
1562
|
-
margins.bottom = 50;
|
|
1563
|
-
margins.right = 50;
|
|
1564
|
-
margins.left = 50;
|
|
1565
|
-
break;
|
|
1566
|
-
case staticLegendPosition.top:
|
|
1567
|
-
margins.top = chartTitleHeight + 50;
|
|
1568
|
-
margins.bottom = 15;
|
|
1569
|
-
margins.right = 15;
|
|
1570
|
-
margins.left = 15;
|
|
1571
|
-
break;
|
|
1572
|
-
case staticLegendPosition.right:
|
|
1573
|
-
margins.right = legendListWidth + 50;
|
|
1574
|
-
margins.top = chartTitleHeight + 15;
|
|
1575
|
-
margins.bottom = 15;
|
|
1576
|
-
margins.left = 15;
|
|
1577
|
-
break;
|
|
1578
|
-
case staticLegendPosition.bottom:
|
|
1579
|
-
margins.bottom = 45;
|
|
1580
|
-
margins.top = chartTitleHeight + 15;
|
|
1581
|
-
margins.right = 15;
|
|
1582
|
-
margins.left = 15;
|
|
1583
|
-
break;
|
|
1584
|
-
case staticLegendPosition.left:
|
|
1585
|
-
margins.left = legendListWidth + 50;
|
|
1586
|
-
margins.top = chartTitleHeight + 15;
|
|
1587
|
-
margins.bottom = 15;
|
|
1588
|
-
margins.right = 15;
|
|
1589
|
-
}
|
|
1590
|
-
let innerHeight = height - margins.top - margins.bottom;
|
|
1591
|
-
let innerWidth = width - margins.left - margins.right;
|
|
1592
|
-
return { margins, innerHeight, innerWidth, legendListWidth, chartTitleHeight };
|
|
1593
|
-
}
|
|
1594
|
-
catch (error) {
|
|
1595
|
-
logError(fileName, "marginCalculationsForChartsWithoutAxis", error);
|
|
1596
|
-
}
|
|
1597
|
-
};
|
|
1598
|
-
/**
|
|
1599
|
-
* Initializes the legend list with total value allowance and appends to svg.
|
|
1600
|
-
* @param chartFormatOptions - The format options for the chart.
|
|
1601
|
-
* @param svg - The D3 selection of the SVG element.
|
|
1602
|
-
* @param seriesData - The data series to be displayed in the legend.
|
|
1603
|
-
* @param width - The width of the SVG element.
|
|
1604
|
-
* @param height - The height of the SVG element.
|
|
1605
|
-
* @param legendListWidth - The width allocated for the legend list.
|
|
1606
|
-
* @param chartTitleHeight - The height of the chart title.
|
|
1607
|
-
* @param chartId - The unique identifier for the chart.
|
|
1608
|
-
* @param margins - The margins for the chart area.
|
|
1609
|
-
*/
|
|
1610
|
-
export const initLegendListWithTotalValueAllowance = (chartFormatOptions, svg, seriesData, width, height, legendListWidth, chartTitleHeight, chartId, margins, shouldAllowTotalValueMargin = true) => {
|
|
1611
|
-
try {
|
|
1612
|
-
let position = chartFormatOptions.legends.legendPosition;
|
|
1613
|
-
let totalPosition = chartFormatOptions.total.totalPosition;
|
|
1614
|
-
let totalAlignment = chartFormatOptions.total.totalAlignment;
|
|
1615
|
-
let shouldTotalValueAdjustment = chartFormatOptions.total.totalVisibility && shouldAllowTotalValueMargin;
|
|
1616
|
-
let horizontalLegendAlignment = chartFormatOptions.legends.legendAlignmentTopBottom;
|
|
1617
|
-
let verticalLegendAlignment = chartFormatOptions.legends.legendAlignment;
|
|
1618
|
-
switch (position) {
|
|
1619
|
-
case staticLegendPosition.none:
|
|
1620
|
-
break;
|
|
1621
|
-
case staticLegendPosition.right:
|
|
1622
|
-
legendsWithScroll(svg, seriesData, width - legendListWidth - 25, chartTitleHeight +
|
|
1623
|
-
5 +
|
|
1624
|
-
(shouldTotalValueAdjustment
|
|
1625
|
-
? totalPosition == staticTotalPosition.top && totalAlignment == staticTotalAlignment.end
|
|
1626
|
-
? 10
|
|
1627
|
-
: 0
|
|
1628
|
-
: 0), legendListWidth + 15, height -
|
|
1629
|
-
chartTitleHeight -
|
|
1630
|
-
10 -
|
|
1631
|
-
(shouldTotalValueAdjustment
|
|
1632
|
-
? totalPosition == staticTotalPosition.top && totalAlignment == staticTotalAlignment.end
|
|
1633
|
-
? 10
|
|
1634
|
-
: totalPosition == staticTotalPosition.bottom && totalAlignment == staticTotalAlignment.start
|
|
1635
|
-
? 20
|
|
1636
|
-
: 0
|
|
1637
|
-
: 0), position, verticalLegendAlignment, staticLegendShape.circle, chartFormatOptions, chartId);
|
|
1638
|
-
break;
|
|
1639
|
-
case staticLegendPosition.top:
|
|
1640
|
-
legendsWithScroll(svg, seriesData, 5, chartTitleHeight + 5, width - 10, 30, position, horizontalLegendAlignment, staticLegendShape.circle, chartFormatOptions, chartId);
|
|
1641
|
-
break;
|
|
1642
|
-
case staticLegendPosition.left:
|
|
1643
|
-
legendsWithScroll(svg, seriesData, 5, margins.top +
|
|
1644
|
-
(shouldTotalValueAdjustment
|
|
1645
|
-
? totalPosition == staticTotalPosition.top && totalAlignment == staticTotalAlignment.start
|
|
1646
|
-
? 10
|
|
1647
|
-
: 0
|
|
1648
|
-
: 0), legendListWidth + 15, height -
|
|
1649
|
-
chartTitleHeight -
|
|
1650
|
-
10 -
|
|
1651
|
-
(shouldTotalValueAdjustment
|
|
1652
|
-
? totalPosition == staticTotalPosition.top && totalAlignment == staticTotalAlignment.start
|
|
1653
|
-
? 10
|
|
1654
|
-
: totalPosition == staticTotalPosition.bottom && totalAlignment == staticTotalAlignment.start
|
|
1655
|
-
? 20
|
|
1656
|
-
: 0
|
|
1657
|
-
: 0), position, verticalLegendAlignment, staticLegendShape.circle, chartFormatOptions, chartId);
|
|
1658
|
-
break;
|
|
1659
|
-
case staticLegendPosition.bottom:
|
|
1660
|
-
legendsWithScroll(svg, seriesData, 5, height - 35, width - 10, 30, position, horizontalLegendAlignment, staticLegendShape.circle, chartFormatOptions, chartId);
|
|
1661
|
-
break;
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
catch (error) {
|
|
1665
|
-
logError(fileName, "initLegendListWithTotalValueAllowance", error);
|
|
1666
|
-
}
|
|
1667
|
-
};
|
|
1668
|
-
/**
|
|
1669
|
-
* Calculates the maximum possible width and height for the legends based on the longest legend string.
|
|
1670
|
-
* @param chartFormatOptions - The format options for the chart.
|
|
1671
|
-
* @param seriesData - The data series to be displayed in the legend.
|
|
1672
|
-
* @returns The maximum possible width and height for the legends.
|
|
1673
|
-
*/
|
|
1674
|
-
export const calculateLegendsMaxPossibleWidth = (chartFormatOptions, seriesData, key = "legend") => {
|
|
1675
|
-
try {
|
|
1676
|
-
let legendDims = preCalculateTextDimensions(findStringWithLongestLength(seriesData, key), convertStringToNumber(chartFormatOptions.legends.legendFontSize), chartFormatOptions.legends.legendFontFamily);
|
|
1677
|
-
return [legendDims.width, legendDims.height];
|
|
1678
|
-
}
|
|
1679
|
-
catch (error) {
|
|
1680
|
-
logError(fileName, "calculateLegendsMaxPossibleWidth", error);
|
|
1681
|
-
}
|
|
1682
|
-
};
|
|
1683
|
-
/**
|
|
1684
|
-
* Calculates the margins and inner dimensions for the charts without legends.
|
|
1685
|
-
* @param chartFormatOptions - The format options for the chart.
|
|
1686
|
-
* @param height - The height of the chart area.
|
|
1687
|
-
* @param width - The width of the chart area.
|
|
1688
|
-
* @param shouldShowColorScale - Only allow treemap to show color scale.
|
|
1689
|
-
* @returns The calculated margins and inner dimensions for the chart.
|
|
1690
|
-
*/
|
|
1691
|
-
export const marginCalculationsForChartsWithoutLegends = (chartFormatOptions, height, width, shouldShowColorScale = false) => {
|
|
1692
|
-
try {
|
|
1693
|
-
let chartTitleHeight = chartFormatOptions.chartTitle.chartTitleVisibility
|
|
1694
|
-
? chartFormatOptions.chartTitle.dynamicTitleText.length !== 0
|
|
1695
|
-
? preCalculateTextDimensions(chartFormatOptions.chartTitle.chartTitleHTML, undefined, undefined).height
|
|
1696
|
-
: preCalculateTextDimensions(chartFormatOptions.chartTitle.chartTitleText, 16, "Helvetica").height
|
|
1697
|
-
: 5;
|
|
1698
|
-
let margins = {
|
|
1699
|
-
top: chartFormatOptions.chartTitle.chartTitleVisibility
|
|
1700
|
-
? chartTitleHeight
|
|
1701
|
-
: 10,
|
|
1702
|
-
bottom: (shouldShowColorScale && chartFormatOptions.colorScale.showColor == colorThemeTypes.colorTheme) ? 40 : 10,
|
|
1703
|
-
left: 10,
|
|
1704
|
-
right: 10,
|
|
1705
|
-
};
|
|
1706
|
-
innerHeight = height - margins.top - margins.bottom;
|
|
1707
|
-
innerWidth = width - margins.left - margins.right;
|
|
1708
|
-
return { margins, chartTitleHeight, innerHeight, innerWidth };
|
|
1709
|
-
}
|
|
1710
|
-
catch (error) {
|
|
1711
|
-
logError(fileName, "marginCalculationsForChartsWithoutLegends", error);
|
|
1712
|
-
}
|
|
1713
|
-
};
|
|
1714
|
-
export const convertStringToNumber = (value) => {
|
|
1715
|
-
try {
|
|
1716
|
-
if (typeof value !== 'string') {
|
|
1717
|
-
return value;
|
|
1718
|
-
}
|
|
1719
|
-
// Trim the string to remove whitespace
|
|
1720
|
-
const trimmed = value.trim();
|
|
1721
|
-
// Check for empty string
|
|
1722
|
-
if (trimmed === '') {
|
|
1723
|
-
return value;
|
|
1724
|
-
}
|
|
1725
|
-
// Try parsing
|
|
1726
|
-
const num = parseFloat(trimmed);
|
|
1727
|
-
// Check if it's a valid number
|
|
1728
|
-
if (isNaN(num)) {
|
|
1729
|
-
return value;
|
|
1730
|
-
}
|
|
1731
|
-
return num;
|
|
1732
|
-
}
|
|
1733
|
-
catch (error) {
|
|
1734
|
-
logError(fileName, "convertStringToNumber", error);
|
|
1735
|
-
}
|
|
1736
|
-
};
|
|
1737
|
-
export function generalizedChartData(chartData, dimensionList) {
|
|
1738
|
-
try {
|
|
1739
|
-
return chartData.map(item => {
|
|
1740
|
-
// Ensure properties exist
|
|
1741
|
-
let properties;
|
|
1742
|
-
if (!item.properties) {
|
|
1743
|
-
properties = {
|
|
1744
|
-
...chartProperties,
|
|
1745
|
-
legend: item.legend,
|
|
1746
|
-
currentLegend: item.legend,
|
|
1747
|
-
alias: item.legend,
|
|
1748
|
-
name: item.legend
|
|
1749
|
-
};
|
|
1750
|
-
}
|
|
1751
|
-
else {
|
|
1752
|
-
properties = { ...chartProperties, ...item.properties };
|
|
1753
|
-
}
|
|
1754
|
-
// Normalize dimensions and clone points
|
|
1755
|
-
const normalizedData = dimensionList
|
|
1756
|
-
? dimensionList.map(dim => {
|
|
1757
|
-
const found = item.data.find(d => d.dimension === dim);
|
|
1758
|
-
if (found) {
|
|
1759
|
-
// clone the point to make it extensible
|
|
1760
|
-
return { ...found };
|
|
1761
|
-
}
|
|
1762
|
-
else {
|
|
1763
|
-
// insert missing dimension with 0 value
|
|
1764
|
-
return {
|
|
1765
|
-
dimension: dim,
|
|
1766
|
-
legend: item.legend,
|
|
1767
|
-
value: 0
|
|
1768
|
-
};
|
|
1769
|
-
}
|
|
1770
|
-
})
|
|
1771
|
-
: item.data.map(d => ({ ...d }));
|
|
1772
|
-
return {
|
|
1773
|
-
...item,
|
|
1774
|
-
properties,
|
|
1775
|
-
data: normalizedData
|
|
1776
|
-
};
|
|
1777
|
-
});
|
|
1778
|
-
}
|
|
1779
|
-
catch (error) {
|
|
1780
|
-
logError(fileName, "generalizedChartData", error);
|
|
1781
|
-
}
|
|
1782
|
-
}
|