@dhis2/analytics 24.5.0-alpha.1 → 24.6.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.
@@ -182,6 +182,20 @@
182
182
  "Fixed periods": "Fixed periods",
183
183
  "Selected Periods": "Selected Periods",
184
184
  "No periods selected": "No periods selected",
185
+ "January": "January",
186
+ "February": "February",
187
+ "March": "March",
188
+ "April": "April",
189
+ "May": "May",
190
+ "June": "June",
191
+ "July": "July",
192
+ "August": "August",
193
+ "September": "September",
194
+ "October": "October",
195
+ "November": "November",
196
+ "December": "December",
197
+ "Week {{weekNumber}}": "Week {{weekNumber}}",
198
+ "Bi-Week {{biWeekNumber}}": "Bi-Week {{biWeekNumber}}",
185
199
  "Daily": "Daily",
186
200
  "Weekly": "Weekly",
187
201
  "Weekly (Start Wednesday)": "Weekly (Start Wednesday)",
@@ -15,10 +15,9 @@ const svgNS = 'http://www.w3.org/2000/svg';
15
15
 
16
16
  const generateValueSVG = _ref => {
17
17
  let {
18
- value,
19
18
  formattedValue,
20
19
  subText,
21
- legendSet,
20
+ valueColor,
22
21
  noData,
23
22
  y
24
23
  } = _ref;
@@ -33,8 +32,8 @@ const generateValueSVG = _ref => {
33
32
 
34
33
  let fillColor = _ui.colors.grey900;
35
34
 
36
- if (legendSet) {
37
- fillColor = (0, _legends.getColorByValueFromLegendSet)(legendSet, value);
35
+ if (valueColor) {
36
+ fillColor = valueColor;
38
37
  } else if (formattedValue === noData.text) {
39
38
  fillColor = _ui.colors.grey600;
40
39
  }
@@ -75,7 +74,7 @@ const generateValueSVG = _ref => {
75
74
 
76
75
  const generateDashboardItem = (config, _ref2) => {
77
76
  let {
78
- legendSet,
77
+ valueColor,
79
78
  noData
80
79
  } = _ref2;
81
80
  const container = document.createElement('div');
@@ -98,10 +97,9 @@ const generateDashboardItem = (config, _ref2) => {
98
97
  }
99
98
 
100
99
  container.appendChild(generateValueSVG({
101
- value: config.value,
102
100
  formattedValue: config.formattedValue,
103
101
  subText: config.subText,
104
- legendSet,
102
+ valueColor,
105
103
  noData,
106
104
  y: 40
107
105
  }));
@@ -138,7 +136,8 @@ const getXFromTextAlign = textAlign => {
138
136
 
139
137
  const generateDVItem = (config, _ref3) => {
140
138
  let {
141
- legendSet,
139
+ valueColor,
140
+ titleColor,
142
141
  parentEl,
143
142
  fontStyle,
144
143
  noData
@@ -161,7 +160,13 @@ const generateDVItem = (config, _ref3) => {
161
160
  title.setAttribute('font-size', "".concat(titleFontStyle[_fontStyle.FONT_STYLE_OPTION_FONT_SIZE], "px"));
162
161
  title.setAttribute('font-weight', titleFontStyle[_fontStyle.FONT_STYLE_OPTION_BOLD] ? _fontStyle.FONT_STYLE_OPTION_BOLD : 'normal');
163
162
  title.setAttribute('font-style', titleFontStyle[_fontStyle.FONT_STYLE_OPTION_ITALIC] ? _fontStyle.FONT_STYLE_OPTION_ITALIC : 'normal');
164
- title.setAttribute('fill', titleFontStyle[_fontStyle.FONT_STYLE_OPTION_TEXT_COLOR]);
163
+
164
+ if (titleColor && titleFontStyle[_fontStyle.FONT_STYLE_OPTION_TEXT_COLOR] === _fontStyle.defaultFontStyle[_fontStyle.FONT_STYLE_VISUALIZATION_TITLE][_fontStyle.FONT_STYLE_OPTION_TEXT_COLOR]) {
165
+ title.setAttribute('fill', titleColor);
166
+ } else {
167
+ title.setAttribute('fill', titleFontStyle[_fontStyle.FONT_STYLE_OPTION_TEXT_COLOR]);
168
+ }
169
+
165
170
  title.setAttribute('data-test', 'visualization-title');
166
171
 
167
172
  if (config.title) {
@@ -178,7 +183,13 @@ const generateDVItem = (config, _ref3) => {
178
183
  subtitle.setAttribute('font-size', "".concat(subtitleFontStyle[_fontStyle.FONT_STYLE_OPTION_FONT_SIZE], "px"));
179
184
  subtitle.setAttribute('font-weight', subtitleFontStyle[_fontStyle.FONT_STYLE_OPTION_BOLD] ? _fontStyle.FONT_STYLE_OPTION_BOLD : 'normal');
180
185
  subtitle.setAttribute('font-style', subtitleFontStyle[_fontStyle.FONT_STYLE_OPTION_ITALIC] ? _fontStyle.FONT_STYLE_OPTION_ITALIC : 'normal');
181
- subtitle.setAttribute('fill', subtitleFontStyle[_fontStyle.FONT_STYLE_OPTION_TEXT_COLOR]);
186
+
187
+ if (titleColor && subtitleFontStyle[_fontStyle.FONT_STYLE_OPTION_TEXT_COLOR] === _fontStyle.defaultFontStyle[_fontStyle.FONT_STYLE_VISUALIZATION_SUBTITLE][_fontStyle.FONT_STYLE_OPTION_TEXT_COLOR]) {
188
+ subtitle.setAttribute('fill', titleColor);
189
+ } else {
190
+ subtitle.setAttribute('fill', subtitleFontStyle[_fontStyle.FONT_STYLE_OPTION_TEXT_COLOR]);
191
+ }
192
+
182
193
  subtitle.setAttribute('data-test', 'visualization-subtitle');
183
194
 
184
195
  if (config.subtitle) {
@@ -187,34 +198,76 @@ const generateDVItem = (config, _ref3) => {
187
198
  }
188
199
 
189
200
  svg.appendChild(generateValueSVG({
190
- value: config.value,
191
201
  formattedValue: config.formattedValue,
192
202
  subText: config.subText,
193
- legendSet,
203
+ valueColor,
194
204
  noData,
195
205
  y: 20
196
206
  }));
197
207
  return svg;
198
208
  };
199
209
 
210
+ const shouldUseContrastColor = inputColor => {
211
+ // based on https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
212
+ var color = inputColor.charAt(0) === '#' ? inputColor.substring(1, 7) : inputColor;
213
+ var r = parseInt(color.substring(0, 2), 16); // hexToR
214
+
215
+ var g = parseInt(color.substring(2, 4), 16); // hexToG
216
+
217
+ var b = parseInt(color.substring(4, 6), 16); // hexToB
218
+
219
+ var uicolors = [r / 255, g / 255, b / 255];
220
+ var c = uicolors.map(col => {
221
+ if (col <= 0.03928) {
222
+ return col / 12.92;
223
+ }
224
+
225
+ return Math.pow((col + 0.055) / 1.055, 2.4);
226
+ });
227
+ var L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];
228
+ return L <= 0.179;
229
+ };
230
+
200
231
  function _default(config, parentEl, _ref4) {
201
232
  let {
202
233
  dashboard,
203
234
  legendSets,
204
235
  fontStyle,
205
- noData
236
+ noData,
237
+ legendOptions
206
238
  } = _ref4;
207
- const legendSet = legendSets[0];
239
+ const legendSet = legendOptions && legendSets[0];
240
+ const legendColor = legendSet && (0, _legends.getColorByValueFromLegendSet)(legendSet, config.value);
241
+ let valueColor, titleColor;
242
+
243
+ if (legendColor) {
244
+ if (legendOptions.style === _legends.LEGEND_DISPLAY_STYLE_FILL) {
245
+ parentEl.style.background = legendColor;
246
+ valueColor = titleColor = shouldUseContrastColor(legendColor) && _ui.colors.white;
247
+ } else {
248
+ valueColor = legendColor;
249
+ }
250
+ }
251
+
208
252
  parentEl.style.overflow = 'hidden';
209
253
  parentEl.style.display = 'flex';
210
254
  parentEl.style.justifyContent = 'center';
211
- return dashboard ? generateDashboardItem(config, {
212
- legendSet,
213
- noData
214
- }) : generateDVItem(config, {
215
- legendSet,
216
- parentEl,
217
- fontStyle,
218
- noData
219
- });
255
+ parentEl.style.borderRadius = _ui.spacers.dp8;
256
+
257
+ if (dashboard) {
258
+ return generateDashboardItem(config, {
259
+ valueColor,
260
+ noData
261
+ });
262
+ } else {
263
+ parentEl.style.margin = _ui.spacers.dp8;
264
+ parentEl.style.height = "calc(100% - (".concat(_ui.spacers.dp8, " * 2))");
265
+ return generateDVItem(config, {
266
+ valueColor,
267
+ titleColor,
268
+ parentEl,
269
+ fontStyle,
270
+ noData
271
+ });
272
+ }
220
273
  }
@@ -80,6 +80,7 @@ function _default(_ref) {
80
80
 
81
81
  this.createVisualization = () => _generator(this.getConfig(), el, { ...extraOptions,
82
82
  noData: DEFAULT_EXTRA_OPTIONS.noData,
83
- fontStyle: layout.fontStyle
83
+ fontStyle: layout.fontStyle,
84
+ legendOptions: layout.legend
84
85
  });
85
86
  }
@@ -2,8 +2,6 @@ import _JSXStyle from "styled-jsx/style";
2
2
 
3
3
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
4
4
 
5
- import { useConfig } from '@dhis2/app-runtime';
6
- import { getNowInCalendar } from '@dhis2/multi-calendar-dates';
7
5
  import { TabBar, Tab, Transfer } from '@dhis2/ui';
8
6
  import PropTypes from 'prop-types';
9
7
  import React, { useState } from 'react';
@@ -27,18 +25,9 @@ const PeriodTransfer = _ref => {
27
25
  rightFooter,
28
26
  excludedPeriodTypes
29
27
  } = _ref;
30
- const {
31
- systemInfo
32
- } = useConfig();
33
- const {
34
- calendar = 'gregory'
35
- } = systemInfo;
36
28
  const defaultRelativePeriodType = excludedPeriodTypes.includes(MONTHLY) ? getRelativePeriodsOptionsById(QUARTERLY) : getRelativePeriodsOptionsById(MONTHLY);
37
- const defaultFixedPeriodType = excludedPeriodTypes.includes(MONTHLY) ? getFixedPeriodsOptionsById(QUARTERLY, calendar) : getFixedPeriodsOptionsById(MONTHLY, calendar);
38
- const now = getNowInCalendar(calendar); // use ".eraYear" rather than ".year" because in Ethiopian calendar, eraYear is what our users expect to see (for other calendars, it doesn't matter)
39
- // there is still a pending decision in Temporal regarding which era to use by default: https://github.com/js-temporal/temporal-polyfill/blob/9350ee7dd0d29f329fc097debf923a517c32f813/lib/calendar.ts#L1964
40
-
41
- const defaultFixedPeriodYear = now.eraYear || now.year;
29
+ const defaultFixedPeriodType = excludedPeriodTypes.includes(MONTHLY) ? getFixedPeriodsOptionsById(QUARTERLY) : getFixedPeriodsOptionsById(MONTHLY);
30
+ const defaultFixedPeriodYear = new Date().getFullYear();
42
31
 
43
32
  const fixedPeriodConfig = year => ({
44
33
  offset: year - defaultFixedPeriodYear,
@@ -60,7 +49,7 @@ const PeriodTransfer = _ref => {
60
49
  const onIsRelativeClick = state => {
61
50
  if (state !== isRelative) {
62
51
  setIsRelative(state);
63
- setAllPeriods(state ? getRelativePeriodsOptionsById(relativeFilter.periodType).getPeriods() : getFixedPeriodsOptionsById(fixedFilter.periodType, calendar).getPeriods(fixedPeriodConfig(Number(fixedFilter.year))));
52
+ setAllPeriods(state ? getRelativePeriodsOptionsById(relativeFilter.periodType).getPeriods() : getFixedPeriodsOptionsById(fixedFilter.periodType).getPeriods(fixedPeriodConfig(Number(fixedFilter.year))));
64
53
  }
65
54
  };
66
55
 
@@ -113,7 +102,7 @@ const PeriodTransfer = _ref => {
113
102
 
114
103
  const onSelectFixedPeriods = filter => {
115
104
  setFixedFilter(filter);
116
- setAllPeriods(getFixedPeriodsOptionsById(filter.periodType, calendar).getPeriods(fixedPeriodConfig(Number(filter.year)), calendar));
105
+ setAllPeriods(getFixedPeriodsOptionsById(filter.periodType).getPeriods(fixedPeriodConfig(Number(filter.year))));
117
106
  };
118
107
 
119
108
  const renderEmptySelection = () => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", {
@@ -1,11 +1,6 @@
1
1
  import { shallow } from 'enzyme';
2
2
  import React from 'react';
3
3
  import PeriodTransfer from '../PeriodTransfer.js';
4
- jest.mock('@dhis2/app-runtime', () => ({
5
- useConfig: () => ({
6
- systemInfo: {}
7
- })
8
- }));
9
4
  describe('The Period Selector component', () => {
10
5
  let props;
11
6
  let shallowPeriodTransfer;