@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.
Files changed (139) hide show
  1. package/build/cjs/__demo__/SingleValue.stories.js +706 -0
  2. package/build/cjs/components/PivotTable/PivotTableValueCell.js +6 -2
  3. package/build/cjs/components/PivotTable/styles/PivotTable.style.js +2 -2
  4. package/build/cjs/locales/en/translations.json +2 -0
  5. package/build/cjs/locales/lo/translations.json +16 -12
  6. package/build/cjs/modules/pivotTable/PivotTableEngine.js +59 -24
  7. package/build/cjs/modules/pivotTable/pivotTableConstants.js +6 -2
  8. package/build/cjs/modules/valueTypes.js +4 -1
  9. package/build/cjs/visualizations/config/adapters/dhis_highcharts/chart/default.js +26 -0
  10. package/build/cjs/visualizations/config/adapters/dhis_highcharts/chart/index.js +18 -0
  11. package/build/cjs/visualizations/config/adapters/dhis_highcharts/chart/singleValue.js +19 -0
  12. package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/index.js +36 -0
  13. package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueBackgroundColor.js +12 -0
  14. package/build/cjs/visualizations/config/adapters/{dhis_dhis/value/index.js → dhis_highcharts/customSVGOptions/singleValue/getSingleValueFormattedValue.js} +8 -6
  15. package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueLegendColor.js +11 -0
  16. package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueSubtext.js +11 -0
  17. package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueTextColor.js +20 -0
  18. package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueTitleColor.js +26 -0
  19. package/build/cjs/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/index.js +31 -0
  20. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/index.js +24 -0
  21. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/index.js +18 -0
  22. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/addIconElement.js +34 -0
  23. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/checkIfFitsWithinContainer.js +19 -0
  24. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/computeLayoutRect.js +39 -0
  25. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/computeSpacingTop.js +21 -0
  26. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/constants.js +11 -0
  27. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/getAvailableSpace.js +14 -0
  28. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/index.js +48 -0
  29. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/positionElements.js +46 -0
  30. package/build/cjs/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/styles.js +109 -0
  31. package/build/cjs/visualizations/config/adapters/dhis_highcharts/exporting.js +30 -0
  32. package/build/cjs/visualizations/config/adapters/dhis_highcharts/index.js +33 -23
  33. package/build/cjs/visualizations/config/adapters/dhis_highcharts/lang.js +17 -0
  34. package/build/cjs/visualizations/config/adapters/dhis_highcharts/plotOptions.js +1 -1
  35. package/build/cjs/visualizations/config/adapters/dhis_highcharts/series/index.js +5 -1
  36. package/build/cjs/visualizations/config/adapters/dhis_highcharts/subtitle/__tests__/singleValue.spec.js +62 -0
  37. package/build/cjs/visualizations/config/adapters/dhis_highcharts/subtitle/index.js +56 -22
  38. package/build/cjs/visualizations/config/adapters/dhis_highcharts/subtitle/singleValue.js +27 -0
  39. package/build/cjs/visualizations/config/adapters/dhis_highcharts/title/__tests__/singleValue.spec.js +44 -0
  40. package/build/cjs/visualizations/config/adapters/dhis_highcharts/title/index.js +50 -22
  41. package/build/cjs/visualizations/config/adapters/dhis_highcharts/title/singleValue.js +31 -0
  42. package/build/cjs/visualizations/config/adapters/dhis_highcharts/type.js +2 -0
  43. package/build/cjs/visualizations/config/adapters/dhis_highcharts/xAxis/index.js +1 -0
  44. package/build/cjs/visualizations/config/adapters/dhis_highcharts/yAxis/index.js +4 -5
  45. package/build/cjs/visualizations/config/adapters/index.js +2 -4
  46. package/build/cjs/visualizations/config/generators/highcharts/index.js +8 -0
  47. package/build/cjs/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/index.js +13 -0
  48. package/build/cjs/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/nonASCIIFont.js +17 -0
  49. package/build/cjs/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/textShadow.js +289 -0
  50. package/build/cjs/visualizations/config/generators/index.js +2 -4
  51. package/build/cjs/visualizations/store/adapters/dhis_highcharts/index.js +3 -0
  52. package/build/cjs/visualizations/store/adapters/dhis_highcharts/singleValue.js +10 -0
  53. package/build/cjs/visualizations/store/adapters/index.js +2 -4
  54. package/build/cjs/visualizations/util/shouldUseContrastColor.js +24 -0
  55. package/build/es/__demo__/SingleValue.stories.js +702 -0
  56. package/build/es/components/PivotTable/PivotTableValueCell.js +6 -2
  57. package/build/es/components/PivotTable/styles/PivotTable.style.js +2 -2
  58. package/build/es/locales/en/translations.json +2 -0
  59. package/build/es/locales/lo/translations.json +16 -12
  60. package/build/es/modules/pivotTable/PivotTableEngine.js +61 -26
  61. package/build/es/modules/pivotTable/pivotTableConstants.js +4 -1
  62. package/build/es/modules/valueTypes.js +2 -0
  63. package/build/es/visualizations/config/adapters/dhis_highcharts/chart/default.js +19 -0
  64. package/build/es/visualizations/config/adapters/dhis_highcharts/chart/index.js +11 -0
  65. package/build/es/visualizations/config/adapters/dhis_highcharts/chart/singleValue.js +12 -0
  66. package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/index.js +29 -0
  67. package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueBackgroundColor.js +6 -0
  68. package/build/es/visualizations/config/adapters/{dhis_dhis/value/index.js → dhis_highcharts/customSVGOptions/singleValue/getSingleValueFormattedValue.js} +4 -4
  69. package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueLegendColor.js +5 -0
  70. package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueSubtext.js +5 -0
  71. package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueTextColor.js +14 -0
  72. package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/getSingleValueTitleColor.js +20 -0
  73. package/build/es/visualizations/config/adapters/dhis_highcharts/customSVGOptions/singleValue/index.js +25 -0
  74. package/build/es/visualizations/config/adapters/dhis_highcharts/events/index.js +16 -0
  75. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/index.js +11 -0
  76. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/addIconElement.js +28 -0
  77. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/checkIfFitsWithinContainer.js +13 -0
  78. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/computeLayoutRect.js +33 -0
  79. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/computeSpacingTop.js +15 -0
  80. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/constants.js +4 -0
  81. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/getAvailableSpace.js +8 -0
  82. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/index.js +42 -0
  83. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/positionElements.js +40 -0
  84. package/build/es/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/styles.js +101 -0
  85. package/build/es/visualizations/config/adapters/dhis_highcharts/exporting.js +23 -0
  86. package/build/es/visualizations/config/adapters/dhis_highcharts/index.js +23 -13
  87. package/build/es/visualizations/config/adapters/dhis_highcharts/lang.js +11 -0
  88. package/build/es/visualizations/config/adapters/dhis_highcharts/plotOptions.js +1 -1
  89. package/build/es/visualizations/config/adapters/dhis_highcharts/series/index.js +6 -2
  90. package/build/es/visualizations/config/adapters/dhis_highcharts/subtitle/__tests__/singleValue.spec.js +59 -0
  91. package/build/es/visualizations/config/adapters/dhis_highcharts/subtitle/index.js +56 -24
  92. package/build/es/visualizations/config/adapters/dhis_highcharts/subtitle/singleValue.js +14 -0
  93. package/build/es/visualizations/config/adapters/dhis_highcharts/title/__tests__/singleValue.spec.js +42 -0
  94. package/build/es/visualizations/config/adapters/dhis_highcharts/title/index.js +52 -24
  95. package/build/es/visualizations/config/adapters/dhis_highcharts/title/singleValue.js +18 -0
  96. package/build/es/visualizations/config/adapters/dhis_highcharts/type.js +3 -1
  97. package/build/es/visualizations/config/adapters/dhis_highcharts/xAxis/index.js +2 -1
  98. package/build/es/visualizations/config/adapters/dhis_highcharts/yAxis/index.js +5 -6
  99. package/build/es/visualizations/config/adapters/index.js +1 -3
  100. package/build/es/visualizations/config/generators/highcharts/index.js +8 -0
  101. package/build/es/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/index.js +6 -0
  102. package/build/es/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/nonASCIIFont.js +11 -0
  103. package/build/es/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/textShadow.js +283 -0
  104. package/build/es/visualizations/config/generators/index.js +1 -3
  105. package/build/es/visualizations/store/adapters/dhis_highcharts/index.js +4 -1
  106. package/build/es/visualizations/store/adapters/dhis_highcharts/singleValue.js +4 -0
  107. package/build/es/visualizations/store/adapters/index.js +1 -3
  108. package/build/es/visualizations/util/shouldUseContrastColor.js +17 -0
  109. package/package.json +1 -2
  110. package/build/cjs/visualizations/config/adapters/dhis_dhis/index.js +0 -39
  111. package/build/cjs/visualizations/config/adapters/dhis_dhis/subtitle/__tests__/index.spec.js +0 -49
  112. package/build/cjs/visualizations/config/adapters/dhis_dhis/subtitle/__tests__/singleValue.spec.js +0 -15
  113. package/build/cjs/visualizations/config/adapters/dhis_dhis/subtitle/index.js +0 -34
  114. package/build/cjs/visualizations/config/adapters/dhis_dhis/subtitle/singleValue.js +0 -11
  115. package/build/cjs/visualizations/config/adapters/dhis_dhis/title/__tests__/index.spec.js +0 -39
  116. package/build/cjs/visualizations/config/adapters/dhis_dhis/title/__tests__/singleValue.spec.js +0 -17
  117. package/build/cjs/visualizations/config/adapters/dhis_dhis/title/index.js +0 -31
  118. package/build/cjs/visualizations/config/adapters/dhis_dhis/title/singleValue.js +0 -18
  119. package/build/cjs/visualizations/config/adapters/dhis_dhis/type.js +0 -19
  120. package/build/cjs/visualizations/config/adapters/dhis_highcharts/chart.js +0 -39
  121. package/build/cjs/visualizations/config/generators/dhis/index.js +0 -28
  122. package/build/cjs/visualizations/config/generators/dhis/singleValue.js +0 -359
  123. package/build/cjs/visualizations/store/adapters/dhis_dhis/index.js +0 -83
  124. package/build/cjs/visualizations/store/adapters/dhis_dhis/singleValue.js +0 -10
  125. package/build/es/visualizations/config/adapters/dhis_dhis/index.js +0 -30
  126. package/build/es/visualizations/config/adapters/dhis_dhis/subtitle/__tests__/index.spec.js +0 -46
  127. package/build/es/visualizations/config/adapters/dhis_dhis/subtitle/__tests__/singleValue.spec.js +0 -12
  128. package/build/es/visualizations/config/adapters/dhis_dhis/subtitle/index.js +0 -27
  129. package/build/es/visualizations/config/adapters/dhis_dhis/subtitle/singleValue.js +0 -4
  130. package/build/es/visualizations/config/adapters/dhis_dhis/title/__tests__/index.spec.js +0 -36
  131. package/build/es/visualizations/config/adapters/dhis_dhis/title/__tests__/singleValue.spec.js +0 -14
  132. package/build/es/visualizations/config/adapters/dhis_dhis/title/index.js +0 -24
  133. package/build/es/visualizations/config/adapters/dhis_dhis/title/singleValue.js +0 -11
  134. package/build/es/visualizations/config/adapters/dhis_dhis/type.js +0 -13
  135. package/build/es/visualizations/config/adapters/dhis_highcharts/chart.js +0 -32
  136. package/build/es/visualizations/config/generators/dhis/index.js +0 -21
  137. package/build/es/visualizations/config/generators/dhis/singleValue.js +0 -353
  138. package/build/es/visualizations/store/adapters/dhis_dhis/index.js +0 -76
  139. 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
- }
@@ -1,4 +0,0 @@
1
- export default function (acc, seriesIds, categoryIds, idValueMap) {
2
- const seriesId = seriesIds[0];
3
- acc.push(idValueMap.get(seriesId));
4
- }