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