@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.
- package/dist/api/seafile-api.js +36 -2
- package/dist/assets/css/simple-editor.css +0 -32
- package/dist/assets/images/revision-avatar.png +0 -0
- package/dist/basic-sdk/assets/css/textlink-hovermenu.css +1 -0
- package/dist/basic-sdk/comment/components/comment-all-participants/index.css +83 -0
- package/dist/basic-sdk/comment/components/comment-all-participants/index.js +56 -0
- package/dist/basic-sdk/comment/components/comment-all-participants/participant-avatar.js +35 -0
- package/dist/basic-sdk/comment/{comment → components}/comment-editor.js +18 -36
- package/dist/basic-sdk/comment/components/comment-input/comment-participant-item.js +47 -0
- package/dist/basic-sdk/comment/components/comment-input/index.css +45 -0
- package/dist/basic-sdk/comment/components/comment-input/index.js +295 -0
- package/dist/basic-sdk/comment/{comment → components}/comment-item-content.js +7 -2
- package/dist/basic-sdk/comment/{comment → components}/comment-item-reply.js +6 -1
- package/dist/basic-sdk/comment/{comment → components}/comment-item-wrapper.js +3 -1
- package/dist/basic-sdk/comment/components/comment-participants-editor/index.css +132 -0
- package/dist/basic-sdk/comment/components/comment-participants-editor/index.js +67 -0
- package/dist/basic-sdk/comment/components/comment-participants-editor/searched-collaborators.js +53 -0
- package/dist/basic-sdk/comment/components/comment-participants-editor/selected-participants.js +39 -0
- package/dist/basic-sdk/comment/{comment → components}/global-comment-header.js +5 -6
- package/dist/basic-sdk/comment/{comment → components}/global-comment.js +3 -2
- package/dist/basic-sdk/comment/{comment → components}/style.css +8 -1
- package/dist/basic-sdk/comment/constants/index.js +11 -0
- package/dist/basic-sdk/comment/hooks/use-comment-list.js +1 -1
- package/dist/basic-sdk/comment/hooks/use-participants.js +90 -0
- package/dist/basic-sdk/comment/index.js +3 -2
- package/dist/basic-sdk/comment/utils/index.js +206 -0
- package/dist/basic-sdk/editor/sdoc-editor.js +3 -2
- package/dist/basic-sdk/extension/plugins/link/hover/index.js +3 -3
- package/dist/components/doc-info/index.css +53 -0
- package/dist/components/doc-info/index.js +11 -2
- package/dist/components/modal-portal/index.js +36 -0
- package/dist/constants/index.js +4 -1
- package/dist/constants/key-codes.js +102 -0
- package/dist/constants/transfer-types.js +3 -0
- package/dist/context.js +38 -8
- package/dist/hooks/index.js +3 -0
- package/dist/hooks/use-collaborators.js +44 -0
- package/dist/layout/layout.js +10 -27
- package/dist/model/index.js +2 -1
- package/dist/model/user.js +12 -0
- package/dist/pages/simple-editor.js +1 -1
- package/dist/utils/get-event-transfer.js +73 -0
- package/dist/utils/hotkey.js +25 -0
- package/dist/utils/index.js +58 -1
- package/package.json +1 -1
- package/public/locales/cs/sdoc-editor.json +6 -1
- package/public/locales/de/sdoc-editor.json +6 -1
- package/public/locales/en/sdoc-editor.json +3 -1
- package/public/locales/es/sdoc-editor.json +6 -1
- package/public/locales/fr/sdoc-editor.json +6 -1
- package/public/locales/it/sdoc-editor.json +6 -1
- package/public/locales/ru/sdoc-editor.json +6 -1
- package/public/locales/zh_CN/sdoc-editor.json +3 -1
- package/public/media/sdoc-editor-font/iconfont.eot +0 -0
- package/public/media/sdoc-editor-font/iconfont.svg +4 -0
- package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
- package/public/media/sdoc-editor-font/iconfont.woff +0 -0
- package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
- package/public/media/sdoc-editor-font.css +14 -6
- /package/dist/basic-sdk/comment/{comment → components}/comment-delete-shadow.js +0 -0
- /package/dist/basic-sdk/comment/{comment → components}/comment-item-resolved-reply.js +0 -0
- /package/dist/basic-sdk/comment/{comment → components}/comment-list.css +0 -0
- /package/dist/basic-sdk/comment/{comment → components}/comment-list.js +0 -0
- /package/dist/basic-sdk/comment/{comment → components}/editor-comment.js +0 -0
- /package/dist/basic-sdk/comment/{comment → components}/elements-comment-count/element-comment-count.js +0 -0
- /package/dist/basic-sdk/comment/{comment → components}/elements-comment-count/index.css +0 -0
- /package/dist/basic-sdk/comment/{comment → components}/elements-comment-count/index.js +0 -0
- /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(
|
|
125
|
-
|
|
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(
|
|
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;
|
package/dist/basic-sdk/comment/components/comment-participants-editor/searched-collaborators.js
ADDED
|
@@ -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;
|
package/dist/basic-sdk/comment/components/comment-participants-editor/selected-participants.js
ADDED
|
@@ -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
|
-
|
|
7
|
-
|
|
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);
|