@seafile/sdoc-editor 0.5.70 → 0.5.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/basic-sdk/editor/editable-article.js +4 -3
- package/dist/basic-sdk/extension/commons/file-insert-dialog/index.js +39 -13
- package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +12 -2
- package/dist/basic-sdk/extension/constants/element-type.js +1 -0
- package/dist/basic-sdk/extension/constants/index.js +2 -2
- package/dist/basic-sdk/extension/plugins/column/column-list-menu.css +35 -0
- package/dist/basic-sdk/extension/plugins/column/column-list-menu.js +47 -0
- package/dist/basic-sdk/extension/plugins/column/helpers.js +13 -8
- package/dist/basic-sdk/extension/plugins/column/index.js +0 -2
- package/dist/basic-sdk/extension/plugins/column/menu/seatable-column.js +31 -0
- package/dist/basic-sdk/extension/plugins/column/model.js +6 -8
- package/dist/basic-sdk/extension/plugins/column/render-elem.js +39 -101
- package/dist/basic-sdk/extension/plugins/index.js +3 -2
- package/dist/basic-sdk/extension/plugins/link/dialog/add-link-dialog/index.js +5 -2
- package/dist/basic-sdk/extension/plugins/link/plugin.js +26 -11
- package/dist/basic-sdk/extension/plugins/sdoc-link/hover-menu/index.js +4 -3
- package/dist/basic-sdk/extension/plugins/sdoc-link/plugin.js +3 -2
- package/dist/basic-sdk/extension/plugins/sdoc-link/render/render-elem.js +8 -2
- package/dist/basic-sdk/extension/plugins/wiki-link/helpers.js +60 -0
- package/dist/basic-sdk/extension/plugins/wiki-link/index.js +9 -0
- package/dist/basic-sdk/extension/render/custom-element.js +10 -6
- package/dist/basic-sdk/extension/toolbar/header-toolbar/index.js +1 -6
- package/dist/basic-sdk/extension/toolbar/header-toolbar/insert-toolbar/index.js +2 -2
- package/dist/constants/index.js +2 -0
- package/dist/pages/document-plugin-editor.js +3 -1
- package/dist/pages/document-plugin-viewer.js +1 -1
- package/package.json +1 -1
- package/public/locales/cs/sdoc-editor.json +2 -1
- package/public/locales/de/sdoc-editor.json +2 -1
- package/public/locales/en/sdoc-editor.json +2 -1
- package/public/locales/es/sdoc-editor.json +2 -1
- package/public/locales/es_AR/sdoc-editor.json +465 -0
- package/public/locales/es_MX/sdoc-editor.json +465 -0
- package/public/locales/fr/sdoc-editor.json +2 -1
- package/public/locales/it/sdoc-editor.json +2 -1
- package/public/locales/ru/sdoc-editor.json +5 -4
- package/public/locales/zh_CN/sdoc-editor.json +2 -1
- package/dist/basic-sdk/extension/plugins/column/menu/index.js +0 -28
- package/public/locales/es-AR/sdoc-editor.json +0 -169
- package/public/locales/es-MX/sdoc-editor.json +0 -169
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, useMemo, Fragment } from 'react';
|
|
2
2
|
import { Editable, ReactEditor, Slate } from '@seafile/slate-react';
|
|
3
|
-
import { Editor, Node, Transforms } from '@seafile/slate';
|
|
3
|
+
import { Editor, Node, Range, Transforms } from '@seafile/slate';
|
|
4
4
|
import scrollIntoView from 'scroll-into-view-if-needed';
|
|
5
5
|
import { renderLeaf, renderElement, ContextToolbar, SideToolbar } from '../extension';
|
|
6
6
|
import { getAboveBlockNode, getNextNode, getPrevNode, isSelectionAtBlockEnd, isSelectionAtBlockStart, getCurrentNode, isCurrentLineEmpty, isCurrentLineHasText } from '../extension/core';
|
|
@@ -89,8 +89,9 @@ const EditableArticle = _ref => {
|
|
|
89
89
|
if (getPrevNode(editor)) {
|
|
90
90
|
[prevNode, prevPath] = getPrevNode(editor);
|
|
91
91
|
}
|
|
92
|
-
// If the cursor is at the beginning, and the current line is not empty, is not a CODE_LINE, and the previous line is a CODE_LINE.
|
|
93
|
-
|
|
92
|
+
// If the cursor is collapsed at the beginning, and the current line is not empty, is not a CODE_LINE, and the previous line is a CODE_LINE.
|
|
93
|
+
const isCursorCollapsed = Range.isCollapsed(editor.selection);
|
|
94
|
+
if (isCursorCollapsed && prevNode && isSelectionAtBlockStart(editor) && !isCurrentLineEmpty(editor) && prevNode.type === CODE_LINE && currentNode.type !== CODE_LINE) {
|
|
94
95
|
if (!isCurrentLineHasText(currentNode)) {
|
|
95
96
|
const prevNodeText = Node.string(prevNode);
|
|
96
97
|
Transforms.removeNodes(editor, {
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { ReactEditor } from '@seafile/slate-react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { Editor } from '@seafile/slate';
|
|
5
|
+
import { Editor, Node } from '@seafile/slate';
|
|
6
6
|
import classNames from 'classnames';
|
|
7
7
|
import context from '../../../../context';
|
|
8
8
|
import { LocalStorage, isEnglish } from '../../../../utils';
|
|
9
9
|
import { EXTERNAL_EVENT } from '../../../../constants';
|
|
10
10
|
import EventBus from '../../../utils/event-bus';
|
|
11
|
-
import { INTERNAL_EVENT } from '../../../constants';
|
|
11
|
+
import { INTERNAL_EVENT, WIKI_EDITOR } from '../../../constants';
|
|
12
12
|
import { SDOC_LINK } from '../../constants';
|
|
13
13
|
import toaster from '../../../../components/toast';
|
|
14
14
|
import { insertSdocFileLink, insertTextWhenRemoveFileNameCollector, removeTempInput } from '../../plugins/sdoc-link/helpers';
|
|
15
|
+
import { insertWikiPageLink } from '../../plugins/wiki-link/helpers';
|
|
15
16
|
import './style.css';
|
|
16
17
|
const FileLinkInsertDialog = _ref => {
|
|
17
18
|
let {
|
|
@@ -19,7 +20,6 @@ const FileLinkInsertDialog = _ref => {
|
|
|
19
20
|
element,
|
|
20
21
|
closeDialog
|
|
21
22
|
} = _ref;
|
|
22
|
-
const eventBus = EventBus.getInstance();
|
|
23
23
|
const historyFileWrapperRef = useRef(document.querySelector('.sdoc-history-files-wrapper'));
|
|
24
24
|
const [files, setFiles] = useState([]);
|
|
25
25
|
const [position, setPosition] = useState({
|
|
@@ -31,6 +31,7 @@ const FileLinkInsertDialog = _ref => {
|
|
|
31
31
|
t
|
|
32
32
|
} = useTranslation();
|
|
33
33
|
const [header, setHeader] = useState(t('Recent_visited'));
|
|
34
|
+
const eventBus = EventBus.getInstance();
|
|
34
35
|
const deleteInputAndInsertText = useCallback(function () {
|
|
35
36
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
36
37
|
args[_key] = arguments[_key];
|
|
@@ -63,6 +64,17 @@ const FileLinkInsertDialog = _ref => {
|
|
|
63
64
|
const counterTopGap = 8;
|
|
64
65
|
popoverTop = top - popoverHeight - counterTopGap;
|
|
65
66
|
}
|
|
67
|
+
if (editor.editorType === WIKI_EDITOR) {
|
|
68
|
+
const wikiEditorContainer = document.querySelector('.sdoc-editor-container');
|
|
69
|
+
if (wikiEditorContainer) {
|
|
70
|
+
const {
|
|
71
|
+
left,
|
|
72
|
+
top
|
|
73
|
+
} = wikiEditorContainer.getBoundingClientRect();
|
|
74
|
+
popoverLeft -= left;
|
|
75
|
+
popoverTop -= top;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
66
78
|
setPosition({
|
|
67
79
|
top: popoverTop,
|
|
68
80
|
left: popoverLeft
|
|
@@ -81,9 +93,10 @@ const FileLinkInsertDialog = _ref => {
|
|
|
81
93
|
getPosition();
|
|
82
94
|
}, [getPosition]);
|
|
83
95
|
const getHistoryFiles = useCallback(e => {
|
|
84
|
-
const
|
|
96
|
+
const getItemKey = editor.editorType === WIKI_EDITOR ? 'wiki-recent-files' : 'sdoc-recent-files';
|
|
97
|
+
const files = LocalStorage.getItem(getItemKey) || [];
|
|
85
98
|
setFiles(files);
|
|
86
|
-
}, []);
|
|
99
|
+
}, [editor.editorType]);
|
|
87
100
|
useEffect(() => {
|
|
88
101
|
getHistoryFiles();
|
|
89
102
|
}, [getHistoryFiles]);
|
|
@@ -168,17 +181,23 @@ const FileLinkInsertDialog = _ref => {
|
|
|
168
181
|
}, []);
|
|
169
182
|
useEffect(() => {
|
|
170
183
|
if (!(element === null || element === void 0 ? void 0 : element.children)) return;
|
|
171
|
-
const searchText = element
|
|
184
|
+
const searchText = Node.string(element);
|
|
172
185
|
onSearch(searchText);
|
|
173
186
|
}, [element, onSearch]);
|
|
174
187
|
const onSelect = useCallback(fileInfo => {
|
|
175
188
|
const {
|
|
176
189
|
doc_uuid,
|
|
177
|
-
name
|
|
190
|
+
name,
|
|
191
|
+
wikiRepoId,
|
|
192
|
+
pageId
|
|
178
193
|
} = fileInfo;
|
|
179
194
|
removeTempInput(editor, element);
|
|
180
195
|
closeDialog();
|
|
181
|
-
|
|
196
|
+
if (editor.editorType === WIKI_EDITOR) {
|
|
197
|
+
insertWikiPageLink(editor, name, wikiRepoId, pageId);
|
|
198
|
+
} else {
|
|
199
|
+
insertSdocFileLink(editor, name, doc_uuid);
|
|
200
|
+
}
|
|
182
201
|
}, [closeDialog, editor, element]);
|
|
183
202
|
const onShowMore = useCallback(() => {
|
|
184
203
|
eventBus.dispatch(INTERNAL_EVENT.INSERT_ELEMENT, {
|
|
@@ -189,10 +208,17 @@ const FileLinkInsertDialog = _ref => {
|
|
|
189
208
|
}, [editor, element, eventBus]);
|
|
190
209
|
const onCreateFile = useCallback(() => {
|
|
191
210
|
const eventBus = EventBus.getInstance();
|
|
192
|
-
|
|
211
|
+
const dispatchEventKey = editor.editorType === WIKI_EDITOR ? EXTERNAL_EVENT.CREATE_WIKI_PAGE : EXTERNAL_EVENT.CREATE_SDOC_FILE;
|
|
212
|
+
eventBus.dispatch(dispatchEventKey, {
|
|
193
213
|
newFileName: newFileName.trim()
|
|
194
214
|
});
|
|
195
|
-
}, [newFileName]);
|
|
215
|
+
}, [editor.editorType, newFileName]);
|
|
216
|
+
const createFileTipDefault = useMemo(() => {
|
|
217
|
+
return editor.editorType === WIKI_EDITOR ? 'New_page' : 'Create_a_new_sdoc_file';
|
|
218
|
+
}, [editor.editorType]);
|
|
219
|
+
const createFileName = useMemo(() => {
|
|
220
|
+
return editor.editorType === WIKI_EDITOR ? newFileName : "".concat(newFileName, ".sdoc");
|
|
221
|
+
}, [editor.editorType, newFileName]);
|
|
196
222
|
return /*#__PURE__*/React.createElement("div", {
|
|
197
223
|
className: "sdoc-history-files-content popover",
|
|
198
224
|
style: _objectSpread(_objectSpread({}, position), {}, {
|
|
@@ -225,7 +251,7 @@ const FileLinkInsertDialog = _ref => {
|
|
|
225
251
|
}), /*#__PURE__*/React.createElement("span", {
|
|
226
252
|
className: "new-file-name"
|
|
227
253
|
}, newFileName ? t('Create_file_name_sdoc', {
|
|
228
|
-
file_name_sdoc:
|
|
229
|
-
}) : t(
|
|
254
|
+
file_name_sdoc: createFileName
|
|
255
|
+
}) : t(createFileTipDefault))));
|
|
230
256
|
};
|
|
231
257
|
export default FileLinkInsertDialog;
|
|
@@ -18,6 +18,8 @@ const InsertElementDialog = _ref => {
|
|
|
18
18
|
const [slateNode, setSlateNode] = useState(null);
|
|
19
19
|
const [insertLinkCallback, setInsertLinkCallback] = useState(null);
|
|
20
20
|
const [validEditor, setValidEditor] = useState(editor);
|
|
21
|
+
const [linkTitle, setLinkTitle] = useState('');
|
|
22
|
+
const [handleSubmit, setHandleSubmit] = useState(() => void 0);
|
|
21
23
|
const uploadLocalImageInputRef = useRef();
|
|
22
24
|
const onFileChanged = useCallback(event => {
|
|
23
25
|
const files = event.target.files;
|
|
@@ -45,7 +47,10 @@ const InsertElementDialog = _ref => {
|
|
|
45
47
|
slateNode,
|
|
46
48
|
insertFileLinkCallback,
|
|
47
49
|
insertSdocFileLinkCallback,
|
|
48
|
-
editor: paramEditor
|
|
50
|
+
editor: paramEditor,
|
|
51
|
+
linkTitle,
|
|
52
|
+
// link shortcut wrapping link
|
|
53
|
+
handleSubmit
|
|
49
54
|
} = _ref2;
|
|
50
55
|
setInsertPosition(insertPosition);
|
|
51
56
|
setSlateNode(slateNode);
|
|
@@ -55,6 +60,8 @@ const InsertElementDialog = _ref => {
|
|
|
55
60
|
insertSdocFileLinkCallback,
|
|
56
61
|
insertFileLinkCallback
|
|
57
62
|
});
|
|
63
|
+
setLinkTitle(linkTitle);
|
|
64
|
+
setHandleSubmit(handleSubmit);
|
|
58
65
|
// Apply for comment editor, as it has a different editor instance
|
|
59
66
|
setValidEditor(paramEditor || editor);
|
|
60
67
|
if (type === LOCAL_IMAGE) {
|
|
@@ -70,13 +77,16 @@ const InsertElementDialog = _ref => {
|
|
|
70
77
|
setDialogType('');
|
|
71
78
|
setInsertLinkCallback(null);
|
|
72
79
|
setValidEditor(null);
|
|
80
|
+
setLinkTitle('');
|
|
73
81
|
}, []);
|
|
74
82
|
const props = {
|
|
75
83
|
insertPosition,
|
|
76
84
|
slateNode,
|
|
77
85
|
editor: validEditor,
|
|
78
86
|
element,
|
|
79
|
-
closeDialog
|
|
87
|
+
closeDialog,
|
|
88
|
+
linkTitle,
|
|
89
|
+
handleSubmit
|
|
80
90
|
};
|
|
81
91
|
switch (dialogType) {
|
|
82
92
|
case ELEMENT_TYPE.TABLE:
|
|
@@ -20,6 +20,7 @@ export const TABLE_ROW = 'table_row';
|
|
|
20
20
|
export const TABLE_CELL = 'table_cell';
|
|
21
21
|
export const LINK = 'link';
|
|
22
22
|
export const SDOC_LINK = 'sdoc_link';
|
|
23
|
+
export const WIKI_LINK = 'wiki_link';
|
|
23
24
|
export const FILE_LINK = 'file_link';
|
|
24
25
|
export const IMAGE = 'image';
|
|
25
26
|
export const IMAGE_BLOCK = 'image_block';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// extension plugin
|
|
2
2
|
import * as ELEMENT_TYPE from './element-type';
|
|
3
3
|
// eslint-disable-next-line no-duplicate-imports
|
|
4
|
-
import { BLOCKQUOTE, TITLE, SUBTITLE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, CHECK_LIST_ITEM, CODE_BLOCK, CODE_LINE, TABLE, TABLE_CELL, TABLE_ROW, LINK, SDOC_LINK, FILE_LINK, IMAGE, IMAGE_BLOCK, TOP_LEVEL_TYPES, INLINE_LEVEL_TYPES, CALL_OUT, MENTION, MENTION_TEMP, FILE_LINK_INSET_INPUT_TEMP, QUICK_INSERT } from './element-type';
|
|
4
|
+
import { BLOCKQUOTE, TITLE, SUBTITLE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, CHECK_LIST_ITEM, CODE_BLOCK, CODE_LINE, TABLE, TABLE_CELL, TABLE_ROW, LINK, SDOC_LINK, FILE_LINK, IMAGE, IMAGE_BLOCK, TOP_LEVEL_TYPES, INLINE_LEVEL_TYPES, CALL_OUT, MENTION, MENTION_TEMP, FILE_LINK_INSET_INPUT_TEMP, QUICK_INSERT, COLUMN } from './element-type';
|
|
5
5
|
export { DEFAULT_COLORS, STANDARD_COLORS, DEFAULT_RECENT_USED_LIST, DEFAULT_FONT_COLOR, RECENT_USED_HIGHLIGHT_COLORS_KEY, RECENT_USED_FONT_COLORS_KEY, RECENT_USED_TABLE_CELL_BACKGROUND_COLORS_KEY, DEFAULT_LAST_USED_FONT_COLOR, DEFAULT_LAST_USED_HIGHLIGHT_COLOR, DEFAULT_LAST_USED_TABLE_CELL_BACKGROUND_COLOR } from './color';
|
|
6
6
|
export { FONT_SIZE, DEFAULT_FONT, FONT, GOOGLE_FONT_CLASS, RECENT_USED_FONTS_KEY, SDOC_FONT_SIZE } from './font';
|
|
7
7
|
export { DIFF_TYPE, ADDED_STYLE, DELETED_STYLE } from './diff-view';
|
|
@@ -38,7 +38,7 @@ export const FILE_TYPE = {
|
|
|
38
38
|
[FILE_LINK]: 'file',
|
|
39
39
|
[SDOC_LINK]: 'sdoc'
|
|
40
40
|
};
|
|
41
|
-
export const SUPPORTED_SIDE_OPERATION_TYPE = [PARAGRAPH, SUBTITLE, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, CHECK_LIST_ITEM, CODE_BLOCK, TABLE, BLOCKQUOTE, CALL_OUT, IMAGE_BLOCK];
|
|
41
|
+
export const SUPPORTED_SIDE_OPERATION_TYPE = [PARAGRAPH, SUBTITLE, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, CHECK_LIST_ITEM, CODE_BLOCK, TABLE, BLOCKQUOTE, CALL_OUT, IMAGE_BLOCK, COLUMN];
|
|
42
42
|
export const MOUSE_ENTER_EVENT_DISABLED_MAP = {
|
|
43
43
|
[PARAGRAPH]: [CALL_OUT],
|
|
44
44
|
[TITLE]: [CALL_OUT],
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.column-list-menu {
|
|
2
|
+
position: absolute;
|
|
3
|
+
left: -8px;
|
|
4
|
+
background-color: #fff;
|
|
5
|
+
min-width: 12rem;
|
|
6
|
+
width: 200px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.column-list-menu .column-list-menu-item-container {
|
|
10
|
+
padding: 3px 12px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.column-list-menu .column-list-menu-item-container .column-list-menu-item {
|
|
14
|
+
height: fit-content;
|
|
15
|
+
width: 100%;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.column-list-menu .column-list-menu-item-container .column-list-menu-item .control-icon {
|
|
21
|
+
margin-right: 10px;
|
|
22
|
+
flex-shrink: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.column-list-menu .column-list-menu-item-container .column-list-menu-item .control-label {
|
|
26
|
+
white-space: nowrap;
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
text-overflow: ellipsis;
|
|
29
|
+
flex-grow: 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.column-list-menu .column-list-menu-item-container:hover {
|
|
33
|
+
background-color: #f5f5f5;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { useMemo, useCallback } from 'react';
|
|
2
|
+
import { COLUMNS_ICON_CONFIG } from './constants/column';
|
|
3
|
+
import { insertSeaTableColumn, getColumnType } from './helpers';
|
|
4
|
+
import { COLUMN } from '../../constants/element-type';
|
|
5
|
+
import './column-list-menu.css';
|
|
6
|
+
const NOT_SUPPORT_COLUMN_TYPES = ['button', 'file'];
|
|
7
|
+
export default function ColumnListMenu(_ref) {
|
|
8
|
+
let {
|
|
9
|
+
editor
|
|
10
|
+
} = _ref;
|
|
11
|
+
const columns = useMemo(() => {
|
|
12
|
+
if (!editor.columns) return [];
|
|
13
|
+
return editor.columns.filter(column => !NOT_SUPPORT_COLUMN_TYPES.includes(column.type));
|
|
14
|
+
}, [editor.columns]);
|
|
15
|
+
const options = useMemo(() => {
|
|
16
|
+
return columns.map(item => {
|
|
17
|
+
const iconClass = COLUMNS_ICON_CONFIG[item.type];
|
|
18
|
+
return {
|
|
19
|
+
value: item.key,
|
|
20
|
+
label: item.name,
|
|
21
|
+
iconClass
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
}, [columns]);
|
|
25
|
+
const isActive = editor => {
|
|
26
|
+
return getColumnType(editor) === COLUMN;
|
|
27
|
+
};
|
|
28
|
+
const onMousedown = useCallback(option => {
|
|
29
|
+
const active = isActive(editor);
|
|
30
|
+
insertSeaTableColumn(editor, active, option);
|
|
31
|
+
}, [editor]);
|
|
32
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
33
|
+
className: "column-list-menu"
|
|
34
|
+
}, options.map(option => {
|
|
35
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
36
|
+
key: option.value,
|
|
37
|
+
className: "column-list-menu-item-container",
|
|
38
|
+
onClick: () => onMousedown(option)
|
|
39
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
40
|
+
className: "column-list-menu-item"
|
|
41
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
42
|
+
className: "control-icon ".concat(option.iconClass)
|
|
43
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
44
|
+
className: "control-label"
|
|
45
|
+
}, option.label)));
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
-
import { Editor, Transforms } from '@seafile/slate';
|
|
2
|
+
import { Editor, Transforms, Range } from '@seafile/slate';
|
|
3
3
|
import slugid from 'slugid';
|
|
4
4
|
import { BLOCKQUOTE, CHECK_LIST_ITEM, COLUMN, IMAGE, ORDERED_LIST, PARAGRAPH, TABLE_CELL, UNORDERED_LIST } from '../../constants/element-type';
|
|
5
5
|
import { focusEditor, getNodeType } from '../../core';
|
|
6
6
|
import Column from './model';
|
|
7
7
|
export const isMenuDisabled = (editor, readonly) => {
|
|
8
8
|
if (readonly) return true;
|
|
9
|
-
|
|
9
|
+
const {
|
|
10
|
+
selection
|
|
11
|
+
} = editor;
|
|
12
|
+
if (selection == null) return true;
|
|
13
|
+
if (!Range.isCollapsed(selection)) return true;
|
|
10
14
|
const [nodeEntry] = Editor.nodes(editor, {
|
|
11
15
|
match: n => {
|
|
12
16
|
const type = getNodeType(n);
|
|
13
17
|
|
|
14
18
|
// Only available for p and blockquote
|
|
15
|
-
if (type ===
|
|
16
|
-
if (type ===
|
|
19
|
+
if (type === BLOCKQUOTE) return false;
|
|
20
|
+
if (type === PARAGRAPH) return false;
|
|
17
21
|
if (type === UNORDERED_LIST) return true;
|
|
18
22
|
if (type === ORDERED_LIST) return true;
|
|
19
23
|
if (type === CHECK_LIST_ITEM) return true;
|
|
20
24
|
if (type === IMAGE) return true;
|
|
21
25
|
if (type === TABLE_CELL) return true;
|
|
26
|
+
if (Editor.isVoid(editor, n)) return true;
|
|
22
27
|
return false;
|
|
23
28
|
},
|
|
24
29
|
universal: true,
|
|
@@ -27,9 +32,9 @@ export const isMenuDisabled = (editor, readonly) => {
|
|
|
27
32
|
|
|
28
33
|
// Match to p blockquote, do not disable
|
|
29
34
|
if (nodeEntry) {
|
|
30
|
-
return
|
|
35
|
+
return true;
|
|
31
36
|
}
|
|
32
|
-
return
|
|
37
|
+
return false;
|
|
33
38
|
};
|
|
34
39
|
export const getColumnType = editor => {
|
|
35
40
|
const [match] = Editor.nodes(editor, {
|
|
@@ -40,9 +45,9 @@ export const getColumnType = editor => {
|
|
|
40
45
|
const [n] = match;
|
|
41
46
|
return getNodeType(n);
|
|
42
47
|
};
|
|
43
|
-
export const insertSeaTableColumn = (editor, active) => {
|
|
48
|
+
export const insertSeaTableColumn = (editor, active, option) => {
|
|
44
49
|
if (!active) {
|
|
45
|
-
const column = new Column(
|
|
50
|
+
const column = new Column(option);
|
|
46
51
|
column.id = slugid.nice();
|
|
47
52
|
Transforms.insertNodes(editor, _objectSpread({}, column));
|
|
48
53
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { COLUMN } from '../../constants/element-type';
|
|
2
|
-
import ColumnMenu from './menu';
|
|
3
2
|
import withColumn from './plugin';
|
|
4
3
|
import renderColumn from './render-elem';
|
|
5
4
|
const ColumnPlugin = {
|
|
6
5
|
type: COLUMN,
|
|
7
6
|
nodeType: 'element',
|
|
8
|
-
editorMenus: [ColumnMenu],
|
|
9
7
|
editorPlugin: withColumn,
|
|
10
8
|
renderElements: [renderColumn]
|
|
11
9
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MENUS_CONFIG_MAP, ELEMENT_TYPE } from '../../../constants';
|
|
3
|
+
import DropdownMenuItem from '../../../commons/dropdown-menu-item';
|
|
4
|
+
import ColumnListMenu from '../column-list-menu';
|
|
5
|
+
import { UncontrolledPopover } from 'reactstrap';
|
|
6
|
+
import { isMenuDisabled } from '../helpers';
|
|
7
|
+
const SeatableColumnMenu = _ref => {
|
|
8
|
+
let {
|
|
9
|
+
editor,
|
|
10
|
+
readonly
|
|
11
|
+
} = _ref;
|
|
12
|
+
const disabled = isMenuDisabled(editor, readonly);
|
|
13
|
+
const menuConfig = MENUS_CONFIG_MAP[ELEMENT_TYPE.COLUMN];
|
|
14
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DropdownMenuItem, {
|
|
15
|
+
disabled: disabled,
|
|
16
|
+
menuConfig: menuConfig,
|
|
17
|
+
className: "pr-2"
|
|
18
|
+
}, !disabled && /*#__PURE__*/React.createElement("i", {
|
|
19
|
+
className: "sdocfont sdoc-right-slide sdoc-dropdown-item-right-icon"
|
|
20
|
+
})), !disabled && /*#__PURE__*/React.createElement(UncontrolledPopover, {
|
|
21
|
+
target: menuConfig.id,
|
|
22
|
+
trigger: "hover",
|
|
23
|
+
placement: "right-start",
|
|
24
|
+
hideArrow: true,
|
|
25
|
+
fade: false
|
|
26
|
+
}, /*#__PURE__*/React.createElement(ColumnListMenu, {
|
|
27
|
+
editor: editor,
|
|
28
|
+
readonly: readonly
|
|
29
|
+
})));
|
|
30
|
+
};
|
|
31
|
+
export default SeatableColumnMenu;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { generateDefaultText } from '../../core';
|
|
2
2
|
class Column {
|
|
3
|
-
constructor(
|
|
4
|
-
this.type =
|
|
5
|
-
this.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
italic: false
|
|
3
|
+
constructor(option) {
|
|
4
|
+
this.type = 'column';
|
|
5
|
+
this.children = [generateDefaultText()];
|
|
6
|
+
this.data = {
|
|
7
|
+
key: option.value,
|
|
8
|
+
name: option.label
|
|
10
9
|
};
|
|
11
|
-
this.children = options.children || [generateDefaultText()];
|
|
12
10
|
}
|
|
13
11
|
}
|
|
14
12
|
export default Column;
|
|
@@ -1,111 +1,49 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
-
import React, {
|
|
3
|
-
import { useReadOnly, useSelected
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { Select } from '../../commons';
|
|
6
|
-
import { COLUMNS_ICON_CONFIG } from './constants/column';
|
|
7
|
-
import { getColumnByKey, setSeaTableColumn } from './helpers';
|
|
8
|
-
const NOT_SUPPORT_COLUMN_TYPES = ['button', 'file'];
|
|
2
|
+
import React, { useState, useEffect } from 'react';
|
|
3
|
+
import { useReadOnly, useSelected } from '@seafile/slate-react';
|
|
9
4
|
const Column = _ref => {
|
|
10
5
|
let {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
element
|
|
6
|
+
props,
|
|
7
|
+
editor
|
|
14
8
|
} = _ref;
|
|
15
|
-
|
|
9
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
10
|
+
const {
|
|
11
|
+
attributes,
|
|
12
|
+
element,
|
|
13
|
+
children
|
|
14
|
+
} = props;
|
|
15
|
+
const isReadOnly = useReadOnly();
|
|
16
16
|
const isSelected = useSelected();
|
|
17
|
+
const data = element.data || {};
|
|
17
18
|
const {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
value: key,
|
|
42
|
-
label: name,
|
|
43
|
-
bold,
|
|
44
|
-
italic
|
|
45
|
-
} = option;
|
|
46
|
-
const newData = _objectSpread(_objectSpread({}, data), {
|
|
47
|
-
key,
|
|
48
|
-
name,
|
|
49
|
-
bold,
|
|
50
|
-
italic
|
|
51
|
-
});
|
|
52
|
-
setSeaTableColumn(editor, newData);
|
|
53
|
-
}, [editor, element]);
|
|
54
|
-
const defaultValue = useMemo(() => {
|
|
55
|
-
const {
|
|
56
|
-
data
|
|
57
|
-
} = element || {}; // column model
|
|
58
|
-
const column = getColumnByKey(columns, data.key);
|
|
59
|
-
const value = column && column.key || '';
|
|
60
|
-
const optionIndex = options.findIndex(item => item.value === value);
|
|
61
|
-
if (optionIndex === -1) return null;
|
|
62
|
-
|
|
63
|
-
// used the old properties
|
|
64
|
-
const option = options[optionIndex];
|
|
65
|
-
const currentOption = _objectSpread(_objectSpread({}, option), {
|
|
66
|
-
bold: data.bold,
|
|
67
|
-
italic: data.italic
|
|
68
|
-
});
|
|
69
|
-
options.splice(optionIndex, 1, currentOption);
|
|
70
|
-
return currentOption;
|
|
71
|
-
}, [columns, element, options]);
|
|
72
|
-
const props = {
|
|
73
|
-
isSelected: isSelected,
|
|
74
|
-
placeholder: t('Select_field'),
|
|
75
|
-
value: defaultValue,
|
|
76
|
-
options,
|
|
77
|
-
onChange: onColumnChanged
|
|
78
|
-
};
|
|
79
|
-
return /*#__PURE__*/React.createElement("span", attributes, /*#__PURE__*/React.createElement(Select, props), children);
|
|
19
|
+
key: columnKey,
|
|
20
|
+
name: columnName
|
|
21
|
+
} = data;
|
|
22
|
+
let displayValue = columnName ? "{".concat(columnName, "}") : '';
|
|
23
|
+
if (editor.getColumnCellValue) {
|
|
24
|
+
displayValue = editor.getColumnCellValue(columnKey) || 'null';
|
|
25
|
+
}
|
|
26
|
+
const [isClicked, setIsClicked] = useState(false);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (isSelected && !isReadOnly) {
|
|
29
|
+
setIsClicked(true);
|
|
30
|
+
} else {
|
|
31
|
+
setIsClicked(false);
|
|
32
|
+
}
|
|
33
|
+
}, [isSelected, isReadOnly]);
|
|
34
|
+
const style = _objectSpread(_objectSpread({}, isClicked && {
|
|
35
|
+
border: '1px solid red'
|
|
36
|
+
}), {}, {
|
|
37
|
+
margin: '0 10px'
|
|
38
|
+
});
|
|
39
|
+
return /*#__PURE__*/React.createElement("span", Object.assign({}, attributes, {
|
|
40
|
+
style: style
|
|
41
|
+
}), displayValue, children);
|
|
80
42
|
};
|
|
81
43
|
const renderColumn = (props, editor) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
attributes,
|
|
87
|
-
element
|
|
88
|
-
} = props;
|
|
89
|
-
const data = element.data || {};
|
|
90
|
-
const {
|
|
91
|
-
key: columnKey,
|
|
92
|
-
name: columnName,
|
|
93
|
-
bold,
|
|
94
|
-
italic
|
|
95
|
-
} = data;
|
|
96
|
-
let displayValue = columnName ? "{".concat(columnName, "}") : '';
|
|
97
|
-
if (editor.getColumnCellValue) {
|
|
98
|
-
displayValue = editor.getColumnCellValue(columnKey);
|
|
99
|
-
}
|
|
100
|
-
const style = _objectSpread(_objectSpread({}, bold && {
|
|
101
|
-
'fontWeight': 600
|
|
102
|
-
}), italic && {
|
|
103
|
-
'fontStyle': 'italic'
|
|
104
|
-
});
|
|
105
|
-
return /*#__PURE__*/React.createElement("span", Object.assign({}, attributes, {
|
|
106
|
-
style: _objectSpread({}, style)
|
|
107
|
-
}), displayValue);
|
|
108
|
-
}
|
|
109
|
-
return /*#__PURE__*/React.createElement(Column, props);
|
|
44
|
+
return /*#__PURE__*/React.createElement(Column, {
|
|
45
|
+
props: props,
|
|
46
|
+
editor: editor
|
|
47
|
+
});
|
|
110
48
|
};
|
|
111
49
|
export default renderColumn;
|
|
@@ -19,8 +19,9 @@ import SearchReplacePlugin from './search-replace';
|
|
|
19
19
|
import MentionPlugin from './mention';
|
|
20
20
|
import QuickInsertPlugin from './quick-insert';
|
|
21
21
|
import ColumnPlugin from './column';
|
|
22
|
+
import WikiLinkPlugin from './wiki-link';
|
|
22
23
|
const Plugins = [MarkDownPlugin, HtmlPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin, SearchReplacePlugin];
|
|
23
|
-
const WikiPlugins = [MarkDownPlugin, HtmlPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin, SearchReplacePlugin, QuickInsertPlugin];
|
|
24
|
+
const WikiPlugins = [MarkDownPlugin, HtmlPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin, SearchReplacePlugin, QuickInsertPlugin, WikiLinkPlugin];
|
|
24
25
|
const CommentPlugins = [MarkDownPlugin, HtmlPlugin, ParagraphPlugin, TextPlugin, ListPlugin, ImagePlugin, LinkPlugin, MentionPlugin, BlockquotePlugin];
|
|
25
26
|
export default Plugins;
|
|
26
|
-
export { MarkDownPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, HtmlPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin, SearchReplacePlugin, MentionPlugin, QuickInsertPlugin, CommentPlugins, WikiPlugins, ColumnPlugin };
|
|
27
|
+
export { MarkDownPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, HtmlPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin, SearchReplacePlugin, MentionPlugin, QuickInsertPlugin, CommentPlugins, WikiPlugins, ColumnPlugin, WikiLinkPlugin };
|
|
@@ -10,7 +10,9 @@ const AddLinkDialog = _ref => {
|
|
|
10
10
|
element,
|
|
11
11
|
insertPosition,
|
|
12
12
|
slateNode,
|
|
13
|
-
closeDialog
|
|
13
|
+
closeDialog,
|
|
14
|
+
linkTitle,
|
|
15
|
+
handleSubmit
|
|
14
16
|
} = _ref;
|
|
15
17
|
const {
|
|
16
18
|
t
|
|
@@ -21,7 +23,7 @@ const AddLinkDialog = _ref => {
|
|
|
21
23
|
title: oldTitle,
|
|
22
24
|
href: oldURL
|
|
23
25
|
} = element || {
|
|
24
|
-
title: '',
|
|
26
|
+
title: linkTitle || '',
|
|
25
27
|
href: ''
|
|
26
28
|
};
|
|
27
29
|
const initTitle = useMemo(() => oldTitle ? oldTitle : getEditorString(editor, editor.selection), [editor, oldTitle]);
|
|
@@ -48,6 +50,7 @@ const AddLinkDialog = _ref => {
|
|
|
48
50
|
} else {
|
|
49
51
|
insertLink(editor, title, url, insertPosition, slateNode);
|
|
50
52
|
}
|
|
53
|
+
handleSubmit && handleSubmit();
|
|
51
54
|
closeDialog();
|
|
52
55
|
|
|
53
56
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|