@dhis2/analytics 24.10.1 → 24.10.3
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/CHANGELOG.md +14 -0
- package/build/cjs/components/AboutAOUnit/AboutAOUnit.js +6 -3
- package/build/cjs/components/Interpretations/InterpretationModal/InterpretationThread.js +6 -1
- package/build/cjs/components/Interpretations/InterpretationsUnit/InterpretationList.js +6 -1
- package/build/cjs/components/Interpretations/common/Message/Message.js +13 -8
- package/build/cjs/modules/pivotTable/PivotTableEngine.js +9 -28
- package/build/cjs/modules/pivotTable/__tests__/addToTotalIfNumber.spec.js +72 -0
- package/build/cjs/modules/pivotTable/addToTotalIfNumber.js +10 -0
- package/build/es/components/AboutAOUnit/AboutAOUnit.js +7 -4
- package/build/es/components/Interpretations/InterpretationModal/InterpretationThread.js +5 -1
- package/build/es/components/Interpretations/InterpretationsUnit/InterpretationList.js +5 -1
- package/build/es/components/Interpretations/common/Message/Message.js +12 -8
- package/build/es/modules/pivotTable/PivotTableEngine.js +8 -28
- package/build/es/modules/pivotTable/__tests__/addToTotalIfNumber.spec.js +69 -0
- package/build/es/modules/pivotTable/addToTotalIfNumber.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [24.10.3](https://github.com/dhis2/analytics/compare/v24.10.2...v24.10.3) (2024-03-20)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* show correct date and time in About AO Unit [DHIS2-15825, DHIS2-16365] [24.x] ([#1642](https://github.com/dhis2/analytics/issues/1642)) ([1c9068c](https://github.com/dhis2/analytics/commit/1c9068c9d153798ccbd61f6b916c1ee94ec122f8))
|
|
7
|
+
|
|
8
|
+
## [24.10.2](https://github.com/dhis2/analytics/compare/v24.10.1...v24.10.2) (2023-10-25)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* avoid undefined in totals DHIS2-14511 v39 ([#1587](https://github.com/dhis2/analytics/issues/1587)) ([9831c17](https://github.com/dhis2/analytics/commit/9831c17f696f763b4ef6125fef9a9999c520f5aa))
|
|
14
|
+
|
|
1
15
|
## [24.10.1](https://github.com/dhis2/analytics/compare/v24.10.0...v24.10.1) (2023-04-24)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -81,6 +81,9 @@ const AboutAOUnit = /*#__PURE__*/(0, _react.forwardRef)((_ref3, ref) => {
|
|
|
81
81
|
renderId
|
|
82
82
|
} = _ref3;
|
|
83
83
|
const [isExpanded, setIsExpanded] = (0, _react.useState)(true);
|
|
84
|
+
const {
|
|
85
|
+
fromServerDate
|
|
86
|
+
} = (0, _appRuntime.useTimeZoneConversion)();
|
|
84
87
|
const queries = (0, _react.useMemo)(() => getQueries(type), [type]);
|
|
85
88
|
const {
|
|
86
89
|
data,
|
|
@@ -194,16 +197,16 @@ const AboutAOUnit = /*#__PURE__*/(0, _react.forwardRef)((_ref3, ref) => {
|
|
|
194
197
|
}, /*#__PURE__*/_react.default.createElement(_ui.IconClock16, {
|
|
195
198
|
color: _ui.colors.grey700
|
|
196
199
|
}), _d2I18n.default.t('Last updated {{time}}', {
|
|
197
|
-
time: (0, _moment.default)(data.ao.lastUpdated).fromNow()
|
|
200
|
+
time: (0, _moment.default)(fromServerDate(data.ao.lastUpdated)).fromNow()
|
|
198
201
|
})), /*#__PURE__*/_react.default.createElement("p", {
|
|
199
202
|
className: "jsx-".concat(_AboutAOUnitStyle.default.__hash) + " " + "detailLine"
|
|
200
203
|
}, /*#__PURE__*/_react.default.createElement(_ui.IconUser16, {
|
|
201
204
|
color: _ui.colors.grey700
|
|
202
205
|
}), (_data$ao$createdBy = data.ao.createdBy) !== null && _data$ao$createdBy !== void 0 && _data$ao$createdBy.displayName ? _d2I18n.default.t('Created {{time}} by {{author}}', {
|
|
203
|
-
time: (0, _moment.default)(data.ao.created).fromNow(),
|
|
206
|
+
time: (0, _moment.default)(fromServerDate(data.ao.created)).fromNow(),
|
|
204
207
|
author: data.ao.createdBy.displayName
|
|
205
208
|
}) : _d2I18n.default.t('Created {{time}}', {
|
|
206
|
-
time: (0, _moment.default)(data.ao.created).fromNow()
|
|
209
|
+
time: (0, _moment.default)(fromServerDate(data.ao.created)).fromNow()
|
|
207
210
|
})), /*#__PURE__*/_react.default.createElement("p", {
|
|
208
211
|
className: "jsx-".concat(_AboutAOUnitStyle.default.__hash) + " " + "detailLine"
|
|
209
212
|
}, /*#__PURE__*/_react.default.createElement(_ui.IconView16, {
|
|
@@ -7,6 +7,8 @@ exports.InterpretationThread = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
|
9
9
|
|
|
10
|
+
var _appRuntime = require("@dhis2/app-runtime");
|
|
11
|
+
|
|
10
12
|
var _ui = require("@dhis2/ui");
|
|
11
13
|
|
|
12
14
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
@@ -39,6 +41,9 @@ const InterpretationThread = _ref => {
|
|
|
39
41
|
onThreadUpdated,
|
|
40
42
|
downloadMenuComponent: DownloadMenu
|
|
41
43
|
} = _ref;
|
|
44
|
+
const {
|
|
45
|
+
fromServerDate
|
|
46
|
+
} = (0, _appRuntime.useTimeZoneConversion)();
|
|
42
47
|
const focusRef = (0, _react.useRef)();
|
|
43
48
|
(0, _react.useEffect)(() => {
|
|
44
49
|
if (initialFocus && focusRef.current) {
|
|
@@ -57,7 +62,7 @@ const InterpretationThread = _ref => {
|
|
|
57
62
|
className: "jsx-615306698" + " " + 'title'
|
|
58
63
|
}, /*#__PURE__*/_react.default.createElement(_ui.IconClock16, {
|
|
59
64
|
color: _ui.colors.grey700
|
|
60
|
-
}), (0, _moment.default)(interpretation.created).format('LLL')), DownloadMenu && /*#__PURE__*/_react.default.createElement(DownloadMenu, {
|
|
65
|
+
}), (0, _moment.default)(fromServerDate(interpretation.created)).format('LLL')), DownloadMenu && /*#__PURE__*/_react.default.createElement(DownloadMenu, {
|
|
61
66
|
relativePeriodDate: interpretation.created,
|
|
62
67
|
className: "jsx-615306698"
|
|
63
68
|
}), /*#__PURE__*/_react.default.createElement("div", {
|
|
@@ -7,6 +7,8 @@ exports.InterpretationList = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
|
9
9
|
|
|
10
|
+
var _appRuntime = require("@dhis2/app-runtime");
|
|
11
|
+
|
|
10
12
|
var _ui = require("@dhis2/ui");
|
|
11
13
|
|
|
12
14
|
var _moment = _interopRequireDefault(require("moment"));
|
|
@@ -43,6 +45,9 @@ const InterpretationList = _ref => {
|
|
|
43
45
|
refresh,
|
|
44
46
|
disabled
|
|
45
47
|
} = _ref;
|
|
48
|
+
const {
|
|
49
|
+
fromServerDate
|
|
50
|
+
} = (0, _appRuntime.useTimeZoneConversion)();
|
|
46
51
|
const interpretationsByDate = interpretations.reduce((groupedInterpretations, interpretation) => {
|
|
47
52
|
const date = interpretation.created.split('T')[0];
|
|
48
53
|
|
|
@@ -67,7 +72,7 @@ const InterpretationList = _ref => {
|
|
|
67
72
|
}), /*#__PURE__*/_react.default.createElement("time", {
|
|
68
73
|
dateTime: date,
|
|
69
74
|
className: _style.default.dynamic([["4058400613", [_ui.spacers.dp8, _ui.spacers.dp8, _ui.spacers.dp16, _ui.colors.grey800, _ui.spacers.dp12, _ui.spacers.dp12, _ui.spacers.dp32, _ui.spacers.dp4]]]) + " " + "date-header"
|
|
70
|
-
}, (0, _moment.default)(date).format('ll'))), /*#__PURE__*/_react.default.createElement("ol", {
|
|
75
|
+
}, (0, _moment.default)(fromServerDate(date)).format('ll'))), /*#__PURE__*/_react.default.createElement("ol", {
|
|
71
76
|
className: _style.default.dynamic([["4058400613", [_ui.spacers.dp8, _ui.spacers.dp8, _ui.spacers.dp16, _ui.colors.grey800, _ui.spacers.dp12, _ui.spacers.dp12, _ui.spacers.dp32, _ui.spacers.dp4]]]) + " " + "interpretation-list"
|
|
72
77
|
}, interpretationsByDate[date].sort(sortByCreatedDateDesc).map(interpretation => /*#__PURE__*/_react.default.createElement(_index.Interpretation, {
|
|
73
78
|
key: interpretation.id,
|
|
@@ -7,6 +7,8 @@ exports.Message = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
|
9
9
|
|
|
10
|
+
var _appRuntime = require("@dhis2/app-runtime");
|
|
11
|
+
|
|
10
12
|
var _d2UiRichText = require("@dhis2/d2-ui-rich-text");
|
|
11
13
|
|
|
12
14
|
var _ui = require("@dhis2/ui");
|
|
@@ -26,24 +28,27 @@ const Message = _ref => {
|
|
|
26
28
|
created,
|
|
27
29
|
username
|
|
28
30
|
} = _ref;
|
|
31
|
+
const {
|
|
32
|
+
fromServerDate
|
|
33
|
+
} = (0, _appRuntime.useTimeZoneConversion)();
|
|
29
34
|
return /*#__PURE__*/_react.default.createElement("li", {
|
|
30
|
-
className: _style.default.dynamic([["
|
|
35
|
+
className: _style.default.dynamic([["4031345705", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]]) + " " + "container"
|
|
31
36
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
32
|
-
className: _style.default.dynamic([["
|
|
37
|
+
className: _style.default.dynamic([["4031345705", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]]) + " " + "header"
|
|
33
38
|
}, /*#__PURE__*/_react.default.createElement(_ui.UserAvatar, {
|
|
34
39
|
name: username,
|
|
35
40
|
extrasmall: true
|
|
36
41
|
}), username, /*#__PURE__*/_react.default.createElement("time", {
|
|
37
42
|
dateTime: created,
|
|
38
|
-
className: _style.default.dynamic([["
|
|
39
|
-
}, (0, _moment.default)(created).format('lll'))), /*#__PURE__*/_react.default.createElement("div", {
|
|
40
|
-
className: _style.default.dynamic([["
|
|
43
|
+
className: _style.default.dynamic([["4031345705", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]])
|
|
44
|
+
}, (0, _moment.default)(fromServerDate(created)).format('lll'))), /*#__PURE__*/_react.default.createElement("div", {
|
|
45
|
+
className: _style.default.dynamic([["4031345705", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]]) + " " + "content"
|
|
41
46
|
}, /*#__PURE__*/_react.default.createElement(_d2UiRichText.Parser, null, text)), /*#__PURE__*/_react.default.createElement("div", {
|
|
42
|
-
className: _style.default.dynamic([["
|
|
47
|
+
className: _style.default.dynamic([["4031345705", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]]) + " " + "footer"
|
|
43
48
|
}, children), /*#__PURE__*/_react.default.createElement(_style.default, {
|
|
44
|
-
id: "
|
|
49
|
+
id: "4031345705",
|
|
45
50
|
dynamic: [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]
|
|
46
|
-
}, [".container.__jsx-style-dynamic-selector{padding:".concat(_ui.spacers.dp8, ";background-color:").concat(_ui.colors.grey100, ";border-radius:5px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:").concat(_ui.spacers.dp8, ";}"), ".header.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:6px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:13px;line-height:16px;color:".concat(_ui.colors.grey900, ";}"), ".header.__jsx-style-dynamic-selector time.__jsx-style-dynamic-selector{font-size:12px;color:".concat(_ui.colors.grey600, ";}"), ".content.__jsx-style-dynamic-selector{font-size:14px;line-height:19px;color:".concat(_ui.colors.grey900, ";}"), ".content.__jsx-style-dynamic-selector p:first-child{margin:0;}", ".footer.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;gap:".concat(_ui.spacers.dp8, ";}")]));
|
|
51
|
+
}, [".container.__jsx-style-dynamic-selector{padding:".concat(_ui.spacers.dp8, ";background-color:").concat(_ui.colors.grey100, ";border-radius:5px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:").concat(_ui.spacers.dp8, ";}"), ".header.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:6px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:13px;line-height:16px;color:".concat(_ui.colors.grey900, ";}"), ".header.__jsx-style-dynamic-selector time.__jsx-style-dynamic-selector{font-size:12px;color:".concat(_ui.colors.grey600, ";}"), ".content.__jsx-style-dynamic-selector{font-size:14px;line-height:19px;color:".concat(_ui.colors.grey900, ";word-break:break-word;white-space:pre-line;}"), ".content.__jsx-style-dynamic-selector p:first-child{margin:0;}", ".footer.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;gap:".concat(_ui.spacers.dp8, ";}")]));
|
|
47
52
|
};
|
|
48
53
|
|
|
49
54
|
exports.Message = Message;
|
|
@@ -17,6 +17,8 @@ var _valueTypes = require("../valueTypes.js");
|
|
|
17
17
|
|
|
18
18
|
var _AdaptiveClippingController = require("./AdaptiveClippingController.js");
|
|
19
19
|
|
|
20
|
+
var _addToTotalIfNumber = require("./addToTotalIfNumber.js");
|
|
21
|
+
|
|
20
22
|
var _parseValue = require("./parseValue.js");
|
|
21
23
|
|
|
22
24
|
var _pivotTableConstants = require("./pivotTableConstants.js");
|
|
@@ -626,10 +628,7 @@ class PivotTableEngine {
|
|
|
626
628
|
dataFields.forEach(field => {
|
|
627
629
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
628
630
|
const value = (0, _parseValue.parseValue)(dataRow[headerIndex]);
|
|
629
|
-
|
|
630
|
-
if (value && !isNaN(value)) {
|
|
631
|
-
totalCell[field] = (totalCell[field] || 0) + value;
|
|
632
|
-
}
|
|
631
|
+
totalCell[field] = (0, _addToTotalIfNumber.addToTotalIfNumber)(value, totalCell[field]);
|
|
633
632
|
});
|
|
634
633
|
}
|
|
635
634
|
|
|
@@ -648,10 +647,7 @@ class PivotTableEngine {
|
|
|
648
647
|
dataFields.forEach(field => {
|
|
649
648
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
650
649
|
const value = (0, _parseValue.parseValue)(dataRow[headerIndex]);
|
|
651
|
-
|
|
652
|
-
if (value && !isNaN(value)) {
|
|
653
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
654
|
-
}
|
|
650
|
+
percentageTotal[field] = (0, _addToTotalIfNumber.addToTotalIfNumber)(value, percentageTotal[field]);
|
|
655
651
|
});
|
|
656
652
|
|
|
657
653
|
if (totals.columnSubtotal) {
|
|
@@ -666,10 +662,7 @@ class PivotTableEngine {
|
|
|
666
662
|
dataFields.forEach(field => {
|
|
667
663
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
668
664
|
const value = (0, _parseValue.parseValue)(dataRow[headerIndex]);
|
|
669
|
-
|
|
670
|
-
if (value && !isNaN(value)) {
|
|
671
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
672
|
-
}
|
|
665
|
+
percentageTotal[field] = (0, _addToTotalIfNumber.addToTotalIfNumber)(value, percentageTotal[field]);
|
|
673
666
|
});
|
|
674
667
|
}
|
|
675
668
|
|
|
@@ -685,10 +678,7 @@ class PivotTableEngine {
|
|
|
685
678
|
dataFields.forEach(field => {
|
|
686
679
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
687
680
|
const value = (0, _parseValue.parseValue)(dataRow[headerIndex]);
|
|
688
|
-
|
|
689
|
-
if (value && !isNaN(value)) {
|
|
690
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
691
|
-
}
|
|
681
|
+
percentageTotal[field] = (0, _addToTotalIfNumber.addToTotalIfNumber)(value, percentageTotal[field]);
|
|
692
682
|
});
|
|
693
683
|
}
|
|
694
684
|
}
|
|
@@ -705,10 +695,7 @@ class PivotTableEngine {
|
|
|
705
695
|
dataFields.forEach(field => {
|
|
706
696
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
707
697
|
const value = (0, _parseValue.parseValue)(dataRow[headerIndex]);
|
|
708
|
-
|
|
709
|
-
if (value && !isNaN(value)) {
|
|
710
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
711
|
-
}
|
|
698
|
+
percentageTotal[field] = (0, _addToTotalIfNumber.addToTotalIfNumber)(value, percentageTotal[field]);
|
|
712
699
|
});
|
|
713
700
|
|
|
714
701
|
if (totals.rowSubtotal) {
|
|
@@ -723,10 +710,7 @@ class PivotTableEngine {
|
|
|
723
710
|
dataFields.forEach(field => {
|
|
724
711
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
725
712
|
const value = (0, _parseValue.parseValue)(dataRow[headerIndex]);
|
|
726
|
-
|
|
727
|
-
if (value && !isNaN(value)) {
|
|
728
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
729
|
-
}
|
|
713
|
+
percentageTotal[field] = (0, _addToTotalIfNumber.addToTotalIfNumber)(value, percentageTotal[field]);
|
|
730
714
|
});
|
|
731
715
|
}
|
|
732
716
|
|
|
@@ -742,10 +726,7 @@ class PivotTableEngine {
|
|
|
742
726
|
dataFields.forEach(field => {
|
|
743
727
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
744
728
|
const value = (0, _parseValue.parseValue)(dataRow[headerIndex]);
|
|
745
|
-
|
|
746
|
-
if (value && !isNaN(value)) {
|
|
747
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
748
|
-
}
|
|
729
|
+
percentageTotal[field] = (0, _addToTotalIfNumber.addToTotalIfNumber)(value, percentageTotal[field]);
|
|
749
730
|
});
|
|
750
731
|
}
|
|
751
732
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _addToTotalIfNumber = require("../addToTotalIfNumber.js");
|
|
4
|
+
|
|
5
|
+
const tests = [{
|
|
6
|
+
testName: 'negative value',
|
|
7
|
+
value: -1,
|
|
8
|
+
total: undefined,
|
|
9
|
+
expected: -1
|
|
10
|
+
}, {
|
|
11
|
+
testName: 'zero value',
|
|
12
|
+
value: 0,
|
|
13
|
+
total: undefined,
|
|
14
|
+
expected: 0
|
|
15
|
+
}, {
|
|
16
|
+
testName: 'positive value',
|
|
17
|
+
value: 1,
|
|
18
|
+
total: undefined,
|
|
19
|
+
expected: 1
|
|
20
|
+
}, {
|
|
21
|
+
testName: 'null value',
|
|
22
|
+
value: null,
|
|
23
|
+
total: undefined,
|
|
24
|
+
expected: undefined
|
|
25
|
+
}, {
|
|
26
|
+
testName: 'undefined value',
|
|
27
|
+
value: undefined,
|
|
28
|
+
total: undefined,
|
|
29
|
+
expected: undefined
|
|
30
|
+
}, {
|
|
31
|
+
testName: 'string value',
|
|
32
|
+
value: 'string',
|
|
33
|
+
total: undefined,
|
|
34
|
+
expected: undefined
|
|
35
|
+
}, {
|
|
36
|
+
testName: 'negative value with existing total',
|
|
37
|
+
value: -1,
|
|
38
|
+
total: 100,
|
|
39
|
+
expected: 99
|
|
40
|
+
}, {
|
|
41
|
+
testName: 'zero value with existing total',
|
|
42
|
+
value: 0,
|
|
43
|
+
total: 100,
|
|
44
|
+
expected: 100
|
|
45
|
+
}, {
|
|
46
|
+
testName: 'positive value with existing total',
|
|
47
|
+
value: 1,
|
|
48
|
+
total: 100,
|
|
49
|
+
expected: 101
|
|
50
|
+
}, {
|
|
51
|
+
testName: 'null value with existing total',
|
|
52
|
+
value: null,
|
|
53
|
+
total: 100,
|
|
54
|
+
expected: 100
|
|
55
|
+
}, {
|
|
56
|
+
testName: 'undefined value with existing total',
|
|
57
|
+
value: undefined,
|
|
58
|
+
total: 100,
|
|
59
|
+
expected: 100
|
|
60
|
+
}, {
|
|
61
|
+
testName: 'string value with existing total',
|
|
62
|
+
value: 'string',
|
|
63
|
+
total: 100,
|
|
64
|
+
expected: 100
|
|
65
|
+
}];
|
|
66
|
+
describe('addToTotalIfNumber', () => {
|
|
67
|
+
tests.forEach(t => {
|
|
68
|
+
it(t.testName, () => {
|
|
69
|
+
expect((0, _addToTotalIfNumber.addToTotalIfNumber)(t.value, t.total)).toEqual(t.expected);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.addToTotalIfNumber = void 0;
|
|
7
|
+
|
|
8
|
+
const addToTotalIfNumber = (value, total) => typeof value === 'number' && Number.isFinite(value) ? (total !== null && total !== void 0 ? total : 0) + value : total;
|
|
9
|
+
|
|
10
|
+
exports.addToTotalIfNumber = addToTotalIfNumber;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
|
2
|
-
import { useDataQuery, useDataMutation } from '@dhis2/app-runtime';
|
|
2
|
+
import { useDataQuery, useDataMutation, useTimeZoneConversion } from '@dhis2/app-runtime';
|
|
3
3
|
import i18n from '@dhis2/d2-i18n';
|
|
4
4
|
import { Parser as RichTextParser } from '@dhis2/d2-ui-rich-text';
|
|
5
5
|
import { Button, CircularLoader, IconChevronDown24, IconChevronUp24, IconClock16, IconShare16, IconSubscribe24, IconSubscribeOff24, IconUser16, IconView16, colors } from '@dhis2/ui';
|
|
@@ -56,6 +56,9 @@ const AboutAOUnit = /*#__PURE__*/forwardRef((_ref3, ref) => {
|
|
|
56
56
|
renderId
|
|
57
57
|
} = _ref3;
|
|
58
58
|
const [isExpanded, setIsExpanded] = useState(true);
|
|
59
|
+
const {
|
|
60
|
+
fromServerDate
|
|
61
|
+
} = useTimeZoneConversion();
|
|
59
62
|
const queries = useMemo(() => getQueries(type), [type]);
|
|
60
63
|
const {
|
|
61
64
|
data,
|
|
@@ -169,16 +172,16 @@ const AboutAOUnit = /*#__PURE__*/forwardRef((_ref3, ref) => {
|
|
|
169
172
|
}, /*#__PURE__*/React.createElement(IconClock16, {
|
|
170
173
|
color: colors.grey700
|
|
171
174
|
}), i18n.t('Last updated {{time}}', {
|
|
172
|
-
time: moment(data.ao.lastUpdated).fromNow()
|
|
175
|
+
time: moment(fromServerDate(data.ao.lastUpdated)).fromNow()
|
|
173
176
|
})), /*#__PURE__*/React.createElement("p", {
|
|
174
177
|
className: "jsx-".concat(styles.__hash) + " " + "detailLine"
|
|
175
178
|
}, /*#__PURE__*/React.createElement(IconUser16, {
|
|
176
179
|
color: colors.grey700
|
|
177
180
|
}), (_data$ao$createdBy = data.ao.createdBy) !== null && _data$ao$createdBy !== void 0 && _data$ao$createdBy.displayName ? i18n.t('Created {{time}} by {{author}}', {
|
|
178
|
-
time: moment(data.ao.created).fromNow(),
|
|
181
|
+
time: moment(fromServerDate(data.ao.created)).fromNow(),
|
|
179
182
|
author: data.ao.createdBy.displayName
|
|
180
183
|
}) : i18n.t('Created {{time}}', {
|
|
181
|
-
time: moment(data.ao.created).fromNow()
|
|
184
|
+
time: moment(fromServerDate(data.ao.created)).fromNow()
|
|
182
185
|
})), /*#__PURE__*/React.createElement("p", {
|
|
183
186
|
className: "jsx-".concat(styles.__hash) + " " + "detailLine"
|
|
184
187
|
}, /*#__PURE__*/React.createElement(IconView16, {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
|
2
|
+
import { useTimeZoneConversion } from '@dhis2/app-runtime';
|
|
2
3
|
import { IconClock16, colors } from '@dhis2/ui';
|
|
3
4
|
import cx from 'classnames';
|
|
4
5
|
import moment from 'moment';
|
|
@@ -18,6 +19,9 @@ const InterpretationThread = _ref => {
|
|
|
18
19
|
onThreadUpdated,
|
|
19
20
|
downloadMenuComponent: DownloadMenu
|
|
20
21
|
} = _ref;
|
|
22
|
+
const {
|
|
23
|
+
fromServerDate
|
|
24
|
+
} = useTimeZoneConversion();
|
|
21
25
|
const focusRef = useRef();
|
|
22
26
|
useEffect(() => {
|
|
23
27
|
if (initialFocus && focusRef.current) {
|
|
@@ -36,7 +40,7 @@ const InterpretationThread = _ref => {
|
|
|
36
40
|
className: "jsx-615306698" + " " + 'title'
|
|
37
41
|
}, /*#__PURE__*/React.createElement(IconClock16, {
|
|
38
42
|
color: colors.grey700
|
|
39
|
-
}), moment(interpretation.created).format('LLL')), DownloadMenu && /*#__PURE__*/React.createElement(DownloadMenu, {
|
|
43
|
+
}), moment(fromServerDate(interpretation.created)).format('LLL')), DownloadMenu && /*#__PURE__*/React.createElement(DownloadMenu, {
|
|
40
44
|
relativePeriodDate: interpretation.created,
|
|
41
45
|
className: "jsx-615306698"
|
|
42
46
|
}), /*#__PURE__*/React.createElement("div", {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
|
2
|
+
import { useTimeZoneConversion } from '@dhis2/app-runtime';
|
|
2
3
|
import { IconCalendar24, colors, spacers } from '@dhis2/ui';
|
|
3
4
|
import moment from 'moment';
|
|
4
5
|
import PropTypes from 'prop-types';
|
|
@@ -29,6 +30,9 @@ export const InterpretationList = _ref => {
|
|
|
29
30
|
refresh,
|
|
30
31
|
disabled
|
|
31
32
|
} = _ref;
|
|
33
|
+
const {
|
|
34
|
+
fromServerDate
|
|
35
|
+
} = useTimeZoneConversion();
|
|
32
36
|
const interpretationsByDate = interpretations.reduce((groupedInterpretations, interpretation) => {
|
|
33
37
|
const date = interpretation.created.split('T')[0];
|
|
34
38
|
|
|
@@ -53,7 +57,7 @@ export const InterpretationList = _ref => {
|
|
|
53
57
|
}), /*#__PURE__*/React.createElement("time", {
|
|
54
58
|
dateTime: date,
|
|
55
59
|
className: _JSXStyle.dynamic([["4058400613", [spacers.dp8, spacers.dp8, spacers.dp16, colors.grey800, spacers.dp12, spacers.dp12, spacers.dp32, spacers.dp4]]]) + " " + "date-header"
|
|
56
|
-
}, moment(date).format('ll'))), /*#__PURE__*/React.createElement("ol", {
|
|
60
|
+
}, moment(fromServerDate(date)).format('ll'))), /*#__PURE__*/React.createElement("ol", {
|
|
57
61
|
className: _JSXStyle.dynamic([["4058400613", [spacers.dp8, spacers.dp8, spacers.dp16, colors.grey800, spacers.dp12, spacers.dp12, spacers.dp32, spacers.dp4]]]) + " " + "interpretation-list"
|
|
58
62
|
}, interpretationsByDate[date].sort(sortByCreatedDateDesc).map(interpretation => /*#__PURE__*/React.createElement(Interpretation, {
|
|
59
63
|
key: interpretation.id,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
|
2
|
+
import { useTimeZoneConversion } from '@dhis2/app-runtime';
|
|
2
3
|
import { Parser as RichTextParser } from '@dhis2/d2-ui-rich-text';
|
|
3
4
|
import { UserAvatar, spacers, colors } from '@dhis2/ui';
|
|
4
5
|
import moment from 'moment';
|
|
@@ -12,24 +13,27 @@ const Message = _ref => {
|
|
|
12
13
|
created,
|
|
13
14
|
username
|
|
14
15
|
} = _ref;
|
|
16
|
+
const {
|
|
17
|
+
fromServerDate
|
|
18
|
+
} = useTimeZoneConversion();
|
|
15
19
|
return /*#__PURE__*/React.createElement("li", {
|
|
16
|
-
className: _JSXStyle.dynamic([["
|
|
20
|
+
className: _JSXStyle.dynamic([["4031345705", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]]) + " " + "container"
|
|
17
21
|
}, /*#__PURE__*/React.createElement("div", {
|
|
18
|
-
className: _JSXStyle.dynamic([["
|
|
22
|
+
className: _JSXStyle.dynamic([["4031345705", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]]) + " " + "header"
|
|
19
23
|
}, /*#__PURE__*/React.createElement(UserAvatar, {
|
|
20
24
|
name: username,
|
|
21
25
|
extrasmall: true
|
|
22
26
|
}), username, /*#__PURE__*/React.createElement("time", {
|
|
23
27
|
dateTime: created,
|
|
24
|
-
className: _JSXStyle.dynamic([["
|
|
25
|
-
}, moment(created).format('lll'))), /*#__PURE__*/React.createElement("div", {
|
|
26
|
-
className: _JSXStyle.dynamic([["
|
|
28
|
+
className: _JSXStyle.dynamic([["4031345705", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]])
|
|
29
|
+
}, moment(fromServerDate(created)).format('lll'))), /*#__PURE__*/React.createElement("div", {
|
|
30
|
+
className: _JSXStyle.dynamic([["4031345705", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]]) + " " + "content"
|
|
27
31
|
}, /*#__PURE__*/React.createElement(RichTextParser, null, text)), /*#__PURE__*/React.createElement("div", {
|
|
28
|
-
className: _JSXStyle.dynamic([["
|
|
32
|
+
className: _JSXStyle.dynamic([["4031345705", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]]) + " " + "footer"
|
|
29
33
|
}, children), /*#__PURE__*/React.createElement(_JSXStyle, {
|
|
30
|
-
id: "
|
|
34
|
+
id: "4031345705",
|
|
31
35
|
dynamic: [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]
|
|
32
|
-
}, [".container.__jsx-style-dynamic-selector{padding:".concat(spacers.dp8, ";background-color:").concat(colors.grey100, ";border-radius:5px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:").concat(spacers.dp8, ";}"), ".header.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:6px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:13px;line-height:16px;color:".concat(colors.grey900, ";}"), ".header.__jsx-style-dynamic-selector time.__jsx-style-dynamic-selector{font-size:12px;color:".concat(colors.grey600, ";}"), ".content.__jsx-style-dynamic-selector{font-size:14px;line-height:19px;color:".concat(colors.grey900, ";}"), ".content.__jsx-style-dynamic-selector p:first-child{margin:0;}", ".footer.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;gap:".concat(spacers.dp8, ";}")]));
|
|
36
|
+
}, [".container.__jsx-style-dynamic-selector{padding:".concat(spacers.dp8, ";background-color:").concat(colors.grey100, ";border-radius:5px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:").concat(spacers.dp8, ";}"), ".header.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:6px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:13px;line-height:16px;color:".concat(colors.grey900, ";}"), ".header.__jsx-style-dynamic-selector time.__jsx-style-dynamic-selector{font-size:12px;color:".concat(colors.grey600, ";}"), ".content.__jsx-style-dynamic-selector{font-size:14px;line-height:19px;color:".concat(colors.grey900, ";word-break:break-word;white-space:pre-line;}"), ".content.__jsx-style-dynamic-selector p:first-child{margin:0;}", ".footer.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;gap:".concat(spacers.dp8, ";}")]));
|
|
33
37
|
};
|
|
34
38
|
|
|
35
39
|
Message.propTypes = {
|
|
@@ -6,6 +6,7 @@ import { DIMENSION_ID_ORGUNIT } from '../predefinedDimensions.js';
|
|
|
6
6
|
import { renderValue } from '../renderValue.js';
|
|
7
7
|
import { VALUE_TYPE_NUMBER, VALUE_TYPE_TEXT } from '../valueTypes.js';
|
|
8
8
|
import { AdaptiveClippingController } from './AdaptiveClippingController.js';
|
|
9
|
+
import { addToTotalIfNumber } from './addToTotalIfNumber.js';
|
|
9
10
|
import { parseValue } from './parseValue.js';
|
|
10
11
|
import { AGGREGATE_TYPE_NA, AGGREGATE_TYPE_AVERAGE, AGGREGATE_TYPE_SUM, CELL_TYPE_VALUE, CELL_TYPE_TOTAL, CELL_TYPE_SUBTOTAL, SORT_ORDER_ASCENDING, SORT_ORDER_DESCENDING, DISPLAY_DENSITY_PADDING_COMPACT, DISPLAY_DENSITY_PADDING_COMFORTABLE, DISPLAY_DENSITY_OPTION_COMFORTABLE, DISPLAY_DENSITY_OPTION_COMPACT, DISPLAY_DENSITY_OPTION_NORMAL, DISPLAY_DENSITY_PADDING_NORMAL, FONT_SIZE_OPTION_SMALL, FONT_SIZE_SMALL, FONT_SIZE_OPTION_LARGE, FONT_SIZE_LARGE, FONT_SIZE_OPTION_NORMAL, FONT_SIZE_NORMAL, NUMBER_TYPE_COLUMN_PERCENTAGE, NUMBER_TYPE_ROW_PERCENTAGE, NUMBER_TYPE_VALUE } from './pivotTableConstants.js';
|
|
11
12
|
const dataFields = ['value', 'numerator', 'denominator', 'factor', 'multiplier', 'divisor'];
|
|
@@ -609,10 +610,7 @@ export class PivotTableEngine {
|
|
|
609
610
|
dataFields.forEach(field => {
|
|
610
611
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
611
612
|
const value = parseValue(dataRow[headerIndex]);
|
|
612
|
-
|
|
613
|
-
if (value && !isNaN(value)) {
|
|
614
|
-
totalCell[field] = (totalCell[field] || 0) + value;
|
|
615
|
-
}
|
|
613
|
+
totalCell[field] = addToTotalIfNumber(value, totalCell[field]);
|
|
616
614
|
});
|
|
617
615
|
}
|
|
618
616
|
|
|
@@ -631,10 +629,7 @@ export class PivotTableEngine {
|
|
|
631
629
|
dataFields.forEach(field => {
|
|
632
630
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
633
631
|
const value = parseValue(dataRow[headerIndex]);
|
|
634
|
-
|
|
635
|
-
if (value && !isNaN(value)) {
|
|
636
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
637
|
-
}
|
|
632
|
+
percentageTotal[field] = addToTotalIfNumber(value, percentageTotal[field]);
|
|
638
633
|
});
|
|
639
634
|
|
|
640
635
|
if (totals.columnSubtotal) {
|
|
@@ -649,10 +644,7 @@ export class PivotTableEngine {
|
|
|
649
644
|
dataFields.forEach(field => {
|
|
650
645
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
651
646
|
const value = parseValue(dataRow[headerIndex]);
|
|
652
|
-
|
|
653
|
-
if (value && !isNaN(value)) {
|
|
654
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
655
|
-
}
|
|
647
|
+
percentageTotal[field] = addToTotalIfNumber(value, percentageTotal[field]);
|
|
656
648
|
});
|
|
657
649
|
}
|
|
658
650
|
|
|
@@ -668,10 +660,7 @@ export class PivotTableEngine {
|
|
|
668
660
|
dataFields.forEach(field => {
|
|
669
661
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
670
662
|
const value = parseValue(dataRow[headerIndex]);
|
|
671
|
-
|
|
672
|
-
if (value && !isNaN(value)) {
|
|
673
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
674
|
-
}
|
|
663
|
+
percentageTotal[field] = addToTotalIfNumber(value, percentageTotal[field]);
|
|
675
664
|
});
|
|
676
665
|
}
|
|
677
666
|
}
|
|
@@ -688,10 +677,7 @@ export class PivotTableEngine {
|
|
|
688
677
|
dataFields.forEach(field => {
|
|
689
678
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
690
679
|
const value = parseValue(dataRow[headerIndex]);
|
|
691
|
-
|
|
692
|
-
if (value && !isNaN(value)) {
|
|
693
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
694
|
-
}
|
|
680
|
+
percentageTotal[field] = addToTotalIfNumber(value, percentageTotal[field]);
|
|
695
681
|
});
|
|
696
682
|
|
|
697
683
|
if (totals.rowSubtotal) {
|
|
@@ -706,10 +692,7 @@ export class PivotTableEngine {
|
|
|
706
692
|
dataFields.forEach(field => {
|
|
707
693
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
708
694
|
const value = parseValue(dataRow[headerIndex]);
|
|
709
|
-
|
|
710
|
-
if (value && !isNaN(value)) {
|
|
711
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
712
|
-
}
|
|
695
|
+
percentageTotal[field] = addToTotalIfNumber(value, percentageTotal[field]);
|
|
713
696
|
});
|
|
714
697
|
}
|
|
715
698
|
|
|
@@ -725,10 +708,7 @@ export class PivotTableEngine {
|
|
|
725
708
|
dataFields.forEach(field => {
|
|
726
709
|
const headerIndex = this.dimensionLookup.dataHeaders[field];
|
|
727
710
|
const value = parseValue(dataRow[headerIndex]);
|
|
728
|
-
|
|
729
|
-
if (value && !isNaN(value)) {
|
|
730
|
-
percentageTotal[field] = (percentageTotal[field] || 0) + value;
|
|
731
|
-
}
|
|
711
|
+
percentageTotal[field] = addToTotalIfNumber(value, percentageTotal[field]);
|
|
732
712
|
});
|
|
733
713
|
}
|
|
734
714
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { addToTotalIfNumber } from '../addToTotalIfNumber.js';
|
|
2
|
+
const tests = [{
|
|
3
|
+
testName: 'negative value',
|
|
4
|
+
value: -1,
|
|
5
|
+
total: undefined,
|
|
6
|
+
expected: -1
|
|
7
|
+
}, {
|
|
8
|
+
testName: 'zero value',
|
|
9
|
+
value: 0,
|
|
10
|
+
total: undefined,
|
|
11
|
+
expected: 0
|
|
12
|
+
}, {
|
|
13
|
+
testName: 'positive value',
|
|
14
|
+
value: 1,
|
|
15
|
+
total: undefined,
|
|
16
|
+
expected: 1
|
|
17
|
+
}, {
|
|
18
|
+
testName: 'null value',
|
|
19
|
+
value: null,
|
|
20
|
+
total: undefined,
|
|
21
|
+
expected: undefined
|
|
22
|
+
}, {
|
|
23
|
+
testName: 'undefined value',
|
|
24
|
+
value: undefined,
|
|
25
|
+
total: undefined,
|
|
26
|
+
expected: undefined
|
|
27
|
+
}, {
|
|
28
|
+
testName: 'string value',
|
|
29
|
+
value: 'string',
|
|
30
|
+
total: undefined,
|
|
31
|
+
expected: undefined
|
|
32
|
+
}, {
|
|
33
|
+
testName: 'negative value with existing total',
|
|
34
|
+
value: -1,
|
|
35
|
+
total: 100,
|
|
36
|
+
expected: 99
|
|
37
|
+
}, {
|
|
38
|
+
testName: 'zero value with existing total',
|
|
39
|
+
value: 0,
|
|
40
|
+
total: 100,
|
|
41
|
+
expected: 100
|
|
42
|
+
}, {
|
|
43
|
+
testName: 'positive value with existing total',
|
|
44
|
+
value: 1,
|
|
45
|
+
total: 100,
|
|
46
|
+
expected: 101
|
|
47
|
+
}, {
|
|
48
|
+
testName: 'null value with existing total',
|
|
49
|
+
value: null,
|
|
50
|
+
total: 100,
|
|
51
|
+
expected: 100
|
|
52
|
+
}, {
|
|
53
|
+
testName: 'undefined value with existing total',
|
|
54
|
+
value: undefined,
|
|
55
|
+
total: 100,
|
|
56
|
+
expected: 100
|
|
57
|
+
}, {
|
|
58
|
+
testName: 'string value with existing total',
|
|
59
|
+
value: 'string',
|
|
60
|
+
total: 100,
|
|
61
|
+
expected: 100
|
|
62
|
+
}];
|
|
63
|
+
describe('addToTotalIfNumber', () => {
|
|
64
|
+
tests.forEach(t => {
|
|
65
|
+
it(t.testName, () => {
|
|
66
|
+
expect(addToTotalIfNumber(t.value, t.total)).toEqual(t.expected);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const addToTotalIfNumber = (value, total) => typeof value === 'number' && Number.isFinite(value) ? (total !== null && total !== void 0 ? total : 0) + value : total;
|