@seafile/sdoc-editor 2.0.69 → 2.0.71

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 (58) hide show
  1. package/dist/basic-sdk/comment/comment-decorate.js +17 -17
  2. package/dist/basic-sdk/comment/components/comment-context-menu/index.css +16 -0
  3. package/dist/basic-sdk/comment/components/comment-context-menu/index.js +38 -0
  4. package/dist/basic-sdk/comment/components/comment-context-menu/menu-item.js +57 -0
  5. package/dist/basic-sdk/comment/components/comment-editor.js +5 -2
  6. package/dist/basic-sdk/comment/components/comment-item-collapse-wrapper.js +17 -1
  7. package/dist/basic-sdk/comment/components/comment-item-wrapper.js +85 -30
  8. package/dist/basic-sdk/comment/components/comment-list.css +34 -0
  9. package/dist/basic-sdk/comment/components/comment-list.js +96 -20
  10. package/dist/basic-sdk/comment/components/editor-comment.js +117 -57
  11. package/dist/basic-sdk/comment/components/elements-comment-count/index.js +15 -3
  12. package/dist/basic-sdk/comment/components/global-comment/index.css +25 -0
  13. package/dist/basic-sdk/comment/helper.js +111 -2
  14. package/dist/basic-sdk/comment/reducer/comment-reducer.js +2 -3
  15. package/dist/basic-sdk/constants/index.js +2 -1
  16. package/dist/basic-sdk/editor/sdoc-editor.js +4 -4
  17. package/dist/basic-sdk/extension/commons/color-menu/index.js +3 -3
  18. package/dist/basic-sdk/extension/commons/file-insert-dialog/index.js +5 -4
  19. package/dist/basic-sdk/extension/commons/wiki-file-insert-dialog/index.js +5 -4
  20. package/dist/basic-sdk/extension/core/queries/index.js +2 -3
  21. package/dist/basic-sdk/extension/core/utils/index.js +1 -29
  22. package/dist/basic-sdk/extension/plugins/ai/ai-icon/index.js +2 -2
  23. package/dist/basic-sdk/extension/plugins/ai/ai-module/helpers.js +4 -0
  24. package/dist/basic-sdk/extension/plugins/font/menu/font-family/index.js +1 -1
  25. package/dist/basic-sdk/extension/plugins/header/placeholder.js +33 -0
  26. package/dist/basic-sdk/extension/plugins/header/render-elem.js +2 -2
  27. package/dist/basic-sdk/extension/plugins/multi-column/helper.js +1 -1
  28. package/dist/basic-sdk/extension/plugins/paragraph/render-elem.js +2 -1
  29. package/dist/basic-sdk/extension/plugins/table/menu/color-selector-popover/index.js +3 -3
  30. package/dist/basic-sdk/extension/plugins/text-style/menu/index.js +2 -1
  31. package/dist/basic-sdk/extension/plugins/text-style/render-elem.js +28 -4
  32. package/dist/basic-sdk/hooks/use-selection-position.js +51 -30
  33. package/dist/basic-sdk/layout/article-container.js +1 -1
  34. package/dist/basic-sdk/layout/editor-content.js +1 -1
  35. package/dist/basic-sdk/node-id/helpers.js +26 -2
  36. package/dist/basic-sdk/node-id/index.js +37 -2
  37. package/dist/basic-sdk/right-panel/index.js +4 -4
  38. package/dist/basic-sdk/utils/common-utils.js +43 -0
  39. package/dist/basic-sdk/utils/default-mode.js +1 -1
  40. package/dist/basic-sdk/utils/document-utils.js +16 -2
  41. package/dist/basic-sdk/utils/full-width-mode.js +1 -1
  42. package/dist/basic-sdk/views/published-revision-diff-viewer.js +1 -1
  43. package/dist/basic-sdk/views/revision-diff-viewer.js +1 -1
  44. package/dist/basic-sdk/views/sdoc-diff-viewer.js +1 -1
  45. package/dist/basic-sdk/views/sdoc-viewer.js +2 -2
  46. package/dist/basic-sdk/views/sdoc-wiki-viewer.js +2 -2
  47. package/dist/components/doc-operations/more-operations.js +1 -1
  48. package/dist/layout/layout.js +3 -3
  49. package/dist/pages/simple-viewer.js +1 -1
  50. package/dist/plugin-module/layout/editor-content.js +1 -1
  51. package/dist/plugin-module/views/plugin-viewer.js +2 -2
  52. package/dist/utils/index.js +2 -61
  53. package/package.json +1 -1
  54. package/public/locales/en/sdoc-editor.json +2 -1
  55. package/public/locales/zh_CN/sdoc-editor.json +2 -1
  56. package/dist/plugin-module/assets/css/sdoc-wiki-viewer.css +0 -28
  57. /package/dist/{assets → basic-sdk/assets}/css/diff-viewer.css +0 -0
  58. /package/dist/{utils → basic-sdk/utils}/local-storage-utils.js +0 -0
@@ -10,23 +10,23 @@ const commentDecorate = editor => _ref => {
10
10
  let [node, path] = _ref;
11
11
  const decorations = [];
12
12
  const comments = ((_editor$element_comme = editor.element_comments_map) === null || _editor$element_comme === void 0 ? void 0 : _editor$element_comme[node.id]) || [];
13
- const unresolvedComments = comments && comments.filter(item => !item.resolved);
14
- if (unresolvedComments && unresolvedComments.length > 0) {
15
- let decoration = {
16
- anchor: {
17
- path,
18
- offset: 0
19
- },
20
- focus: {
21
- path: path,
22
- offset: _slate.Node.string(node).length
23
- }
24
- };
25
-
26
- // rgba prevents occlusion of the cursor
27
- decoration['computed_background_color'] = 'rgba(129, 237, 247, 0.5)';
28
- decoration['comment_count'] = unresolvedComments === null || unresolvedComments === void 0 ? void 0 : unresolvedComments.length;
29
- decorations.push(decoration);
13
+ const unresolvedComments = comments && comments.filter(item => !(item !== null && item !== void 0 && item.resolved));
14
+ for (const comment of unresolvedComments) {
15
+ if (comment.detail.element_id) {
16
+ const commentedContextId = comment.detail.text_comment_id;
17
+ // rgba prevents occlusion of the cursor
18
+ decorations.push({
19
+ anchor: {
20
+ path,
21
+ offset: 0
22
+ },
23
+ focus: {
24
+ path: path,
25
+ offset: _slate.Node.string(node).length
26
+ },
27
+ [`sdoc_comment_${commentedContextId}`]: true
28
+ });
29
+ }
30
30
  }
31
31
  return decorations;
32
32
  };
@@ -0,0 +1,16 @@
1
+ .menu-group-item.sdoc-comment-menu-container {
2
+ width: 90px;
3
+ color: #212529;
4
+ font-size: 14px;
5
+ }
6
+
7
+ .sdoc-comment-menu-item .sdoc-comments {
8
+ margin-right: 4px;
9
+ }
10
+
11
+ .sdoc-context-menu-divider {
12
+ margin-right: 8px;
13
+ border-left: 1px solid #e5e5e5;
14
+ width: 1px;
15
+ height: 24px;
16
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _constants = require("../../../constants");
11
+ var _eventBus = _interopRequireDefault(require("../../../utils/event-bus"));
12
+ var _menuItem = _interopRequireDefault(require("./menu-item"));
13
+ require("./index.css");
14
+ const CommentContextMenu = _ref => {
15
+ let {
16
+ isRichEditor
17
+ } = _ref;
18
+ const onCommentClick = (0, _react.useCallback)(event => {
19
+ const eventBus = _eventBus.default.getInstance();
20
+ eventBus.dispatch(_constants.INTERNAL_EVENT.ADD_CONTEXT_COMMENT);
21
+ }, []);
22
+ const commentProps = {
23
+ id: 'context-toolbar-comment',
24
+ isRichEditor,
25
+ className: 'menu-group-item sdoc-comment-menu-container',
26
+ disabled: false,
27
+ isActive: false,
28
+ onMouseDown: onCommentClick,
29
+ iconClass: 'sdocfont sdoc-comments',
30
+ text: 'Comment',
31
+ ariaLabel: 'Add_Comment',
32
+ type: 'sdoc-add-comment'
33
+ };
34
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
35
+ className: "sdoc-context-menu-divider"
36
+ }), /*#__PURE__*/_react.default.createElement(_menuItem.default, commentProps));
37
+ };
38
+ var _default = exports.default = CommentContextMenu;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _reactI18next = require("react-i18next");
11
+ var _classnames = _interopRequireDefault(require("classnames"));
12
+ var _tooltip = _interopRequireDefault(require("../../../../components/tooltip"));
13
+ const MenuItem = _ref => {
14
+ let {
15
+ isRichEditor = true,
16
+ className = 'menu-group-item',
17
+ disabled,
18
+ isActive,
19
+ type,
20
+ onMouseDown,
21
+ id,
22
+ text,
23
+ ariaLabel,
24
+ iconClass
25
+ } = _ref;
26
+ const {
27
+ t
28
+ } = (0, _reactI18next.useTranslation)('sdoc-editor');
29
+ const onClick = (0, _react.useCallback)(event => {
30
+ if (disabled) return;
31
+ onMouseDown(event, type);
32
+
33
+ // eslint-disable-next-line react-hooks/exhaustive-deps
34
+ }, [disabled, type]);
35
+ const validClassName = (0, _classnames.default)('', className, {
36
+ 'btn btn-icon btn-secondary btn-active': !isRichEditor,
37
+ 'rich-icon-btn': isRichEditor,
38
+ 'rich-icon-btn-disabled': isRichEditor && disabled,
39
+ 'rich-icon-btn-hover': isRichEditor && !disabled
40
+ });
41
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("button", {
42
+ id: id,
43
+ type: "button",
44
+ "aria-label": ariaLabel,
45
+ className: validClassName,
46
+ disabled: disabled,
47
+ "data-active": isActive,
48
+ onClick: onClick
49
+ }, /*#__PURE__*/_react.default.createElement("span", {
50
+ className: "sdoc-comment-menu-item"
51
+ }, /*#__PURE__*/_react.default.createElement("span", {
52
+ className: iconClass
53
+ }), /*#__PURE__*/_react.default.createElement("span", null, t(text)))), /*#__PURE__*/_react.default.createElement(_tooltip.default, {
54
+ target: id
55
+ }, t(ariaLabel)));
56
+ };
57
+ var _default = exports.default = MenuItem;
@@ -40,7 +40,9 @@ const CommentEditor = _ref => {
40
40
  setIsEditing,
41
41
  hiddenComment,
42
42
  hiddenUserInfo,
43
- onContentChange
43
+ onContentChange,
44
+ isContextComment,
45
+ closeComment
44
46
  } = _ref;
45
47
  const commentWrapperRef = (0, _react.useRef)();
46
48
  const {
@@ -88,7 +90,8 @@ const CommentEditor = _ref => {
88
90
  })];
89
91
  _slate.Transforms.select(editor, _slate.Editor.start(editor, []));
90
92
  onContentChange && onContentChange(null);
91
- }, [editor, updateValue, addParticipants, userInfo.username, placeholder, onContentChange]);
93
+ closeComment && closeComment();
94
+ }, [editor, updateValue, addParticipants, userInfo.username, placeholder, onContentChange, closeComment]);
92
95
  const onSubmitByEnterKey = (0, _react.useCallback)(event => {
93
96
  if (!_slateReact.ReactEditor.isFocused(editor)) return;
94
97
  onSubmit(event);
@@ -14,8 +14,10 @@ var _classnames = _interopRequireDefault(require("classnames"));
14
14
  var _dayjs = _interopRequireDefault(require("dayjs"));
15
15
  var _mdToHtml = _interopRequireDefault(require("../../../slate-convert/md-to-html"));
16
16
  var _constants = require("../constants");
17
+ var _helper = require("../helper");
17
18
  var _notificationHooks = require("../hooks/notification-hooks");
18
19
  const CommentItemCollapseWrapper = _ref => {
20
+ var _topLevelComment$deta;
19
21
  let {
20
22
  element,
21
23
  topLevelComment,
@@ -82,7 +84,21 @@ const CommentItemCollapseWrapper = _ref => {
82
84
  'd-flex flex-column': element
83
85
  }),
84
86
  onClick: onItemClick
85
- }, element && /*#__PURE__*/_react.default.createElement("div", {
87
+ }, topLevelComment.detail.element_id_list && /*#__PURE__*/_react.default.createElement("div", {
88
+ className: (0, _classnames.default)('comment-item-selected-text-container', {
89
+ 'detail-context-comment': ((_topLevelComment$deta = topLevelComment.detail.element_id_list) === null || _topLevelComment$deta === void 0 ? void 0 : _topLevelComment$deta.length) > 0
90
+ }),
91
+ onClick: handleScrollToArticle
92
+ }, /*#__PURE__*/_react.default.createElement("i", {
93
+ className: "sdocfont sdoc-comment-quote mr-2"
94
+ }), /*#__PURE__*/_react.default.createElement("div", {
95
+ className: "comment-item-selected-text"
96
+ }, topLevelComment.detail.element_id_list.map((elementId, index) => {
97
+ return /*#__PURE__*/_react.default.createElement("div", {
98
+ className: "context-comment-item-selected-text",
99
+ key: index
100
+ }, (0, _helper.getCommentedTextsByElementId)(elementId, topLevelComment.detail.text_comment_id));
101
+ }))), element && /*#__PURE__*/_react.default.createElement("div", {
86
102
  className: "comment-item-selected-text-container",
87
103
  onClick: handleScrollToArticle
88
104
  }, /*#__PURE__*/_react.default.createElement("i", {
@@ -13,24 +13,31 @@ var _classnames = _interopRequireDefault(require("classnames"));
13
13
  var _dayjs = _interopRequireDefault(require("dayjs"));
14
14
  var _context = _interopRequireDefault(require("../../../context"));
15
15
  var _constants = require("../constants");
16
+ var _helper = require("../helper");
16
17
  var _useCommentContext = require("../hooks/comment-hooks/use-comment-context");
17
18
  var _commentDeletePopover = _interopRequireDefault(require("./comment-delete-popover"));
18
19
  var _commentItemContent = _interopRequireDefault(require("./comment-item-content"));
19
20
  var _commentItemReply = _interopRequireDefault(require("./comment-item-reply"));
20
- const CommentItemWrapper = _ref => {
21
+ const CommentItemWrapper = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
21
22
  let {
22
23
  container = 'sdoc-comment-list-container',
23
24
  editor,
24
25
  element,
25
26
  isActive,
26
27
  comment,
28
+ commentsDetail,
29
+ setIsClickedContextComment,
30
+ setIsCommentPanelVisible,
31
+ onSelectElement,
27
32
  isGlobalComment,
28
33
  commentDetailRef,
29
34
  updateScrollPosition,
30
35
  setCurrentCommentGroup,
31
36
  onCommentClick,
32
37
  isEmptyComment,
33
- isCollapseCommentEditor
38
+ isCollapseCommentEditor,
39
+ isClickedContextComment = false,
40
+ closeComment
34
41
  } = _ref;
35
42
  const listRef = (0, _react.useRef)(null);
36
43
  const {
@@ -44,9 +51,15 @@ const CommentItemWrapper = _ref => {
44
51
  } : {};
45
52
  const deleteComment = (0, _react.useCallback)(async commentId => {
46
53
  await _context.default.deleteComment(commentId);
47
- const {
48
- element_id: elementId
54
+ let {
55
+ element_id: elementId,
56
+ element_id_list
49
57
  } = comment.detail;
58
+ if (element_id_list) {
59
+ var _comment$detail;
60
+ elementId = element_id_list[0];
61
+ (0, _helper.updateCommentedElementsAttrs)(element_id_list, editor, (_comment$detail = comment.detail) === null || _comment$detail === void 0 ? void 0 : _comment$detail.text_comment_id, false, true);
62
+ }
50
63
  dispatch({
51
64
  type: 'DELETE_COMMENT',
52
65
  payload: {
@@ -54,12 +67,11 @@ const CommentItemWrapper = _ref => {
54
67
  comment_id: commentId
55
68
  }
56
69
  });
57
- }, [comment.detail, dispatch]);
70
+ closeComment && closeComment();
71
+ }, [comment.detail, dispatch, editor]);
58
72
  const updateComment = (0, _react.useCallback)(async (commentId, newComment) => {
59
73
  await _context.default.updateComment(commentId, newComment);
60
- const {
61
- element_id: elementId
62
- } = comment.detail;
74
+ const elementId = (0, _helper.getPrimaryElementId)(comment.detail);
63
75
  dispatch({
64
76
  type: 'UPDATE_COMMENT',
65
77
  payload: {
@@ -91,9 +103,26 @@ const CommentItemWrapper = _ref => {
91
103
  user_name: returnReply.user_name,
92
104
  avatar_url: returnReply.avatar_url
93
105
  };
94
- const {
95
- element_id: elementId
96
- } = comment.detail;
106
+ const elementId = (0, _helper.getPrimaryElementId)(comment.detail);
107
+ if (newComment.resolved === true) {
108
+ const resolvedComment = commentsDetail ? Object.values(commentsDetail).find(comments => comments.id === commentId) : comment;
109
+ if (resolvedComment.detail.element_id_list) {
110
+ var _resolvedComment$deta;
111
+ (0, _helper.updateCommentedElementsAttrs)(resolvedComment.detail.element_id_list, editor, (_resolvedComment$deta = resolvedComment.detail) === null || _resolvedComment$deta === void 0 ? void 0 : _resolvedComment$deta.text_comment_id, !newComment.resolved);
112
+ closeComment && closeComment();
113
+ }
114
+ if (commentsDetail && Object.values(commentsDetail).length === 1) {
115
+ setIsClickedContextComment(false);
116
+ setIsCommentPanelVisible(false);
117
+ }
118
+ }
119
+ if (newComment.resolved === false && comment.detail.element_id_list) {
120
+ const unresolvedComment = commentsDetail ? Object.values(commentsDetail).find(comments => comments.id === commentId) : comment;
121
+ if (unresolvedComment.detail.element_id_list) {
122
+ var _unresolvedComment$de;
123
+ (0, _helper.updateCommentedElementsAttrs)(unresolvedComment.detail.element_id_list, editor, (_unresolvedComment$de = unresolvedComment.detail) === null || _unresolvedComment$de === void 0 ? void 0 : _unresolvedComment$de.text_comment_id, !newComment.resolved);
124
+ }
125
+ }
97
126
  dispatch({
98
127
  type: 'INSERT_REPLY',
99
128
  payload: {
@@ -115,16 +144,14 @@ const CommentItemWrapper = _ref => {
115
144
  });
116
145
 
117
146
  // If the status of the comment is set to resolved, the page jumps to the position of the comment
118
- if (newComment.resolved === true) {
147
+ if (!isClickedContextComment && newComment.resolved === true) {
119
148
  setTimeout(() => {
120
149
  updateScrollPosition && updateScrollPosition();
121
150
  }, 100);
122
151
  }
123
- }, [comment.detail, dispatch, updateScrollPosition]);
152
+ }, [comment, commentsDetail, dispatch, editor, isClickedContextComment, setIsClickedContextComment, setIsCommentPanelVisible, updateScrollPosition]);
124
153
  const insertReply = (0, _react.useCallback)(async (commentId, replies) => {
125
- const {
126
- element_id: elementId
127
- } = comment.detail;
154
+ const elementId = (0, _helper.getPrimaryElementId)(comment.detail);
128
155
  for (let i = 0; i < replies.length; i++) {
129
156
  const reply = replies[i];
130
157
  const res = await _context.default.insertReply(commentId, reply);
@@ -199,14 +226,12 @@ const CommentItemWrapper = _ref => {
199
226
  replies.push(reply);
200
227
  insertReply(comment.id, replies);
201
228
  }, [comment.id, comment.resolved, insertReply]);
202
- (0, _react.useImperativeHandle)(commentDetailRef, () => ({
229
+ (0, _react.useImperativeHandle)(ref ? ref : commentDetailRef, () => ({
203
230
  insertContent
204
231
  }));
205
232
  const deleteReply = (0, _react.useCallback)(async replyId => {
206
233
  const commentId = comment.id;
207
- const {
208
- element_id: elementId
209
- } = comment.detail;
234
+ const elementId = (0, _helper.getPrimaryElementId)(comment.detail);
210
235
  await _context.default.deleteReply(commentId, replyId);
211
236
  dispatch({
212
237
  type: 'DELETE_REPLY',
@@ -219,9 +244,7 @@ const CommentItemWrapper = _ref => {
219
244
  }, [comment.detail, comment.id, dispatch]);
220
245
  const updateReply = (0, _react.useCallback)(async (replyId, newReply) => {
221
246
  const commentId = comment.id;
222
- const {
223
- element_id: elementId
224
- } = comment.detail;
247
+ const elementId = (0, _helper.getPrimaryElementId)(comment.detail);
225
248
  await _context.default.updateReply(commentId, replyId, newReply);
226
249
  dispatch({
227
250
  type: 'UPDATE_REPLY',
@@ -244,7 +267,16 @@ const CommentItemWrapper = _ref => {
244
267
  deleteComment(comment.id);
245
268
  setIsShowDeletePopover(false);
246
269
  setCurrentCommentGroup && setCurrentCommentGroup(null);
247
- }, [comment.id, deleteComment, setCurrentCommentGroup]);
270
+ if (isClickedContextComment) {
271
+ if (Object.values(commentsDetail).length === 1) {
272
+ setIsClickedContextComment(false);
273
+ setIsCommentPanelVisible(false);
274
+ } else {
275
+ const newCommentIdArray = Object.values(commentsDetail).filter(item => item.id !== comment.id).map(item => item.detail.text_comment_id);
276
+ onSelectElement(newCommentIdArray, true);
277
+ }
278
+ }
279
+ }, [comment.id, commentsDetail, deleteComment, isClickedContextComment, onSelectElement, setCurrentCommentGroup, setIsClickedContextComment, setIsCommentPanelVisible]);
248
280
  (0, _react.useEffect)(() => {
249
281
  if (!isActive) {
250
282
  setIsShowDeletePopover(false);
@@ -266,8 +298,9 @@ const CommentItemWrapper = _ref => {
266
298
  behavior: 'smooth'
267
299
  });
268
300
  }, [editor, element, scrollRef]);
301
+ const newCommentId = isClickedContextComment && comment !== null && comment !== void 0 && comment.detail.element_id_list ? comment === null || comment === void 0 ? void 0 : comment.detail.element_id_list[0] : comment === null || comment === void 0 ? void 0 : comment.id;
269
302
  return /*#__PURE__*/_react.default.createElement("div", {
270
- id: `comment-item-wrapper_${comment === null || comment === void 0 ? void 0 : comment.id}`,
303
+ id: `comment-item-wrapper_${newCommentId}`,
271
304
  className: className,
272
305
  onClick: onItemClick
273
306
  }, element && /*#__PURE__*/_react.default.createElement("div", {
@@ -281,16 +314,38 @@ const CommentItemWrapper = _ref => {
281
314
  ref: listRef,
282
315
  className: "comment-item-list",
283
316
  style: style
284
- }, /*#__PURE__*/_react.default.createElement(_commentItemContent.default, {
285
- key: comment.id,
317
+ }, comment.detail.element_id_list && !isGlobalComment && /*#__PURE__*/_react.default.createElement("div", {
318
+ className: "context-comment-item-selected-text-container"
319
+ }, /*#__PURE__*/_react.default.createElement("i", {
320
+ className: "sdocfont sdoc-comment-quote mr-2"
321
+ }), /*#__PURE__*/_react.default.createElement("div", {
322
+ className: "context-comment-items"
323
+ }, comment.detail.element_id_list.map((elementId, index) => {
324
+ return /*#__PURE__*/_react.default.createElement("div", {
325
+ className: "context-comment-item-selected-text",
326
+ key: index
327
+ }, (0, _helper.getCommentedTextsByElementId)(elementId, comment.detail.text_comment_id));
328
+ }))), /*#__PURE__*/_react.default.createElement(_commentItemContent.default, {
329
+ key: newCommentId,
286
330
  container: container,
287
331
  isActive: isActive,
288
332
  comment: comment,
289
333
  updateComment: updateComment,
290
334
  updateCommentState: updateCommentState,
291
335
  onDeleteComment: onDeleteComment,
292
- targetId: commentOpToolsId
293
- }), comment.replies && comment.replies.length > 0 && comment.replies.map(reply => {
336
+ targetId: commentOpToolsId,
337
+ isClickedContextComment: isClickedContextComment
338
+ }), isClickedContextComment && comment.replies && comment.replies.length > 0 && comment.replies.filter(item => item.type === 'reply').map(reply => {
339
+ const props = {
340
+ key: reply.id,
341
+ isActive,
342
+ container,
343
+ reply,
344
+ deleteReply,
345
+ updateReply
346
+ };
347
+ return /*#__PURE__*/_react.default.createElement(_commentItemReply.default, props);
348
+ }), !isClickedContextComment && comment.replies && comment.replies.length > 0 && comment.replies.filter(item => item.type === 'reply').map(reply => {
294
349
  const props = {
295
350
  key: reply.id,
296
351
  isActive,
@@ -307,5 +362,5 @@ const CommentItemWrapper = _ref => {
307
362
  setIsShowDeletePopover: setIsShowDeletePopover,
308
363
  parentDom: listRef.current
309
364
  }));
310
- };
365
+ });
311
366
  var _default = exports.default = CommentItemWrapper;
@@ -38,6 +38,40 @@
38
38
  padding-bottom: 0px;
39
39
  }
40
40
 
41
+ .sdoc-context-comment-list-container {
42
+ max-height: 430px;
43
+ overflow-y: auto;
44
+ }
45
+
46
+ .sdoc-context-comment-popover-wrapper .comment-item-list {
47
+ border-bottom: none !important;
48
+ }
49
+
50
+ .sdoc-context-comment-popover-wrapper .non-global-comment-input-wrapper {
51
+ border-bottom: 1px solid #ececec;
52
+ }
53
+
54
+ .sdoc-comment-list-container .sdoc-context-comment-popover-wrapper:last-child .non-global-comment-input-wrapper {
55
+ border-bottom: none !important;
56
+ }
57
+
58
+ .sdoc-comment-list-container .comment-item-list .context-comment-item-selected-text-container {
59
+ padding: 16px 16px 0 16px;
60
+ color: #666;
61
+ display: flex;
62
+ }
63
+
64
+ .comment-item-list .context-comment-item-selected-text-container .sdoc-comment-quote {
65
+ font-size: 12px;
66
+ padding-top: 2px;
67
+ }
68
+
69
+ .comment-item-list .context-comment-item-selected-text-container .context-comment-items {
70
+ display: flex;
71
+ flex-direction: column;
72
+ font-size: 14px;
73
+ }
74
+
41
75
  .sdoc-comment-list-container .comment-item {
42
76
  position: relative;
43
77
  padding: 0px;
@@ -9,38 +9,56 @@ exports.default = void 0;
9
9
  var _react = _interopRequireWildcard(require("react"));
10
10
  var _reactI18next = require("react-i18next");
11
11
  var _reactstrap = require("reactstrap");
12
+ var _classnames = _interopRequireDefault(require("classnames"));
12
13
  var _dayjs = _interopRequireDefault(require("dayjs"));
14
+ var _slugid = _interopRequireDefault(require("slugid"));
13
15
  var _context = _interopRequireDefault(require("../../../context"));
14
16
  var _useSelectionPosition = require("../../hooks/use-selection-position");
17
+ var _helper = require("../helper");
15
18
  var _useCommentContext = require("../hooks/comment-hooks/use-comment-context");
16
19
  var _commentEditor = _interopRequireDefault(require("./comment-editor"));
17
20
  var _commentItemWrapper = _interopRequireDefault(require("./comment-item-wrapper"));
18
21
  require("./comment-list.css");
19
22
  const CommentList = _ref => {
20
23
  let {
21
- activeElement,
24
+ activeElementIds,
22
25
  commentDetail = {},
23
26
  onSetCommentDetail,
27
+ isContextComment = false,
28
+ isClickedContextComment = false,
29
+ setIsClickedContextComment,
30
+ onSelectElement,
31
+ closeComment,
32
+ commentedDom,
33
+ editor,
24
34
  t
25
35
  } = _ref;
26
36
  const commentPopover = (0, _react.useRef)(null);
27
37
  const commentDetailRef = (0, _react.useRef)(null);
28
- const position = (0, _useSelectionPosition.useCommentListPosition)(activeElement);
38
+ const position = (0, _useSelectionPosition.useCommentListPosition)(activeElementIds, isContextComment, isClickedContextComment, commentedDom, commentDetail, closeComment);
29
39
  const {
30
40
  dispatch
31
41
  } = (0, _useCommentContext.useCommentContext)();
32
42
  const [showEditor, setShowEditor] = (0, _react.useState)(false);
33
43
  const [inputContent, setInputContent] = (0, _react.useState)(null);
34
- const [translateY, setTranslateY] = (0, _react.useState)(0);
44
+ const [activeCommentKey, setActiveCommentKey] = (0, _react.useState)(null);
45
+ const [translateY, setTranslateY] = (0, _react.useState)();
35
46
  const isEmptyComment = Object.keys(commentDetail).length ? false : true;
36
47
  const isCollapseCommentEditor = !isEmptyComment && !showEditor;
37
- const insertComment = (0, _react.useCallback)(async (elementId, comment) => {
48
+ const [isCommentPanelVisible, setIsCommentPanelVisible] = (0, _react.useState)(true);
49
+
50
+ // Multi context comments
51
+ const [commentInputs, setCommentInputs] = (0, _react.useState)({});
52
+ const contextCommentRef = (0, _react.useRef)({});
53
+ const insertComment = (0, _react.useCallback)(async function (elementId, comment) {
54
+ let isContextComment = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
38
55
  const res = await _context.default.insertComment(comment);
39
56
  const {
40
57
  comment: returnComment
41
58
  } = res.data;
42
59
  const newComment = {
43
60
  ...comment,
61
+ isContextComment: isContextComment,
44
62
  id: returnComment.id,
45
63
  user_name: returnComment.user_name,
46
64
  avatar_url: returnComment.avatar_url,
@@ -58,19 +76,20 @@ const CommentList = _ref => {
58
76
  }, [dispatch, onSetCommentDetail]);
59
77
  const addNewComment = (0, _react.useCallback)(content => {
60
78
  const user = _context.default.getUserInfo();
61
- const elementId = activeElement === null || activeElement === void 0 ? void 0 : activeElement.id;
62
79
  const time = (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss');
80
+ const textCommentId = _slugid.default.nice();
63
81
  const comment = {
64
82
  comment: content,
65
83
  detail: {
66
- element_id: elementId,
67
- comment: content
84
+ text_comment_id: textCommentId,
85
+ element_id_list: activeElementIds
68
86
  },
69
87
  author: user.username,
70
88
  updated_at: time
71
89
  };
72
- insertComment(elementId, comment);
73
- }, [insertComment, activeElement === null || activeElement === void 0 ? void 0 : activeElement.id]);
90
+ (0, _helper.updateElementsAttrs)(activeElementIds, editor, textCommentId);
91
+ insertComment(activeElementIds[0], comment, isContextComment);
92
+ }, [isContextComment, activeElementIds, editor, insertComment]);
74
93
  const replyComment = (0, _react.useCallback)(content => {
75
94
  if (commentDetailRef !== null && commentDetailRef !== void 0 && commentDetailRef.current) {
76
95
  commentDetailRef.current.insertContent(content);
@@ -81,7 +100,7 @@ const CommentList = _ref => {
81
100
  }, []);
82
101
  (0, _react.useEffect)(() => {
83
102
  queueMicrotask(() => {
84
- if (commentPopover !== null && commentPopover !== void 0 && commentPopover.current) {
103
+ if (commentPopover !== null && commentPopover !== void 0 && commentPopover.current && Array.isArray(activeElementIds)) {
85
104
  const {
86
105
  bottom
87
106
  } = commentPopover.current.getBoundingClientRect();
@@ -94,23 +113,78 @@ const CommentList = _ref => {
94
113
  }
95
114
  }
96
115
  });
97
- }, [activeElement]);
116
+ }, [activeElementIds]);
117
+ const handleInputChange = (id, value) => {
118
+ setCommentInputs(prev => ({
119
+ ...prev,
120
+ [id]: value
121
+ }));
122
+ };
123
+ const handleReplySubmit = (content, id) => {
124
+ var _contextCommentRef$cu;
125
+ if (contextCommentRef !== null && contextCommentRef !== void 0 && (_contextCommentRef$cu = contextCommentRef.current) !== null && _contextCommentRef$cu !== void 0 && _contextCommentRef$cu[id]) {
126
+ contextCommentRef.current[id].insertContent(content);
127
+ }
128
+ };
98
129
  return /*#__PURE__*/_react.default.createElement("div", {
99
130
  ref: commentPopover,
100
131
  id: "sdoc-comment-list-container",
101
- className: "sdoc-comment-list-container sdoc-comment-list-container-popover",
132
+ className: (0, _classnames.default)('sdoc-comment-list-container sdoc-comment-list-container-popover', 'sdoc-context-comment-list-container'),
102
133
  style: {
103
134
  top: position.y,
135
+ ...(isContextComment || isClickedContextComment ? {
136
+ right: position.right
137
+ } : {}),
104
138
  width: '300px',
105
139
  transform: `translateY(${translateY}px)`
106
140
  }
107
- }, /*#__PURE__*/_react.default.createElement(_commentItemWrapper.default, {
108
- commentDetailRef: commentDetailRef,
109
- comment: commentDetail,
110
- isActive: true,
111
- isEmptyComment: isEmptyComment,
112
- isCollapseCommentEditor: isCollapseCommentEditor
113
- }), /*#__PURE__*/_react.default.createElement("div", {
141
+ }, Object.values(commentDetail).length !== 0 && isCommentPanelVisible && Object.values(commentDetail).map((item, index) => {
142
+ const isActiveEditor = activeCommentKey === index;
143
+ return /*#__PURE__*/_react.default.createElement("div", {
144
+ className: "sdoc-context-comment-popover-wrapper",
145
+ key: item.id || index
146
+ }, /*#__PURE__*/_react.default.createElement(_commentItemWrapper.default, {
147
+ ref: el => {
148
+ if (el) contextCommentRef.current[item.id] = el;else delete contextCommentRef.current[item.id];
149
+ },
150
+ editor: editor,
151
+ comment: item,
152
+ commentsDetail: commentDetail,
153
+ setIsClickedContextComment: setIsClickedContextComment,
154
+ setIsCommentPanelVisible: setIsCommentPanelVisible,
155
+ onSelectElement: onSelectElement,
156
+ isActive: true,
157
+ isEmptyComment: isEmptyComment,
158
+ isCollapseCommentEditor: isCollapseCommentEditor,
159
+ isClickedContextComment: isClickedContextComment,
160
+ closeComment: closeComment
161
+ }), /*#__PURE__*/_react.default.createElement("div", {
162
+ className: "non-global-comment-input-wrapper",
163
+ style: {
164
+ paddingTop: isEmptyComment ? '16px' : ''
165
+ }
166
+ }, isEmptyComment && /*#__PURE__*/_react.default.createElement(_commentEditor.default, {
167
+ type: "comment",
168
+ insertContent: addNewComment,
169
+ hiddenComment: hiddenComment,
170
+ isContextComment: isContextComment,
171
+ closeComment: closeComment
172
+ }), !isEmptyComment && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !isActiveEditor && /*#__PURE__*/_react.default.createElement(_reactstrap.Input, {
173
+ value: inputContent !== null && inputContent !== void 0 && inputContent.trim() ? '.....' : '',
174
+ readOnly: true,
175
+ placeholder: t('Enter_reply'),
176
+ onFocus: () => {
177
+ setActiveCommentKey(index);
178
+ }
179
+ }), isActiveEditor && /*#__PURE__*/_react.default.createElement(_commentEditor.default, {
180
+ type: "reply",
181
+ placeholder: 'Enter_reply_shift_Enter_for_new_line_Enter_to_send',
182
+ commentContent: commentInputs[item.id] || '',
183
+ insertContent: value => handleReplySubmit(value, item.id),
184
+ onContentChange: content => handleInputChange(item.id, content),
185
+ hiddenComment: hiddenComment
186
+ }))));
187
+ }), Object.values(commentDetail).length === 0 && /*#__PURE__*/_react.default.createElement("div", {
114
188
  className: "non-global-comment-input-wrapper",
115
189
  style: {
116
190
  paddingTop: isEmptyComment ? '16px' : ''
@@ -118,7 +192,9 @@ const CommentList = _ref => {
118
192
  }, isEmptyComment && /*#__PURE__*/_react.default.createElement(_commentEditor.default, {
119
193
  type: "comment",
120
194
  insertContent: addNewComment,
121
- hiddenComment: hiddenComment
195
+ hiddenComment: hiddenComment,
196
+ isContextComment: isContextComment,
197
+ closeComment: closeComment
122
198
  }), !isEmptyComment && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !showEditor && /*#__PURE__*/_react.default.createElement(_reactstrap.Input, {
123
199
  value: inputContent !== null && inputContent !== void 0 && inputContent.trim() ? '.....' : '',
124
200
  readOnly: true,