@dhis2/analytics 26.8.6 → 26.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/__demo__/SingleValue.stories.js +706 -0
- package/build/cjs/components/PivotTable/PivotTableValueCell.js +6 -2
- package/build/cjs/components/PivotTable/styles/PivotTable.style.js +2 -2
- package/build/cjs/locales/en/translations.json +2 -0
- package/build/cjs/locales/lo/translations.json +16 -12
- package/build/cjs/modules/pivotTable/PivotTableEngine.js +59 -24
- package/build/cjs/modules/pivotTable/pivotTableConstants.js +6 -2
- package/build/cjs/modules/valueTypes.js +4 -1
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/chart/default.js +26 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/chart/index.js +18 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/chart/singleValue.js +19 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/index.js +36 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueBackgroundColor.js +12 -0
- package/build/cjs/visualizations/config/adapters/{dhis_dhis/value/index.js → dhis_highcharts/customSVGOptions/singleValue/getSingleValueFormattedValue.js} +8 -6
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueLegendColor.js +11 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueSubtext.js +11 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueTextColor.js +20 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueTitleColor.js +26 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/index.js +31 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/index.js +24 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/index.js +18 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/addIconElement.js +34 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/checkIfFitsWithinContainer.js +19 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/computeLayoutRect.js +39 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/computeSpacingTop.js +21 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/constants.js +11 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/getAvailableSpace.js +14 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/index.js +48 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/positionElements.js +46 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/styles.js +109 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/exporting.js +30 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/index.js +33 -23
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/lang.js +17 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/plotOptions.js +1 -1
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/series/index.js +5 -1
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/subtitle/__tests__/singleValue.spec.js +62 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/subtitle/index.js +56 -22
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/subtitle/singleValue.js +27 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/title/__tests__/singleValue.spec.js +44 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/title/index.js +50 -22
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/title/singleValue.js +31 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/type.js +2 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/xAxis/index.js +1 -0
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/yAxis/index.js +4 -5
- package/build/cjs/visualizations/config/adapters/index.js +2 -4
- package/build/cjs/visualizations/config/generators/highcharts/index.js +8 -0
- package/build/cjs/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/index.js +13 -0
- package/build/cjs/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/nonASCIIFont.js +17 -0
- package/build/cjs/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/textShadow.js +289 -0
- package/build/cjs/visualizations/config/generators/index.js +2 -4
- package/build/cjs/visualizations/store/adapters/dhis_highcharts/index.js +3 -0
- package/build/cjs/visualizations/store/adapters/dhis_highcharts/singleValue.js +10 -0
- package/build/cjs/visualizations/store/adapters/index.js +2 -4
- package/build/cjs/visualizations/util/shouldUseContrastColor.js +24 -0
- package/build/es/__demo__/SingleValue.stories.js +702 -0
- package/build/es/components/PivotTable/PivotTableValueCell.js +6 -2
- package/build/es/components/PivotTable/styles/PivotTable.style.js +2 -2
- package/build/es/locales/en/translations.json +2 -0
- package/build/es/locales/lo/translations.json +16 -12
- package/build/es/modules/pivotTable/PivotTableEngine.js +61 -26
- package/build/es/modules/pivotTable/pivotTableConstants.js +4 -1
- package/build/es/modules/valueTypes.js +2 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/chart/default.js +19 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/chart/index.js +11 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/chart/singleValue.js +12 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/index.js +29 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueBackgroundColor.js +6 -0
- package/build/es/visualizations/config/adapters/{dhis_dhis/value/index.js → dhis_highcharts/customSVGOptions/singleValue/getSingleValueFormattedValue.js} +4 -4
- package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueLegendColor.js +5 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueSubtext.js +5 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueTextColor.js +14 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueTitleColor.js +20 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/index.js +25 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/index.js +16 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/index.js +11 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/addIconElement.js +28 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/checkIfFitsWithinContainer.js +13 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/computeLayoutRect.js +33 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/computeSpacingTop.js +15 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/constants.js +4 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/getAvailableSpace.js +8 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/index.js +42 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/positionElements.js +40 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/styles.js +101 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/exporting.js +23 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/index.js +23 -13
- package/build/es/visualizations/config/adapters/dhis_highcharts/lang.js +11 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/plotOptions.js +1 -1
- package/build/es/visualizations/config/adapters/dhis_highcharts/series/index.js +6 -2
- package/build/es/visualizations/config/adapters/dhis_highcharts/subtitle/__tests__/singleValue.spec.js +59 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/subtitle/index.js +56 -24
- package/build/es/visualizations/config/adapters/dhis_highcharts/subtitle/singleValue.js +14 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/title/__tests__/singleValue.spec.js +42 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/title/index.js +52 -24
- package/build/es/visualizations/config/adapters/dhis_highcharts/title/singleValue.js +18 -0
- package/build/es/visualizations/config/adapters/dhis_highcharts/type.js +3 -1
- package/build/es/visualizations/config/adapters/dhis_highcharts/xAxis/index.js +2 -1
- package/build/es/visualizations/config/adapters/dhis_highcharts/yAxis/index.js +5 -6
- package/build/es/visualizations/config/adapters/index.js +1 -3
- package/build/es/visualizations/config/generators/highcharts/index.js +8 -0
- package/build/es/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/index.js +6 -0
- package/build/es/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/nonASCIIFont.js +11 -0
- package/build/es/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/textShadow.js +283 -0
- package/build/es/visualizations/config/generators/index.js +1 -3
- package/build/es/visualizations/store/adapters/dhis_highcharts/index.js +4 -1
- package/build/es/visualizations/store/adapters/dhis_highcharts/singleValue.js +4 -0
- package/build/es/visualizations/store/adapters/index.js +1 -3
- package/build/es/visualizations/util/shouldUseContrastColor.js +17 -0
- package/package.json +1 -2
- package/build/cjs/visualizations/config/adapters/dhis_dhis/index.js +0 -39
- package/build/cjs/visualizations/config/adapters/dhis_dhis/subtitle/__tests__/index.spec.js +0 -49
- package/build/cjs/visualizations/config/adapters/dhis_dhis/subtitle/__tests__/singleValue.spec.js +0 -15
- package/build/cjs/visualizations/config/adapters/dhis_dhis/subtitle/index.js +0 -34
- package/build/cjs/visualizations/config/adapters/dhis_dhis/subtitle/singleValue.js +0 -11
- package/build/cjs/visualizations/config/adapters/dhis_dhis/title/__tests__/index.spec.js +0 -39
- package/build/cjs/visualizations/config/adapters/dhis_dhis/title/__tests__/singleValue.spec.js +0 -17
- package/build/cjs/visualizations/config/adapters/dhis_dhis/title/index.js +0 -31
- package/build/cjs/visualizations/config/adapters/dhis_dhis/title/singleValue.js +0 -18
- package/build/cjs/visualizations/config/adapters/dhis_dhis/type.js +0 -19
- package/build/cjs/visualizations/config/adapters/dhis_highcharts/chart.js +0 -39
- package/build/cjs/visualizations/config/generators/dhis/index.js +0 -28
- package/build/cjs/visualizations/config/generators/dhis/singleValue.js +0 -359
- package/build/cjs/visualizations/store/adapters/dhis_dhis/index.js +0 -83
- package/build/cjs/visualizations/store/adapters/dhis_dhis/singleValue.js +0 -10
- package/build/es/visualizations/config/adapters/dhis_dhis/index.js +0 -30
- package/build/es/visualizations/config/adapters/dhis_dhis/subtitle/__tests__/index.spec.js +0 -46
- package/build/es/visualizations/config/adapters/dhis_dhis/subtitle/__tests__/singleValue.spec.js +0 -12
- package/build/es/visualizations/config/adapters/dhis_dhis/subtitle/index.js +0 -27
- package/build/es/visualizations/config/adapters/dhis_dhis/subtitle/singleValue.js +0 -4
- package/build/es/visualizations/config/adapters/dhis_dhis/title/__tests__/index.spec.js +0 -36
- package/build/es/visualizations/config/adapters/dhis_dhis/title/__tests__/singleValue.spec.js +0 -14
- package/build/es/visualizations/config/adapters/dhis_dhis/title/index.js +0 -24
- package/build/es/visualizations/config/adapters/dhis_dhis/title/singleValue.js +0 -11
- package/build/es/visualizations/config/adapters/dhis_dhis/type.js +0 -13
- package/build/es/visualizations/config/adapters/dhis_highcharts/chart.js +0 -32
- package/build/es/visualizations/config/generators/dhis/index.js +0 -21
- package/build/es/visualizations/config/generators/dhis/singleValue.js +0 -353
- package/build/es/visualizations/store/adapters/dhis_dhis/index.js +0 -76
- package/build/es/visualizations/store/adapters/dhis_dhis/singleValue.js +0 -4
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
import { colors } from '@dhis2/ui';
|
|
2
|
-
import { FONT_STYLE_VISUALIZATION_TITLE, FONT_STYLE_VISUALIZATION_SUBTITLE, FONT_STYLE_OPTION_FONT_SIZE, FONT_STYLE_OPTION_TEXT_COLOR, FONT_STYLE_OPTION_TEXT_ALIGN, FONT_STYLE_OPTION_ITALIC, FONT_STYLE_OPTION_BOLD, TEXT_ALIGN_LEFT, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER, mergeFontStyleWithDefault, defaultFontStyle } from '../../../../modules/fontStyle.js';
|
|
3
|
-
import { getColorByValueFromLegendSet, LEGEND_DISPLAY_STYLE_FILL } from '../../../../modules/legends.js';
|
|
4
|
-
const svgNS = 'http://www.w3.org/2000/svg';
|
|
5
|
-
|
|
6
|
-
// multiply text width with this factor
|
|
7
|
-
// to get very close to actual text width
|
|
8
|
-
// nb: dependent on viewbox etc
|
|
9
|
-
const ACTUAL_TEXT_WIDTH_FACTOR = 0.9;
|
|
10
|
-
|
|
11
|
-
// multiply value text size with this factor
|
|
12
|
-
// to get very close to the actual number height
|
|
13
|
-
// as numbers don't go below the baseline like e.g. "j" and "g"
|
|
14
|
-
const ACTUAL_NUMBER_HEIGHT_FACTOR = 0.67;
|
|
15
|
-
|
|
16
|
-
// do not allow text width to exceed this threshold
|
|
17
|
-
// a threshold >1 does not really make sense but text width vs viewbox is complicated
|
|
18
|
-
const TEXT_WIDTH_CONTAINER_WIDTH_FACTOR = 1.3;
|
|
19
|
-
|
|
20
|
-
// do not allow text size to exceed this
|
|
21
|
-
const TEXT_SIZE_CONTAINER_HEIGHT_FACTOR = 0.6;
|
|
22
|
-
const TEXT_SIZE_MAX_THRESHOLD = 400;
|
|
23
|
-
|
|
24
|
-
// multiply text size with this factor
|
|
25
|
-
// to get an appropriate letter spacing
|
|
26
|
-
const LETTER_SPACING_TEXT_SIZE_FACTOR = 1 / 35 * -1;
|
|
27
|
-
const LETTER_SPACING_MIN_THRESHOLD = -6;
|
|
28
|
-
const LETTER_SPACING_MAX_THRESHOLD = -1;
|
|
29
|
-
|
|
30
|
-
// fixed top margin above title/subtitle
|
|
31
|
-
const TOP_MARGIN_FIXED = 16;
|
|
32
|
-
|
|
33
|
-
// multiply text size with this factor
|
|
34
|
-
// to get an appropriate sub text size
|
|
35
|
-
const SUB_TEXT_SIZE_FACTOR = 0.5;
|
|
36
|
-
const SUB_TEXT_SIZE_MIN_THRESHOLD = 26;
|
|
37
|
-
const SUB_TEXT_SIZE_MAX_THRESHOLD = 40;
|
|
38
|
-
|
|
39
|
-
// multiply text size with this factor
|
|
40
|
-
// to get an appropriate icon padding
|
|
41
|
-
const ICON_PADDING_FACTOR = 0.3;
|
|
42
|
-
|
|
43
|
-
// Compute text width before rendering
|
|
44
|
-
// Not exactly precise but close enough
|
|
45
|
-
const getTextWidth = (text, font) => {
|
|
46
|
-
const canvas = document.createElement('canvas');
|
|
47
|
-
const context = canvas.getContext('2d');
|
|
48
|
-
context.font = font;
|
|
49
|
-
return Math.round(context.measureText(text).width * ACTUAL_TEXT_WIDTH_FACTOR);
|
|
50
|
-
};
|
|
51
|
-
const getTextHeightForNumbers = textSize => textSize * ACTUAL_NUMBER_HEIGHT_FACTOR;
|
|
52
|
-
const getIconPadding = textSize => Math.round(textSize * ICON_PADDING_FACTOR);
|
|
53
|
-
const getTextSize = (formattedValue, containerWidth, containerHeight, showIcon) => {
|
|
54
|
-
let size = Math.min(Math.round(containerHeight * TEXT_SIZE_CONTAINER_HEIGHT_FACTOR), TEXT_SIZE_MAX_THRESHOLD);
|
|
55
|
-
const widthThreshold = Math.round(containerWidth * TEXT_WIDTH_CONTAINER_WIDTH_FACTOR);
|
|
56
|
-
const textWidth = getTextWidth(formattedValue, `${size}px Roboto`) + (showIcon ? getIconPadding(size) : 0);
|
|
57
|
-
if (textWidth > widthThreshold) {
|
|
58
|
-
size = Math.round(size * (widthThreshold / textWidth));
|
|
59
|
-
}
|
|
60
|
-
return size;
|
|
61
|
-
};
|
|
62
|
-
const generateValueSVG = _ref => {
|
|
63
|
-
let {
|
|
64
|
-
formattedValue,
|
|
65
|
-
subText,
|
|
66
|
-
valueColor,
|
|
67
|
-
textColor,
|
|
68
|
-
icon,
|
|
69
|
-
noData,
|
|
70
|
-
containerWidth,
|
|
71
|
-
containerHeight,
|
|
72
|
-
topMargin = 0
|
|
73
|
-
} = _ref;
|
|
74
|
-
const showIcon = icon && formattedValue !== noData.text;
|
|
75
|
-
const textSize = getTextSize(formattedValue, containerWidth, containerHeight, showIcon);
|
|
76
|
-
const textWidth = getTextWidth(formattedValue, `${textSize}px Roboto`);
|
|
77
|
-
const iconSize = textSize;
|
|
78
|
-
const subTextSize = textSize * SUB_TEXT_SIZE_FACTOR > SUB_TEXT_SIZE_MAX_THRESHOLD ? SUB_TEXT_SIZE_MAX_THRESHOLD : textSize * SUB_TEXT_SIZE_FACTOR < SUB_TEXT_SIZE_MIN_THRESHOLD ? SUB_TEXT_SIZE_MIN_THRESHOLD : textSize * SUB_TEXT_SIZE_FACTOR;
|
|
79
|
-
const svgValue = document.createElementNS(svgNS, 'svg');
|
|
80
|
-
svgValue.setAttribute('viewBox', `0 0 ${containerWidth} ${containerHeight}`);
|
|
81
|
-
svgValue.setAttribute('width', '50%');
|
|
82
|
-
svgValue.setAttribute('height', '50%');
|
|
83
|
-
svgValue.setAttribute('x', '50%');
|
|
84
|
-
svgValue.setAttribute('y', '50%');
|
|
85
|
-
svgValue.setAttribute('style', 'overflow: visible');
|
|
86
|
-
let fillColor = colors.grey900;
|
|
87
|
-
if (valueColor) {
|
|
88
|
-
fillColor = valueColor;
|
|
89
|
-
} else if (formattedValue === noData.text) {
|
|
90
|
-
fillColor = colors.grey600;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// show icon if configured in maintenance app
|
|
94
|
-
if (showIcon) {
|
|
95
|
-
// embed icon to allow changing color
|
|
96
|
-
// (elements with fill need to use "currentColor" for this to work)
|
|
97
|
-
const iconSvgNode = document.createElementNS(svgNS, 'svg');
|
|
98
|
-
iconSvgNode.setAttribute('viewBox', '0 0 48 48');
|
|
99
|
-
iconSvgNode.setAttribute('width', iconSize);
|
|
100
|
-
iconSvgNode.setAttribute('height', iconSize);
|
|
101
|
-
iconSvgNode.setAttribute('y', (iconSize / 2 - topMargin / 2) * -1);
|
|
102
|
-
iconSvgNode.setAttribute('x', `-${(iconSize + getIconPadding(textSize) + textWidth) / 2}`);
|
|
103
|
-
iconSvgNode.setAttribute('style', `color: ${fillColor}`);
|
|
104
|
-
iconSvgNode.setAttribute('data-test', 'visualization-icon');
|
|
105
|
-
const parser = new DOMParser();
|
|
106
|
-
const svgIconDocument = parser.parseFromString(icon, 'image/svg+xml');
|
|
107
|
-
Array.from(svgIconDocument.documentElement.children).forEach(node => iconSvgNode.appendChild(node));
|
|
108
|
-
svgValue.appendChild(iconSvgNode);
|
|
109
|
-
}
|
|
110
|
-
const letterSpacing = Math.round(textSize * LETTER_SPACING_TEXT_SIZE_FACTOR);
|
|
111
|
-
const textNode = document.createElementNS(svgNS, 'text');
|
|
112
|
-
textNode.setAttribute('font-size', textSize);
|
|
113
|
-
textNode.setAttribute('font-weight', '300');
|
|
114
|
-
textNode.setAttribute('letter-spacing', letterSpacing < LETTER_SPACING_MIN_THRESHOLD ? LETTER_SPACING_MIN_THRESHOLD : letterSpacing > LETTER_SPACING_MAX_THRESHOLD ? LETTER_SPACING_MAX_THRESHOLD : letterSpacing);
|
|
115
|
-
textNode.setAttribute('text-anchor', 'middle');
|
|
116
|
-
textNode.setAttribute('x', showIcon ? `${(iconSize + getIconPadding(textSize)) / 2}` : 0);
|
|
117
|
-
textNode.setAttribute('y', topMargin / 2 + getTextHeightForNumbers(textSize) / 2);
|
|
118
|
-
textNode.setAttribute('fill', fillColor);
|
|
119
|
-
textNode.setAttribute('data-test', 'visualization-primary-value');
|
|
120
|
-
textNode.appendChild(document.createTextNode(formattedValue));
|
|
121
|
-
svgValue.appendChild(textNode);
|
|
122
|
-
if (subText) {
|
|
123
|
-
const subTextNode = document.createElementNS(svgNS, 'text');
|
|
124
|
-
subTextNode.setAttribute('text-anchor', 'middle');
|
|
125
|
-
subTextNode.setAttribute('font-size', subTextSize);
|
|
126
|
-
subTextNode.setAttribute('y', iconSize / 2 + topMargin / 2);
|
|
127
|
-
subTextNode.setAttribute('dy', subTextSize * 1.7);
|
|
128
|
-
subTextNode.setAttribute('fill', textColor);
|
|
129
|
-
subTextNode.appendChild(document.createTextNode(subText));
|
|
130
|
-
svgValue.appendChild(subTextNode);
|
|
131
|
-
}
|
|
132
|
-
return svgValue;
|
|
133
|
-
};
|
|
134
|
-
const generateDashboardItem = (config, _ref2) => {
|
|
135
|
-
let {
|
|
136
|
-
svgContainer,
|
|
137
|
-
width,
|
|
138
|
-
height,
|
|
139
|
-
valueColor,
|
|
140
|
-
titleColor,
|
|
141
|
-
backgroundColor,
|
|
142
|
-
noData,
|
|
143
|
-
icon
|
|
144
|
-
} = _ref2;
|
|
145
|
-
svgContainer.appendChild(generateValueSVG({
|
|
146
|
-
formattedValue: config.formattedValue,
|
|
147
|
-
subText: config.subText,
|
|
148
|
-
valueColor,
|
|
149
|
-
textColor: titleColor,
|
|
150
|
-
noData,
|
|
151
|
-
icon,
|
|
152
|
-
containerWidth: width,
|
|
153
|
-
containerHeight: height
|
|
154
|
-
}));
|
|
155
|
-
const container = document.createElement('div');
|
|
156
|
-
container.setAttribute('style', `display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; height: 100%; padding-top: 8px; ${backgroundColor ? `background-color:${backgroundColor};` : ''}`);
|
|
157
|
-
const titleStyle = `padding: 0 8px; text-align: center; font-size: 12px; color: ${titleColor || '#666'};`;
|
|
158
|
-
const title = document.createElement('span');
|
|
159
|
-
title.setAttribute('style', titleStyle);
|
|
160
|
-
if (config.title) {
|
|
161
|
-
title.appendChild(document.createTextNode(config.title));
|
|
162
|
-
container.appendChild(title);
|
|
163
|
-
}
|
|
164
|
-
if (config.subtitle) {
|
|
165
|
-
const subtitle = document.createElement('span');
|
|
166
|
-
subtitle.setAttribute('style', titleStyle + ' margin-top: 4px;');
|
|
167
|
-
subtitle.appendChild(document.createTextNode(config.subtitle));
|
|
168
|
-
container.appendChild(subtitle);
|
|
169
|
-
}
|
|
170
|
-
container.appendChild(svgContainer);
|
|
171
|
-
return container;
|
|
172
|
-
};
|
|
173
|
-
const getTextAnchorFromTextAlign = textAlign => {
|
|
174
|
-
switch (textAlign) {
|
|
175
|
-
default:
|
|
176
|
-
case TEXT_ALIGN_LEFT:
|
|
177
|
-
return 'start';
|
|
178
|
-
case TEXT_ALIGN_CENTER:
|
|
179
|
-
return 'middle';
|
|
180
|
-
case TEXT_ALIGN_RIGHT:
|
|
181
|
-
return 'end';
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
const getXFromTextAlign = textAlign => {
|
|
185
|
-
switch (textAlign) {
|
|
186
|
-
default:
|
|
187
|
-
case TEXT_ALIGN_LEFT:
|
|
188
|
-
return '1%';
|
|
189
|
-
case TEXT_ALIGN_CENTER:
|
|
190
|
-
return '50%';
|
|
191
|
-
case TEXT_ALIGN_RIGHT:
|
|
192
|
-
return '99%';
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
const generateDVItem = (config, _ref3) => {
|
|
196
|
-
let {
|
|
197
|
-
svgContainer,
|
|
198
|
-
width,
|
|
199
|
-
height,
|
|
200
|
-
valueColor,
|
|
201
|
-
noData,
|
|
202
|
-
backgroundColor,
|
|
203
|
-
titleColor,
|
|
204
|
-
fontStyle,
|
|
205
|
-
icon
|
|
206
|
-
} = _ref3;
|
|
207
|
-
if (backgroundColor) {
|
|
208
|
-
svgContainer.setAttribute('style', `background-color: ${backgroundColor};`);
|
|
209
|
-
const background = document.createElementNS(svgNS, 'rect');
|
|
210
|
-
background.setAttribute('width', '100%');
|
|
211
|
-
background.setAttribute('height', '100%');
|
|
212
|
-
background.setAttribute('fill', backgroundColor);
|
|
213
|
-
svgContainer.appendChild(background);
|
|
214
|
-
}
|
|
215
|
-
const svgWrapper = document.createElementNS(svgNS, 'svg');
|
|
216
|
-
|
|
217
|
-
// title
|
|
218
|
-
const title = document.createElementNS(svgNS, 'text');
|
|
219
|
-
const titleFontStyle = mergeFontStyleWithDefault(fontStyle && fontStyle[FONT_STYLE_VISUALIZATION_TITLE], FONT_STYLE_VISUALIZATION_TITLE);
|
|
220
|
-
const titleYPosition = TOP_MARGIN_FIXED + parseInt(titleFontStyle[FONT_STYLE_OPTION_FONT_SIZE]) + 'px';
|
|
221
|
-
const titleAttributes = {
|
|
222
|
-
x: getXFromTextAlign(titleFontStyle[FONT_STYLE_OPTION_TEXT_ALIGN]),
|
|
223
|
-
y: titleYPosition,
|
|
224
|
-
'text-anchor': getTextAnchorFromTextAlign(titleFontStyle[FONT_STYLE_OPTION_TEXT_ALIGN]),
|
|
225
|
-
'font-size': `${titleFontStyle[FONT_STYLE_OPTION_FONT_SIZE]}px`,
|
|
226
|
-
'font-weight': titleFontStyle[FONT_STYLE_OPTION_BOLD] ? FONT_STYLE_OPTION_BOLD : 'normal',
|
|
227
|
-
'font-style': titleFontStyle[FONT_STYLE_OPTION_ITALIC] ? FONT_STYLE_OPTION_ITALIC : 'normal',
|
|
228
|
-
'data-test': 'visualization-title',
|
|
229
|
-
fill: titleColor && titleFontStyle[FONT_STYLE_OPTION_TEXT_COLOR] === defaultFontStyle[FONT_STYLE_VISUALIZATION_TITLE][FONT_STYLE_OPTION_TEXT_COLOR] ? titleColor : titleFontStyle[FONT_STYLE_OPTION_TEXT_COLOR]
|
|
230
|
-
};
|
|
231
|
-
Object.entries(titleAttributes).forEach(_ref4 => {
|
|
232
|
-
let [key, value] = _ref4;
|
|
233
|
-
return title.setAttribute(key, value);
|
|
234
|
-
});
|
|
235
|
-
if (config.title) {
|
|
236
|
-
title.appendChild(document.createTextNode(config.title));
|
|
237
|
-
svgWrapper.appendChild(title);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// subtitle
|
|
241
|
-
const subtitle = document.createElementNS(svgNS, 'text');
|
|
242
|
-
const subtitleFontStyle = mergeFontStyleWithDefault(fontStyle && fontStyle[FONT_STYLE_VISUALIZATION_SUBTITLE], FONT_STYLE_VISUALIZATION_SUBTITLE);
|
|
243
|
-
const subtitleAttributes = {
|
|
244
|
-
x: getXFromTextAlign(subtitleFontStyle[FONT_STYLE_OPTION_TEXT_ALIGN]),
|
|
245
|
-
y: titleYPosition,
|
|
246
|
-
dy: `${subtitleFontStyle[FONT_STYLE_OPTION_FONT_SIZE] + 10}`,
|
|
247
|
-
'text-anchor': getTextAnchorFromTextAlign(subtitleFontStyle[FONT_STYLE_OPTION_TEXT_ALIGN]),
|
|
248
|
-
'font-size': `${subtitleFontStyle[FONT_STYLE_OPTION_FONT_SIZE]}px`,
|
|
249
|
-
'font-weight': subtitleFontStyle[FONT_STYLE_OPTION_BOLD] ? FONT_STYLE_OPTION_BOLD : 'normal',
|
|
250
|
-
'font-style': subtitleFontStyle[FONT_STYLE_OPTION_ITALIC] ? FONT_STYLE_OPTION_ITALIC : 'normal',
|
|
251
|
-
fill: titleColor && subtitleFontStyle[FONT_STYLE_OPTION_TEXT_COLOR] === defaultFontStyle[FONT_STYLE_VISUALIZATION_SUBTITLE][FONT_STYLE_OPTION_TEXT_COLOR] ? titleColor : subtitleFontStyle[FONT_STYLE_OPTION_TEXT_COLOR],
|
|
252
|
-
'data-test': 'visualization-subtitle'
|
|
253
|
-
};
|
|
254
|
-
Object.entries(subtitleAttributes).forEach(_ref5 => {
|
|
255
|
-
let [key, value] = _ref5;
|
|
256
|
-
return subtitle.setAttribute(key, value);
|
|
257
|
-
});
|
|
258
|
-
if (config.subtitle) {
|
|
259
|
-
subtitle.appendChild(document.createTextNode(config.subtitle));
|
|
260
|
-
svgWrapper.appendChild(subtitle);
|
|
261
|
-
}
|
|
262
|
-
svgContainer.appendChild(svgWrapper);
|
|
263
|
-
svgContainer.appendChild(generateValueSVG({
|
|
264
|
-
formattedValue: config.formattedValue,
|
|
265
|
-
subText: config.subText,
|
|
266
|
-
valueColor,
|
|
267
|
-
textColor: titleColor,
|
|
268
|
-
noData,
|
|
269
|
-
icon,
|
|
270
|
-
containerWidth: width,
|
|
271
|
-
containerHeight: height,
|
|
272
|
-
topMargin: TOP_MARGIN_FIXED + ((config.title ? parseInt(title.getAttribute('font-size')) : 0) + (config.subtitle ? parseInt(subtitle.getAttribute('font-size')) : 0)) * 2.5
|
|
273
|
-
}));
|
|
274
|
-
return svgContainer;
|
|
275
|
-
};
|
|
276
|
-
const shouldUseContrastColor = function () {
|
|
277
|
-
let inputColor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
278
|
-
// based on https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
|
|
279
|
-
var color = inputColor.charAt(0) === '#' ? inputColor.substring(1, 7) : inputColor;
|
|
280
|
-
var r = parseInt(color.substring(0, 2), 16); // hexToR
|
|
281
|
-
var g = parseInt(color.substring(2, 4), 16); // hexToG
|
|
282
|
-
var b = parseInt(color.substring(4, 6), 16); // hexToB
|
|
283
|
-
var uicolors = [r / 255, g / 255, b / 255];
|
|
284
|
-
var c = uicolors.map(col => {
|
|
285
|
-
if (col <= 0.03928) {
|
|
286
|
-
return col / 12.92;
|
|
287
|
-
}
|
|
288
|
-
return Math.pow((col + 0.055) / 1.055, 2.4);
|
|
289
|
-
});
|
|
290
|
-
var L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];
|
|
291
|
-
return L <= 0.179;
|
|
292
|
-
};
|
|
293
|
-
export default function (config, parentEl, _ref6) {
|
|
294
|
-
let {
|
|
295
|
-
dashboard,
|
|
296
|
-
legendSets,
|
|
297
|
-
fontStyle,
|
|
298
|
-
noData,
|
|
299
|
-
legendOptions,
|
|
300
|
-
icon
|
|
301
|
-
} = _ref6;
|
|
302
|
-
const legendSet = legendOptions && legendSets[0];
|
|
303
|
-
const legendColor = legendSet && getColorByValueFromLegendSet(legendSet, config.value);
|
|
304
|
-
let valueColor, titleColor, backgroundColor;
|
|
305
|
-
if (legendColor) {
|
|
306
|
-
if (legendOptions.style === LEGEND_DISPLAY_STYLE_FILL) {
|
|
307
|
-
backgroundColor = legendColor;
|
|
308
|
-
valueColor = titleColor = shouldUseContrastColor(legendColor) && colors.white;
|
|
309
|
-
} else {
|
|
310
|
-
valueColor = legendColor;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
parentEl.style.overflow = 'hidden';
|
|
314
|
-
parentEl.style.display = 'flex';
|
|
315
|
-
parentEl.style.justifyContent = 'center';
|
|
316
|
-
const parentElBBox = parentEl.getBoundingClientRect();
|
|
317
|
-
const width = parentElBBox.width;
|
|
318
|
-
const height = parentElBBox.height;
|
|
319
|
-
const svgContainer = document.createElementNS(svgNS, 'svg');
|
|
320
|
-
svgContainer.setAttribute('xmlns', svgNS);
|
|
321
|
-
svgContainer.setAttribute('viewBox', `0 0 ${width} ${height}`);
|
|
322
|
-
svgContainer.setAttribute('width', dashboard ? '100%' : width);
|
|
323
|
-
svgContainer.setAttribute('height', dashboard ? '100%' : height);
|
|
324
|
-
svgContainer.setAttribute('data-test', 'visualization-container');
|
|
325
|
-
if (dashboard) {
|
|
326
|
-
parentEl.style.borderRadius = '3px';
|
|
327
|
-
return generateDashboardItem(config, {
|
|
328
|
-
svgContainer,
|
|
329
|
-
width,
|
|
330
|
-
height,
|
|
331
|
-
valueColor,
|
|
332
|
-
backgroundColor,
|
|
333
|
-
noData,
|
|
334
|
-
icon,
|
|
335
|
-
...(legendOptions.style === LEGEND_DISPLAY_STYLE_FILL && legendColor && shouldUseContrastColor(legendColor) ? {
|
|
336
|
-
titleColor: colors.white
|
|
337
|
-
} : {})
|
|
338
|
-
});
|
|
339
|
-
} else {
|
|
340
|
-
parentEl.style.height = `100%`;
|
|
341
|
-
return generateDVItem(config, {
|
|
342
|
-
svgContainer,
|
|
343
|
-
width,
|
|
344
|
-
height,
|
|
345
|
-
valueColor,
|
|
346
|
-
backgroundColor,
|
|
347
|
-
titleColor,
|
|
348
|
-
noData,
|
|
349
|
-
icon,
|
|
350
|
-
fontStyle
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { VIS_TYPE_SINGLE_VALUE } from '../../../../modules/visTypes.js';
|
|
2
|
-
import getSingleValue from './singleValue.js';
|
|
3
|
-
const VALUE_ID = 'value';
|
|
4
|
-
function getHeaderIdIndexMap(headers) {
|
|
5
|
-
const map = new Map();
|
|
6
|
-
headers.forEach((header, index) => {
|
|
7
|
-
map.set(header.name, index);
|
|
8
|
-
});
|
|
9
|
-
return map;
|
|
10
|
-
}
|
|
11
|
-
function getPrefixedId(row, header) {
|
|
12
|
-
return (header.isPrefix ? header.name + '_' : '') + row[header.index];
|
|
13
|
-
}
|
|
14
|
-
function getIdValueMap(rows, seriesHeader, categoryHeader, valueIndex) {
|
|
15
|
-
const map = new Map();
|
|
16
|
-
let key;
|
|
17
|
-
let value;
|
|
18
|
-
rows.forEach(row => {
|
|
19
|
-
key = [...(seriesHeader ? [getPrefixedId(row, seriesHeader)] : []), ...(categoryHeader ? [getPrefixedId(row, categoryHeader)] : [])].join('-');
|
|
20
|
-
value = row[valueIndex];
|
|
21
|
-
map.set(key, value);
|
|
22
|
-
});
|
|
23
|
-
return map;
|
|
24
|
-
}
|
|
25
|
-
function getDefault(acc, seriesIds, categoryIds, idValueMap, metaData) {
|
|
26
|
-
seriesIds.forEach(seriesId => {
|
|
27
|
-
const serieData = [];
|
|
28
|
-
categoryIds.forEach(categoryId => {
|
|
29
|
-
const value = idValueMap.get(`${seriesId}-${categoryId}`);
|
|
30
|
-
|
|
31
|
-
// DHIS2-1261: 0 is a valid value
|
|
32
|
-
// undefined value means the key was not found within the rows
|
|
33
|
-
// in that case null is returned as value in the serie
|
|
34
|
-
serieData.push(value === undefined ? null : parseFloat(value));
|
|
35
|
-
});
|
|
36
|
-
acc.push({
|
|
37
|
-
id: seriesId,
|
|
38
|
-
name: metaData.items[seriesId].name,
|
|
39
|
-
data: serieData
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
return acc;
|
|
43
|
-
}
|
|
44
|
-
function getValueFunction(type) {
|
|
45
|
-
switch (type) {
|
|
46
|
-
case VIS_TYPE_SINGLE_VALUE:
|
|
47
|
-
return getSingleValue;
|
|
48
|
-
default:
|
|
49
|
-
return getDefault;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
export default function (_ref) {
|
|
53
|
-
let {
|
|
54
|
-
type,
|
|
55
|
-
data,
|
|
56
|
-
seriesId,
|
|
57
|
-
categoryId
|
|
58
|
-
} = _ref;
|
|
59
|
-
const valueFunction = getValueFunction(type);
|
|
60
|
-
return data.reduce((acc, res) => {
|
|
61
|
-
const headers = res.headers;
|
|
62
|
-
const metaData = res.metaData;
|
|
63
|
-
const rows = res.rows;
|
|
64
|
-
const headerIdIndexMap = getHeaderIdIndexMap(headers);
|
|
65
|
-
const seriesIndex = headerIdIndexMap.get(seriesId);
|
|
66
|
-
const categoryIndex = headerIdIndexMap.get(categoryId);
|
|
67
|
-
const valueIndex = headerIdIndexMap.get(VALUE_ID);
|
|
68
|
-
const seriesHeader = headers[seriesIndex];
|
|
69
|
-
const categoryHeader = headers[categoryIndex];
|
|
70
|
-
const idValueMap = getIdValueMap(rows, seriesHeader, categoryHeader, valueIndex);
|
|
71
|
-
const seriesIds = metaData.dimensions[seriesId];
|
|
72
|
-
const categoryIds = metaData.dimensions[categoryId];
|
|
73
|
-
valueFunction(acc, seriesIds, categoryIds, idValueMap, metaData);
|
|
74
|
-
return acc;
|
|
75
|
-
}, []);
|
|
76
|
-
}
|