@seafile/sdoc-editor 0.2.27 → 0.2.29-beta
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 +26 -0
- package/dist/assets/images/content-replaced.png +0 -0
- package/dist/basic-sdk/comment/hooks/use-comment-mount.js +7 -0
- package/dist/basic-sdk/editor/sdoc-editor.js +2 -3
- package/dist/basic-sdk/extension/constants/element-type.js +3 -2
- package/dist/basic-sdk/extension/constants/index.js +2 -2
- package/dist/basic-sdk/extension/plugins/html/helper.js +17 -16
- package/dist/basic-sdk/extension/plugins/html/rules/blockquote.js +0 -1
- package/dist/basic-sdk/extension/plugins/html/rules/check-list.js +0 -2
- package/dist/basic-sdk/extension/plugins/html/rules/code-block.js +0 -10
- package/dist/basic-sdk/extension/plugins/html/rules/header.js +0 -1
- package/dist/basic-sdk/extension/plugins/html/rules/image.js +0 -1
- package/dist/basic-sdk/extension/plugins/html/rules/link.js +0 -2
- package/dist/basic-sdk/extension/plugins/html/rules/list.js +3 -9
- package/dist/basic-sdk/extension/plugins/html/rules/paragraph.js +0 -1
- package/dist/basic-sdk/extension/plugins/html/rules/table.js +0 -3
- package/dist/basic-sdk/extension/plugins/html/rules/text.js +0 -7
- package/dist/basic-sdk/extension/plugins/list/helpers.js +0 -1
- package/dist/basic-sdk/extension/plugins/list/model.js +3 -3
- package/dist/basic-sdk/extension/plugins/list/plugin/insert-fragment-list.js +4 -4
- package/dist/basic-sdk/extension/plugins/list/plugin/normalize-list.js +2 -13
- package/dist/basic-sdk/extension/plugins/list/transforms/insert-list-item.js +13 -11
- package/dist/basic-sdk/extension/plugins/list/transforms/move-list-items.js +2 -2
- package/dist/basic-sdk/extension/plugins/list/transforms/normalize-list-item.js +7 -7
- package/dist/basic-sdk/extension/plugins/list/transforms/toggle-list.js +16 -19
- package/dist/basic-sdk/extension/plugins/list/transforms/unwrap-list.js +5 -13
- package/dist/basic-sdk/extension/plugins/table/helpers.js +0 -1
- package/dist/basic-sdk/extension/render/custom-element.js +14 -14
- package/dist/basic-sdk/socket/socket-client.js +7 -0
- package/dist/basic-sdk/socket/socket-manager.js +3 -0
- package/dist/components/doc-operations/index.js +2 -1
- package/dist/components/doc-operations/notifications-operation/index.css +14 -0
- package/dist/components/doc-operations/notifications-operation/index.js +170 -0
- package/dist/components/doc-operations/notifications-operation/notifications-dialog/index.css +97 -0
- package/dist/components/doc-operations/notifications-operation/notifications-dialog/index.js +107 -0
- package/dist/components/doc-operations/notifications-operation/notifications-dialog/notification.js +25 -0
- package/dist/components/doc-operations/notifications-operation/notifications-popover/index.css +173 -0
- package/dist/components/doc-operations/notifications-operation/notifications-popover/index.js +78 -0
- package/dist/components/doc-operations/notifications-operation/notifications-popover/notification.js +54 -0
- package/dist/components/doc-operations/revision-operations/more-revision-operations/index.js +1 -2
- package/dist/components/doc-operations/tag-operation/tag-popover/index.css +1 -0
- package/dist/components/tip-dialog/index.css +44 -0
- package/dist/components/tip-dialog/index.js +51 -18
- package/dist/constants/index.js +2 -3
- package/dist/context.js +26 -0
- package/dist/layout/index.js +2 -1
- package/dist/layout/other.js +8 -0
- package/dist/model/index.js +2 -1
- package/dist/model/notification.js +21 -0
- package/dist/pages/published-revision-viewer.js +2 -2
- package/dist/pages/simple-editor.js +6 -6
- package/dist/utils/index.js +3 -33
- package/dist/utils/notification-utils.js +46 -0
- package/package.json +1 -1
- package/public/locales/cs/sdoc-editor.json +1 -1
- package/public/locales/de/sdoc-editor.json +1 -1
- package/public/locales/en/sdoc-editor.json +13 -3
- package/public/locales/es/sdoc-editor.json +1 -1
- package/public/locales/fr/sdoc-editor.json +1 -1
- package/public/locales/it/sdoc-editor.json +1 -1
- package/public/locales/ru/sdoc-editor.json +1 -1
- package/public/locales/zh_CN/sdoc-editor.json +4 -2
- package/public/media/sdoc-editor-font/iconfont.eot +0 -0
- package/public/media/sdoc-editor-font/iconfont.svg +2 -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 +4 -0
|
@@ -2,15 +2,15 @@ import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIt
|
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
3
3
|
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
4
4
|
import { Transforms, Editor, Path, Element } from '@seafile/slate';
|
|
5
|
-
import {
|
|
5
|
+
import { PARAGRAPH } from '../../../constants';
|
|
6
6
|
import { getChildren, getDeepInlineChildren, match } from '../../../core';
|
|
7
7
|
import { getListTypes } from '../queries';
|
|
8
8
|
import { movedListItemUp } from './move-list-item-up';
|
|
9
|
-
import {
|
|
9
|
+
import { generateEmptyListContent } from '../model';
|
|
10
10
|
export var normalizeListItem = function normalizeListItem(editor, _ref) {
|
|
11
11
|
var listItem = _ref.listItem;
|
|
12
12
|
var changed = false;
|
|
13
|
-
var validLiChildrenTypes = [].concat(_toConsumableArray(getListTypes()), [
|
|
13
|
+
var validLiChildrenTypes = [].concat(_toConsumableArray(getListTypes()), [PARAGRAPH]);
|
|
14
14
|
var _listItem = _slicedToArray(listItem, 2),
|
|
15
15
|
liPath = _listItem[1];
|
|
16
16
|
var liChildren = getChildren(listItem);
|
|
@@ -29,14 +29,14 @@ export var normalizeListItem = function normalizeListItem(editor, _ref) {
|
|
|
29
29
|
firstLiChildNode = _ref7[0],
|
|
30
30
|
firstLiChildPath = _ref7[1];
|
|
31
31
|
if (!firstLiChild || !Editor.isBlock(editor, firstLiChildNode)) {
|
|
32
|
-
var
|
|
33
|
-
Transforms.insertNodes(editor,
|
|
32
|
+
var itemContent = generateEmptyListContent();
|
|
33
|
+
Transforms.insertNodes(editor, itemContent, {
|
|
34
34
|
at: liPath.concat([0])
|
|
35
35
|
});
|
|
36
36
|
return true;
|
|
37
37
|
}
|
|
38
38
|
if (Editor.isBlock(editor, firstLiChildNode) && !match(firstLiChildNode, [], {
|
|
39
|
-
type: [
|
|
39
|
+
type: [PARAGRAPH]
|
|
40
40
|
})) {
|
|
41
41
|
if (match(firstLiChildNode, [], {
|
|
42
42
|
type: getListTypes()
|
|
@@ -59,7 +59,7 @@ export var normalizeListItem = function normalizeListItem(editor, _ref) {
|
|
|
59
59
|
return true;
|
|
60
60
|
}
|
|
61
61
|
Transforms.setNodes(editor, {
|
|
62
|
-
type:
|
|
62
|
+
type: PARAGRAPH
|
|
63
63
|
}, {
|
|
64
64
|
at: firstLiChildPath
|
|
65
65
|
});
|
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
3
3
|
import { Node, Range, Transforms, Element, Editor } from '@seafile/slate';
|
|
4
|
-
import { LIST_ITEM,
|
|
5
|
-
import { findNode, getNodeEntries, getNodeType, getSelectedNodeEntryByType, isRangeAcrossBlocks
|
|
4
|
+
import { LIST_ITEM, PARAGRAPH, INSERT_POSITION } from '../../../constants';
|
|
5
|
+
import { findNode, getNodeEntries, getNodeType, getSelectedNodeEntryByType, isRangeAcrossBlocks } from '../../../core';
|
|
6
6
|
import { getListItemEntry, getListTypes } from '../queries';
|
|
7
7
|
import { unwrapList } from './unwrap-list';
|
|
8
|
-
import { generateEmptyList, generateEmptyListItem } from '../model';
|
|
8
|
+
import { generateEmptyList, generateEmptyListContent, generateEmptyListItem } from '../model';
|
|
9
9
|
var wrapLineList = function wrapLineList(editor, type) {
|
|
10
10
|
var list = generateEmptyList(type);
|
|
11
11
|
Transforms.wrapNodes(editor, list);
|
|
12
12
|
var nodeEntry = getSelectedNodeEntryByType(editor, PARAGRAPH);
|
|
13
13
|
if (!nodeEntry) return;
|
|
14
|
+
|
|
15
|
+
// select is paragraph
|
|
16
|
+
// 1 handle paragraph
|
|
17
|
+
|
|
18
|
+
// 2 wrap list_item
|
|
14
19
|
var _nodeEntry = _slicedToArray(nodeEntry, 2),
|
|
15
|
-
node = _nodeEntry[0],
|
|
16
20
|
path = _nodeEntry[1];
|
|
17
|
-
if (node.type !== LIST_LIC) {
|
|
18
|
-
// paragraph to list-lic
|
|
19
|
-
Transforms.setNodes(editor, {
|
|
20
|
-
type: LIST_LIC
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
21
|
var listItem = generateEmptyListItem();
|
|
24
22
|
Transforms.wrapNodes(editor, listItem, {
|
|
25
23
|
at: path
|
|
@@ -91,17 +89,16 @@ var wrapRangeList = function wrapRangeList(editor, type) {
|
|
|
91
89
|
mode: 'all'
|
|
92
90
|
});
|
|
93
91
|
} else {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
at: n[1]
|
|
99
|
-
});
|
|
100
|
-
}
|
|
92
|
+
// select content is paragraph
|
|
93
|
+
// 1 handle content
|
|
94
|
+
|
|
95
|
+
// 2. wrap list_item
|
|
101
96
|
var listItem = generateEmptyListItem();
|
|
102
97
|
Transforms.wrapNodes(editor, listItem, {
|
|
103
98
|
at: n[1]
|
|
104
99
|
});
|
|
100
|
+
|
|
101
|
+
// 3. wrap list
|
|
105
102
|
var list = generateEmptyList(type);
|
|
106
103
|
Transforms.wrapNodes(editor, list, {
|
|
107
104
|
at: n[1]
|
|
@@ -113,9 +110,9 @@ var wrapRangeList = function wrapRangeList(editor, type) {
|
|
|
113
110
|
var toggleList = function toggleList(editor, type, insertPosition) {
|
|
114
111
|
if (insertPosition === INSERT_POSITION.AFTER) {
|
|
115
112
|
var list = generateEmptyList(type);
|
|
116
|
-
var
|
|
113
|
+
var listContent = generateEmptyListContent();
|
|
117
114
|
var path = Editor.path(editor, editor.selection);
|
|
118
|
-
Transforms.insertNodes(editor,
|
|
115
|
+
Transforms.insertNodes(editor, listContent, {
|
|
119
116
|
at: [path[0] + 1]
|
|
120
117
|
});
|
|
121
118
|
Transforms.select(editor, [path[0] + 1]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Editor, Transforms, Element, Node } from '@seafile/slate';
|
|
2
|
-
import { LIST_ITEM
|
|
3
|
-
import {
|
|
2
|
+
import { LIST_ITEM } from '../../../constants';
|
|
3
|
+
import { getAboveNode, getNodeType } from '../../../core';
|
|
4
4
|
import { getListTypes } from '../queries';
|
|
5
5
|
export var unwrapList = function unwrapList(editor) {
|
|
6
6
|
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
@@ -25,17 +25,7 @@ export var unwrapList = function unwrapList(editor) {
|
|
|
25
25
|
};
|
|
26
26
|
Editor.withoutNormalizing(editor, function () {
|
|
27
27
|
do {
|
|
28
|
-
|
|
29
|
-
at: at,
|
|
30
|
-
match: {
|
|
31
|
-
type: LIST_LIC
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
if (licEntry) {
|
|
35
|
-
Transforms.setNodes(editor, {
|
|
36
|
-
type: PARAGRAPH
|
|
37
|
-
});
|
|
38
|
-
}
|
|
28
|
+
// unwrap list_item
|
|
39
29
|
Transforms.unwrapNodes(editor, {
|
|
40
30
|
at: at,
|
|
41
31
|
match: function match(n) {
|
|
@@ -43,6 +33,8 @@ export var unwrapList = function unwrapList(editor) {
|
|
|
43
33
|
},
|
|
44
34
|
split: true
|
|
45
35
|
});
|
|
36
|
+
|
|
37
|
+
// unwrap list
|
|
46
38
|
Transforms.unwrapNodes(editor, {
|
|
47
39
|
at: at,
|
|
48
40
|
match: function match(n) {
|
|
@@ -31,7 +31,6 @@ export var isTableMenuDisabled = function isTableMenuDisabled(editor, readonly)
|
|
|
31
31
|
if (type === ELEMENT_TYPE.UNORDERED_LIST) return true;
|
|
32
32
|
if (type === ELEMENT_TYPE.BLOCKQUOTE) return true;
|
|
33
33
|
if (type === ELEMENT_TYPE.LIST_ITEM) return true;
|
|
34
|
-
if (type === ELEMENT_TYPE.LIST_LIC) return true;
|
|
35
34
|
if (type === ELEMENT_TYPE.TABLE) return true;
|
|
36
35
|
if (type === ELEMENT_TYPE.TABLE_CELL) return true;
|
|
37
36
|
if (type === ELEMENT_TYPE.TABLE_ROW) return true;
|
|
@@ -2,7 +2,7 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
3
3
|
import { useCallback } from 'react';
|
|
4
4
|
import { useSlateStatic } from '@seafile/slate-react';
|
|
5
|
-
import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM,
|
|
5
|
+
import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM, ORDERED_LIST, PARAGRAPH, UNORDERED_LIST, CODE_BLOCK, CODE_LINE, IMAGE, ELEMENT_TYPE, SDOC_LINK, FILE_LINK, TITLE, SUBTITLE } from '../constants';
|
|
6
6
|
import { BlockquotePlugin, LinkPlugin, CheckListPlugin, HeaderPlugin, ListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin } from '../plugins';
|
|
7
7
|
import EventBus from '../../utils/event-bus';
|
|
8
8
|
import { INTERNAL_EVENT } from '../../constants';
|
|
@@ -19,9 +19,15 @@ var CustomRenderElement = function CustomRenderElement(props) {
|
|
|
19
19
|
switch (element.type) {
|
|
20
20
|
case PARAGRAPH:
|
|
21
21
|
{
|
|
22
|
+
var parentNode = getParentNode(editor.children, element.id);
|
|
23
|
+
if (parentNode && parentNode.type === LIST_ITEM) {
|
|
24
|
+
var _ParagraphPlugin$rend = _slicedToArray(ParagraphPlugin.renderElements, 1),
|
|
25
|
+
_renderParagraph = _ParagraphPlugin$rend[0];
|
|
26
|
+
return _renderParagraph(props);
|
|
27
|
+
}
|
|
22
28
|
attributes['onMouseEnter'] = onMouseEnter;
|
|
23
|
-
var _ParagraphPlugin$
|
|
24
|
-
renderParagraph = _ParagraphPlugin$
|
|
29
|
+
var _ParagraphPlugin$rend2 = _slicedToArray(ParagraphPlugin.renderElements, 1),
|
|
30
|
+
renderParagraph = _ParagraphPlugin$rend2[0];
|
|
25
31
|
return renderParagraph(props);
|
|
26
32
|
}
|
|
27
33
|
case TITLE:
|
|
@@ -76,12 +82,6 @@ var CustomRenderElement = function CustomRenderElement(props) {
|
|
|
76
82
|
renderListItem = _ListPlugin$renderEle2[1];
|
|
77
83
|
return renderListItem(props, editor);
|
|
78
84
|
}
|
|
79
|
-
case LIST_LIC:
|
|
80
|
-
{
|
|
81
|
-
var _ListPlugin$renderEle3 = _slicedToArray(ListPlugin.renderElements, 3),
|
|
82
|
-
renderListLic = _ListPlugin$renderEle3[2];
|
|
83
|
-
return renderListLic(props, editor);
|
|
84
|
-
}
|
|
85
85
|
case CHECK_LIST_ITEM:
|
|
86
86
|
{
|
|
87
87
|
attributes['onMouseEnter'] = onMouseEnter;
|
|
@@ -105,8 +105,8 @@ var CustomRenderElement = function CustomRenderElement(props) {
|
|
|
105
105
|
case IMAGE:
|
|
106
106
|
{
|
|
107
107
|
var _editor$element_comme;
|
|
108
|
-
var
|
|
109
|
-
var comments = ((_editor$element_comme = editor.element_comments_map) === null || _editor$element_comme === void 0 ? void 0 : _editor$element_comme[
|
|
108
|
+
var _parentNode = getParentNode(editor.children, element.id);
|
|
109
|
+
var comments = ((_editor$element_comme = editor.element_comments_map) === null || _editor$element_comme === void 0 ? void 0 : _editor$element_comme[_parentNode.id]) || [];
|
|
110
110
|
var unresolvedComments = comments && comments.filter(function (item) {
|
|
111
111
|
return !item.resolved;
|
|
112
112
|
});
|
|
@@ -153,9 +153,9 @@ var CustomRenderElement = function CustomRenderElement(props) {
|
|
|
153
153
|
}
|
|
154
154
|
default:
|
|
155
155
|
{
|
|
156
|
-
var _ParagraphPlugin$
|
|
157
|
-
|
|
158
|
-
return
|
|
156
|
+
var _ParagraphPlugin$rend3 = _slicedToArray(ParagraphPlugin.renderElements, 1),
|
|
157
|
+
_renderParagraph2 = _ParagraphPlugin$rend3[0];
|
|
158
|
+
return _renderParagraph2(props);
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
};
|
|
@@ -143,6 +143,10 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
|
143
143
|
var socketManager = SocketManager.getInstance();
|
|
144
144
|
socketManager.receiveRemoveDocumentError();
|
|
145
145
|
};
|
|
146
|
+
this.receiveNewNotification = function (notification) {
|
|
147
|
+
var socketManager = SocketManager.getInstance();
|
|
148
|
+
socketManager.receiveNewNotification(notification);
|
|
149
|
+
};
|
|
146
150
|
this.config = config;
|
|
147
151
|
this.isReconnect = false;
|
|
148
152
|
this.socket = io(config.sdocServer, {
|
|
@@ -170,6 +174,9 @@ var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
|
170
174
|
this.socket.on('doc-removed', this.receiveRemoveDocument);
|
|
171
175
|
this.socket.on('doc-removed-error', this.receiveRemoveDocumentError);
|
|
172
176
|
this.socket.on('update-cursor', this.receiveCursorLocation);
|
|
177
|
+
|
|
178
|
+
// notification
|
|
179
|
+
this.socket.on('new-notification', this.receiveNewNotification);
|
|
173
180
|
this.socket.io.on('reconnect', this.onReconnect);
|
|
174
181
|
this.socket.io.on('reconnect_attempt', this.onReconnectAttempt);
|
|
175
182
|
this.socket.io.on('reconnect_error', this.onReconnectError);
|
|
@@ -48,6 +48,9 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, _do
|
|
|
48
48
|
this.receiveDocumentReplacedError = function () {
|
|
49
49
|
_this.eventBus.dispatch(EXTERNAL_EVENT.DOCUMENT_REPLACED_ERROR);
|
|
50
50
|
};
|
|
51
|
+
this.receiveNewNotification = function (notification) {
|
|
52
|
+
_this.eventBus.dispatch(EXTERNAL_EVENT.NEW_NOTIFICATION, notification);
|
|
53
|
+
};
|
|
51
54
|
this.onReceiveLocalOperations = function (operations) {
|
|
52
55
|
_this.pendingOperationList.push(operations);
|
|
53
56
|
var lastOpBeginTime = new Date().getTime();
|
|
@@ -9,6 +9,7 @@ import CommentsOperation from './comments-operation';
|
|
|
9
9
|
import ShareOperation from './share-operation';
|
|
10
10
|
import TagOperation from './tag-operation';
|
|
11
11
|
import { isMobile } from '../../utils';
|
|
12
|
+
import NotificationOperation from './notifications-operation';
|
|
12
13
|
import './style.css';
|
|
13
14
|
var DocOperations = function DocOperations(_ref) {
|
|
14
15
|
var isShowChanges = _ref.isShowChanges,
|
|
@@ -33,6 +34,6 @@ var DocOperations = function DocOperations(_ref) {
|
|
|
33
34
|
handleViewChangesToggle: handleViewChangesToggle,
|
|
34
35
|
handleRevisionMerged: handleRevisionMerged,
|
|
35
36
|
handleRevisionPublished: handleRevisionPublished
|
|
36
|
-
}), !isPublished && /*#__PURE__*/React.createElement(TagOperation, null), !isPublished && /*#__PURE__*/React.createElement(CommentsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(ShareOperation, null), /*#__PURE__*/React.createElement(HistoryOperation, null), !isPublished && /*#__PURE__*/React.createElement(CollaboratorsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(MoreOperations, null));
|
|
37
|
+
}), !isPublished && /*#__PURE__*/React.createElement(TagOperation, null), !isPublished && /*#__PURE__*/React.createElement(NotificationOperation, null), !isPublished && /*#__PURE__*/React.createElement(CommentsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(ShareOperation, null), /*#__PURE__*/React.createElement(HistoryOperation, null), !isPublished && /*#__PURE__*/React.createElement(CollaboratorsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(MoreOperations, null));
|
|
37
38
|
};
|
|
38
39
|
export default withTranslation('sdoc-editor')(DocOperations);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.sdoc-notification-icon-container .sdoc-notification-count {
|
|
2
|
+
position: absolute;
|
|
3
|
+
color: #fff;
|
|
4
|
+
font-size: 12px;
|
|
5
|
+
top: -7px;
|
|
6
|
+
right: -6px;
|
|
7
|
+
padding: 2px;
|
|
8
|
+
background: #fc6440;
|
|
9
|
+
border-radius: 50%;
|
|
10
|
+
min-width: 20px;
|
|
11
|
+
min-height: 20px;
|
|
12
|
+
transform: scale(.7);
|
|
13
|
+
text-align: center;
|
|
14
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { EventBus } from '../../../basic-sdk';
|
|
5
|
+
import { EXTERNAL_EVENT } from '../../../constants';
|
|
6
|
+
import { createNotify, getErrorMsg } from '../../../utils';
|
|
7
|
+
import { useCollaborators } from '../../../hooks';
|
|
8
|
+
import context from '../../../context';
|
|
9
|
+
import { Notification } from '../../../model';
|
|
10
|
+
import NotificationPopover from './notifications-popover';
|
|
11
|
+
import AllNotificationsDialog from './notifications-dialog';
|
|
12
|
+
import toaster from '../../toast';
|
|
13
|
+
import './index.css';
|
|
14
|
+
var PER_PAGE = 25;
|
|
15
|
+
var NotificationOperation = function NotificationOperation() {
|
|
16
|
+
var _useState = useState([]),
|
|
17
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
18
|
+
notifications = _useState2[0],
|
|
19
|
+
setNotifications = _useState2[1];
|
|
20
|
+
var _useState3 = useState(true),
|
|
21
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
22
|
+
hasMore = _useState4[0],
|
|
23
|
+
setHasMore = _useState4[1];
|
|
24
|
+
var _useState5 = useState(1),
|
|
25
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
26
|
+
page = _useState6[0],
|
|
27
|
+
setPage = _useState6[1];
|
|
28
|
+
var _useState7 = useState(false),
|
|
29
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
30
|
+
showNotificationsDialog = _useState8[0],
|
|
31
|
+
setShowNotificationsDialog = _useState8[1];
|
|
32
|
+
var _useTranslation = useTranslation(),
|
|
33
|
+
t = _useTranslation.t;
|
|
34
|
+
var _useCollaborators = useCollaborators(),
|
|
35
|
+
collaborators = _useCollaborators.collaborators;
|
|
36
|
+
var id = 'sdoc-notification';
|
|
37
|
+
var popupBrowserCommentNotification = useCallback(function (notification) {
|
|
38
|
+
if (!notification) return;
|
|
39
|
+
var author = notification.author,
|
|
40
|
+
msgType = notification.msg_type,
|
|
41
|
+
reply = notification.reply,
|
|
42
|
+
comment = notification.comment;
|
|
43
|
+
var authorInfo = collaborators.find(function (collaborator) {
|
|
44
|
+
return collaborator.email === author;
|
|
45
|
+
});
|
|
46
|
+
var notificationContent = comment || reply;
|
|
47
|
+
var titleKey = msgType === 'comment' ? 'xxx_added_a_new_comment' : 'xxx_added_a_reply';
|
|
48
|
+
var title = t(titleKey, {
|
|
49
|
+
author: authorInfo ? authorInfo.name : t('Unknown')
|
|
50
|
+
});
|
|
51
|
+
var options = {
|
|
52
|
+
body: "".concat(notificationContent)
|
|
53
|
+
};
|
|
54
|
+
createNotify(title, options);
|
|
55
|
+
}, [collaborators, t]);
|
|
56
|
+
var _listNotifications = useCallback(function (page) {
|
|
57
|
+
var perPage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : PER_PAGE;
|
|
58
|
+
var forceAcquisition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
59
|
+
if (!forceAcquisition && !hasMore) return;
|
|
60
|
+
var newNotifications = page === 1 ? [] : notifications.slice(0);
|
|
61
|
+
context.listNotifications(page, perPage).then(function (res) {
|
|
62
|
+
var _res$data = res.data,
|
|
63
|
+
loadedNotifications = _res$data.notifications,
|
|
64
|
+
total_count = _res$data.total_count;
|
|
65
|
+
var hasMore = total_count > notifications.length + newNotifications.length;
|
|
66
|
+
loadedNotifications.forEach(function (n) {
|
|
67
|
+
var notification = new Notification(n);
|
|
68
|
+
newNotifications.push(notification);
|
|
69
|
+
});
|
|
70
|
+
setHasMore(hasMore);
|
|
71
|
+
setPage(page + 1);
|
|
72
|
+
setNotifications(newNotifications);
|
|
73
|
+
}).catch(function (error) {
|
|
74
|
+
var errMsg = getErrorMsg(error, true);
|
|
75
|
+
if (!error.response || error.response.status !== 403) {
|
|
76
|
+
toaster.danger(t(errMsg));
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}, [notifications, hasMore, t]);
|
|
80
|
+
var onNewNotification = useCallback(function (notification) {
|
|
81
|
+
popupBrowserCommentNotification(notification);
|
|
82
|
+
_listNotifications(1, PER_PAGE, true);
|
|
83
|
+
}, [popupBrowserCommentNotification, _listNotifications]);
|
|
84
|
+
useEffect(function () {
|
|
85
|
+
_listNotifications(1, PER_PAGE);
|
|
86
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
|
+
}, []);
|
|
88
|
+
useEffect(function () {
|
|
89
|
+
var eventBus = EventBus.getInstance();
|
|
90
|
+
var unsubscribeNewNotification = eventBus.subscribe(EXTERNAL_EVENT.NEW_NOTIFICATION, onNewNotification);
|
|
91
|
+
return function () {
|
|
92
|
+
unsubscribeNewNotification();
|
|
93
|
+
};
|
|
94
|
+
}, [onNewNotification]);
|
|
95
|
+
var markAllNotificationsRead = useCallback(function () {
|
|
96
|
+
context.markAllNotificationsRead().then(function (res) {
|
|
97
|
+
var newNotifications = notifications.slice(0).map(function (n) {
|
|
98
|
+
n.seen = true;
|
|
99
|
+
return n;
|
|
100
|
+
});
|
|
101
|
+
setNotifications(newNotifications);
|
|
102
|
+
}).catch(function (error) {
|
|
103
|
+
var errMsg = getErrorMsg(error, true);
|
|
104
|
+
if (!error.response || error.response.status !== 403) {
|
|
105
|
+
toaster.danger(t(errMsg));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}, [notifications, t]);
|
|
109
|
+
var markNotificationRead = useCallback(function (notificationId) {
|
|
110
|
+
context.markNotificationRead(notificationId).then(function (res) {
|
|
111
|
+
var newNotifications = notifications.slice(0).map(function (n) {
|
|
112
|
+
if (n.id === notificationId) {
|
|
113
|
+
n.seen = true;
|
|
114
|
+
}
|
|
115
|
+
return n;
|
|
116
|
+
});
|
|
117
|
+
setNotifications(newNotifications);
|
|
118
|
+
}).catch(function (error) {
|
|
119
|
+
var errMsg = getErrorMsg(error, true);
|
|
120
|
+
if (!error.response || error.response.status !== 403) {
|
|
121
|
+
toaster.danger(t(errMsg));
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}, [notifications, t]);
|
|
125
|
+
var deleteAllNotifications = useCallback(function () {
|
|
126
|
+
context.deleteAllNotifications().then(function (res) {
|
|
127
|
+
setNotifications([]);
|
|
128
|
+
setPage(1);
|
|
129
|
+
setHasMore(true);
|
|
130
|
+
}).catch(function (error) {
|
|
131
|
+
var errMsg = getErrorMsg(error);
|
|
132
|
+
if (!error.response || error.response.status !== 403) {
|
|
133
|
+
toaster.danger(t(errMsg));
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}, [t]);
|
|
137
|
+
var toggleNotificationsDialog = useCallback(function () {
|
|
138
|
+
setShowNotificationsDialog(!showNotificationsDialog);
|
|
139
|
+
}, [showNotificationsDialog]);
|
|
140
|
+
var unreadNotificationsCount = notifications.filter(function (n) {
|
|
141
|
+
return !n.seen;
|
|
142
|
+
}).length;
|
|
143
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
|
144
|
+
className: "op-item sdoc-notification-icon-container",
|
|
145
|
+
id: id
|
|
146
|
+
}, /*#__PURE__*/React.createElement("i", {
|
|
147
|
+
className: "sdocfont sdoc-notification"
|
|
148
|
+
}), unreadNotificationsCount > 0 && /*#__PURE__*/React.createElement("span", {
|
|
149
|
+
className: "sdoc-notification-count"
|
|
150
|
+
}, unreadNotificationsCount)), /*#__PURE__*/React.createElement(NotificationPopover, {
|
|
151
|
+
target: id,
|
|
152
|
+
notifications: notifications,
|
|
153
|
+
listNotifications: function listNotifications() {
|
|
154
|
+
return _listNotifications(page, PER_PAGE);
|
|
155
|
+
},
|
|
156
|
+
markAllNotificationsRead: markAllNotificationsRead,
|
|
157
|
+
markNotificationRead: markNotificationRead,
|
|
158
|
+
onToggleNotificationsDialog: toggleNotificationsDialog
|
|
159
|
+
}), showNotificationsDialog && /*#__PURE__*/React.createElement(AllNotificationsDialog, {
|
|
160
|
+
notifications: notifications,
|
|
161
|
+
listNotifications: function listNotifications() {
|
|
162
|
+
return _listNotifications(page, PER_PAGE);
|
|
163
|
+
},
|
|
164
|
+
markNotificationRead: markNotificationRead,
|
|
165
|
+
markAllNotificationsRead: markAllNotificationsRead,
|
|
166
|
+
deleteAllNotifications: deleteAllNotifications,
|
|
167
|
+
toggle: toggleNotificationsDialog
|
|
168
|
+
}));
|
|
169
|
+
};
|
|
170
|
+
export default NotificationOperation;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
.sdoc-all-notifications-dialog {
|
|
2
|
+
width: 720px;
|
|
3
|
+
max-width: 720px;
|
|
4
|
+
height: calc(100% - 56px);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.sdoc-all-notifications-dialog .modal-content {
|
|
8
|
+
height: 100%;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.sdoc-all-notifications-dialog .sdoc-notification-header-close {
|
|
12
|
+
display: flex;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.sdoc-all-notifications-dialog .sdoc-notification-dropdown-toggle {
|
|
16
|
+
display: flex;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
align-items: center;
|
|
19
|
+
height: 24px;
|
|
20
|
+
width: 24px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.sdoc-all-notifications-dialog .sdoc-notification-operation-btn {
|
|
24
|
+
height: 24px;
|
|
25
|
+
width: 24px;
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
color: #000;
|
|
30
|
+
opacity: .5;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.sdoc-all-notifications-dialog .sdoc-notification-operation-btn:hover {
|
|
34
|
+
opacity: .75;
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sdoc-all-notifications-dialog .sdoc-all-notifications-body {
|
|
39
|
+
height: 100%;
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
padding: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.sdoc-all-notifications-dialog .sdoc-all-notifications-container {
|
|
45
|
+
overflow: auto;
|
|
46
|
+
padding: 2rem 1rem;
|
|
47
|
+
height: 100%;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.sdoc-all-notifications-dialog .sdoc-all-notifications-container table {
|
|
51
|
+
width: 100%;
|
|
52
|
+
table-layout: fixed;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.sdoc-all-notifications-dialog .sdoc-all-notifications-container .sdoc-notifications-table-header-sm {
|
|
56
|
+
font-size: 13px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.sdoc-all-notifications-dialog .sdoc-all-notifications-container table thead tr {
|
|
60
|
+
height: 2.1875rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.sdoc-all-notifications-dialog .sdoc-all-notifications-container table th {
|
|
64
|
+
padding: 0.3125rem 0.1875rem;
|
|
65
|
+
border-bottom: 1px solid #eee;
|
|
66
|
+
text-align: left;
|
|
67
|
+
font-weight: 400;
|
|
68
|
+
line-height: 1.6;
|
|
69
|
+
color: #9c9c9c;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.sdoc-all-notifications-dialog .sdoc-all-notifications-container table td {
|
|
73
|
+
padding: 0.5rem 0.1875rem;
|
|
74
|
+
border-bottom: 1px solid #eee;
|
|
75
|
+
color: #333;
|
|
76
|
+
font-size: 14px;
|
|
77
|
+
word-break: break-all;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.sdoc-all-notifications-dialog .sdoc-all-notifications-container table tbody tr:hover {
|
|
81
|
+
background: #f5f5f5;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.sdoc-all-notifications-dialog .sdoc-empty-notifications-tip {
|
|
86
|
+
height: 100%;
|
|
87
|
+
width: 100%;
|
|
88
|
+
padding: 5.5em 1em;
|
|
89
|
+
border-radius: 3px;
|
|
90
|
+
background-color: #fff;
|
|
91
|
+
text-align: center;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.sdoc-all-notifications-dialog .sdoc-empty-notifications-tip .sdoc-empty-notifications-img-tip {
|
|
95
|
+
width: 100px;
|
|
96
|
+
height: 100px;
|
|
97
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
+
import React, { useCallback, useState, useRef } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Modal, ModalHeader, ModalBody, Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
|
5
|
+
import context from '../../../../context';
|
|
6
|
+
import Notification from './notification';
|
|
7
|
+
import './index.css';
|
|
8
|
+
var AllNotificationsDialog = function AllNotificationsDialog(_ref) {
|
|
9
|
+
var notifications = _ref.notifications,
|
|
10
|
+
toggle = _ref.toggle,
|
|
11
|
+
markAllNotificationsRead = _ref.markAllNotificationsRead,
|
|
12
|
+
deleteAllNotifications = _ref.deleteAllNotifications,
|
|
13
|
+
markNotificationRead = _ref.markNotificationRead,
|
|
14
|
+
listNotifications = _ref.listNotifications;
|
|
15
|
+
var _useTranslation = useTranslation(),
|
|
16
|
+
t = _useTranslation.t;
|
|
17
|
+
var _useState = useState(false),
|
|
18
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
19
|
+
isMenuShow = _useState2[0],
|
|
20
|
+
setMenuShow = _useState2[1];
|
|
21
|
+
var containerRef = useRef(null);
|
|
22
|
+
var tableRef = useRef(null);
|
|
23
|
+
var toggleMenu = useCallback(function () {
|
|
24
|
+
setMenuShow(!isMenuShow);
|
|
25
|
+
}, [isMenuShow]);
|
|
26
|
+
var onScroll = useCallback(function () {
|
|
27
|
+
if (containerRef.current.offsetHeight + containerRef.current.scrollTop + 1 >= tableRef.current.offsetHeight + 64) {
|
|
28
|
+
// 64 is padding height
|
|
29
|
+
listNotifications();
|
|
30
|
+
}
|
|
31
|
+
}, [listNotifications, containerRef, tableRef]);
|
|
32
|
+
var renderHeaderRowBtn = useCallback(function () {
|
|
33
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
34
|
+
className: "sdoc-notification-header-close"
|
|
35
|
+
}, /*#__PURE__*/React.createElement(Dropdown, {
|
|
36
|
+
isOpen: isMenuShow,
|
|
37
|
+
toggle: toggleMenu
|
|
38
|
+
}, /*#__PURE__*/React.createElement(DropdownToggle, {
|
|
39
|
+
tag: "span",
|
|
40
|
+
"data-toggle": "dropdown",
|
|
41
|
+
"aria-expanded": isMenuShow,
|
|
42
|
+
className: "sdoc-notification-dropdown-toggle"
|
|
43
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
44
|
+
className: "sdoc-notification-operation-btn"
|
|
45
|
+
}, /*#__PURE__*/React.createElement("i", {
|
|
46
|
+
className: "sdocfont sdoc-more"
|
|
47
|
+
}))), /*#__PURE__*/React.createElement(DropdownMenu, {
|
|
48
|
+
right: true,
|
|
49
|
+
className: "sdoc-dropdown-menu large"
|
|
50
|
+
}, /*#__PURE__*/React.createElement(DropdownItem, {
|
|
51
|
+
className: "sdoc-dropdown-menu-item",
|
|
52
|
+
onClick: markAllNotificationsRead
|
|
53
|
+
}, t('Mark_all_as_read')), /*#__PURE__*/React.createElement(DropdownItem, {
|
|
54
|
+
className: "sdoc-dropdown-menu-item",
|
|
55
|
+
onClick: deleteAllNotifications
|
|
56
|
+
}, t('Delete_all_notifications')))), /*#__PURE__*/React.createElement("div", {
|
|
57
|
+
className: "sdoc-notification-operation-btn",
|
|
58
|
+
onClick: toggle
|
|
59
|
+
}, /*#__PURE__*/React.createElement("i", {
|
|
60
|
+
className: "sdocfont sdoc-sm-close"
|
|
61
|
+
})));
|
|
62
|
+
}, [deleteAllNotifications, isMenuShow, markAllNotificationsRead, t, toggle, toggleMenu]);
|
|
63
|
+
var renderNotifications = useCallback(function () {
|
|
64
|
+
if (!Array.isArray(notifications) || notifications.length === 0) {
|
|
65
|
+
var mediaUrl = context.getSetting('mediaUrl');
|
|
66
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
67
|
+
className: "sdoc-empty-notifications-tip"
|
|
68
|
+
}, /*#__PURE__*/React.createElement("img", {
|
|
69
|
+
src: mediaUrl + 'img/no-items-tip.png',
|
|
70
|
+
className: "sdoc-empty-notifications-img-tip",
|
|
71
|
+
alt: ""
|
|
72
|
+
}), /*#__PURE__*/React.createElement("p", null, t('No_notification')));
|
|
73
|
+
}
|
|
74
|
+
return /*#__PURE__*/React.createElement("table", {
|
|
75
|
+
ref: tableRef
|
|
76
|
+
}, /*#__PURE__*/React.createElement("thead", {
|
|
77
|
+
className: "sdoc-notifications-table-header-sm"
|
|
78
|
+
}, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", {
|
|
79
|
+
width: "10%"
|
|
80
|
+
}), /*#__PURE__*/React.createElement("th", {
|
|
81
|
+
width: "70%"
|
|
82
|
+
}, t('News')), /*#__PURE__*/React.createElement("th", {
|
|
83
|
+
width: "20%"
|
|
84
|
+
}, t('Update_date')))), /*#__PURE__*/React.createElement("tbody", null, notifications.map(function (item) {
|
|
85
|
+
return /*#__PURE__*/React.createElement(Notification, {
|
|
86
|
+
key: item.id,
|
|
87
|
+
notification: item,
|
|
88
|
+
markNotificationRead: markNotificationRead
|
|
89
|
+
});
|
|
90
|
+
})));
|
|
91
|
+
}, [notifications, t, markNotificationRead]);
|
|
92
|
+
return /*#__PURE__*/React.createElement(Modal, {
|
|
93
|
+
isOpen: true,
|
|
94
|
+
toggle: toggle,
|
|
95
|
+
className: "sdoc-all-notifications-dialog"
|
|
96
|
+
}, /*#__PURE__*/React.createElement(ModalHeader, {
|
|
97
|
+
close: renderHeaderRowBtn(),
|
|
98
|
+
toggle: toggle
|
|
99
|
+
}, t('All_notifications')), /*#__PURE__*/React.createElement(ModalBody, {
|
|
100
|
+
className: "sdoc-all-notifications-body"
|
|
101
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
102
|
+
className: "sdoc-all-notifications-container",
|
|
103
|
+
ref: containerRef,
|
|
104
|
+
onScroll: onScroll
|
|
105
|
+
}, renderNotifications())));
|
|
106
|
+
};
|
|
107
|
+
export default AllNotificationsDialog;
|