@dhis2/analytics 24.10.2 → 24.10.4

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 CHANGED
@@ -1,3 +1,17 @@
1
+ ## [24.10.4](https://github.com/dhis2/analytics/compare/v24.10.3...v24.10.4) (2024-04-02)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * interpretations panel renders with flashing when liking or unliking an interpretation ([#1643](https://github.com/dhis2/analytics/issues/1643)) ([4148bf9](https://github.com/dhis2/analytics/commit/4148bf9ae1c8aa386abd7b2b7ad2c01636d8b06d)), closes [#1600](https://github.com/dhis2/analytics/issues/1600)
7
+
8
+ ## [24.10.3](https://github.com/dhis2/analytics/compare/v24.10.2...v24.10.3) (2024-03-20)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * 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))
14
+
1
15
  ## [24.10.2](https://github.com/dhis2/analytics/compare/v24.10.1...v24.10.2) (2023-10-25)
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, {
@@ -90,7 +90,7 @@ const InterpretationModal = _ref2 => {
90
90
  });
91
91
  const interpretation = data === null || data === void 0 ? void 0 : data.interpretation;
92
92
  const shouldRenderModalContent = !error && interpretation;
93
- const shouldCssHideModal = loading || isVisualizationLoading;
93
+ const loadingInProgress = loading || isVisualizationLoading;
94
94
 
95
95
  const handleClose = () => {
96
96
  if (isDirty) {
@@ -111,6 +111,15 @@ const InterpretationModal = _ref2 => {
111
111
  });
112
112
  };
113
113
 
114
+ const onLikeToggled = _ref3 => {
115
+ let {
116
+ likedBy
117
+ } = _ref3;
118
+ setIsDirty(true);
119
+ interpretation.likedBy = likedBy;
120
+ interpretation.likes = likedBy.length;
121
+ };
122
+
114
123
  const onInterpretationDeleted = () => {
115
124
  setIsDirty(false);
116
125
  onInterpretationUpdate();
@@ -124,11 +133,11 @@ const InterpretationModal = _ref2 => {
124
133
  });
125
134
  }
126
135
  }, [interpretationId, refetch]);
127
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, shouldCssHideModal && /*#__PURE__*/_react.default.createElement(_ui.Layer, null, /*#__PURE__*/_react.default.createElement(_ui.CenteredContent, null, /*#__PURE__*/_react.default.createElement(_ui.CircularLoader, null))), /*#__PURE__*/_react.default.createElement(_ui.Modal, {
136
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, loadingInProgress && /*#__PURE__*/_react.default.createElement(_ui.Layer, null, /*#__PURE__*/_react.default.createElement(_ui.CenteredContent, null, /*#__PURE__*/_react.default.createElement(_ui.CircularLoader, null))), /*#__PURE__*/_react.default.createElement(_ui.Modal, {
128
137
  fluid: true,
129
138
  onClose: handleClose,
130
139
  className: (0, _classnames.default)(modalCSS.className, {
131
- hidden: shouldCssHideModal
140
+ hidden: loadingInProgress
132
141
  }),
133
142
  dataTest: "interpretation-modal"
134
143
  }, /*#__PURE__*/_react.default.createElement("h1", {
@@ -166,7 +175,8 @@ const InterpretationModal = _ref2 => {
166
175
  onInterpretationDeleted: onInterpretationDeleted,
167
176
  onThreadUpdated: onThreadUpdated,
168
177
  initialFocus: initialFocus,
169
- downloadMenuComponent: downloadMenuComponent
178
+ downloadMenuComponent: downloadMenuComponent,
179
+ onLikeToggled: onLikeToggled
170
180
  }))))), /*#__PURE__*/_react.default.createElement(_ui.ModalActions, null, /*#__PURE__*/_react.default.createElement(_ui.Button, {
171
181
  disabled: fetching,
172
182
  onClick: handleClose
@@ -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"));
@@ -35,10 +37,14 @@ const InterpretationThread = _ref => {
35
37
  fetching,
36
38
  interpretation,
37
39
  onInterpretationDeleted,
40
+ onLikeToggled,
38
41
  initialFocus,
39
42
  onThreadUpdated,
40
43
  downloadMenuComponent: DownloadMenu
41
44
  } = _ref;
45
+ const {
46
+ fromServerDate
47
+ } = (0, _appRuntime.useTimeZoneConversion)();
42
48
  const focusRef = (0, _react.useRef)();
43
49
  (0, _react.useEffect)(() => {
44
50
  if (initialFocus && focusRef.current) {
@@ -57,7 +63,7 @@ const InterpretationThread = _ref => {
57
63
  className: "jsx-615306698" + " " + 'title'
58
64
  }, /*#__PURE__*/_react.default.createElement(_ui.IconClock16, {
59
65
  color: _ui.colors.grey700
60
- }), (0, _moment.default)(interpretation.created).format('LLL')), DownloadMenu && /*#__PURE__*/_react.default.createElement(DownloadMenu, {
66
+ }), (0, _moment.default)(fromServerDate(interpretation.created)).format('LLL')), DownloadMenu && /*#__PURE__*/_react.default.createElement(DownloadMenu, {
61
67
  relativePeriodDate: interpretation.created,
62
68
  className: "jsx-615306698"
63
69
  }), /*#__PURE__*/_react.default.createElement("div", {
@@ -71,7 +77,8 @@ const InterpretationThread = _ref => {
71
77
  return (_focusRef$current = focusRef.current) === null || _focusRef$current === void 0 ? void 0 : _focusRef$current.focus();
72
78
  },
73
79
  onUpdated: () => onThreadUpdated(true),
74
- onDeleted: onInterpretationDeleted
80
+ onDeleted: onInterpretationDeleted,
81
+ onLikeToggled: onLikeToggled
75
82
  }), /*#__PURE__*/_react.default.createElement("div", {
76
83
  className: "jsx-615306698" + " " + 'comments'
77
84
  }, interpretation.comments.map(comment => /*#__PURE__*/_react.default.createElement(_Comment.Comment, {
@@ -96,6 +103,7 @@ InterpretationThread.propTypes = {
96
103
  fetching: _propTypes.default.bool.isRequired,
97
104
  interpretation: _propTypes.default.object.isRequired,
98
105
  onInterpretationDeleted: _propTypes.default.func.isRequired,
106
+ onLikeToggled: _propTypes.default.func.isRequired,
99
107
  downloadMenuComponent: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.func]),
100
108
  initialFocus: _propTypes.default.bool,
101
109
  onThreadUpdated: _propTypes.default.func
@@ -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"));
@@ -39,10 +41,14 @@ const InterpretationList = _ref => {
39
41
  currentUser,
40
42
  interpretations,
41
43
  onInterpretationClick,
44
+ onLikeToggled,
42
45
  onReplyIconClick,
43
46
  refresh,
44
47
  disabled
45
48
  } = _ref;
49
+ const {
50
+ fromServerDate
51
+ } = (0, _appRuntime.useTimeZoneConversion)();
46
52
  const interpretationsByDate = interpretations.reduce((groupedInterpretations, interpretation) => {
47
53
  const date = interpretation.created.split('T')[0];
48
54
 
@@ -67,13 +73,14 @@ const InterpretationList = _ref => {
67
73
  }), /*#__PURE__*/_react.default.createElement("time", {
68
74
  dateTime: date,
69
75
  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", {
76
+ }, (0, _moment.default)(fromServerDate(date)).format('ll'))), /*#__PURE__*/_react.default.createElement("ol", {
71
77
  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
78
  }, interpretationsByDate[date].sort(sortByCreatedDateDesc).map(interpretation => /*#__PURE__*/_react.default.createElement(_index.Interpretation, {
73
79
  key: interpretation.id,
74
80
  interpretation: interpretation,
75
81
  currentUser: currentUser,
76
82
  onClick: onInterpretationClick,
83
+ onLikeToggled: onLikeToggled,
77
84
  onReplyIconClick: onReplyIconClick,
78
85
  onDeleted: refresh,
79
86
  onUpdated: refresh,
@@ -90,6 +97,7 @@ InterpretationList.propTypes = {
90
97
  interpretations: _propTypes.default.array.isRequired,
91
98
  refresh: _propTypes.default.func.isRequired,
92
99
  onInterpretationClick: _propTypes.default.func.isRequired,
100
+ onLikeToggled: _propTypes.default.func.isRequired,
93
101
  onReplyIconClick: _propTypes.default.func.isRequired,
94
102
  disabled: _propTypes.default.bool
95
103
  };
@@ -55,13 +55,14 @@ const InterpretationsUnit = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) =>
55
55
  renderId
56
56
  } = _ref2;
57
57
  const [isExpanded, setIsExpanded] = (0, _react.useState)(true);
58
+ const [interpretations, setInterpretations] = (0, _react.useState)([]);
58
59
  const {
59
- data,
60
60
  loading,
61
61
  fetching,
62
62
  refetch
63
63
  } = (0, _appRuntime.useDataQuery)(interpretationsQuery, {
64
- lazy: true
64
+ lazy: true,
65
+ onComplete: data => setInterpretations(data.interpretations.interpretations)
65
66
  });
66
67
  const onCompleteAction = (0, _react.useCallback)(() => {
67
68
  refetch({
@@ -80,6 +81,17 @@ const InterpretationsUnit = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) =>
80
81
  });
81
82
  }
82
83
  }, [type, id, renderId, refetch]);
84
+
85
+ const onLikeToggled = _ref3 => {
86
+ let {
87
+ id,
88
+ likedBy
89
+ } = _ref3;
90
+ const interpretation = interpretations.find(interp => interp.id === id);
91
+ interpretation.likedBy = likedBy;
92
+ interpretation.likes = likedBy.length;
93
+ };
94
+
83
95
  return /*#__PURE__*/_react.default.createElement("div", {
84
96
  className: _style.default.dynamic([["4120713286", [_ui.spacers.dp16, _ui.colors.grey400, _ui.colors.white, _ui.spacers.dp32, _ui.colors.grey900]]]) + " " + ((0, _classnames.default)('container', {
85
97
  expanded: isExpanded
@@ -101,7 +113,7 @@ const InterpretationsUnit = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) =>
101
113
  className: _style.default.dynamic([["4120713286", [_ui.spacers.dp16, _ui.colors.grey400, _ui.colors.white, _ui.spacers.dp32, _ui.colors.grey900]]]) + " " + "loader"
102
114
  }, /*#__PURE__*/_react.default.createElement(_ui.CircularLoader, {
103
115
  small: true
104
- })), data && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_InterpretationForm.InterpretationForm, {
116
+ })), interpretations && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_InterpretationForm.InterpretationForm, {
105
117
  currentUser: currentUser,
106
118
  type: type,
107
119
  id: id,
@@ -109,8 +121,9 @@ const InterpretationsUnit = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) =>
109
121
  disabled: disabled
110
122
  }), /*#__PURE__*/_react.default.createElement(_InterpretationList.InterpretationList, {
111
123
  currentUser: currentUser,
112
- interpretations: data.interpretations.interpretations,
124
+ interpretations: interpretations,
113
125
  onInterpretationClick: onInterpretationClick,
126
+ onLikeToggled: onLikeToggled,
114
127
  onReplyIconClick: onReplyIconClick,
115
128
  refresh: onCompleteAction,
116
129
  disabled: disabled
@@ -35,7 +35,8 @@ const Interpretation = _ref => {
35
35
  onUpdated,
36
36
  onDeleted,
37
37
  disabled,
38
- onReplyIconClick
38
+ onReplyIconClick,
39
+ onLikeToggled
39
40
  } = _ref;
40
41
  const [isUpdateMode, setIsUpdateMode] = (0, _react.useState)(false);
41
42
  const [showSharingDialog, setShowSharingDialog] = (0, _react.useState)(false);
@@ -46,7 +47,10 @@ const Interpretation = _ref => {
46
47
  } = (0, _useLike.useLike)({
47
48
  interpretation,
48
49
  currentUser,
49
- onComplete: onUpdated
50
+ onComplete: likedBy => onLikeToggled({
51
+ id: interpretation.id,
52
+ likedBy
53
+ })
50
54
  });
51
55
  const shouldShowButton = !!onClick && !disabled;
52
56
  return isUpdateMode ? /*#__PURE__*/_react.default.createElement(_InterpretationUpdateForm.InterpretationUpdateForm, {
@@ -107,6 +111,7 @@ Interpretation.propTypes = {
107
111
  currentUser: _propTypes.default.object.isRequired,
108
112
  interpretation: _propTypes.default.object.isRequired,
109
113
  onDeleted: _propTypes.default.func.isRequired,
114
+ onLikeToggled: _propTypes.default.func.isRequired,
110
115
  onReplyIconClick: _propTypes.default.func.isRequired,
111
116
  onUpdated: _propTypes.default.func.isRequired,
112
117
  disabled: _propTypes.default.bool,
@@ -27,12 +27,22 @@ const useLike = _ref => {
27
27
  const [like, {
28
28
  loading: likeLoading
29
29
  }] = (0, _appRuntime.useDataMutation)(likeMutationRef.current, {
30
- onComplete
30
+ onComplete: () => {
31
+ const newLikedBy = interpretation.likedBy.concat({
32
+ id: currentUser.id
33
+ });
34
+ setIsLikedByCurrentUser(true);
35
+ onComplete(newLikedBy);
36
+ }
31
37
  });
32
38
  const [unlike, {
33
39
  loading: unlikeLoading
34
40
  }] = (0, _appRuntime.useDataMutation)(unlikeMutationRef.current, {
35
- onComplete
41
+ onComplete: () => {
42
+ const newLikedBy = interpretation.likedBy.filter(lb => lb.id !== currentUser.id);
43
+ setIsLikedByCurrentUser(false);
44
+ onComplete(newLikedBy);
45
+ }
36
46
  });
37
47
  const [isLikedByCurrentUser, setIsLikedByCurrentUser] = (0, _react.useState)(false);
38
48
 
@@ -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([["2436588813", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]]) + " " + "container"
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([["2436588813", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]]) + " " + "header"
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([["2436588813", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]])
39
- }, (0, _moment.default)(created).format('lll'))), /*#__PURE__*/_react.default.createElement("div", {
40
- className: _style.default.dynamic([["2436588813", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]]) + " " + "content"
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([["2436588813", [_ui.spacers.dp8, _ui.colors.grey100, _ui.spacers.dp8, _ui.colors.grey900, _ui.colors.grey600, _ui.colors.grey900, _ui.spacers.dp8]]]) + " " + "footer"
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: "2436588813",
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;
@@ -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, {
@@ -68,7 +68,7 @@ const InterpretationModal = _ref2 => {
68
68
  });
69
69
  const interpretation = data === null || data === void 0 ? void 0 : data.interpretation;
70
70
  const shouldRenderModalContent = !error && interpretation;
71
- const shouldCssHideModal = loading || isVisualizationLoading;
71
+ const loadingInProgress = loading || isVisualizationLoading;
72
72
 
73
73
  const handleClose = () => {
74
74
  if (isDirty) {
@@ -89,6 +89,15 @@ const InterpretationModal = _ref2 => {
89
89
  });
90
90
  };
91
91
 
92
+ const onLikeToggled = _ref3 => {
93
+ let {
94
+ likedBy
95
+ } = _ref3;
96
+ setIsDirty(true);
97
+ interpretation.likedBy = likedBy;
98
+ interpretation.likes = likedBy.length;
99
+ };
100
+
92
101
  const onInterpretationDeleted = () => {
93
102
  setIsDirty(false);
94
103
  onInterpretationUpdate();
@@ -102,11 +111,11 @@ const InterpretationModal = _ref2 => {
102
111
  });
103
112
  }
104
113
  }, [interpretationId, refetch]);
105
- return /*#__PURE__*/React.createElement(React.Fragment, null, shouldCssHideModal && /*#__PURE__*/React.createElement(Layer, null, /*#__PURE__*/React.createElement(CenteredContent, null, /*#__PURE__*/React.createElement(CircularLoader, null))), /*#__PURE__*/React.createElement(Modal, {
114
+ return /*#__PURE__*/React.createElement(React.Fragment, null, loadingInProgress && /*#__PURE__*/React.createElement(Layer, null, /*#__PURE__*/React.createElement(CenteredContent, null, /*#__PURE__*/React.createElement(CircularLoader, null))), /*#__PURE__*/React.createElement(Modal, {
106
115
  fluid: true,
107
116
  onClose: handleClose,
108
117
  className: cx(modalCSS.className, {
109
- hidden: shouldCssHideModal
118
+ hidden: loadingInProgress
110
119
  }),
111
120
  dataTest: "interpretation-modal"
112
121
  }, /*#__PURE__*/React.createElement("h1", {
@@ -144,7 +153,8 @@ const InterpretationModal = _ref2 => {
144
153
  onInterpretationDeleted: onInterpretationDeleted,
145
154
  onThreadUpdated: onThreadUpdated,
146
155
  initialFocus: initialFocus,
147
- downloadMenuComponent: downloadMenuComponent
156
+ downloadMenuComponent: downloadMenuComponent,
157
+ onLikeToggled: onLikeToggled
148
158
  }))))), /*#__PURE__*/React.createElement(ModalActions, null, /*#__PURE__*/React.createElement(Button, {
149
159
  disabled: fetching,
150
160
  onClick: handleClose
@@ -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';
@@ -14,10 +15,14 @@ const InterpretationThread = _ref => {
14
15
  fetching,
15
16
  interpretation,
16
17
  onInterpretationDeleted,
18
+ onLikeToggled,
17
19
  initialFocus,
18
20
  onThreadUpdated,
19
21
  downloadMenuComponent: DownloadMenu
20
22
  } = _ref;
23
+ const {
24
+ fromServerDate
25
+ } = useTimeZoneConversion();
21
26
  const focusRef = useRef();
22
27
  useEffect(() => {
23
28
  if (initialFocus && focusRef.current) {
@@ -36,7 +41,7 @@ const InterpretationThread = _ref => {
36
41
  className: "jsx-615306698" + " " + 'title'
37
42
  }, /*#__PURE__*/React.createElement(IconClock16, {
38
43
  color: colors.grey700
39
- }), moment(interpretation.created).format('LLL')), DownloadMenu && /*#__PURE__*/React.createElement(DownloadMenu, {
44
+ }), moment(fromServerDate(interpretation.created)).format('LLL')), DownloadMenu && /*#__PURE__*/React.createElement(DownloadMenu, {
40
45
  relativePeriodDate: interpretation.created,
41
46
  className: "jsx-615306698"
42
47
  }), /*#__PURE__*/React.createElement("div", {
@@ -50,7 +55,8 @@ const InterpretationThread = _ref => {
50
55
  return (_focusRef$current = focusRef.current) === null || _focusRef$current === void 0 ? void 0 : _focusRef$current.focus();
51
56
  },
52
57
  onUpdated: () => onThreadUpdated(true),
53
- onDeleted: onInterpretationDeleted
58
+ onDeleted: onInterpretationDeleted,
59
+ onLikeToggled: onLikeToggled
54
60
  }), /*#__PURE__*/React.createElement("div", {
55
61
  className: "jsx-615306698" + " " + 'comments'
56
62
  }, interpretation.comments.map(comment => /*#__PURE__*/React.createElement(Comment, {
@@ -74,6 +80,7 @@ InterpretationThread.propTypes = {
74
80
  fetching: PropTypes.bool.isRequired,
75
81
  interpretation: PropTypes.object.isRequired,
76
82
  onInterpretationDeleted: PropTypes.func.isRequired,
83
+ onLikeToggled: PropTypes.func.isRequired,
77
84
  downloadMenuComponent: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
78
85
  initialFocus: PropTypes.bool,
79
86
  onThreadUpdated: PropTypes.func
@@ -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';
@@ -25,10 +26,14 @@ export const InterpretationList = _ref => {
25
26
  currentUser,
26
27
  interpretations,
27
28
  onInterpretationClick,
29
+ onLikeToggled,
28
30
  onReplyIconClick,
29
31
  refresh,
30
32
  disabled
31
33
  } = _ref;
34
+ const {
35
+ fromServerDate
36
+ } = useTimeZoneConversion();
32
37
  const interpretationsByDate = interpretations.reduce((groupedInterpretations, interpretation) => {
33
38
  const date = interpretation.created.split('T')[0];
34
39
 
@@ -53,13 +58,14 @@ export const InterpretationList = _ref => {
53
58
  }), /*#__PURE__*/React.createElement("time", {
54
59
  dateTime: date,
55
60
  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", {
61
+ }, moment(fromServerDate(date)).format('ll'))), /*#__PURE__*/React.createElement("ol", {
57
62
  className: _JSXStyle.dynamic([["4058400613", [spacers.dp8, spacers.dp8, spacers.dp16, colors.grey800, spacers.dp12, spacers.dp12, spacers.dp32, spacers.dp4]]]) + " " + "interpretation-list"
58
63
  }, interpretationsByDate[date].sort(sortByCreatedDateDesc).map(interpretation => /*#__PURE__*/React.createElement(Interpretation, {
59
64
  key: interpretation.id,
60
65
  interpretation: interpretation,
61
66
  currentUser: currentUser,
62
67
  onClick: onInterpretationClick,
68
+ onLikeToggled: onLikeToggled,
63
69
  onReplyIconClick: onReplyIconClick,
64
70
  onDeleted: refresh,
65
71
  onUpdated: refresh,
@@ -74,6 +80,7 @@ InterpretationList.propTypes = {
74
80
  interpretations: PropTypes.array.isRequired,
75
81
  refresh: PropTypes.func.isRequired,
76
82
  onInterpretationClick: PropTypes.func.isRequired,
83
+ onLikeToggled: PropTypes.func.isRequired,
77
84
  onReplyIconClick: PropTypes.func.isRequired,
78
85
  disabled: PropTypes.bool
79
86
  };
@@ -33,13 +33,14 @@ export const InterpretationsUnit = /*#__PURE__*/forwardRef((_ref2, ref) => {
33
33
  renderId
34
34
  } = _ref2;
35
35
  const [isExpanded, setIsExpanded] = useState(true);
36
+ const [interpretations, setInterpretations] = useState([]);
36
37
  const {
37
- data,
38
38
  loading,
39
39
  fetching,
40
40
  refetch
41
41
  } = useDataQuery(interpretationsQuery, {
42
- lazy: true
42
+ lazy: true,
43
+ onComplete: data => setInterpretations(data.interpretations.interpretations)
43
44
  });
44
45
  const onCompleteAction = useCallback(() => {
45
46
  refetch({
@@ -58,6 +59,17 @@ export const InterpretationsUnit = /*#__PURE__*/forwardRef((_ref2, ref) => {
58
59
  });
59
60
  }
60
61
  }, [type, id, renderId, refetch]);
62
+
63
+ const onLikeToggled = _ref3 => {
64
+ let {
65
+ id,
66
+ likedBy
67
+ } = _ref3;
68
+ const interpretation = interpretations.find(interp => interp.id === id);
69
+ interpretation.likedBy = likedBy;
70
+ interpretation.likes = likedBy.length;
71
+ };
72
+
61
73
  return /*#__PURE__*/React.createElement("div", {
62
74
  className: _JSXStyle.dynamic([["4120713286", [spacers.dp16, colors.grey400, colors.white, spacers.dp32, colors.grey900]]]) + " " + (cx('container', {
63
75
  expanded: isExpanded
@@ -79,7 +91,7 @@ export const InterpretationsUnit = /*#__PURE__*/forwardRef((_ref2, ref) => {
79
91
  className: _JSXStyle.dynamic([["4120713286", [spacers.dp16, colors.grey400, colors.white, spacers.dp32, colors.grey900]]]) + " " + "loader"
80
92
  }, /*#__PURE__*/React.createElement(CircularLoader, {
81
93
  small: true
82
- })), data && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(InterpretationForm, {
94
+ })), interpretations && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(InterpretationForm, {
83
95
  currentUser: currentUser,
84
96
  type: type,
85
97
  id: id,
@@ -87,8 +99,9 @@ export const InterpretationsUnit = /*#__PURE__*/forwardRef((_ref2, ref) => {
87
99
  disabled: disabled
88
100
  }), /*#__PURE__*/React.createElement(InterpretationList, {
89
101
  currentUser: currentUser,
90
- interpretations: data.interpretations.interpretations,
102
+ interpretations: interpretations,
91
103
  onInterpretationClick: onInterpretationClick,
104
+ onLikeToggled: onLikeToggled,
92
105
  onReplyIconClick: onReplyIconClick,
93
106
  refresh: onCompleteAction,
94
107
  disabled: disabled
@@ -14,7 +14,8 @@ export const Interpretation = _ref => {
14
14
  onUpdated,
15
15
  onDeleted,
16
16
  disabled,
17
- onReplyIconClick
17
+ onReplyIconClick,
18
+ onLikeToggled
18
19
  } = _ref;
19
20
  const [isUpdateMode, setIsUpdateMode] = useState(false);
20
21
  const [showSharingDialog, setShowSharingDialog] = useState(false);
@@ -25,7 +26,10 @@ export const Interpretation = _ref => {
25
26
  } = useLike({
26
27
  interpretation,
27
28
  currentUser,
28
- onComplete: onUpdated
29
+ onComplete: likedBy => onLikeToggled({
30
+ id: interpretation.id,
31
+ likedBy
32
+ })
29
33
  });
30
34
  const shouldShowButton = !!onClick && !disabled;
31
35
  return isUpdateMode ? /*#__PURE__*/React.createElement(InterpretationUpdateForm, {
@@ -84,6 +88,7 @@ Interpretation.propTypes = {
84
88
  currentUser: PropTypes.object.isRequired,
85
89
  interpretation: PropTypes.object.isRequired,
86
90
  onDeleted: PropTypes.func.isRequired,
91
+ onLikeToggled: PropTypes.func.isRequired,
87
92
  onReplyIconClick: PropTypes.func.isRequired,
88
93
  onUpdated: PropTypes.func.isRequired,
89
94
  disabled: PropTypes.bool,
@@ -19,12 +19,22 @@ const useLike = _ref => {
19
19
  const [like, {
20
20
  loading: likeLoading
21
21
  }] = useDataMutation(likeMutationRef.current, {
22
- onComplete
22
+ onComplete: () => {
23
+ const newLikedBy = interpretation.likedBy.concat({
24
+ id: currentUser.id
25
+ });
26
+ setIsLikedByCurrentUser(true);
27
+ onComplete(newLikedBy);
28
+ }
23
29
  });
24
30
  const [unlike, {
25
31
  loading: unlikeLoading
26
32
  }] = useDataMutation(unlikeMutationRef.current, {
27
- onComplete
33
+ onComplete: () => {
34
+ const newLikedBy = interpretation.likedBy.filter(lb => lb.id !== currentUser.id);
35
+ setIsLikedByCurrentUser(false);
36
+ onComplete(newLikedBy);
37
+ }
28
38
  });
29
39
  const [isLikedByCurrentUser, setIsLikedByCurrentUser] = useState(false);
30
40
 
@@ -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([["2436588813", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]]) + " " + "container"
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([["2436588813", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]]) + " " + "header"
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([["2436588813", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]])
25
- }, moment(created).format('lll'))), /*#__PURE__*/React.createElement("div", {
26
- className: _JSXStyle.dynamic([["2436588813", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]]) + " " + "content"
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([["2436588813", [spacers.dp8, colors.grey100, spacers.dp8, colors.grey900, colors.grey600, colors.grey900, spacers.dp8]]]) + " " + "footer"
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: "2436588813",
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 = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2/analytics",
3
- "version": "24.10.2",
3
+ "version": "24.10.4",
4
4
  "main": "./build/cjs/index.js",
5
5
  "module": "./build/es/index.js",
6
6
  "exports": {