@seafile/sdoc-editor 0.4.0 → 0.4.2
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/basic-sdk/constants/index.js +2 -2
- package/dist/basic-sdk/extension/plugins/blockquote/plugin.js +47 -55
- package/dist/basic-sdk/extension/plugins/file-link/render-elem.js +2 -2
- package/dist/basic-sdk/extension/plugins/image/hover-menu/index.js +13 -6
- package/dist/basic-sdk/extension/plugins/image/render-elem.js +15 -10
- package/dist/basic-sdk/extension/plugins/sdoc-link/render-elem.js +2 -2
- package/dist/basic-sdk/extension/plugins/table/plugin.js +20 -3
- package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/index.css +26 -9
- package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-delete-modify-decorate.js +9 -9
- package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-modify-delete-decorate.js +8 -8
- package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-modify-modify-decorate.js +8 -11
- package/dist/basic-sdk/utils/rebase.js +20 -4
- package/dist/components/doc-operations/index.js +1 -2
- package/dist/components/doc-operations/more-operations.js +17 -4
- package/dist/components/tip-dialog/index.js +1 -1
- package/package.json +1 -1
- package/public/locales/en/sdoc-editor.json +4 -1
- package/public/locales/fr/sdoc-editor.json +2 -1
- package/public/locales/ru/sdoc-editor.json +2 -2
- package/public/locales/zh_CN/sdoc-editor.json +5 -2
- package/dist/components/doc-operations/history-operation.js +0 -23
|
@@ -29,9 +29,9 @@ export const MODIFY_TYPE = {
|
|
|
29
29
|
export const REBASE_TYPE = {
|
|
30
30
|
MODIFY_MODIFY: 'modify_modify',
|
|
31
31
|
DELETE_MODIFY: 'delete_modify',
|
|
32
|
-
MODIFY_DELETE: 'modify_delete'
|
|
33
|
-
CHILDREN_MODIFY: 'children_modify'
|
|
32
|
+
MODIFY_DELETE: 'modify_delete'
|
|
34
33
|
};
|
|
34
|
+
export const REBASE_TYPES = [REBASE_TYPE.MODIFY_DELETE, REBASE_TYPE.DELETE_MODIFY, REBASE_TYPE.MODIFY_MODIFY];
|
|
35
35
|
export const REBASE_MARK_KEY = {
|
|
36
36
|
ORIGIN: 'origin',
|
|
37
37
|
REBASE_TYPE: 'rebase_type',
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { ReactEditor } from '@seafile/slate-react';
|
|
4
|
-
import { generateEmptyElement, getSelectedNodeByType, isSelectionAtBlockStart } from '../../core';
|
|
1
|
+
import { Editor, Element, Transforms, Node } from '@seafile/slate';
|
|
2
|
+
import { focusEditor, generateDefaultText, getSelectedNodeByType, isSelectionAtBlockStart } from '../../core';
|
|
5
3
|
import { BLOCKQUOTE, PARAGRAPH, CODE_BLOCK, TABLE } from '../../constants';
|
|
6
4
|
import { setBlockQuoteType, getFormattedElements, getFormattedRestElements } from './helpers';
|
|
7
|
-
import { getCalloutEntry, insertElementAtNewLineInCallout } from '../callout/helper';
|
|
8
5
|
const withBlockquote = editor => {
|
|
9
6
|
const {
|
|
10
7
|
insertBreak,
|
|
11
|
-
insertText,
|
|
12
8
|
deleteBackward,
|
|
13
9
|
insertFragment
|
|
14
10
|
} = editor;
|
|
@@ -18,40 +14,38 @@ const withBlockquote = editor => {
|
|
|
18
14
|
selection
|
|
19
15
|
} = editor;
|
|
20
16
|
if (selection == null) return insertBreak();
|
|
21
|
-
const [
|
|
17
|
+
const [quoteBlockEntry] = Editor.nodes(editor, {
|
|
22
18
|
match: n => Element.isElement(n) && n.type === BLOCKQUOTE,
|
|
23
19
|
universal: true
|
|
24
20
|
});
|
|
25
|
-
if (!
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
// Step 1: Remove the last \n
|
|
43
|
-
editor.deleteBackward('character');
|
|
44
|
-
// Step 2: Insert a paragraph
|
|
45
|
-
const p = generateEmptyElement(PARAGRAPH);
|
|
46
|
-
Transforms.insertNodes(newEditor, p, {
|
|
47
|
-
mode: 'highest'
|
|
21
|
+
if (!quoteBlockEntry) return insertBreak();
|
|
22
|
+
const [currentLineEntry] = Editor.nodes(newEditor, {
|
|
23
|
+
match: n => Element.isElement(n) && n.type === PARAGRAPH,
|
|
24
|
+
mode: 'lowest'
|
|
25
|
+
});
|
|
26
|
+
// Exit blockquote when current line is empty
|
|
27
|
+
const isAtEnd = currentLineEntry[1].slice(-1)[0] === quoteBlockEntry[0].children.length - 1;
|
|
28
|
+
if (isAtEnd) {
|
|
29
|
+
const isEmptyLine = !(currentLineEntry && Editor.string(newEditor, currentLineEntry[1]).length);
|
|
30
|
+
const movePath = quoteBlockEntry[1];
|
|
31
|
+
movePath.push(movePath.pop() + 1);
|
|
32
|
+
if (isEmptyLine) {
|
|
33
|
+
Transforms.moveNodes(newEditor, {
|
|
34
|
+
at: currentLineEntry[1],
|
|
35
|
+
to: movePath
|
|
48
36
|
});
|
|
49
37
|
return;
|
|
50
38
|
}
|
|
51
39
|
}
|
|
52
40
|
|
|
53
|
-
//
|
|
54
|
-
|
|
41
|
+
// Insert new line
|
|
42
|
+
Transforms.insertNodes(editor, {
|
|
43
|
+
type: PARAGRAPH,
|
|
44
|
+
children: [generateDefaultText()]
|
|
45
|
+
}, {
|
|
46
|
+
at: newEditor.selection,
|
|
47
|
+
select: true
|
|
48
|
+
});
|
|
55
49
|
};
|
|
56
50
|
newEditor.deleteBackward = unit => {
|
|
57
51
|
const {
|
|
@@ -63,32 +57,30 @@ const withBlockquote = editor => {
|
|
|
63
57
|
}
|
|
64
58
|
const node = getSelectedNodeByType(editor, BLOCKQUOTE);
|
|
65
59
|
if (node) {
|
|
66
|
-
|
|
60
|
+
const [currentLineEntry] = Editor.nodes(newEditor, {
|
|
61
|
+
match: n => Element.isElement(n) && n.type === PARAGRAPH,
|
|
62
|
+
mode: 'lowest'
|
|
63
|
+
});
|
|
64
|
+
if (!currentLineEntry) return deleteBackward(unit);
|
|
65
|
+
const currentLineIndex = currentLineEntry[1].slice(-1)[0];
|
|
66
|
+
if (currentLineIndex === 0) {
|
|
67
67
|
setBlockQuoteType(editor, PARAGRAPH);
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
|
-
if (
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}); // cursor at middle or end of line, save \n
|
|
85
|
-
Transforms.delete(editor, {
|
|
86
|
-
at: deleteRange
|
|
87
|
-
});
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
deleteBackward(unit);
|
|
70
|
+
if (isSelectionAtBlockStart(editor)) {
|
|
71
|
+
const lineText = Node.string(currentLineEntry[0]);
|
|
72
|
+
const previousNodeEntry = Editor.previous(editor, {
|
|
73
|
+
at: currentLineEntry[1]
|
|
74
|
+
});
|
|
75
|
+
const focusPoint = Editor.end(newEditor, previousNodeEntry[1]);
|
|
76
|
+
Transforms.insertText(newEditor, lineText, {
|
|
77
|
+
at: Editor.end(newEditor, previousNodeEntry[1])
|
|
78
|
+
});
|
|
79
|
+
Transforms.removeNodes(editor, {
|
|
80
|
+
at: currentLineEntry[1]
|
|
81
|
+
});
|
|
82
|
+
focusEditor(newEditor, focusPoint);
|
|
83
|
+
return;
|
|
92
84
|
}
|
|
93
85
|
}
|
|
94
86
|
deleteBackward(unit);
|
|
@@ -86,9 +86,9 @@ const FileLink = _ref => {
|
|
|
86
86
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
87
|
}, []);
|
|
88
88
|
let style = {};
|
|
89
|
-
if (element.
|
|
89
|
+
if (element.add) {
|
|
90
90
|
style = _objectSpread({}, ADDED_STYLE);
|
|
91
|
-
} else if (element.
|
|
91
|
+
} else if (element.delete) {
|
|
92
92
|
style = _objectSpread({}, DELETED_STYLE);
|
|
93
93
|
}
|
|
94
94
|
if (style.computed_background_color) {
|
|
@@ -19,7 +19,6 @@ const ImageHoverMenu = _ref => {
|
|
|
19
19
|
element,
|
|
20
20
|
parentNodeEntry,
|
|
21
21
|
onHideImageHoverMenu,
|
|
22
|
-
onShowCaption,
|
|
23
22
|
t
|
|
24
23
|
} = _ref;
|
|
25
24
|
const {
|
|
@@ -31,7 +30,7 @@ const ImageHoverMenu = _ref => {
|
|
|
31
30
|
type
|
|
32
31
|
} = parentNodeEntry[0];
|
|
33
32
|
const {
|
|
34
|
-
|
|
33
|
+
show_caption = false
|
|
35
34
|
} = data;
|
|
36
35
|
const [popoverState, setPopoverState] = useState({
|
|
37
36
|
displayPopover: false,
|
|
@@ -125,6 +124,14 @@ const ImageHoverMenu = _ref => {
|
|
|
125
124
|
onHideImageHoverMenu();
|
|
126
125
|
return;
|
|
127
126
|
}
|
|
127
|
+
if (Object.keys(props)[0] === 'show_caption') {
|
|
128
|
+
Transforms.setNodes(editor, {
|
|
129
|
+
data: _objectSpread(_objectSpread({}, data), props)
|
|
130
|
+
}, {
|
|
131
|
+
at: path
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
128
135
|
}
|
|
129
136
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
130
137
|
}, []);
|
|
@@ -182,11 +189,11 @@ const ImageHoverMenu = _ref => {
|
|
|
182
189
|
id: "sdoc_image_caption",
|
|
183
190
|
role: "button",
|
|
184
191
|
className: classnames('op-item', 'ml-1', {
|
|
185
|
-
'active':
|
|
192
|
+
'active': show_caption
|
|
186
193
|
}),
|
|
187
|
-
onClick:
|
|
188
|
-
|
|
189
|
-
}
|
|
194
|
+
onClick: event => onSelect(event, {
|
|
195
|
+
'show_caption': !show_caption
|
|
196
|
+
})
|
|
190
197
|
}, /*#__PURE__*/React.createElement("i", {
|
|
191
198
|
className: "sdocfont sdoc-describe icon-font mr-1"
|
|
192
199
|
}), isShowTooltip && /*#__PURE__*/React.createElement(Tooltip, {
|
|
@@ -10,9 +10,10 @@ import { INTERNAL_EVENT } from '../../../constants';
|
|
|
10
10
|
import ImageHoverMenu from './hover-menu';
|
|
11
11
|
import { useScrollContext } from '../../../hooks/use-scroll-context';
|
|
12
12
|
import { IMAGE_BORDER_TYPE } from './constants';
|
|
13
|
-
import { ADDED_STYLE, DELETED_STYLE } from '../../constants';
|
|
13
|
+
import { ADDED_STYLE, DELETED_STYLE, IMAGE_BLOCK } from '../../constants';
|
|
14
14
|
import imagePlaceholder from '../../../assets/images/image-placeholder.png';
|
|
15
15
|
const Image = _ref => {
|
|
16
|
+
var _imageRef$current, _imageRef$current2;
|
|
16
17
|
let {
|
|
17
18
|
element,
|
|
18
19
|
editor,
|
|
@@ -27,6 +28,9 @@ const Image = _ref => {
|
|
|
27
28
|
data,
|
|
28
29
|
border_type = IMAGE_BORDER_TYPE[0].type
|
|
29
30
|
} = element;
|
|
31
|
+
const {
|
|
32
|
+
show_caption = false
|
|
33
|
+
} = data;
|
|
30
34
|
const path = ReactEditor.findPath(editor, element);
|
|
31
35
|
const nodeEntry = Editor.node(editor, [path[0]]);
|
|
32
36
|
const imageStyle = {
|
|
@@ -42,7 +46,6 @@ const Image = _ref => {
|
|
|
42
46
|
const [isShowImageHoverMenu, setIsShowImageHoverMenu] = useState(false);
|
|
43
47
|
const [menuPosition, setMenuPosition] = useState({});
|
|
44
48
|
const [caption, setCaption] = useState((data === null || data === void 0 ? void 0 : data.caption) || '');
|
|
45
|
-
const [isShowCaption, setIsShowCaption] = useState(false);
|
|
46
49
|
const registerEvent = useCallback(eventList => {
|
|
47
50
|
eventList.forEach(element => {
|
|
48
51
|
document.addEventListener(element.eventName, element.event);
|
|
@@ -114,7 +117,8 @@ const Image = _ref => {
|
|
|
114
117
|
var _imagePreviewer$;
|
|
115
118
|
if (isResizing) return;
|
|
116
119
|
const imagePreviewer = document.getElementsByClassName('sf-editor-image-previewer');
|
|
117
|
-
|
|
120
|
+
const isCaptionInput = e.target.id === 'sdoc-image-caption-input';
|
|
121
|
+
if (e.target === imageRef.current || ((_imagePreviewer$ = imagePreviewer[0]) === null || _imagePreviewer$ === void 0 ? void 0 : _imagePreviewer$.contains(e.target)) || isCaptionInput) return;
|
|
118
122
|
setIsShowImageHoverMenu(false);
|
|
119
123
|
}, [isResizing]);
|
|
120
124
|
useEffect(() => {
|
|
@@ -225,10 +229,11 @@ const Image = _ref => {
|
|
|
225
229
|
}), isResizing && /*#__PURE__*/React.createElement("span", {
|
|
226
230
|
className: "image-size",
|
|
227
231
|
contentEditable: false
|
|
228
|
-
}, /*#__PURE__*/React.createElement("span", null, t('Width'), ':', parseInt(movingWidth || imageRef.current.clientWidth)), /*#__PURE__*/React.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/React.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type ===
|
|
232
|
+
}, /*#__PURE__*/React.createElement("span", null, t('Width'), ':', parseInt(movingWidth || ((_imageRef$current = imageRef.current) === null || _imageRef$current === void 0 ? void 0 : _imageRef$current.clientWidth))), /*#__PURE__*/React.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/React.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type === IMAGE_BLOCK && show_caption && /*#__PURE__*/React.createElement("input", {
|
|
233
|
+
id: "sdoc-image-caption-input",
|
|
229
234
|
className: "sdoc-image-caption-input-wrapper",
|
|
230
235
|
style: {
|
|
231
|
-
width: (data === null || data === void 0 ? void 0 : data.width) || imageRef.current.clientWidth
|
|
236
|
+
width: (data === null || data === void 0 ? void 0 : data.width) || ((_imageRef$current2 = imageRef.current) === null || _imageRef$current2 === void 0 ? void 0 : _imageRef$current2.clientWidth)
|
|
232
237
|
},
|
|
233
238
|
placeholder: t('Insert_caption'),
|
|
234
239
|
value: caption,
|
|
@@ -246,9 +251,6 @@ const Image = _ref => {
|
|
|
246
251
|
parentNodeEntry: nodeEntry,
|
|
247
252
|
onHideImageHoverMenu: () => {
|
|
248
253
|
setIsShowImageHoverMenu(false);
|
|
249
|
-
},
|
|
250
|
-
onShowCaption: () => {
|
|
251
|
-
setIsShowCaption(true);
|
|
252
254
|
}
|
|
253
255
|
})));
|
|
254
256
|
};
|
|
@@ -266,8 +268,11 @@ export function renderImage(props, editor) {
|
|
|
266
268
|
if (leaf && leaf.computed_background_color) {
|
|
267
269
|
style['backgroundColor'] = leaf.computed_background_color;
|
|
268
270
|
}
|
|
269
|
-
if (element.
|
|
270
|
-
style = Object.assign({}, style, element.
|
|
271
|
+
if (element.add || element.delete) {
|
|
272
|
+
style = Object.assign({}, style, element.add ? ADDED_STYLE : DELETED_STYLE);
|
|
273
|
+
if (style.computed_background_color) {
|
|
274
|
+
style['backgroundColor'] = style.computed_background_color;
|
|
275
|
+
}
|
|
271
276
|
}
|
|
272
277
|
return /*#__PURE__*/React.createElement(SdocImage, Object.assign({}, props, {
|
|
273
278
|
style: style,
|
|
@@ -88,9 +88,9 @@ const SdocFileLink = _ref => {
|
|
|
88
88
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89
89
|
}, []);
|
|
90
90
|
let style = {};
|
|
91
|
-
if (element.
|
|
91
|
+
if (element.add) {
|
|
92
92
|
style = _objectSpread({}, ADDED_STYLE);
|
|
93
|
-
} else if (element.
|
|
93
|
+
} else if (element.delete) {
|
|
94
94
|
style = _objectSpread({}, DELETED_STYLE);
|
|
95
95
|
}
|
|
96
96
|
if (style.computed_background_color) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
2
|
import isHotkey from 'is-hotkey';
|
|
3
|
-
import { Editor, Transforms, Path } from '@seafile/slate';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { Editor, Transforms, Path, Element } from '@seafile/slate';
|
|
4
|
+
import { ReactEditor } from '@seafile/slate-react';
|
|
5
|
+
import { getNodeType, getParentNode, getSelectedNodeByType, isLastNode, generateEmptyElement, focusEditor } from '../../core';
|
|
6
|
+
import { ELEMENT_TYPE, KEYBOARD, PARAGRAPH, CLIPBOARD_FORMAT_KEY, CHECK_LIST_ITEM, ORDERED_LIST, UNORDERED_LIST } from '../../constants';
|
|
6
7
|
import { TABLE_MAX_ROWS, EMPTY_SELECTED_RANGE, TABLE_ELEMENT, TABLE_ELEMENT_POSITION } from './constants';
|
|
7
8
|
import ObjectUtils from '../../../utils/object-utils';
|
|
8
9
|
import { getSelectedInfo, insertTableElement, removeTable, insertMultipleRowsAndColumns, setTableFragmentData, deleteTableRangeData, focusCell, deleteHandler, isTableLocation, isLastTableCell } from './helpers';
|
|
@@ -88,9 +89,25 @@ const withTable = editor => {
|
|
|
88
89
|
const before = Editor.before(newEditor, selection);
|
|
89
90
|
if (before) {
|
|
90
91
|
// If the current is not a table and the previous one is a table, no deletion will be performed. Otherwise, the last cell of the table will be deleted
|
|
92
|
+
// If deleting node is empty check-list, order-list, unordered-list, change to paragraph
|
|
91
93
|
const isTableOnBeforeLocation = isTableLocation(newEditor, before);
|
|
92
94
|
const isTableOnCurSelection = isTableLocation(newEditor, selection);
|
|
93
95
|
if (isTableOnBeforeLocation && !isTableOnCurSelection) {
|
|
96
|
+
const transformTypes = [CHECK_LIST_ITEM, ORDERED_LIST, UNORDERED_LIST];
|
|
97
|
+
const [currentNodeEntry] = Editor.nodes(editor, {
|
|
98
|
+
match: n => Element.isElement(n) && !Editor.parent(n, ReactEditor.findPath(editor, n))[1].length
|
|
99
|
+
});
|
|
100
|
+
if (!currentNodeEntry) return;
|
|
101
|
+
const [currentNode, currentPath] = Array.from(currentNodeEntry);
|
|
102
|
+
if (transformTypes.includes(currentNode.type)) {
|
|
103
|
+
Transforms.delete(newEditor, {
|
|
104
|
+
at: currentPath
|
|
105
|
+
});
|
|
106
|
+
Transforms.insertNodes(newEditor, generateEmptyElement(PARAGRAPH), {
|
|
107
|
+
at: currentPath
|
|
108
|
+
});
|
|
109
|
+
focusEditor(editor, Editor.start(editor, currentPath));
|
|
110
|
+
}
|
|
94
111
|
return;
|
|
95
112
|
}
|
|
96
113
|
}
|
|
@@ -1,29 +1,46 @@
|
|
|
1
1
|
.sdoc-rebase-btn-group {
|
|
2
|
+
display: flex;
|
|
3
|
+
width: 100%;
|
|
2
4
|
color: #aaa;
|
|
5
|
+
margin-bottom: 3px;
|
|
3
6
|
}
|
|
4
7
|
|
|
5
8
|
.sdoc-rebase-btn-group .sdoc-rebase-btn {
|
|
6
9
|
cursor: pointer;
|
|
7
10
|
}
|
|
8
11
|
|
|
9
|
-
.sdoc-rebase-
|
|
12
|
+
.sdoc-rebase-other-changes-title {
|
|
13
|
+
width: 100%;
|
|
14
|
+
padding-left: 4px;
|
|
10
15
|
background-color: rgb(202, 232, 254);
|
|
16
|
+
border-radius: 3px 3px 0 0;
|
|
11
17
|
}
|
|
12
18
|
|
|
13
|
-
.sdoc-rebase-
|
|
19
|
+
.sdoc-rebase-other-changes {
|
|
14
20
|
background-color: rgba(202, 232, 254, .8);
|
|
21
|
+
border-radius: 0 0 3px 3px;
|
|
22
|
+
margin-bottom: 3px;
|
|
15
23
|
}
|
|
16
24
|
|
|
17
|
-
.sdoc-rebase-
|
|
25
|
+
.sdoc-rebase-my-changes-title {
|
|
26
|
+
width: 100%;
|
|
27
|
+
padding-left: 4px;
|
|
28
|
+
background-color: rgb(212, 212, 254);
|
|
29
|
+
border-radius: 3px 3px 0 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.sdoc-rebase-my-changes {
|
|
18
33
|
background-color: rgb(222, 232, 254);
|
|
34
|
+
border-radius: 0 0 3px 3px;
|
|
19
35
|
}
|
|
20
36
|
|
|
21
|
-
.sdoc-rebase-
|
|
22
|
-
.sdoc-rebase-
|
|
23
|
-
|
|
24
|
-
padding: 0.8em 0 0.8em 0.2em;
|
|
37
|
+
.sdoc-rebase-my-changes.empty,
|
|
38
|
+
.sdoc-rebase-other-changes.empty {
|
|
39
|
+
height: 3px;
|
|
25
40
|
}
|
|
26
41
|
|
|
27
|
-
.sdoc-rebase-
|
|
28
|
-
|
|
42
|
+
.sdoc-rebase-my-changes > *:first-child,
|
|
43
|
+
.sdoc-rebase-other-changes > *:first-child {
|
|
44
|
+
margin: 0;
|
|
45
|
+
padding: 0.8em 0 0.8em 0.2em;
|
|
29
46
|
}
|
|
@@ -35,7 +35,7 @@ const RebaseDeleteModifyDecorate = _ref => {
|
|
|
35
35
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
36
36
|
}, [editor, element]);
|
|
37
37
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
38
|
-
className: "
|
|
38
|
+
className: "sdoc-rebase-btn-group",
|
|
39
39
|
contentEditable: false
|
|
40
40
|
}, /*#__PURE__*/React.createElement("div", {
|
|
41
41
|
className: "sdoc-rebase-btn",
|
|
@@ -51,17 +51,17 @@ const RebaseDeleteModifyDecorate = _ref => {
|
|
|
51
51
|
className: "sdoc-rebase-btn",
|
|
52
52
|
onClick: deleteMark
|
|
53
53
|
}, t('Keep_both_modification'))), /*#__PURE__*/React.createElement("div", {
|
|
54
|
-
className: "
|
|
54
|
+
className: "sdoc-rebase-other-changes-title",
|
|
55
55
|
contentEditable: false
|
|
56
|
-
}, '
|
|
57
|
-
className: "
|
|
56
|
+
}, t('Other_modification')), /*#__PURE__*/React.createElement("div", {
|
|
57
|
+
className: "sdoc-rebase-other-changes empty",
|
|
58
58
|
contentEditable: false
|
|
59
|
-
}
|
|
60
|
-
className: "
|
|
59
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
60
|
+
className: "sdoc-rebase-my-changes-title",
|
|
61
61
|
contentEditable: false
|
|
62
|
-
},
|
|
63
|
-
className: "
|
|
62
|
+
}, t('My_modification')), /*#__PURE__*/React.createElement("div", {
|
|
63
|
+
className: "sdoc-rebase-my-changes",
|
|
64
64
|
contentEditable: false
|
|
65
|
-
},
|
|
65
|
+
}, children));
|
|
66
66
|
};
|
|
67
67
|
export default RebaseDeleteModifyDecorate;
|
|
@@ -35,7 +35,7 @@ const RebaseModifyDeleteDecorate = _ref => {
|
|
|
35
35
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
36
36
|
}, [editor, element]);
|
|
37
37
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
38
|
-
className: "
|
|
38
|
+
className: "sdoc-rebase-btn-group",
|
|
39
39
|
contentEditable: false
|
|
40
40
|
}, /*#__PURE__*/React.createElement("div", {
|
|
41
41
|
className: "sdoc-rebase-btn",
|
|
@@ -51,17 +51,17 @@ const RebaseModifyDeleteDecorate = _ref => {
|
|
|
51
51
|
className: "sdoc-rebase-btn",
|
|
52
52
|
onClick: deleteMark
|
|
53
53
|
}, t('Keep_both_modification'))), /*#__PURE__*/React.createElement("div", {
|
|
54
|
-
className: "
|
|
54
|
+
className: "sdoc-rebase-other-changes-title",
|
|
55
55
|
contentEditable: false
|
|
56
|
-
}, '
|
|
57
|
-
className: "w-100 sdoc-rebase-
|
|
56
|
+
}, t('Other_modification')), /*#__PURE__*/React.createElement("div", {
|
|
57
|
+
className: "w-100 sdoc-rebase-my-changes",
|
|
58
58
|
contentEditable: false
|
|
59
59
|
}, children), /*#__PURE__*/React.createElement("div", {
|
|
60
|
-
className: "
|
|
60
|
+
className: "sdoc-rebase-my-changes-title",
|
|
61
61
|
contentEditable: false
|
|
62
|
-
}, '
|
|
63
|
-
className: "
|
|
62
|
+
}, t('My_modification')), /*#__PURE__*/React.createElement("div", {
|
|
63
|
+
className: "sdoc-rebase-my-changes empty",
|
|
64
64
|
contentEditable: false
|
|
65
|
-
}
|
|
65
|
+
}));
|
|
66
66
|
};
|
|
67
67
|
export default RebaseModifyDeleteDecorate;
|
|
@@ -62,7 +62,7 @@ const RebaseModifyModifyDecorate = _ref => {
|
|
|
62
62
|
}, [editor, element]);
|
|
63
63
|
if (element[REBASE_MARK_KEY.ORIGIN] === REBASE_ORIGIN.OTHER) {
|
|
64
64
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
65
|
-
className: "
|
|
65
|
+
className: "sdoc-rebase-btn-group",
|
|
66
66
|
contentEditable: false
|
|
67
67
|
}, /*#__PURE__*/React.createElement("div", {
|
|
68
68
|
className: "sdoc-rebase-btn",
|
|
@@ -78,22 +78,19 @@ const RebaseModifyModifyDecorate = _ref => {
|
|
|
78
78
|
className: "sdoc-rebase-btn",
|
|
79
79
|
onClick: useBothChanges
|
|
80
80
|
}, t('Keep_both_modification'))), /*#__PURE__*/React.createElement("div", {
|
|
81
|
-
className: "
|
|
81
|
+
className: "sdoc-rebase-other-changes-title",
|
|
82
82
|
contentEditable: false
|
|
83
|
-
}, '
|
|
84
|
-
className: "
|
|
83
|
+
}, t('Other_modification')), /*#__PURE__*/React.createElement("div", {
|
|
84
|
+
className: "sdoc-rebase-other-changes",
|
|
85
85
|
contentEditable: false
|
|
86
86
|
}, children));
|
|
87
87
|
}
|
|
88
88
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
89
|
-
className: "
|
|
89
|
+
className: "sdoc-rebase-my-changes-title",
|
|
90
90
|
contentEditable: false
|
|
91
|
-
}, '
|
|
92
|
-
className: "
|
|
91
|
+
}, t('My_modification')), /*#__PURE__*/React.createElement("div", {
|
|
92
|
+
className: "sdoc-rebase-my-changes",
|
|
93
93
|
contentEditable: false
|
|
94
|
-
}, children)
|
|
95
|
-
className: "w-100 sdoc-rebase-incoming-changes-end",
|
|
96
|
-
contentEditable: false
|
|
97
|
-
}, '>>>>>>>'));
|
|
94
|
+
}, children));
|
|
98
95
|
};
|
|
99
96
|
export default RebaseModifyModifyDecorate;
|
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
2
|
import { generateIdMapAndIds, getIdDiffs } from './diff';
|
|
3
3
|
import ObjectUtils from './object-utils';
|
|
4
|
-
import { MODIFY_TYPE, REBASE_TYPE, REBASE_MARK_KEY, REBASE_ORIGIN } from '../constants';
|
|
4
|
+
import { MODIFY_TYPE, REBASE_TYPE, REBASE_MARK_KEY, REBASE_ORIGIN, REBASE_TYPES } from '../constants';
|
|
5
5
|
import { ELEMENT_TYPE } from '../extension/constants';
|
|
6
6
|
import { replaceNodeId } from '../node-id/helpers';
|
|
7
7
|
export const hasConflict = content => {
|
|
8
8
|
if (!Array.isArray(content) || content.length === 0) return false;
|
|
9
|
-
|
|
9
|
+
let flag = false;
|
|
10
|
+
for (let i = 0; i < content.length; i++) {
|
|
11
|
+
const element = content[i];
|
|
12
|
+
const {
|
|
13
|
+
rebase_type,
|
|
14
|
+
children
|
|
15
|
+
} = element;
|
|
16
|
+
if (REBASE_TYPES.includes(rebase_type)) {
|
|
17
|
+
flag = true;
|
|
18
|
+
break;
|
|
19
|
+
} else {
|
|
20
|
+
const childrenFlag = hasConflict(children);
|
|
21
|
+
if (!childrenFlag) continue;
|
|
22
|
+
flag = childrenFlag;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return flag;
|
|
10
27
|
};
|
|
11
28
|
const getChanges = (masterContent, revisionContent) => {
|
|
12
29
|
const {
|
|
@@ -156,8 +173,7 @@ const getMergeElement = (diffElement, baseElement) => {
|
|
|
156
173
|
content: childrenContent
|
|
157
174
|
} = getMergeContent(baseElement, diffElement.children);
|
|
158
175
|
return [_objectSpread(_objectSpread({}, newElement), {}, {
|
|
159
|
-
children: childrenContent
|
|
160
|
-
[REBASE_MARK_KEY.REBASE_TYPE]: REBASE_TYPE.CHILDREN_MODIFY
|
|
176
|
+
children: childrenContent
|
|
161
177
|
})];
|
|
162
178
|
}
|
|
163
179
|
newElement[REBASE_MARK_KEY.OLD_ELEMENT] && delete newElement[REBASE_MARK_KEY.OLD_ELEMENT];
|
|
@@ -2,7 +2,6 @@ import React from 'react';
|
|
|
2
2
|
import { withTranslation } from 'react-i18next';
|
|
3
3
|
import context from '../../context';
|
|
4
4
|
import RevisionOperations from './revision-operations';
|
|
5
|
-
import HistoryOperation from './history-operation';
|
|
6
5
|
import CollaboratorsOperation from './collaborators-operation';
|
|
7
6
|
import MoreOperations from './more-operations';
|
|
8
7
|
import CommentsOperation from './comments-operation';
|
|
@@ -34,6 +33,6 @@ const DocOperations = _ref => {
|
|
|
34
33
|
handleViewChangesToggle: handleViewChangesToggle,
|
|
35
34
|
handleRevisionMerged: handleRevisionMerged,
|
|
36
35
|
handleRevisionPublished: handleRevisionPublished
|
|
37
|
-
}), !isPublished && /*#__PURE__*/React.createElement(TagOperation, null), !isPublished && /*#__PURE__*/React.createElement(CommentsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(ShareOperation, null),
|
|
36
|
+
}), !isPublished && /*#__PURE__*/React.createElement(TagOperation, null), !isPublished && /*#__PURE__*/React.createElement(CommentsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(ShareOperation, null), !isPublished && /*#__PURE__*/React.createElement(CollaboratorsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(MoreOperations, null));
|
|
38
37
|
};
|
|
39
38
|
export default withTranslation('sdoc-editor')(DocOperations);
|
|
@@ -9,6 +9,12 @@ const MoreOperations = _ref => {
|
|
|
9
9
|
t
|
|
10
10
|
} = _ref;
|
|
11
11
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
12
|
+
const parentFolderURL = context.getSetting('parentFolderURL');
|
|
13
|
+
const isPro = context.getSetting('isPro');
|
|
14
|
+
const isFreezed = context.getSetting('isFreezed');
|
|
15
|
+
const docPerm = context.getSetting('docPerm');
|
|
16
|
+
const historyURL = context.getSetting('historyURL');
|
|
17
|
+
const isSdocRevision = context.getSetting('isSdocRevision');
|
|
12
18
|
const toggleDropdown = useCallback(isDropdownOpen => {
|
|
13
19
|
setIsDropdownOpen(!isDropdownOpen);
|
|
14
20
|
}, []);
|
|
@@ -20,9 +26,13 @@ const MoreOperations = _ref => {
|
|
|
20
26
|
const eventBus = EventBus.getInstance();
|
|
21
27
|
eventBus.dispatch(EXTERNAL_EVENT.UNFREEZE);
|
|
22
28
|
}, []);
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
const handleClickHistory = useCallback(event => {
|
|
30
|
+
if (docPerm !== 'rw' || !historyURL) return;
|
|
31
|
+
if (isSdocRevision) return;
|
|
32
|
+
event.stopPropagation();
|
|
33
|
+
event.nativeEvent.stopImmediatePropagation();
|
|
34
|
+
window.location.href = historyURL;
|
|
35
|
+
}, [docPerm, historyURL, isSdocRevision]);
|
|
26
36
|
return /*#__PURE__*/React.createElement(Dropdown, {
|
|
27
37
|
isOpen: isDropdownOpen,
|
|
28
38
|
toggle: () => toggleDropdown(isDropdownOpen)
|
|
@@ -44,6 +54,9 @@ const MoreOperations = _ref => {
|
|
|
44
54
|
}, t('Unfreeze')), isPro && !isFreezed && /*#__PURE__*/React.createElement(DropdownItem, {
|
|
45
55
|
className: "sdoc-dropdown-menu-item",
|
|
46
56
|
onClick: onFreezeDocument
|
|
47
|
-
}, t('Freeze_Document'))
|
|
57
|
+
}, t('Freeze_Document')), /*#__PURE__*/React.createElement(DropdownItem, {
|
|
58
|
+
className: "sdoc-dropdown-menu-item",
|
|
59
|
+
onClick: handleClickHistory
|
|
60
|
+
}, t('Document_history'))));
|
|
48
61
|
};
|
|
49
62
|
export default withTranslation('sdoc-editor')(MoreOperations);
|
|
@@ -27,7 +27,7 @@ const TipDialog = _ref => {
|
|
|
27
27
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28
28
|
}, [tipType, isSubmitting]);
|
|
29
29
|
const onSubmit = useCallback(() => {
|
|
30
|
-
if (
|
|
30
|
+
if ([TIP_TYPE.HAS_CONFLICT_BEFORE_VIEW_CHANGES, TIP_TYPE.HAS_CONFLICT_BEFORE_PUBLISH].includes(tipType)) {
|
|
31
31
|
closeDialog();
|
|
32
32
|
return;
|
|
33
33
|
}
|
package/package.json
CHANGED
|
@@ -425,5 +425,8 @@
|
|
|
425
425
|
"Column_number": "Column number",
|
|
426
426
|
"The_maximum_row_number_is_{number}": "The maximum row number is {number}",
|
|
427
427
|
"Freeze_Document": "Freeze Document",
|
|
428
|
-
"Unfreeze": "Unfreeze"
|
|
428
|
+
"Unfreeze": "Unfreeze",
|
|
429
|
+
"Other_modification": "Other's modification",
|
|
430
|
+
"My_modification": "My modification",
|
|
431
|
+
"Document_history": "Document history"
|
|
429
432
|
}
|
|
@@ -424,5 +424,6 @@
|
|
|
424
424
|
"Row_number": "Row number",
|
|
425
425
|
"Column_number": "Column number",
|
|
426
426
|
"The_maximum_row_number_is_{number}": "The maximum row number is {number}",
|
|
427
|
-
"
|
|
427
|
+
"Freeze_Document": "Freeze Document",
|
|
428
|
+
"Unfreeze": "Unfreeze"
|
|
428
429
|
}
|
|
@@ -424,6 +424,6 @@
|
|
|
424
424
|
"Row_number": "Номер строки",
|
|
425
425
|
"Column_number": "Номер столбца",
|
|
426
426
|
"The_maximum_row_number_is_{number}": "Максимальное количество строк - {number}",
|
|
427
|
-
"Freeze_Document": "
|
|
428
|
-
"Unfreeze": "
|
|
427
|
+
"Freeze_Document": "Заморозить документ",
|
|
428
|
+
"Unfreeze": "Разморозить"
|
|
429
429
|
}
|
|
@@ -376,7 +376,7 @@
|
|
|
376
376
|
"Link_sdoc": "链接 sdoc",
|
|
377
377
|
"Link_file": "文件链接",
|
|
378
378
|
"Keep_my_modification": "保留我的更改",
|
|
379
|
-
"Keep_other_modification": "
|
|
379
|
+
"Keep_other_modification": "保留他人的更改",
|
|
380
380
|
"Keep_both_modification": "保留两者更改",
|
|
381
381
|
"Tip": "提示",
|
|
382
382
|
"Rebase_delete_no_change_revision_tip": "修订改没有更改,是否删除修订稿?",
|
|
@@ -425,5 +425,8 @@
|
|
|
425
425
|
"Column_number": "列数",
|
|
426
426
|
"The_maximum_row_number_is_{number}": "最大行数为 {number}",
|
|
427
427
|
"Freeze_Document": "冻结文档",
|
|
428
|
-
"Unfreeze": "取消冻结"
|
|
428
|
+
"Unfreeze": "取消冻结",
|
|
429
|
+
"Other_modification": "他人更改",
|
|
430
|
+
"My_modification": "我的更改",
|
|
431
|
+
"Document_history":"文档历史"
|
|
429
432
|
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import React, { useCallback } from 'react';
|
|
2
|
-
import context from '../../context';
|
|
3
|
-
const HistoryOperation = () => {
|
|
4
|
-
const docPerm = context.getSetting('docPerm');
|
|
5
|
-
const historyURL = context.getSetting('historyURL');
|
|
6
|
-
const isSdocRevision = context.getSetting('isSdocRevision');
|
|
7
|
-
const toggleHistory = useCallback(event => {
|
|
8
|
-
event.stopPropagation();
|
|
9
|
-
event.nativeEvent.stopImmediatePropagation();
|
|
10
|
-
window.location.href = historyURL;
|
|
11
|
-
|
|
12
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
13
|
-
}, []);
|
|
14
|
-
if (docPerm !== 'rw' || !historyURL) return null;
|
|
15
|
-
if (isSdocRevision) return null;
|
|
16
|
-
return /*#__PURE__*/React.createElement("span", {
|
|
17
|
-
className: "op-item",
|
|
18
|
-
onClick: toggleHistory
|
|
19
|
-
}, /*#__PURE__*/React.createElement("i", {
|
|
20
|
-
className: "sdocfont sdoc-history"
|
|
21
|
-
}));
|
|
22
|
-
};
|
|
23
|
-
export default HistoryOperation;
|