@seafile/sdoc-editor 0.2.16 → 0.2.18

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 (68) hide show
  1. package/dist/api/seafile-api.js +36 -2
  2. package/dist/assets/css/simple-editor.css +0 -32
  3. package/dist/assets/images/revision-avatar.png +0 -0
  4. package/dist/basic-sdk/assets/css/textlink-hovermenu.css +1 -0
  5. package/dist/basic-sdk/comment/components/comment-all-participants/index.css +83 -0
  6. package/dist/basic-sdk/comment/components/comment-all-participants/index.js +56 -0
  7. package/dist/basic-sdk/comment/components/comment-all-participants/participant-avatar.js +35 -0
  8. package/dist/basic-sdk/comment/{comment → components}/comment-editor.js +18 -36
  9. package/dist/basic-sdk/comment/components/comment-input/comment-participant-item.js +47 -0
  10. package/dist/basic-sdk/comment/components/comment-input/index.css +45 -0
  11. package/dist/basic-sdk/comment/components/comment-input/index.js +295 -0
  12. package/dist/basic-sdk/comment/{comment → components}/comment-item-content.js +7 -2
  13. package/dist/basic-sdk/comment/{comment → components}/comment-item-reply.js +6 -1
  14. package/dist/basic-sdk/comment/{comment → components}/comment-item-wrapper.js +3 -1
  15. package/dist/basic-sdk/comment/components/comment-participants-editor/index.css +132 -0
  16. package/dist/basic-sdk/comment/components/comment-participants-editor/index.js +67 -0
  17. package/dist/basic-sdk/comment/components/comment-participants-editor/searched-collaborators.js +53 -0
  18. package/dist/basic-sdk/comment/components/comment-participants-editor/selected-participants.js +39 -0
  19. package/dist/basic-sdk/comment/{comment → components}/global-comment-header.js +5 -6
  20. package/dist/basic-sdk/comment/{comment → components}/global-comment.js +3 -2
  21. package/dist/basic-sdk/comment/{comment → components}/style.css +8 -1
  22. package/dist/basic-sdk/comment/constants/index.js +11 -0
  23. package/dist/basic-sdk/comment/hooks/use-comment-list.js +1 -1
  24. package/dist/basic-sdk/comment/hooks/use-participants.js +90 -0
  25. package/dist/basic-sdk/comment/index.js +3 -2
  26. package/dist/basic-sdk/comment/utils/index.js +206 -0
  27. package/dist/basic-sdk/editor/sdoc-editor.js +3 -2
  28. package/dist/basic-sdk/extension/plugins/link/hover/index.js +3 -3
  29. package/dist/components/doc-info/index.css +53 -0
  30. package/dist/components/doc-info/index.js +11 -2
  31. package/dist/components/modal-portal/index.js +36 -0
  32. package/dist/constants/index.js +4 -1
  33. package/dist/constants/key-codes.js +102 -0
  34. package/dist/constants/transfer-types.js +3 -0
  35. package/dist/context.js +38 -8
  36. package/dist/hooks/index.js +3 -0
  37. package/dist/hooks/use-collaborators.js +44 -0
  38. package/dist/layout/layout.js +10 -27
  39. package/dist/model/index.js +2 -1
  40. package/dist/model/user.js +12 -0
  41. package/dist/pages/simple-editor.js +1 -1
  42. package/dist/utils/get-event-transfer.js +73 -0
  43. package/dist/utils/hotkey.js +25 -0
  44. package/dist/utils/index.js +58 -1
  45. package/package.json +1 -1
  46. package/public/locales/cs/sdoc-editor.json +6 -1
  47. package/public/locales/de/sdoc-editor.json +6 -1
  48. package/public/locales/en/sdoc-editor.json +3 -1
  49. package/public/locales/es/sdoc-editor.json +6 -1
  50. package/public/locales/fr/sdoc-editor.json +6 -1
  51. package/public/locales/it/sdoc-editor.json +6 -1
  52. package/public/locales/ru/sdoc-editor.json +6 -1
  53. package/public/locales/zh_CN/sdoc-editor.json +3 -1
  54. package/public/media/sdoc-editor-font/iconfont.eot +0 -0
  55. package/public/media/sdoc-editor-font/iconfont.svg +4 -0
  56. package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
  57. package/public/media/sdoc-editor-font/iconfont.woff +0 -0
  58. package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
  59. package/public/media/sdoc-editor-font.css +14 -6
  60. /package/dist/basic-sdk/comment/{comment → components}/comment-delete-shadow.js +0 -0
  61. /package/dist/basic-sdk/comment/{comment → components}/comment-item-resolved-reply.js +0 -0
  62. /package/dist/basic-sdk/comment/{comment → components}/comment-list.css +0 -0
  63. /package/dist/basic-sdk/comment/{comment → components}/comment-list.js +0 -0
  64. /package/dist/basic-sdk/comment/{comment → components}/editor-comment.js +0 -0
  65. /package/dist/basic-sdk/comment/{comment → components}/elements-comment-count/element-comment-count.js +0 -0
  66. /package/dist/basic-sdk/comment/{comment → components}/elements-comment-count/index.css +0 -0
  67. /package/dist/basic-sdk/comment/{comment → components}/elements-comment-count/index.js +0 -0
  68. /package/dist/basic-sdk/comment/{comment → components}/index.js +0 -0
@@ -0,0 +1,295 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import React, { useCallback, useEffect, useRef, useState, useImperativeHandle, forwardRef } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { useCollaborators } from '../../../../hooks';
5
+ import { useParticipantsContext } from '../../hooks/use-participants';
6
+ import ModalPortal from '../../../../components/modal-portal';
7
+ import { KeyCodes } from '../../../../constants';
8
+ import { searchCollaborators, CommentUtilities, convertComment, checkMentionOperation } from '../../utils';
9
+ import { DOWN, UP, POPOVER_ADDING_HEIGHT, FONT_SIZE_WIDTH, LINE_HEIGHT } from '../../constants';
10
+ import { eventStopPropagation } from '../../../utils/mouse-event';
11
+ import CommentParticipantItem from './comment-participant-item';
12
+ import { Hotkey, getSelectionCoords } from '../../../../utils';
13
+ import './index.css';
14
+ var CommentInput = forwardRef(function (_ref, ref) {
15
+ var placeholder = _ref.placeholder,
16
+ content = _ref.content,
17
+ type = _ref.type,
18
+ onCancel = _ref.onCancel,
19
+ onSubmit = _ref.onSubmit;
20
+ var commentRef = useRef();
21
+ var collaboratorsPopoverRef = useRef();
22
+ var _useTranslation = useTranslation(),
23
+ t = _useTranslation.t;
24
+ var _useCollaborators = useCollaborators(),
25
+ collaborators = _useCollaborators.collaborators;
26
+ var _useParticipantsConte = useParticipantsContext(),
27
+ addParticipants = _useParticipantsConte.addParticipants;
28
+ var _useState = useState(),
29
+ _useState2 = _slicedToArray(_useState, 2),
30
+ range = _useState2[0],
31
+ setRange = _useState2[1];
32
+ var _useState3 = useState([]),
33
+ _useState4 = _slicedToArray(_useState3, 2),
34
+ searchedCollaborators = _useState4[0],
35
+ setSearchedCollaborators = _useState4[1];
36
+ var _useState5 = useState(-1),
37
+ _useState6 = _slicedToArray(_useState5, 2),
38
+ activeCollaboratorIndex = _useState6[0],
39
+ setActiveCollaboratorIndex = _useState6[1];
40
+ var commentUtilities = new CommentUtilities();
41
+
42
+ // onMount: comment content
43
+ useEffect(function () {
44
+ if (!content) return;
45
+ commentRef.current.textContent = content;
46
+ // eslint-disable-next-line react-hooks/exhaustive-deps
47
+ }, []);
48
+
49
+ // onMount: set input focus
50
+ useEffect(function () {
51
+ if (type !== 'comment') return;
52
+ commentRef.current && commentRef.current.focus();
53
+ // eslint-disable-next-line react-hooks/exhaustive-deps
54
+ }, []);
55
+
56
+ // onMount: handleCommentPopover
57
+ useEffect(function () {
58
+ document.addEventListener('mousedown', handleCommentPopover);
59
+ return function () {
60
+ document.removeEventListener('mousedown', handleCommentPopover);
61
+ };
62
+ });
63
+
64
+ // The parent component can call the method of this component through ref
65
+ useImperativeHandle(ref, function () {
66
+ return {
67
+ getValue: function getValue() {
68
+ var comment = convertComment(commentRef.current.textContent);
69
+ return comment;
70
+ },
71
+ setValue: function setValue(value) {
72
+ commentRef.current.textContent = value || '';
73
+ }
74
+
75
+ // eslint-disable-next-line react-hooks/exhaustive-deps
76
+ };
77
+ }, [commentRef]);
78
+ var hideCommentPopover = useCallback(function () {
79
+ if (searchedCollaborators.length === 0) return;
80
+ setSearchedCollaborators([]);
81
+ setActiveCollaboratorIndex(-1);
82
+ }, [searchedCollaborators]);
83
+ var handleCommentPopover = useCallback(function (event) {
84
+ if (collaboratorsPopoverRef.current && event && !collaboratorsPopoverRef.current.contains(event.target)) {
85
+ hideCommentPopover();
86
+ }
87
+ }, [hideCommentPopover, collaboratorsPopoverRef]);
88
+ var setScrollTop = useCallback(function (offsetTop, itemOffsetHeight, mouseDownType) {
89
+ var _collaboratorsPopover = collaboratorsPopoverRef.current,
90
+ offsetHeight = _collaboratorsPopover.offsetHeight,
91
+ scrollTop = _collaboratorsPopover.scrollTop;
92
+ if (mouseDownType === DOWN) {
93
+ if (offsetTop + itemOffsetHeight - scrollTop - offsetHeight + POPOVER_ADDING_HEIGHT > 0) {
94
+ var top = offsetTop + itemOffsetHeight - offsetHeight + POPOVER_ADDING_HEIGHT;
95
+ collaboratorsPopoverRef.current.scrollTop = top;
96
+ }
97
+ }
98
+ if (mouseDownType === UP) {
99
+ if (offsetTop < scrollTop) {
100
+ collaboratorsPopoverRef.current.scrollTop = offsetTop - POPOVER_ADDING_HEIGHT;
101
+ }
102
+ }
103
+ }, []);
104
+ var setCollaboratorsPopoverPosition = useCallback(function (caretPosition) {
105
+ var _collaboratorsPopover2 = collaboratorsPopoverRef.current.getBoundingClientRect(),
106
+ height = _collaboratorsPopover2.height,
107
+ width = _collaboratorsPopover2.width;
108
+ var offsetHeight = collaboratorsPopoverRef.current.offsetHeight;
109
+
110
+ // Whether the vertical direction exceeds the screen
111
+ var isVerticalDirectionBeyondScreen = height + caretPosition.y + LINE_HEIGHT > window.innerHeight;
112
+
113
+ // if the vertical direction exceeds the screen, collaboratorsPopoverRef appear above the cursor
114
+ var top = isVerticalDirectionBeyondScreen ? "".concat(caretPosition.y - offsetHeight + LINE_HEIGHT, "px") : "".concat(caretPosition.y + LINE_HEIGHT, "px");
115
+ collaboratorsPopoverRef.current.style.top = top;
116
+
117
+ // Whether the horizontal direction exceeds the screen
118
+ var isHorizontalDirectionBeyondScreen = caretPosition.x + FONT_SIZE_WIDTH + width > window.innerWidth;
119
+
120
+ // if the horizontal direction exceeds the screen, collaboratorsPopoverRef is displayed against the right side of the screen
121
+ var left = isHorizontalDirectionBeyondScreen ? "".concat(window.innerWidth - width, "px") : "".concat(caretPosition.x + FONT_SIZE_WIDTH, "px");
122
+ collaboratorsPopoverRef.current.style.left = left;
123
+ }, [collaboratorsPopoverRef]);
124
+ var getAtInfo = useCallback(function (event) {
125
+ var isValidOperation = checkMentionOperation(event);
126
+ if (!isValidOperation) return {
127
+ index: -1
128
+ };
129
+ var selection = window.getSelection();
130
+ var isCollapsed = selection.isCollapsed,
131
+ anchorNode = selection.anchorNode,
132
+ anchorOffset = selection.anchorOffset;
133
+ if (!isCollapsed || !anchorNode || !anchorNode.data) return {
134
+ index: -1
135
+ };
136
+ var text = anchorNode.data;
137
+ var index = commentUtilities.getAtIndexWithAnchorPosition(anchorOffset, text);
138
+ return {
139
+ index: index,
140
+ text: text,
141
+ selection: selection
142
+ };
143
+ }, [commentUtilities]);
144
+ var getSearchedCollaborators = useCallback(function (_ref2) {
145
+ var atIndex = _ref2.atIndex,
146
+ text = _ref2.text,
147
+ anchorOffset = _ref2.anchorOffset;
148
+ if (atIndex !== 0 && text[atIndex - 1] !== ' ') return [];
149
+ if (atIndex === anchorOffset - 1) return collaborators;
150
+ var searchingText = text.substring(atIndex + 1);
151
+ if (searchingText) return searchCollaborators(collaborators, searchingText);
152
+ return [];
153
+ }, [collaborators]);
154
+ var handleInvolvedKeyUp = useCallback(function (event) {
155
+ // atIndex: Positional index of @
156
+ var _getAtInfo = getAtInfo(event),
157
+ atIndex = _getAtInfo.index,
158
+ text = _getAtInfo.text,
159
+ selection = _getAtInfo.selection;
160
+ if (atIndex === -1) {
161
+ hideCommentPopover();
162
+ return;
163
+ }
164
+ var anchorOffset = selection.anchorOffset;
165
+ var searchedCollaborators = getSearchedCollaborators({
166
+ atIndex: atIndex,
167
+ text: text,
168
+ anchorOffset: anchorOffset
169
+ });
170
+ if (searchedCollaborators.length === 0) {
171
+ hideCommentPopover();
172
+ return;
173
+ }
174
+ setActiveCollaboratorIndex(0);
175
+ setRange(selection.getRangeAt(0));
176
+ setSearchedCollaborators(searchedCollaborators);
177
+ setTimeout(function () {
178
+ var caretPosition = getSelectionCoords();
179
+ setCollaboratorsPopoverPosition(caretPosition);
180
+ }, 1);
181
+ }, [getSearchedCollaborators, getAtInfo, hideCommentPopover, setCollaboratorsPopoverPosition]);
182
+ var handleSelectingCollaborator = useCallback(function (event, direction) {
183
+ eventStopPropagation(event);
184
+ var collaboratorsLen = searchedCollaborators.length;
185
+ if (collaboratorsLen === 0) return;
186
+ var nextActiveCollaboratorIndex = activeCollaboratorIndex;
187
+ if (direction === DOWN) {
188
+ nextActiveCollaboratorIndex++;
189
+ if (nextActiveCollaboratorIndex >= collaboratorsLen) {
190
+ nextActiveCollaboratorIndex = 0;
191
+ }
192
+ } else {
193
+ nextActiveCollaboratorIndex--;
194
+ if (nextActiveCollaboratorIndex < 0) {
195
+ nextActiveCollaboratorIndex = collaboratorsLen - 1;
196
+ }
197
+ }
198
+ setActiveCollaboratorIndex(nextActiveCollaboratorIndex);
199
+ }, [searchedCollaborators, activeCollaboratorIndex]);
200
+ var onSelectCollaborator = useCallback(function (collaborator) {
201
+ var selection = window.getSelection();
202
+ var callBack = function callBack() {
203
+ hideCommentPopover();
204
+ addParticipants(collaborator.username);
205
+ };
206
+ var newRange = commentUtilities.onSelectParticipant({
207
+ selection: selection,
208
+ range: range,
209
+ participant: collaborator,
210
+ callBack: callBack,
211
+ commentRef: commentRef
212
+ });
213
+ setRange(newRange);
214
+ }, [range, commentUtilities, hideCommentPopover, addParticipants]);
215
+ var handleSelectCollaborator = useCallback(function (event) {
216
+ if (searchedCollaborators.length === 0) return;
217
+ onSelectCollaborator(searchedCollaborators[activeCollaboratorIndex]);
218
+ }, [searchedCollaborators, activeCollaboratorIndex, onSelectCollaborator]);
219
+ var onKeyDown = useCallback(function (event) {
220
+ if (Hotkey.isModZ(event)) {
221
+ event.preventDefault();
222
+ event.stopPropagation();
223
+ hideCommentPopover();
224
+ event.nativeEvent.stopImmediatePropagation();
225
+ commentRef.current.innerHTML = '';
226
+ return;
227
+ }
228
+ if (Hotkey.isShiftEnter(event)) return;
229
+ if (Hotkey.isModP(event)) {
230
+ commentRef.current.blur();
231
+ }
232
+ if (event.keyCode === KeyCodes.Enter) {
233
+ event.preventDefault();
234
+ if (searchedCollaborators.length > 0) return;
235
+ onSubmit();
236
+ }
237
+ if (event.keyCode === KeyCodes.Esc) {
238
+ event.preventDefault();
239
+ onCancel();
240
+ }
241
+ if (event.keyCode === KeyCodes.UpArrow || event.keyCode === KeyCodes.DownArrow) {
242
+ event.stopPropagation();
243
+ if (searchedCollaborators.length > 0) {
244
+ event.preventDefault();
245
+ }
246
+ }
247
+ }, [onCancel, onSubmit, searchedCollaborators, commentRef, hideCommentPopover]);
248
+ var onKeyUp = useCallback(function (event) {
249
+ var selection = window.getSelection();
250
+ setRange(selection.getRangeAt(0));
251
+ if (event.keyCode === KeyCodes.DownArrow) {
252
+ handleSelectingCollaborator(event, DOWN);
253
+ return;
254
+ }
255
+ if (event.keyCode === KeyCodes.UpArrow) {
256
+ handleSelectingCollaborator(event, UP);
257
+ return;
258
+ }
259
+ if (event.keyCode === KeyCodes.Enter) {
260
+ handleSelectCollaborator();
261
+ return;
262
+ }
263
+ handleInvolvedKeyUp(event);
264
+ }, [handleSelectingCollaborator, handleInvolvedKeyUp, handleSelectCollaborator]);
265
+ var onMouseUp = useCallback(function () {
266
+ var selection = window.getSelection();
267
+ setRange(selection.getRangeAt(0));
268
+ }, []);
269
+ var onPaste = useCallback(function (event) {
270
+ commentUtilities.onPaste(event);
271
+ }, [commentUtilities]);
272
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
273
+ ref: commentRef,
274
+ contentEditable: "true",
275
+ className: "comment-editor",
276
+ placeholder: t(placeholder),
277
+ onKeyDown: onKeyDown,
278
+ onKeyUp: onKeyUp,
279
+ onMouseUp: onMouseUp,
280
+ onPaste: onPaste
281
+ }), searchedCollaborators.length > 0 && /*#__PURE__*/React.createElement(ModalPortal, null, /*#__PURE__*/React.createElement("div", {
282
+ className: "sdoc-comment-caret-list",
283
+ ref: collaboratorsPopoverRef
284
+ }, searchedCollaborators.map(function (participant, index) {
285
+ return /*#__PURE__*/React.createElement(CommentParticipantItem, {
286
+ key: participant.username,
287
+ participantIndex: index,
288
+ activeParticipantIndex: activeCollaboratorIndex,
289
+ participant: participant,
290
+ setScrollTop: setScrollTop,
291
+ onSelectParticipant: onSelectCollaborator
292
+ });
293
+ }))));
294
+ });
295
+ export default CommentInput;
@@ -6,6 +6,7 @@ import { Dropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap
6
6
  import dayjs from 'dayjs';
7
7
  import CommentEditor from './comment-editor';
8
8
  import Tooltip from '../../../components/tooltip';
9
+ import { textToHtml } from '../utils';
9
10
  var CommentItem = function CommentItem(_ref) {
10
11
  var isActive = _ref.isActive,
11
12
  container = _ref.container,
@@ -121,8 +122,12 @@ var CommentItem = function CommentItem(_ref) {
121
122
  onClick: resubmit
122
123
  }, t('Resubmit')))))), /*#__PURE__*/React.createElement("div", {
123
124
  className: "comment-content"
124
- }, !isEditing && /*#__PURE__*/React.createElement(React.Fragment, null, comment.comment)), isEditing && /*#__PURE__*/React.createElement(CommentEditor, {
125
- className: 'pb-3',
125
+ }, !isEditing && /*#__PURE__*/React.createElement("div", {
126
+ dangerouslySetInnerHTML: {
127
+ __html: textToHtml(comment.comment)
128
+ }
129
+ })), isEditing && /*#__PURE__*/React.createElement(CommentEditor, {
130
+ className: "pb-3",
126
131
  content: comment.comment,
127
132
  updateContent: updateContent,
128
133
  setIsEditing: setIsEditing
@@ -6,6 +6,7 @@ import dayjs from 'dayjs';
6
6
  import context from '../../../context';
7
7
  import CommentEditor from './comment-editor';
8
8
  import CommentDeleteShadow from './comment-delete-shadow';
9
+ import { textToHtml } from '../utils';
9
10
  var CommentItemReply = function CommentItemReply(_ref) {
10
11
  var isActive = _ref.isActive,
11
12
  container = _ref.container,
@@ -89,7 +90,11 @@ var CommentItemReply = function CommentItemReply(_ref) {
89
90
  onClick: onDeleteToggle
90
91
  }, t('Delete')))))), /*#__PURE__*/React.createElement("div", {
91
92
  className: "comment-content"
92
- }, !isEditing && /*#__PURE__*/React.createElement(React.Fragment, null, reply.reply)), isEditing && /*#__PURE__*/React.createElement(CommentEditor, {
93
+ }, !isEditing && /*#__PURE__*/React.createElement("div", {
94
+ dangerouslySetInnerHTML: {
95
+ __html: textToHtml(reply.reply)
96
+ }
97
+ })), isEditing && /*#__PURE__*/React.createElement(CommentEditor, {
93
98
  className: 'pb-3',
94
99
  type: "reply",
95
100
  content: reply.reply,
@@ -12,6 +12,7 @@ import CommentItemReply from './comment-item-reply';
12
12
  import CommentEditor from './comment-editor';
13
13
  import CommentItemResolvedReply from './comment-item-resolved-reply';
14
14
  import CommentDeleteShadow from './comment-delete-shadow';
15
+ import { COMMENT_URL_CLASSNAME } from '../constants';
15
16
  export default function CommentItemWrapper(_ref) {
16
17
  var container = _ref.container,
17
18
  isActive = _ref.isActive,
@@ -300,7 +301,8 @@ export default function CommentItemWrapper(_ref) {
300
301
  return _ref7.apply(this, arguments);
301
302
  };
302
303
  }(), [comment.detail, comment.id, dispatch]);
303
- var onItemClick = useCallback(function () {
304
+ var onItemClick = useCallback(function (event) {
305
+ if (event.target.className === COMMENT_URL_CLASSNAME) return;
304
306
  onCommentClick(comment);
305
307
  }, [comment, onCommentClick]);
306
308
  var _useState = useState(false),
@@ -0,0 +1,132 @@
1
+ .sdoc-comments-participants-popover .popover {
2
+ max-width: 282px;
3
+ margin-top: 0px;
4
+ }
5
+
6
+ .sdoc-comments-participants-popover .sdoc-comments-participants-editor-container {
7
+ min-height: 160px;
8
+ width: 280px;
9
+ }
10
+
11
+ .sdoc-comments-participants-popover .selected-participants {
12
+ background-color: #f6f6f6;
13
+ padding: 5px;
14
+ border-bottom: 1px solid #dde2ea;
15
+ border-radius: 3px 3px 0 0;
16
+ min-height: 34px;
17
+ }
18
+
19
+ .sdoc-comments-participants-popover .selected-participant {
20
+ display: inline-flex;
21
+ align-items: center;
22
+ height: 20px;
23
+ margin-right: 10px;
24
+ padding: 0 8px 0 2px;
25
+ font-size: 13px;
26
+ border-radius: 10px;
27
+ background: #eaeaea;
28
+ }
29
+
30
+ .sdoc-comments-participants-popover .selected-participant img {
31
+ width: 16px;
32
+ height: 16px;
33
+ border-radius: 50%;
34
+ vertical-align: middle;
35
+ }
36
+
37
+ .sdoc-comments-participants-popover .selected-participant .selected-participant-name {
38
+ margin-left: 4px;
39
+ flex: 1 1;
40
+ color: #16181b;
41
+ }
42
+
43
+ .sdoc-comments-participants-popover .selected-participant .selected-participant-delete {
44
+ width: 20px;
45
+ height: 20px;
46
+ display: flex;
47
+ justify-content: flex-end;
48
+ align-items: center;
49
+ padding-top: 1px;
50
+ cursor: pointer;
51
+ }
52
+
53
+ .sdoc-comments-participants-popover .selected-participant .selected-participant-delete .sdocfont {
54
+ display: inline-block;
55
+ font-size: 12px;
56
+ color: #909090;
57
+ }
58
+
59
+ .sdoc-comments-participants-popover .selected-participant .selected-participant-delete:hover .sdocfont {
60
+ color: #5a5a5a;
61
+ }
62
+
63
+ .sdoc-comments-participants-popover .search-collaborators {
64
+ padding: 10px;
65
+ }
66
+
67
+ .sdoc-comments-participants-popover .search-collaborators input {
68
+ height: 28px;
69
+ }
70
+
71
+ .sdoc-comments-participants-popover .searched-collaborators {
72
+ display: flex;
73
+ flex-direction: column;
74
+ align-items: center;
75
+ max-height: 200px;
76
+ padding: 10px;
77
+ overflow: auto;
78
+ }
79
+
80
+ .sdoc-comments-participants-popover .searched-collaborators.empty-tip {
81
+ opacity: .5;
82
+ font-size: 14px;
83
+ align-items: flex-start;
84
+ }
85
+
86
+ .sdoc-comments-participants-popover .searched-collaborator {
87
+ display: flex;
88
+ align-items: center;
89
+ width: 100%;
90
+ padding: 0.25rem 0;
91
+ clear: both;
92
+ font-weight: 400;
93
+ color: #212529;
94
+ height: 30px;
95
+ border-radius: 2px;
96
+ font-size: 14px;
97
+ }
98
+
99
+ .sdoc-comments-participants-popover .searched-collaborator:hover {
100
+ cursor: pointer;
101
+ background-color: #f8f9fa;
102
+ }
103
+
104
+ .sdoc-comments-participants-popover .searched-collaborator img {
105
+ width: 16px;
106
+ height: 16px;
107
+ margin-left: 10px;
108
+ border-radius: 50%;
109
+ vertical-align: middle;
110
+ }
111
+
112
+ .sdoc-comments-participants-popover .searched-collaborator .selected-participant-name {
113
+ flex: 1;
114
+ overflow: hidden;
115
+ text-overflow: ellipsis;
116
+ white-space: nowrap;
117
+ margin-left: 4px;
118
+ color: #16181b;
119
+ }
120
+
121
+ .sdoc-comments-participants-popover .searched-collaborator .searched-collaborator-operation {
122
+ width: 20px;
123
+ height: 20px;
124
+ display: flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ }
128
+
129
+ .sdoc-comments-participants-popover .searched-collaborator .searched-collaborator-operation .sdocfont {
130
+ font-size: 12px;
131
+ color: #798d99;
132
+ }
@@ -0,0 +1,67 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import React, { useCallback, useRef, useState, useImperativeHandle, forwardRef } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { UncontrolledPopover } from 'reactstrap';
5
+ import { useCollaborators } from '../../../../hooks/';
6
+ import SelectedParticipants from './selected-participants';
7
+ import SearchedCollaborators from './searched-collaborators';
8
+ import { searchCollaborators } from '../../utils';
9
+ import { eventStopPropagation } from '../../../utils/mouse-event';
10
+ import './index.css';
11
+ var CommentParticipantsEditor = forwardRef(function (_ref, ref) {
12
+ var target = _ref.target;
13
+ var popoverRef = useRef();
14
+ var _useCollaborators = useCollaborators(),
15
+ collaborators = _useCollaborators.collaborators;
16
+ var _useTranslation = useTranslation(),
17
+ t = _useTranslation.t;
18
+ var _useState = useState(''),
19
+ _useState2 = _slicedToArray(_useState, 2),
20
+ searchValue = _useState2[0],
21
+ setSearchValue = _useState2[1];
22
+ var _useState3 = useState([]),
23
+ _useState4 = _slicedToArray(_useState3, 2),
24
+ searchedCollaborators = _useState4[0],
25
+ setSearchedCollaborators = _useState4[1];
26
+ useImperativeHandle(ref, function () {
27
+ return {
28
+ toggle: function toggle() {
29
+ popoverRef.current && popoverRef.current.toggle();
30
+ }
31
+
32
+ // eslint-disable-next-line react-hooks/exhaustive-deps
33
+ };
34
+ }, [popoverRef.current]);
35
+ var onChangeSearch = useCallback(function (event) {
36
+ var newSearchValue = event.target.value;
37
+ if (searchValue === newSearchValue) return;
38
+ var searchedCollaborators = searchCollaborators(collaborators, newSearchValue);
39
+ setSearchValue(newSearchValue);
40
+ setSearchedCollaborators(searchedCollaborators);
41
+ }, [searchValue, collaborators]);
42
+ return /*#__PURE__*/React.createElement(UncontrolledPopover, {
43
+ target: target,
44
+ className: "sdoc-comments-participants-popover",
45
+ placement: "bottom-start",
46
+ hideArrow: true,
47
+ trigger: "legacy",
48
+ fade: false,
49
+ ref: popoverRef
50
+ }, /*#__PURE__*/React.createElement("div", {
51
+ className: "sdoc-comments-participants-editor-container",
52
+ onClick: function onClick(event) {
53
+ return eventStopPropagation(event);
54
+ }
55
+ }, /*#__PURE__*/React.createElement(SelectedParticipants, null), /*#__PURE__*/React.createElement("div", {
56
+ className: "search-collaborators"
57
+ }, /*#__PURE__*/React.createElement("input", {
58
+ className: "form-control",
59
+ type: "text",
60
+ placeholder: t('Find_a_collaborator'),
61
+ value: searchValue,
62
+ onChange: onChangeSearch
63
+ })), /*#__PURE__*/React.createElement(SearchedCollaborators, {
64
+ collaborators: searchValue ? searchedCollaborators : collaborators
65
+ })));
66
+ });
67
+ export default CommentParticipantsEditor;
@@ -0,0 +1,53 @@
1
+ import React, { useCallback } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { useParticipantsContext } from '../../hooks/use-participants';
4
+ import { eventStopPropagation } from '../../../utils/mouse-event';
5
+ var SearchedCollaborators = function SearchedCollaborators(_ref) {
6
+ var collaborators = _ref.collaborators;
7
+ var _useParticipantsConte = useParticipantsContext(),
8
+ participants = _useParticipantsConte.participants,
9
+ deleteParticipant = _useParticipantsConte.deleteParticipant,
10
+ addParticipants = _useParticipantsConte.addParticipants;
11
+ var _useTranslation = useTranslation(),
12
+ t = _useTranslation.t;
13
+ var onSelectParticipant = useCallback(function (event, participant, isSelected) {
14
+ eventStopPropagation(event);
15
+ if (isSelected) {
16
+ deleteParticipant(participant.username);
17
+ return;
18
+ }
19
+ addParticipants(participant.username);
20
+ }, [deleteParticipant, addParticipants]);
21
+ if (!Array.isArray(collaborators) || collaborators.length === 0) {
22
+ return /*#__PURE__*/React.createElement("div", {
23
+ className: "searched-collaborators empty-tip"
24
+ }, t('No_collaborators_available'));
25
+ }
26
+ return /*#__PURE__*/React.createElement("div", {
27
+ className: "searched-collaborators"
28
+ }, collaborators.map(function (collaborator) {
29
+ var name = collaborator.name,
30
+ username = collaborator.username,
31
+ avatar_url = collaborator.avatar_url;
32
+ var isSelected = participants.find(function (participant) {
33
+ return participant.username === username;
34
+ });
35
+ return /*#__PURE__*/React.createElement("div", {
36
+ key: username,
37
+ className: "searched-collaborator",
38
+ onClick: function onClick(event) {
39
+ return onSelectParticipant(event, collaborator, isSelected);
40
+ }
41
+ }, /*#__PURE__*/React.createElement("img", {
42
+ src: avatar_url,
43
+ alt: ""
44
+ }), /*#__PURE__*/React.createElement("div", {
45
+ className: "selected-participant-name"
46
+ }, name), /*#__PURE__*/React.createElement("div", {
47
+ className: "searched-collaborator-operation"
48
+ }, isSelected && /*#__PURE__*/React.createElement("i", {
49
+ className: "sdocfont sdoc-check-mark"
50
+ })));
51
+ }));
52
+ };
53
+ export default SearchedCollaborators;
@@ -0,0 +1,39 @@
1
+ import React, { useCallback } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { useParticipantsContext } from '../../hooks/use-participants';
4
+ var SelectedParticipants = function SelectedParticipants() {
5
+ var _useParticipantsConte = useParticipantsContext(),
6
+ participants = _useParticipantsConte.participants,
7
+ deleteParticipant = _useParticipantsConte.deleteParticipant;
8
+ var _useTranslation = useTranslation(),
9
+ t = _useTranslation.t;
10
+ var onDeleteParticipant = useCallback(function (participant) {
11
+ deleteParticipant(participant.username);
12
+ }, [deleteParticipant]);
13
+ if (!Array.isArray(participants) || participants.length === 0) return null;
14
+ return /*#__PURE__*/React.createElement("div", {
15
+ className: "selected-participants"
16
+ }, participants.map(function (participant) {
17
+ var name = participant.name,
18
+ username = participant.username,
19
+ avatar_url = participant.avatar_url;
20
+ return /*#__PURE__*/React.createElement("div", {
21
+ key: username,
22
+ className: "selected-participant"
23
+ }, /*#__PURE__*/React.createElement("img", {
24
+ src: avatar_url,
25
+ alt: ""
26
+ }), /*#__PURE__*/React.createElement("div", {
27
+ className: "selected-participant-name"
28
+ }, name), /*#__PURE__*/React.createElement("div", {
29
+ className: "selected-participant-delete",
30
+ onClick: function onClick() {
31
+ return onDeleteParticipant(participant);
32
+ },
33
+ title: t('Delete')
34
+ }, /*#__PURE__*/React.createElement("i", {
35
+ className: "sdocfont sdoc-sm-close"
36
+ })));
37
+ }));
38
+ };
39
+ export default SelectedParticipants;
@@ -3,11 +3,8 @@ import React, { useCallback, useState } from 'react';
3
3
  import { withTranslation } from 'react-i18next';
4
4
  import { Dropdown, DropdownItem, DropdownMenu, DropdownToggle } from 'reactstrap';
5
5
  import { eventStopPropagation } from '../../utils/mouse-event';
6
- export var COMMENT_TYPES = {
7
- all: 'All_comments',
8
- resolved: 'Resolved_comments',
9
- unresolved: 'Unresolved_comments'
10
- };
6
+ import { COMMENT_TYPES } from '../constants';
7
+ import CommentAllParticipants from './comment-all-participants';
11
8
  function GlobalCommentHeader(_ref) {
12
9
  var commentType = _ref.commentType,
13
10
  commentList = _ref.commentList,
@@ -34,6 +31,8 @@ function GlobalCommentHeader(_ref) {
34
31
  var id = 'comment-type-controller';
35
32
  return /*#__PURE__*/React.createElement("div", {
36
33
  className: "comments-panel-body__header"
34
+ }, /*#__PURE__*/React.createElement(CommentAllParticipants, null), /*#__PURE__*/React.createElement("div", {
35
+ className: "comments-types-count"
37
36
  }, /*#__PURE__*/React.createElement("div", {
38
37
  id: "comment-types",
39
38
  className: "comment-type"
@@ -71,6 +70,6 @@ function GlobalCommentHeader(_ref) {
71
70
  }
72
71
  }, t(COMMENT_TYPES.unresolved))))), /*#__PURE__*/React.createElement("div", {
73
72
  className: "comment-count-tip"
74
- }, commentTip));
73
+ }, commentTip)));
75
74
  }
76
75
  export default withTranslation('sdoc-editor')(GlobalCommentHeader);