@dhis2/analytics 26.0.11 → 26.0.13

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 (57) hide show
  1. package/build/cjs/components/Interpretations/InterpretationModal/Comment.js +7 -4
  2. package/build/cjs/components/Interpretations/InterpretationModal/CommentDeleteButton.js +24 -5
  3. package/build/cjs/components/Interpretations/InterpretationModal/CommentUpdateForm.js +1 -1
  4. package/build/cjs/components/Interpretations/InterpretationModal/InterpretationModal.js +1 -1
  5. package/build/cjs/components/Interpretations/InterpretationModal/InterpretationThread.js +8 -5
  6. package/build/cjs/components/Interpretations/InterpretationsUnit/InterpretationsUnit.js +1 -1
  7. package/build/cjs/components/Interpretations/common/Interpretation/Interpretation.js +26 -10
  8. package/build/cjs/components/Interpretations/common/Message/MessageIconButton.js +9 -6
  9. package/build/cjs/components/Interpretations/common/__tests__/getInterpretationAccess.spec.js +152 -0
  10. package/build/cjs/components/Interpretations/common/getInterpretationAccess.js +25 -0
  11. package/build/cjs/components/Interpretations/common/index.js +11 -0
  12. package/build/cjs/locales/ar/translations.json +10 -1
  13. package/build/cjs/locales/cs/translations.json +8 -1
  14. package/build/cjs/locales/en/translations.json +5 -1
  15. package/build/cjs/locales/es/translations.json +5 -1
  16. package/build/cjs/locales/fr/translations.json +6 -1
  17. package/build/cjs/locales/id/translations.json +5 -1
  18. package/build/cjs/locales/nb/translations.json +6 -1
  19. package/build/cjs/locales/nl/translations.json +5 -1
  20. package/build/cjs/locales/pt/translations.json +5 -1
  21. package/build/cjs/locales/ru/translations.json +8 -1
  22. package/build/cjs/locales/uk/translations.json +8 -1
  23. package/build/cjs/locales/ur/translations.json +6 -1
  24. package/build/cjs/locales/uz/translations.json +5 -1
  25. package/build/cjs/locales/uz_Latn/translations.json +5 -1
  26. package/build/cjs/locales/vi/translations.json +5 -1
  27. package/build/cjs/locales/zh/translations.json +4 -1
  28. package/build/cjs/locales/zh_CN/translations.json +5 -1
  29. package/build/es/components/Interpretations/InterpretationModal/Comment.js +8 -5
  30. package/build/es/components/Interpretations/InterpretationModal/CommentDeleteButton.js +23 -6
  31. package/build/es/components/Interpretations/InterpretationModal/CommentUpdateForm.js +1 -1
  32. package/build/es/components/Interpretations/InterpretationModal/InterpretationModal.js +1 -1
  33. package/build/es/components/Interpretations/InterpretationModal/InterpretationThread.js +9 -6
  34. package/build/es/components/Interpretations/InterpretationsUnit/InterpretationsUnit.js +1 -1
  35. package/build/es/components/Interpretations/common/Interpretation/Interpretation.js +27 -11
  36. package/build/es/components/Interpretations/common/Message/MessageIconButton.js +9 -6
  37. package/build/es/components/Interpretations/common/__tests__/getInterpretationAccess.spec.js +150 -0
  38. package/build/es/components/Interpretations/common/getInterpretationAccess.js +17 -0
  39. package/build/es/components/Interpretations/common/index.js +2 -1
  40. package/build/es/locales/ar/translations.json +10 -1
  41. package/build/es/locales/cs/translations.json +8 -1
  42. package/build/es/locales/en/translations.json +5 -1
  43. package/build/es/locales/es/translations.json +5 -1
  44. package/build/es/locales/fr/translations.json +6 -1
  45. package/build/es/locales/id/translations.json +5 -1
  46. package/build/es/locales/nb/translations.json +6 -1
  47. package/build/es/locales/nl/translations.json +5 -1
  48. package/build/es/locales/pt/translations.json +5 -1
  49. package/build/es/locales/ru/translations.json +8 -1
  50. package/build/es/locales/uk/translations.json +8 -1
  51. package/build/es/locales/ur/translations.json +6 -1
  52. package/build/es/locales/uz/translations.json +5 -1
  53. package/build/es/locales/uz_Latn/translations.json +5 -1
  54. package/build/es/locales/vi/translations.json +5 -1
  55. package/build/es/locales/zh/translations.json +4 -1
  56. package/build/es/locales/zh_CN/translations.json +5 -1
  57. package/package.json +1 -1
@@ -19,9 +19,11 @@ const Comment = _ref => {
19
19
  comment,
20
20
  currentUser,
21
21
  interpretationId,
22
- onThreadUpdated
22
+ onThreadUpdated,
23
+ canComment
23
24
  } = _ref;
24
25
  const [isUpdateMode, setIsUpdateMode] = (0, _react.useState)(false);
26
+ const commentAccess = (0, _index.getCommentAccess)(comment, canComment, currentUser);
25
27
  return isUpdateMode ? /*#__PURE__*/_react.default.createElement(_CommentUpdateForm.CommentUpdateForm, {
26
28
  close: () => setIsUpdateMode(false),
27
29
  commentId: comment.id,
@@ -33,11 +35,11 @@ const Comment = _ref => {
33
35
  text: comment.text,
34
36
  created: comment.created,
35
37
  username: comment.createdBy.displayName
36
- }, /*#__PURE__*/_react.default.createElement(_index.MessageStatsBar, null, comment.access.update && /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
38
+ }, commentAccess.edit && /*#__PURE__*/_react.default.createElement(_index.MessageStatsBar, null, /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
37
39
  iconComponent: _ui.IconEdit16,
38
40
  tooltipContent: _d2I18n.default.t('Edit'),
39
41
  onClick: () => setIsUpdateMode(true)
40
- }), comment.access.delete && /*#__PURE__*/_react.default.createElement(_CommentDeleteButton.CommentDeleteButton, {
42
+ }), commentAccess.delete && /*#__PURE__*/_react.default.createElement(_CommentDeleteButton.CommentDeleteButton, {
41
43
  commentId: comment.id,
42
44
  interpretationId: interpretationId,
43
45
  onComplete: () => onThreadUpdated(true)
@@ -48,5 +50,6 @@ Comment.propTypes = {
48
50
  comment: _propTypes.default.object.isRequired,
49
51
  currentUser: _propTypes.default.object.isRequired,
50
52
  interpretationId: _propTypes.default.string.isRequired,
51
- onThreadUpdated: _propTypes.default.func.isRequired
53
+ onThreadUpdated: _propTypes.default.func.isRequired,
54
+ canComment: _propTypes.default.bool
52
55
  };
@@ -4,12 +4,15 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.CommentDeleteButton = void 0;
7
+ var _style = _interopRequireDefault(require("styled-jsx/style"));
7
8
  var _appRuntime = require("@dhis2/app-runtime");
8
9
  var _d2I18n = _interopRequireDefault(require("@dhis2/d2-i18n"));
9
10
  var _ui = require("@dhis2/ui");
10
11
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
- var _react = _interopRequireDefault(require("react"));
12
+ var _react = _interopRequireWildcard(require("react"));
12
13
  var _index = require("../common/index.js");
14
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
13
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
17
  const mutation = {
15
18
  resource: 'interpretations',
@@ -28,21 +31,37 @@ const CommentDeleteButton = _ref2 => {
28
31
  interpretationId,
29
32
  onComplete
30
33
  } = _ref2;
34
+ const [deleteError, setDeleteError] = (0, _react.useState)(null);
31
35
  const [remove, {
32
36
  loading
33
37
  }] = (0, _appRuntime.useDataMutation)(mutation, {
34
- onComplete,
38
+ onComplete: () => {
39
+ setDeleteError(null);
40
+ onComplete();
41
+ },
42
+ onError: () => setDeleteError(_d2I18n.default.t('Delete failed')),
35
43
  variables: {
36
44
  commentId,
37
45
  interpretationId
38
46
  }
39
47
  });
40
- return /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
48
+ const onDelete = () => {
49
+ setDeleteError(null);
50
+ remove();
51
+ };
52
+ return /*#__PURE__*/_react.default.createElement("div", {
53
+ className: _style.default.dynamic([["945681082", [_ui.colors.red500]]]) + " " + "delete-button-container"
54
+ }, /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
41
55
  tooltipContent: _d2I18n.default.t('Delete'),
42
56
  iconComponent: _ui.IconDelete16,
43
- onClick: remove,
57
+ onClick: onDelete,
44
58
  disabled: loading
45
- });
59
+ }), deleteError && /*#__PURE__*/_react.default.createElement("span", {
60
+ className: _style.default.dynamic([["945681082", [_ui.colors.red500]]]) + " " + "delete-error"
61
+ }, deleteError), /*#__PURE__*/_react.default.createElement(_style.default, {
62
+ id: "945681082",
63
+ dynamic: [_ui.colors.red500]
64
+ }, [".delete-button-container.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:4px;}", `.delete-error.__jsx-style-dynamic-selector{color:${_ui.colors.red500};font-size:12px;line-height:12px;}`]));
46
65
  };
47
66
  exports.CommentDeleteButton = CommentDeleteButton;
48
67
  CommentDeleteButton.propTypes = {
@@ -44,7 +44,7 @@ const CommentUpdateForm = _ref => {
44
44
  close();
45
45
  }
46
46
  });
47
- const errorText = error ? error.message || _d2I18n.default.t('Could not update comment') : '';
47
+ const errorText = error ? _d2I18n.default.t('Could not update comment') : '';
48
48
  return /*#__PURE__*/_react.default.createElement("div", {
49
49
  className: _style.default.dynamic([["2690082310", [_ui.spacers.dp8, _ui.spacers.dp8, _ui.colors.grey100]]]) + " " + "message"
50
50
  }, /*#__PURE__*/_react.default.createElement(_index.MessageEditorContainer, {
@@ -41,7 +41,7 @@ const query = {
41
41
  return id;
42
42
  },
43
43
  params: {
44
- fields: ['access', 'id', 'text', 'created', 'user[id,displayName]', 'likes', 'likedBy', 'comments[access,id,text,created,createdBy[id,displayName]]']
44
+ fields: ['access[write,manage]', 'id', 'text', 'created', 'createdBy[id,displayName]', 'likes', 'likedBy', 'comments[id,text,created,createdBy[id,displayName]]']
45
45
  }
46
46
  }
47
47
  };
@@ -34,6 +34,7 @@ const InterpretationThread = _ref => {
34
34
  });
35
35
  }
36
36
  }, [initialFocus]);
37
+ const interpretationAccess = (0, _index.getInterpretationAccess)(interpretation, currentUser);
37
38
  return /*#__PURE__*/_react.default.createElement("div", {
38
39
  className: "jsx-615306698" + " " + ((0, _classnames.default)('container', {
39
40
  fetching
@@ -52,12 +53,13 @@ const InterpretationThread = _ref => {
52
53
  }, /*#__PURE__*/_react.default.createElement(_index.Interpretation, {
53
54
  currentUser: currentUser,
54
55
  interpretation: interpretation,
55
- onReplyIconClick: () => {
56
+ onReplyIconClick: interpretationAccess.comment ? () => {
56
57
  var _focusRef$current;
57
58
  return (_focusRef$current = focusRef.current) === null || _focusRef$current === void 0 ? void 0 : _focusRef$current.focus();
58
- },
59
+ } : null,
59
60
  onUpdated: () => onThreadUpdated(true),
60
- onDeleted: onInterpretationDeleted
61
+ onDeleted: onInterpretationDeleted,
62
+ isInThread: true
61
63
  }), /*#__PURE__*/_react.default.createElement("div", {
62
64
  className: "jsx-615306698" + " " + 'comments'
63
65
  }, interpretation.comments.map(comment => /*#__PURE__*/_react.default.createElement(_Comment.Comment, {
@@ -65,8 +67,9 @@ const InterpretationThread = _ref => {
65
67
  comment: comment,
66
68
  currentUser: currentUser,
67
69
  interpretationId: interpretation.id,
68
- onThreadUpdated: onThreadUpdated
69
- }))), /*#__PURE__*/_react.default.createElement(_CommentAddForm.CommentAddForm, {
70
+ onThreadUpdated: onThreadUpdated,
71
+ canComment: interpretationAccess.comment
72
+ }))), interpretationAccess.comment && /*#__PURE__*/_react.default.createElement(_CommentAddForm.CommentAddForm, {
70
73
  currentUser: currentUser,
71
74
  interpretationId: interpretation.id,
72
75
  onSave: () => onThreadUpdated(true),
@@ -25,7 +25,7 @@ const interpretationsQuery = {
25
25
  id
26
26
  } = _ref;
27
27
  return {
28
- fields: ['access', 'id', 'user[displayName]', 'created', 'text', 'comments[id]', 'likes', 'likedBy[id]'],
28
+ fields: ['access[write,manage]', 'id', 'createdBy[id,displayName]', 'created', 'text', 'comments[id]', 'likes', 'likedBy[id]'],
29
29
  filter: `${type}.id:eq:${id}`
30
30
  };
31
31
  }
@@ -23,7 +23,8 @@ const Interpretation = _ref => {
23
23
  onUpdated,
24
24
  onDeleted,
25
25
  disabled,
26
- onReplyIconClick
26
+ onReplyIconClick,
27
+ isInThread
27
28
  } = _ref;
28
29
  const [isUpdateMode, setIsUpdateMode] = (0, _react.useState)(false);
29
30
  const [showSharingDialog, setShowSharingDialog] = (0, _react.useState)(false);
@@ -37,17 +38,30 @@ const Interpretation = _ref => {
37
38
  onComplete: onUpdated
38
39
  });
39
40
  const shouldShowButton = !!onClick && !disabled;
41
+ const interpretationAccess = (0, _index.getInterpretationAccess)(interpretation, currentUser);
42
+ let tooltip = _d2I18n.default.t('Reply');
43
+ if (!interpretationAccess.comment) {
44
+ if (isInThread) {
45
+ tooltip = _d2I18n.default.t('{{count}} replies', {
46
+ count: interpretation.comments.length,
47
+ defaultValue: '{{count}} reply',
48
+ defaultValue_plural: '{{count}} replies'
49
+ });
50
+ } else {
51
+ tooltip = _d2I18n.default.t('View replies');
52
+ }
53
+ }
40
54
  return isUpdateMode ? /*#__PURE__*/_react.default.createElement(_InterpretationUpdateForm.InterpretationUpdateForm, {
41
55
  close: () => setIsUpdateMode(false),
42
56
  id: interpretation.id,
43
- showSharingLink: interpretation.access.manage,
57
+ showSharingLink: interpretationAccess.share,
44
58
  onComplete: onUpdated,
45
59
  text: interpretation.text,
46
60
  currentUser: currentUser
47
61
  }) : /*#__PURE__*/_react.default.createElement(_index.Message, {
48
62
  text: interpretation.text,
49
63
  created: interpretation.created,
50
- username: interpretation.user.displayName
64
+ username: interpretation.createdBy.displayName
51
65
  }, !disabled && /*#__PURE__*/_react.default.createElement(_index.MessageStatsBar, null, /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
52
66
  tooltipContent: isLikedByCurrentUser ? _d2I18n.default.t('Unlike') : _d2I18n.default.t('Like'),
53
67
  iconComponent: _ui.IconThumbUp16,
@@ -57,12 +71,13 @@ const Interpretation = _ref => {
57
71
  disabled: toggleLikeInProgress,
58
72
  dataTest: "interpretation-like-unlike-button"
59
73
  }), /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
60
- tooltipContent: _d2I18n.default.t('Reply'),
74
+ tooltipContent: tooltip,
61
75
  iconComponent: _ui.IconReply16,
62
- onClick: () => onReplyIconClick(interpretation.id),
76
+ onClick: () => onReplyIconClick && onReplyIconClick(interpretation.id),
63
77
  count: interpretation.comments.length,
64
- dataTest: "interpretation-reply-button"
65
- }), interpretation.access.manage && /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
78
+ dataTest: "interpretation-reply-button",
79
+ viewOnly: isInThread && !interpretationAccess.comment
80
+ }), interpretationAccess.share && /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
66
81
  iconComponent: _ui.IconShare16,
67
82
  tooltipContent: _d2I18n.default.t('Share'),
68
83
  onClick: () => setShowSharingDialog(true),
@@ -72,15 +87,15 @@ const Interpretation = _ref => {
72
87
  type: 'interpretation',
73
88
  id: interpretation.id,
74
89
  onClose: () => setShowSharingDialog(false)
75
- }), interpretation.access.update && /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
90
+ }), /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, interpretationAccess.edit && /*#__PURE__*/_react.default.createElement(_index.MessageIconButton, {
76
91
  iconComponent: _ui.IconEdit16,
77
92
  tooltipContent: _d2I18n.default.t('Edit'),
78
93
  onClick: () => setIsUpdateMode(true),
79
94
  dataTest: "interpretation-edit-button"
80
- }), interpretation.access.delete && /*#__PURE__*/_react.default.createElement(_InterpretationDeleteButton.InterpretationDeleteButton, {
95
+ }), interpretationAccess.delete && /*#__PURE__*/_react.default.createElement(_InterpretationDeleteButton.InterpretationDeleteButton, {
81
96
  id: interpretation.id,
82
97
  onComplete: onDeleted
83
- })), shouldShowButton && /*#__PURE__*/_react.default.createElement(_ui.Button, {
98
+ }))), shouldShowButton && /*#__PURE__*/_react.default.createElement(_ui.Button, {
84
99
  secondary: true,
85
100
  small: true,
86
101
  onClick: (_, event) => {
@@ -97,5 +112,6 @@ Interpretation.propTypes = {
97
112
  onReplyIconClick: _propTypes.default.func.isRequired,
98
113
  onUpdated: _propTypes.default.func.isRequired,
99
114
  disabled: _propTypes.default.bool,
115
+ isInThread: _propTypes.default.bool,
100
116
  onClick: _propTypes.default.func
101
117
  };
@@ -18,7 +18,8 @@ const MessageIconButton = _ref => {
18
18
  selected,
19
19
  count,
20
20
  iconComponent: Icon,
21
- dataTest
21
+ dataTest,
22
+ viewOnly
22
23
  } = _ref;
23
24
  return /*#__PURE__*/_react.default.createElement(_ui.Tooltip, {
24
25
  closeDelay: 200,
@@ -33,7 +34,7 @@ const MessageIconButton = _ref => {
33
34
  ref: ref,
34
35
  onMouseOver: onMouseOver,
35
36
  onMouseOut: onMouseOut,
36
- className: _style.default.dynamic([["250657028", [_ui.spacers.dp4, _ui.colors.grey700, _ui.colors.teal600, _ui.colors.grey900, _ui.colors.teal800, _ui.colors.teal500, _ui.colors.teal700, _ui.theme.disabled, _ui.theme.disabled]]]) + " " + "wrapper"
37
+ className: _style.default.dynamic([["163818318", [_ui.spacers.dp4, _ui.colors.grey700, _ui.colors.teal600, _ui.colors.grey900, _ui.colors.teal800, _ui.colors.teal500, _ui.colors.teal700, _ui.theme.disabled, _ui.theme.disabled]]]) + " " + "wrapper"
37
38
  }, /*#__PURE__*/_react.default.createElement("button", {
38
39
  onClick: event => {
39
40
  event.stopPropagation();
@@ -41,13 +42,14 @@ const MessageIconButton = _ref => {
41
42
  },
42
43
  disabled: disabled,
43
44
  "data-test": dataTest,
44
- className: _style.default.dynamic([["250657028", [_ui.spacers.dp4, _ui.colors.grey700, _ui.colors.teal600, _ui.colors.grey900, _ui.colors.teal800, _ui.colors.teal500, _ui.colors.teal700, _ui.theme.disabled, _ui.theme.disabled]]]) + " " + ((0, _classnames.default)('button', {
45
- selected
45
+ className: _style.default.dynamic([["163818318", [_ui.spacers.dp4, _ui.colors.grey700, _ui.colors.teal600, _ui.colors.grey900, _ui.colors.teal800, _ui.colors.teal500, _ui.colors.teal700, _ui.theme.disabled, _ui.theme.disabled]]]) + " " + ((0, _classnames.default)('button', {
46
+ selected,
47
+ viewOnly
46
48
  }) || "")
47
49
  }, count && count, /*#__PURE__*/_react.default.createElement(Icon, null)), /*#__PURE__*/_react.default.createElement(_style.default, {
48
- id: "250657028",
50
+ id: "163818318",
49
51
  dynamic: [_ui.spacers.dp4, _ui.colors.grey700, _ui.colors.teal600, _ui.colors.grey900, _ui.colors.teal800, _ui.colors.teal500, _ui.colors.teal700, _ui.theme.disabled, _ui.theme.disabled]
50
- }, [".wrapper.__jsx-style-dynamic-selector{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;}", `.button.__jsx-style-dynamic-selector{all:unset;cursor:pointer;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;gap:${_ui.spacers.dp4};-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:12px;line-height:14px;color:${_ui.colors.grey700};}`, `.button.selected.__jsx-style-dynamic-selector{color:${_ui.colors.teal600};font-weight:500;}`, `.button.__jsx-style-dynamic-selector:hover{color:${_ui.colors.grey900};}`, `.button.selected.__jsx-style-dynamic-selector:hover{color:${_ui.colors.teal800};}`, `.button.selected.__jsx-style-dynamic-selector svg{color:${_ui.colors.teal500};}`, `.button.selected.__jsx-style-dynamic-selector:hover svg{color:${_ui.colors.teal700};}`, `.button.__jsx-style-dynamic-selector:disabled{color:${_ui.theme.disabled};cursor:not-allowed;}`, `.button.__jsx-style-dynamic-selector:disabled svg{color:${_ui.theme.disabled};}`]));
52
+ }, [".wrapper.__jsx-style-dynamic-selector{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;}", `.button.__jsx-style-dynamic-selector{all:unset;cursor:pointer;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;gap:${_ui.spacers.dp4};-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:12px;line-height:14px;color:${_ui.colors.grey700};}`, ".viewOnly.__jsx-style-dynamic-selector{cursor:default;}", `.button.selected.__jsx-style-dynamic-selector{color:${_ui.colors.teal600};font-weight:500;}`, `.button.__jsx-style-dynamic-selector:hover{color:${_ui.colors.grey900};}`, `.button.selected.__jsx-style-dynamic-selector:hover{color:${_ui.colors.teal800};}`, `.button.selected.__jsx-style-dynamic-selector svg{color:${_ui.colors.teal500};}`, `.button.selected.__jsx-style-dynamic-selector:hover svg{color:${_ui.colors.teal700};}`, `.button.__jsx-style-dynamic-selector:disabled{color:${_ui.theme.disabled};cursor:not-allowed;}`, `.button.__jsx-style-dynamic-selector:disabled svg{color:${_ui.theme.disabled};}`]));
51
53
  });
52
54
  };
53
55
  exports.MessageIconButton = MessageIconButton;
@@ -58,5 +60,6 @@ MessageIconButton.propTypes = {
58
60
  dataTest: _propTypes.default.string,
59
61
  disabled: _propTypes.default.bool,
60
62
  selected: _propTypes.default.bool,
63
+ viewOnly: _propTypes.default.bool,
61
64
  onClick: _propTypes.default.func
62
65
  };
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+
3
+ var _getInterpretationAccess = require("../getInterpretationAccess.js");
4
+ const superuser = {
5
+ id: 'iamsuper',
6
+ authorities: new Set(['ALL'])
7
+ };
8
+ const userJoe = {
9
+ id: 'johndoe',
10
+ authorities: new Set(['Some'])
11
+ };
12
+ const userJane = {
13
+ id: 'jane',
14
+ authorities: new Set(['Some'])
15
+ };
16
+ describe('interpretation and comment access', () => {
17
+ describe('getInterpretationAccess', () => {
18
+ it('returns true for all accesses for superuser', () => {
19
+ const interpretation = {
20
+ access: {
21
+ write: true,
22
+ manage: true
23
+ },
24
+ createdBy: userJoe
25
+ };
26
+ expect((0, _getInterpretationAccess.getInterpretationAccess)(interpretation, superuser)).toMatchObject({
27
+ share: true,
28
+ comment: true,
29
+ edit: true,
30
+ delete: true
31
+ });
32
+ });
33
+ it('returns true for all accesses for creator', () => {
34
+ const interpretation = {
35
+ access: {
36
+ write: true,
37
+ manage: true
38
+ },
39
+ createdBy: userJoe
40
+ };
41
+ expect((0, _getInterpretationAccess.getInterpretationAccess)(interpretation, userJoe)).toMatchObject({
42
+ share: true,
43
+ comment: true,
44
+ edit: true,
45
+ delete: true
46
+ });
47
+ });
48
+ it('returns false for edit/delete if user is not creator/superuser', () => {
49
+ const interpretation = {
50
+ access: {
51
+ write: true,
52
+ manage: true
53
+ },
54
+ createdBy: userJane
55
+ };
56
+ expect((0, _getInterpretationAccess.getInterpretationAccess)(interpretation, userJoe)).toMatchObject({
57
+ share: true,
58
+ comment: true,
59
+ edit: false,
60
+ delete: false
61
+ });
62
+ });
63
+ it('returns false for comment/edit/delete if user is not creator/superuser and no write access', () => {
64
+ const interpretation = {
65
+ access: {
66
+ write: false,
67
+ manage: true
68
+ },
69
+ createdBy: userJane
70
+ };
71
+ expect((0, _getInterpretationAccess.getInterpretationAccess)(interpretation, userJoe)).toMatchObject({
72
+ share: true,
73
+ comment: false,
74
+ edit: false,
75
+ delete: false
76
+ });
77
+ });
78
+ it('returns false for share/comment/edit/delete if user is not creator/superuser and no write or manage access', () => {
79
+ const interpretation = {
80
+ access: {
81
+ write: false,
82
+ manage: false
83
+ },
84
+ createdBy: userJane
85
+ };
86
+ expect((0, _getInterpretationAccess.getInterpretationAccess)(interpretation, userJoe)).toMatchObject({
87
+ share: false,
88
+ comment: false,
89
+ edit: false,
90
+ delete: false
91
+ });
92
+ });
93
+ });
94
+ describe('getCommentAccess', () => {
95
+ it('returns true for all accesses for superuser', () => {
96
+ const interpretation = {
97
+ access: {
98
+ write: true
99
+ }
100
+ };
101
+ const comment = {
102
+ createdBy: userJoe
103
+ };
104
+ expect((0, _getInterpretationAccess.getCommentAccess)(comment, interpretation.access.write, superuser)).toMatchObject({
105
+ edit: true,
106
+ delete: true
107
+ });
108
+ });
109
+ it('returns true for all accesses for creator when interpretation has write access', () => {
110
+ const interpretation = {
111
+ access: {
112
+ write: true
113
+ }
114
+ };
115
+ const comment = {
116
+ createdBy: userJoe
117
+ };
118
+ expect((0, _getInterpretationAccess.getCommentAccess)(comment, interpretation.access.write, userJoe)).toMatchObject({
119
+ edit: true,
120
+ delete: true
121
+ });
122
+ });
123
+ it('returns true for edit and false for delete for creator when interpretation does not have write access', () => {
124
+ const interpretation = {
125
+ access: {
126
+ write: false
127
+ }
128
+ };
129
+ const comment = {
130
+ createdBy: userJoe
131
+ };
132
+ expect((0, _getInterpretationAccess.getCommentAccess)(comment, interpretation.access.write, userJoe)).toMatchObject({
133
+ edit: true,
134
+ delete: false
135
+ });
136
+ });
137
+ it('returns false for edit/delete for user who is not creator or superuser', () => {
138
+ const interpretation = {
139
+ access: {
140
+ write: true
141
+ }
142
+ };
143
+ const comment = {
144
+ createdBy: userJane
145
+ };
146
+ expect((0, _getInterpretationAccess.getCommentAccess)(comment, interpretation.access.write, userJoe)).toMatchObject({
147
+ edit: false,
148
+ delete: false
149
+ });
150
+ });
151
+ });
152
+ });
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getInterpretationAccess = exports.getCommentAccess = void 0;
7
+ const isCreatorOrSuperuser = (object, currentUser) => (object === null || object === void 0 ? void 0 : object.createdBy.id) === (currentUser === null || currentUser === void 0 ? void 0 : currentUser.id) || (currentUser === null || currentUser === void 0 ? void 0 : currentUser.authorities.has('ALL'));
8
+ const getInterpretationAccess = (interpretation, currentUser) => {
9
+ const canEditDelete = isCreatorOrSuperuser(interpretation, currentUser);
10
+ return {
11
+ share: interpretation.access.manage,
12
+ comment: interpretation.access.write,
13
+ edit: canEditDelete,
14
+ delete: canEditDelete
15
+ };
16
+ };
17
+ exports.getInterpretationAccess = getInterpretationAccess;
18
+ const getCommentAccess = (comment, hasInterpretationReplyAccess, currentUser) => {
19
+ const canEditDelete = isCreatorOrSuperuser(comment, currentUser);
20
+ return {
21
+ edit: canEditDelete,
22
+ delete: canEditDelete && hasInterpretationReplyAccess
23
+ };
24
+ };
25
+ exports.getCommentAccess = getCommentAccess;
@@ -35,4 +35,15 @@ Object.keys(_index3).forEach(function (key) {
35
35
  return _index3[key];
36
36
  }
37
37
  });
38
+ });
39
+ var _getInterpretationAccess = require("./getInterpretationAccess.js");
40
+ Object.keys(_getInterpretationAccess).forEach(function (key) {
41
+ if (key === "default" || key === "__esModule") return;
42
+ if (key in exports && exports[key] === _getInterpretationAccess[key]) return;
43
+ Object.defineProperty(exports, key, {
44
+ enumerable: true,
45
+ get: function () {
46
+ return _getInterpretationAccess[key];
47
+ }
48
+ });
38
49
  });
@@ -111,6 +111,7 @@
111
111
  "Edit": "تعديل",
112
112
  "Write a reply": "كتابة رد",
113
113
  "Post reply": "",
114
+ "Delete failed": "فشل الحذف",
114
115
  "Could not update comment": "",
115
116
  "Enter comment text": "",
116
117
  "Update": "تحديث",
@@ -121,9 +122,16 @@
121
122
  "Write an interpretation": "كتابة تفسير",
122
123
  "Post interpretation": "",
123
124
  "Interpretations": "التفسيرات",
125
+ "Reply": "رد",
126
+ "{{count}} replies_0": "{{count}} رد",
127
+ "{{count}} replies_1": "{{count}} رد",
128
+ "{{count}} replies_2": "{{count}} رد",
129
+ "{{count}} replies_3": "{{count}} رد",
130
+ "{{count}} replies_4": "{{count}} رد",
131
+ "{{count}} replies_5": "{{count}} رد",
132
+ "View replies": "",
124
133
  "Unlike": "إلغاء الإعجاب",
125
134
  "Like": "إعجاب",
126
- "Reply": "رد",
127
135
  "Share": "مشاركة",
128
136
  "See interpretation": "",
129
137
  "Manage sharing": "إدارة المشاركة",
@@ -283,6 +291,7 @@
283
291
  "Six-months": "ستة-أشهر",
284
292
  "Financial Years": "السنوات المالية",
285
293
  "Years": "السنوات",
294
+ "Interpretations and details": "",
286
295
  "Translating to": "",
287
296
  "Choose a locale": "",
288
297
  "Base locale reference": "",
@@ -109,6 +109,7 @@
109
109
  "Edit": "Upravit",
110
110
  "Write a reply": "Napsat odpověď",
111
111
  "Post reply": "Odpovědět",
112
+ "Delete failed": "Smazání se nezdařilo",
112
113
  "Could not update comment": "Komentář se nepodařilo aktualizovat",
113
114
  "Enter comment text": "Zadejte text komentáře",
114
115
  "Update": "Aktualizovat",
@@ -119,9 +120,14 @@
119
120
  "Write an interpretation": "Napsat interpretaci",
120
121
  "Post interpretation": "Vložit interpretaci",
121
122
  "Interpretations": "Interpretace",
123
+ "Reply": "Odpovědět",
124
+ "{{count}} replies_0": "{{count}} odpověď",
125
+ "{{count}} replies_1": " {{count}} odpovědi",
126
+ "{{count}} replies_2": "{{count}} odpovědí",
127
+ "{{count}} replies_3": "{{count}} odpovědi",
128
+ "View replies": "",
122
129
  "Unlike": "Na rozdíl od",
123
130
  "Like": "Jako",
124
- "Reply": "Odpovědět",
125
131
  "Share": "Sdílet",
126
132
  "See interpretation": "Zobrazit interpretaci",
127
133
  "Manage sharing": "Spravovat sdílení",
@@ -275,6 +281,7 @@
275
281
  "Six-months": "Půlrok",
276
282
  "Financial Years": "Finanční roky",
277
283
  "Years": "Let",
284
+ "Interpretations and details": "",
278
285
  "Translating to": "Překlad do",
279
286
  "Choose a locale": "Vyberte národní prostředí",
280
287
  "Base locale reference": "Odkaz na základní národní prostředí",
@@ -107,6 +107,7 @@
107
107
  "Edit": "Edit",
108
108
  "Write a reply": "Write a reply",
109
109
  "Post reply": "Post reply",
110
+ "Delete failed": "Delete failed",
110
111
  "Could not update comment": "Could not update comment",
111
112
  "Enter comment text": "Enter comment text",
112
113
  "Update": "Update",
@@ -117,9 +118,12 @@
117
118
  "Write an interpretation": "Write an interpretation",
118
119
  "Post interpretation": "Post interpretation",
119
120
  "Interpretations": "Interpretations",
121
+ "Reply": "Reply",
122
+ "{{count}} replies": "{{count}} reply",
123
+ "{{count}} replies_plural": "{{count}} replies",
124
+ "View replies": "View replies",
120
125
  "Unlike": "Unlike",
121
126
  "Like": "Like",
122
- "Reply": "Reply",
123
127
  "Share": "Share",
124
128
  "See interpretation": "See interpretation",
125
129
  "Manage sharing": "Manage sharing",
@@ -107,6 +107,7 @@
107
107
  "Edit": "Editar",
108
108
  "Write a reply": "Escribe una respuesta",
109
109
  "Post reply": "Publicar respuesta",
110
+ "Delete failed": "Fallado el proceso de eliminar",
110
111
  "Could not update comment": "No se pudo actualizar el comentario",
111
112
  "Enter comment text": "Introducir el texto del comentario",
112
113
  "Update": "Actualizar",
@@ -117,9 +118,12 @@
117
118
  "Write an interpretation": "Escribir una interpretación",
118
119
  "Post interpretation": "",
119
120
  "Interpretations": "Interpretaciones",
121
+ "Reply": "Responder",
122
+ "{{count}} replies": "{{contar}} respuesta",
123
+ "{{count}} replies_plural": "{{count}} respuestas",
124
+ "View replies": "",
120
125
  "Unlike": "diferente a",
121
126
  "Like": "como",
122
- "Reply": "Responder",
123
127
  "Share": "Compartir",
124
128
  "See interpretation": "Ver interpretación",
125
129
  "Manage sharing": "Administrar compartir",
@@ -107,6 +107,7 @@
107
107
  "Edit": "Modifier",
108
108
  "Write a reply": "Ecrire une réponse",
109
109
  "Post reply": "",
110
+ "Delete failed": "Échec de la suppression",
110
111
  "Could not update comment": "",
111
112
  "Enter comment text": "",
112
113
  "Update": "Mettre à jour",
@@ -117,9 +118,12 @@
117
118
  "Write an interpretation": "Ecrire une interprétation",
118
119
  "Post interpretation": "",
119
120
  "Interpretations": "Interprétations",
121
+ "Reply": "Répondre",
122
+ "{{count}} replies": "{{count}} réponses",
123
+ "{{count}} replies_plural": "{{count}} réponses",
124
+ "View replies": "",
120
125
  "Unlike": "Je n'aime plus",
121
126
  "Like": "J'aime",
122
- "Reply": "Répondre",
123
127
  "Share": "Partager",
124
128
  "See interpretation": "",
125
129
  "Manage sharing": "Gérer le partage",
@@ -267,6 +271,7 @@
267
271
  "Six-months": "Semestres",
268
272
  "Financial Years": "Années fiscales",
269
273
  "Years": "Années",
274
+ "Interpretations and details": "",
270
275
  "Translating to": "",
271
276
  "Choose a locale": "",
272
277
  "Base locale reference": "",