@seafile/sdoc-editor 0.5.70 → 0.5.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/basic-sdk/editor/editable-article.js +4 -3
  2. package/dist/basic-sdk/extension/commons/file-insert-dialog/index.js +39 -13
  3. package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +12 -2
  4. package/dist/basic-sdk/extension/constants/element-type.js +2 -0
  5. package/dist/basic-sdk/extension/constants/index.js +3 -3
  6. package/dist/basic-sdk/extension/constants/menus-config.js +8 -2
  7. package/dist/basic-sdk/extension/plugins/index.js +5 -3
  8. package/dist/basic-sdk/extension/plugins/link/dialog/add-link-dialog/index.js +5 -2
  9. package/dist/basic-sdk/extension/plugins/link/plugin.js +26 -11
  10. package/dist/basic-sdk/extension/plugins/sdoc-link/hover-menu/index.js +4 -3
  11. package/dist/basic-sdk/extension/plugins/sdoc-link/plugin.js +3 -2
  12. package/dist/basic-sdk/extension/plugins/sdoc-link/render/render-elem.js +8 -2
  13. package/dist/basic-sdk/extension/plugins/{column → seatable-column}/helpers.js +59 -8
  14. package/dist/basic-sdk/extension/plugins/{column → seatable-column}/index.js +2 -4
  15. package/dist/basic-sdk/extension/plugins/seatable-column/menu/column-list-menu.css +35 -0
  16. package/dist/basic-sdk/extension/plugins/seatable-column/menu/column-list-menu.js +47 -0
  17. package/dist/basic-sdk/extension/plugins/seatable-column/menu/index.js +31 -0
  18. package/dist/basic-sdk/extension/plugins/seatable-column/model.js +12 -0
  19. package/dist/basic-sdk/extension/plugins/seatable-column/render-elem.js +48 -0
  20. package/dist/basic-sdk/extension/plugins/seatable-views/helpers.js +50 -0
  21. package/dist/basic-sdk/extension/plugins/seatable-views/index.js +14 -0
  22. package/dist/basic-sdk/extension/plugins/seatable-views/menu/index.js +40 -0
  23. package/dist/basic-sdk/extension/plugins/seatable-views/model.js +12 -0
  24. package/dist/basic-sdk/extension/plugins/seatable-views/plugin.js +52 -0
  25. package/dist/basic-sdk/extension/plugins/seatable-views/render-element/index.css +20 -0
  26. package/dist/basic-sdk/extension/plugins/seatable-views/render-element/index.js +8 -0
  27. package/dist/basic-sdk/extension/plugins/seatable-views/render-element/record-header.js +19 -0
  28. package/dist/basic-sdk/extension/plugins/seatable-views/render-element/record-item.js +22 -0
  29. package/dist/basic-sdk/extension/plugins/seatable-views/render-element/record-list.js +19 -0
  30. package/dist/basic-sdk/extension/plugins/seatable-views/render-element/seatable-view.js +57 -0
  31. package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/index.js +0 -1
  32. package/dist/basic-sdk/extension/plugins/wiki-link/helpers.js +60 -0
  33. package/dist/basic-sdk/extension/plugins/wiki-link/index.js +9 -0
  34. package/dist/basic-sdk/extension/render/custom-element.js +16 -7
  35. package/dist/basic-sdk/extension/toolbar/header-toolbar/index.js +1 -6
  36. package/dist/basic-sdk/extension/toolbar/header-toolbar/insert-toolbar/index.js +3 -2
  37. package/dist/constants/index.js +2 -0
  38. package/dist/index.js +1 -2
  39. package/dist/pages/document-plugin-editor.js +25 -5
  40. package/package.json +1 -1
  41. package/public/locales/cs/sdoc-editor.json +2 -1
  42. package/public/locales/de/sdoc-editor.json +2 -1
  43. package/public/locales/en/sdoc-editor.json +4 -2
  44. package/public/locales/es/sdoc-editor.json +2 -1
  45. package/public/locales/es_AR/sdoc-editor.json +465 -0
  46. package/public/locales/es_MX/sdoc-editor.json +465 -0
  47. package/public/locales/fr/sdoc-editor.json +2 -1
  48. package/public/locales/it/sdoc-editor.json +2 -1
  49. package/public/locales/ru/sdoc-editor.json +5 -4
  50. package/public/locales/zh_CN/sdoc-editor.json +2 -1
  51. package/dist/basic-sdk/extension/plugins/column/menu/index.js +0 -28
  52. package/dist/basic-sdk/extension/plugins/column/model.js +0 -14
  53. package/dist/basic-sdk/extension/plugins/column/render-elem.js +0 -111
  54. package/dist/pages/document-plugin-viewer.js +0 -55
  55. package/public/locales/es-AR/sdoc-editor.json +0 -169
  56. package/public/locales/es-MX/sdoc-editor.json +0 -169
  57. /package/dist/basic-sdk/extension/plugins/{column → seatable-column}/constants/cell-types.js +0 -0
  58. /package/dist/basic-sdk/extension/plugins/{column → seatable-column}/constants/column.js +0 -0
  59. /package/dist/basic-sdk/extension/plugins/{column → seatable-column}/plugin.js +0 -0
@@ -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
- if (prevNode && isSelectionAtBlockStart(editor) && !isCurrentLineEmpty(editor) && prevNode.type === CODE_LINE && currentNode.type !== CODE_LINE) {
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 files = LocalStorage.getItem('sdoc-recent-files') || [];
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.children[0].text;
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
- insertSdocFileLink(editor, name, doc_uuid);
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
- eventBus.dispatch(EXTERNAL_EVENT.CREATE_SDOC_FILE, {
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: "".concat(newFileName, ".sdoc")
229
- }) : t('Create_a_new_sdoc_file'))));
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';
@@ -29,6 +30,7 @@ export const MENTION_TEMP = 'mention_temp';
29
30
  export const FILE_LINK_INSET_INPUT_TEMP = 'file_link_insert_input_temp';
30
31
  export const QUICK_INSERT = 'quick_insert';
31
32
  export const COLUMN = 'column';
33
+ export const SEATABLE_VIEW = 'seatable_view';
32
34
 
33
35
  // font
34
36
  export const FONT_SIZE = 'font-size';
@@ -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, SEATABLE_VIEW } 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],
@@ -57,4 +57,4 @@ export const MOUSE_ENTER_EVENT_DISABLED_MAP = {
57
57
  [CALL_OUT]: [CALL_OUT]
58
58
  };
59
59
  export const ROOT_ELEMENT_TYPES = [PARAGRAPH, TITLE, SUBTITLE, CHECK_LIST_ITEM, ORDERED_LIST, UNORDERED_LIST, BLOCKQUOTE, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, CALL_OUT, TABLE, CODE_BLOCK, IMAGE_BLOCK];
60
- export { ELEMENT_TYPE, 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 };
60
+ export { ELEMENT_TYPE, 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, SEATABLE_VIEW };
@@ -1,5 +1,5 @@
1
1
  import { RECENT_USED_HIGHLIGHT_COLORS_KEY, DEFAULT_LAST_USED_HIGHLIGHT_COLOR, RECENT_USED_FONT_COLORS_KEY, DEFAULT_FONT_COLOR, DEFAULT_LAST_USED_FONT_COLOR } from './color';
2
- import { BLOCKQUOTE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, ORDERED_LIST, UNORDERED_LIST, CHECK_LIST_ITEM, CODE_BLOCK, LINK, IMAGE, TABLE, SDOC_LINK, FILE_LINK, PARAGRAPH, CALL_OUT, COLUMN } from './element-type';
2
+ import { BLOCKQUOTE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, ORDERED_LIST, UNORDERED_LIST, CHECK_LIST_ITEM, CODE_BLOCK, LINK, IMAGE, TABLE, SDOC_LINK, FILE_LINK, PARAGRAPH, CALL_OUT, COLUMN, SEATABLE_VIEW } from './element-type';
3
3
  export const UNDO = 'undo';
4
4
  export const REDO = 'redo';
5
5
  export const CLEAR_FORMAT = 'clear_format';
@@ -195,7 +195,13 @@ export const MENUS_CONFIG_MAP = {
195
195
  [COLUMN]: {
196
196
  id: "sdoc".concat(COLUMN),
197
197
  iconClass: 'sdocfont sdoc-choose-column',
198
- text: 'Insert_column'
198
+ text: 'SeaTable_column'
199
+ },
200
+ [SEATABLE_VIEW]: {
201
+ id: SEATABLE_VIEW,
202
+ iconClass: 'sdocfont sdoc-header4',
203
+ type: SEATABLE_VIEW,
204
+ text: 'SeaTable_view'
199
205
  }
200
206
  };
201
207
 
@@ -18,9 +18,11 @@ import CalloutPlugin from './callout';
18
18
  import SearchReplacePlugin from './search-replace';
19
19
  import MentionPlugin from './mention';
20
20
  import QuickInsertPlugin from './quick-insert';
21
- import ColumnPlugin from './column';
21
+ import WikiLinkPlugin from './wiki-link';
22
+ import SeaTableColumnPlugin from './seatable-column';
23
+ import SeaTableViewsPlugin from './seatable-views';
22
24
  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];
25
+ const WikiPlugins = [...Plugins, QuickInsertPlugin, WikiLinkPlugin];
24
26
  const CommentPlugins = [MarkDownPlugin, HtmlPlugin, ParagraphPlugin, TextPlugin, ListPlugin, ImagePlugin, LinkPlugin, MentionPlugin, BlockquotePlugin];
25
27
  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 };
28
+ export { MarkDownPlugin, HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, TextPlugin, HtmlPlugin, TextAlignPlugin, FontPlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin, SearchReplacePlugin, MentionPlugin, QuickInsertPlugin, CommentPlugins, WikiPlugins, WikiLinkPlugin, SeaTableColumnPlugin, SeaTableViewsPlugin };
@@ -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
@@ -1,10 +1,10 @@
1
- import { Transforms, Node, Editor, Range, Element } from '@seafile/slate';
1
+ import { Transforms, Node, Editor, Range, Element, Text } from '@seafile/slate';
2
2
  import isUrl from 'is-url';
3
3
  import isHotkey from 'is-hotkey';
4
4
  import context from '../../../../context';
5
5
  import { insertSdocFileLink } from '../sdoc-link/helpers';
6
6
  import { genLinkNode, isSdocFile } from './helpers';
7
- import { getNodeType, getSelectedNodeByType } from '../../core';
7
+ import { getNodeType, getSelectedElems, getSelectedNodeByType } from '../../core';
8
8
  import { isImage, isSameDomain } from '../../utils';
9
9
  import { ELEMENT_TYPE, LINK, ORDERED_LIST, UNORDERED_LIST } from '../../constants';
10
10
  import EventBus from '../../../utils/event-bus';
@@ -68,18 +68,33 @@ const withLink = editor => {
68
68
  return insertFragment(data);
69
69
  };
70
70
  newEditor.onHotKeyDown = e => {
71
- const {
72
- selection
73
- } = newEditor;
74
- const isCollapsed = Range.isCollapsed(selection);
75
- if (isHotkey('mod+k', e) && isCollapsed) {
71
+ if (isHotkey('mod+k', e)) {
76
72
  // Prevent edge behavior
77
73
  e.preventDefault();
74
+ const {
75
+ selection
76
+ } = newEditor;
77
+ const isCollapsed = Range.isCollapsed(selection);
78
78
  const eventBus = EventBus.getInstance();
79
- eventBus.dispatch(INTERNAL_EVENT.INSERT_ELEMENT, {
80
- type: ELEMENT_TYPE.LINK,
81
- newEditor
82
- });
79
+ if (isCollapsed) {
80
+ eventBus.dispatch(INTERNAL_EVENT.INSERT_ELEMENT, {
81
+ type: ELEMENT_TYPE.LINK,
82
+ editor
83
+ });
84
+ } else {
85
+ const [firstSelectedNode, ...restNodes] = getSelectedElems(newEditor);
86
+ if (!firstSelectedNode || restNodes) return; // If select more than one node or not select any node, return
87
+ const isSelectTextNodes = firstSelectedNode.children.some(node => Text.isText(node));
88
+ if (!isSelectTextNodes) return;
89
+ const selectContent = window.getSelection().toString();
90
+ const replaceLinkNode = () => Editor.deleteBackward(editor, selection);
91
+ eventBus.dispatch(INTERNAL_EVENT.INSERT_ELEMENT, {
92
+ type: ELEMENT_TYPE.LINK,
93
+ editor: newEditor,
94
+ linkTitle: selectContent,
95
+ handleSubmit: replaceLinkNode
96
+ });
97
+ }
83
98
  }
84
99
  return onHotKeyDown && onHotKeyDown(e);
85
100
  };
@@ -6,7 +6,7 @@ import classnames from 'classnames';
6
6
  import { SDOC_LINK_TYPE_CONFIG, SDOC_LINK_TYPE, SDOC_LINK_TYPES } from '../constants';
7
7
  import { ElementPopover } from '../../../commons';
8
8
  import toaster from '../../../../../components/toast';
9
- import { getUrl, onCopySdocLinkNode } from '../helpers';
9
+ import { onCopySdocLinkNode } from '../helpers';
10
10
  import './index.css';
11
11
  const SdocLinkHoverMenu = _ref => {
12
12
  let {
@@ -15,7 +15,8 @@ const SdocLinkHoverMenu = _ref => {
15
15
  element,
16
16
  onUnwrapFileLinkNode,
17
17
  onHideInsertHoverMenu,
18
- t
18
+ t,
19
+ url
19
20
  } = _ref;
20
21
  const readOnly = useReadOnly();
21
22
  const [isShowDisplayStylePopover, setIsShowDisplayStylePopover] = useState(false);
@@ -60,7 +61,7 @@ const SdocLinkHoverMenu = _ref => {
60
61
  'ml-0': readOnly
61
62
  })
62
63
  }, /*#__PURE__*/React.createElement("a", {
63
- href: getUrl(element.doc_uuid),
64
+ href: url,
64
65
  target: "_blank",
65
66
  rel: "noopener noreferrer",
66
67
  className: "link-op-menu-link"
@@ -3,6 +3,7 @@ import { ReactEditor } from '@seafile/slate-react';
3
3
  import { FILE_LINK_INSET_INPUT_TEMP, SDOC_LINK } from '../../constants';
4
4
  import { getFileSearchInputEntry, insertTempInput, isTriggeredByShortcut } from './helpers';
5
5
  import { getSelectedElems } from '../../core';
6
+ import { WIKI_LINK } from '../../constants/element-type';
6
7
  const withSdocLink = editor => {
7
8
  const {
8
9
  isInline,
@@ -17,7 +18,7 @@ const withSdocLink = editor => {
17
18
  const {
18
19
  type
19
20
  } = elem;
20
- const isInlineElem = [SDOC_LINK, FILE_LINK_INSET_INPUT_TEMP].includes(type);
21
+ const isInlineElem = [WIKI_LINK, SDOC_LINK, FILE_LINK_INSET_INPUT_TEMP].includes(type);
21
22
  if (isInlineElem) return true;
22
23
  return isInline(elem);
23
24
  };
@@ -43,7 +44,7 @@ const withSdocLink = editor => {
43
44
  const beforePath = nodeEntry[1];
44
45
  beforePath.splice(-1, 1, Math.max(nodeEntry[1].at(-1) - 1, 0));
45
46
  const beforeNodeEntry = Editor.node(newEditor, beforePath);
46
- if (beforeNodeEntry && [SDOC_LINK, FILE_LINK_INSET_INPUT_TEMP].includes(beforeNodeEntry[0].type)) {
47
+ if (beforeNodeEntry && [WIKI_LINK, SDOC_LINK, FILE_LINK_INSET_INPUT_TEMP].includes(beforeNodeEntry[0].type)) {
47
48
  Transforms.delete(newEditor, {
48
49
  at: beforeNodeEntry[1]
49
50
  });
@@ -1,5 +1,5 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
- import React, { useCallback, useEffect, useState, useRef } from 'react';
2
+ import React, { useCallback, useEffect, useState, useRef, useMemo } from 'react';
3
3
  import { Editor, Range } from '@seafile/slate';
4
4
  import { ReactEditor, useReadOnly } from '@seafile/slate-react';
5
5
  import { useScrollContext } from '../../../../hooks/use-scroll-context';
@@ -8,6 +8,8 @@ import HoverMenu from '../hover-menu';
8
8
  import { DELETED_STYLE, ADDED_STYLE } from '../../../constants';
9
9
  import { SDOC_LINK_TYPE } from '../constants';
10
10
  import { focusEditor } from '../../../core';
11
+ import { WIKI_LINK } from '../../../constants/element-type';
12
+ import { getWikiUrl } from '../../wiki-link/helpers';
11
13
  import './render-elem.css';
12
14
  const SdocFileLink = _ref => {
13
15
  let {
@@ -106,6 +108,9 @@ const SdocFileLink = _ref => {
106
108
  if (style.computed_background_color) {
107
109
  style['backgroundColor'] = style.computed_background_color;
108
110
  }
111
+ const url = useMemo(() => {
112
+ return element.type === WIKI_LINK ? getWikiUrl(element.wiki_repo_id, element.page_id) : getUrl(element.doc_uuid);
113
+ }, [element.doc_uuid, element.page_id, element.type, element.wiki_repo_id]);
109
114
  return /*#__PURE__*/React.createElement("span", Object.assign({}, attributes, {
110
115
  "data-id": element.id,
111
116
  contentEditable: false,
@@ -123,12 +128,13 @@ const SdocFileLink = _ref => {
123
128
  className: 'sdoc-file-text-link',
124
129
  style: style
125
130
  }, /*#__PURE__*/React.createElement("a", {
126
- href: getUrl(element.doc_uuid),
131
+ href: url,
127
132
  onClick: e => {
128
133
  e.preventDefault();
129
134
  },
130
135
  title: element.title
131
136
  }, children))), isShowInsertHoverMenu && !readOnly && editor.selection && Range.isCollapsed(editor.selection) && /*#__PURE__*/React.createElement(HoverMenu, {
137
+ url: url,
132
138
  editor: editor,
133
139
  menuPosition: menuPosition,
134
140
  element: element,
@@ -1,24 +1,30 @@
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
+ import * as CellType from './constants/cell-types';
7
8
  export const isMenuDisabled = (editor, readonly) => {
8
9
  if (readonly) return true;
9
- if (editor.selection == null) return true;
10
+ const {
11
+ selection
12
+ } = editor;
13
+ if (selection == null) return true;
14
+ if (!Range.isCollapsed(selection)) return true;
10
15
  const [nodeEntry] = Editor.nodes(editor, {
11
16
  match: n => {
12
17
  const type = getNodeType(n);
13
18
 
14
19
  // Only available for p and blockquote
15
- if (type === PARAGRAPH) return true;
16
- if (type === BLOCKQUOTE) return true;
20
+ if (type === BLOCKQUOTE) return false;
21
+ if (type === PARAGRAPH) return false;
17
22
  if (type === UNORDERED_LIST) return true;
18
23
  if (type === ORDERED_LIST) return true;
19
24
  if (type === CHECK_LIST_ITEM) return true;
20
25
  if (type === IMAGE) return true;
21
26
  if (type === TABLE_CELL) return true;
27
+ if (Editor.isVoid(editor, n)) return true;
22
28
  return false;
23
29
  },
24
30
  universal: true,
@@ -27,9 +33,9 @@ export const isMenuDisabled = (editor, readonly) => {
27
33
 
28
34
  // Match to p blockquote, do not disable
29
35
  if (nodeEntry) {
30
- return false;
36
+ return true;
31
37
  }
32
- return true;
38
+ return false;
33
39
  };
34
40
  export const getColumnType = editor => {
35
41
  const [match] = Editor.nodes(editor, {
@@ -40,9 +46,9 @@ export const getColumnType = editor => {
40
46
  const [n] = match;
41
47
  return getNodeType(n);
42
48
  };
43
- export const insertSeaTableColumn = (editor, active) => {
49
+ export const insertSeaTableColumn = (editor, active, option) => {
44
50
  if (!active) {
45
- const column = new Column({});
51
+ const column = new Column(option);
46
52
  column.id = slugid.nice();
47
53
  Transforms.insertNodes(editor, _objectSpread({}, column));
48
54
  }
@@ -59,4 +65,49 @@ export const setSeaTableColumn = (editor, data) => {
59
65
  export const getColumnByKey = (columns, key) => {
60
66
  const column = columns.find(item => item.key === key);
61
67
  return column || null;
68
+ };
69
+ export const getColumnWidth = column => {
70
+ let {
71
+ type,
72
+ data
73
+ } = column;
74
+ switch (type) {
75
+ case CellType.DATE:
76
+ {
77
+ let isShowHourAndMinute = data && data.format && data.format.indexOf('HH:mm') > -1;
78
+ return isShowHourAndMinute ? 160 : 100;
79
+ }
80
+ case CellType.CTIME:
81
+ case CellType.MTIME:
82
+ case CellType.LINK:
83
+ case CellType.GEOLOCATION:
84
+ {
85
+ return 160;
86
+ }
87
+ case CellType.COLLABORATOR:
88
+ {
89
+ return 100;
90
+ }
91
+ case CellType.CHECKBOX:
92
+ {
93
+ return 40;
94
+ }
95
+ case CellType.NUMBER:
96
+ case CellType.AUTO_NUMBER:
97
+ {
98
+ return 120;
99
+ }
100
+ case CellType.RATE:
101
+ {
102
+ const {
103
+ rate_max_number
104
+ } = data || {};
105
+ const rateMaxNumber = rate_max_number || 5;
106
+ return 16 * rateMaxNumber + 20;
107
+ }
108
+ default:
109
+ {
110
+ return 100;
111
+ }
112
+ }
62
113
  };
@@ -1,12 +1,10 @@
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
- const ColumnPlugin = {
4
+ const SeaTableColumnPlugin = {
6
5
  type: COLUMN,
7
6
  nodeType: 'element',
8
- editorMenus: [ColumnMenu],
9
7
  editorPlugin: withColumn,
10
8
  renderElements: [renderColumn]
11
9
  };
12
- export default ColumnPlugin;
10
+ export default SeaTableColumnPlugin;
@@ -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
+ }