@seafile/sdoc-editor 0.4.16 → 0.4.17

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.
@@ -0,0 +1,65 @@
1
+ .sdoc-history-files-wrapper {
2
+ position: absolute;
3
+ z-index: 101;
4
+ width: 400px;
5
+ cursor: pointer;
6
+ }
7
+
8
+ .sdoc-history-files-wrapper .sdoc-history-files-search-input {
9
+ border: 0;
10
+ outline: none;
11
+ margin-top: -21px;
12
+ position: absolute;
13
+ background-color: transparent;
14
+ padding: 0px;
15
+ color: #212529;
16
+ font-size: 14px;
17
+ }
18
+
19
+ .sdoc-history-files-wrapper .sdoc-history-files-content .sdoc-history-files-header {
20
+ color: #999999;
21
+ font-size: 14px;
22
+ margin-top: 8px;
23
+ height: 32px;
24
+ display: flex;
25
+ align-items: center;
26
+ padding: 0px 16px;
27
+ }
28
+
29
+ .sdoc-history-files-wrapper .sdoc-history-files-content .sdoc-history-files {
30
+ max-height: 306px;
31
+ overflow-y: scroll;
32
+ }
33
+
34
+ .sdoc-history-files-wrapper .sdoc-history-files-content .sdoc-history-files .sdoc-history-files-item {
35
+ font-size: 14px;
36
+ line-height: 32px;
37
+ height: 32px;
38
+ padding: 0px 16px;
39
+ overflow:hidden;
40
+ text-overflow:ellipsis;
41
+ white-space:nowrap;
42
+ }
43
+
44
+ .sdoc-history-files-wrapper .sdoc-history-files-content .sdoc-history-files .sdoc-history-files-item :first-child {
45
+ font-size: 12px;
46
+ margin-right: 5px;
47
+ }
48
+
49
+ .sdoc-history-files-wrapper .sdoc-history-files-content .sdoc-history-files .sdoc-history-files-item:hover {
50
+ background-color: #f5f5f5;
51
+ }
52
+
53
+ .sdoc-history-files-wrapper .sdoc-history-files-content .sdoc-history-files-add {
54
+ height: 32px;
55
+ padding: 0px 16px;
56
+ border-top: 1px solid #e9ecef;
57
+ font-size: 14px;
58
+ display: flex;
59
+ align-items: center;
60
+ }
61
+
62
+ .sdoc-history-files-wrapper .sdoc-history-files-content .sdoc-history-files-add :first-child {
63
+ color: #444444;
64
+ margin-right: 10px;
65
+ }
@@ -0,0 +1,156 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import React, { useCallback, useEffect, useState, useRef } from 'react';
3
+ import { Editor } from '@seafile/slate';
4
+ import { ReactEditor } from '@seafile/slate-react';
5
+ import { withTranslation } from 'react-i18next';
6
+ import EventBus from '../../../utils/event-bus';
7
+ import { insertSdocFileLink } from '../../plugins/sdoc-link/helpers';
8
+ import { LocalStorage } from '../../../../utils';
9
+ import { INTERNAL_EVENT } from '../../../constants';
10
+ import { EXTERNAL_EVENT } from '../../../../constants';
11
+ import { SDOC_LINK } from '../../constants';
12
+ import './index.css';
13
+ const HistoryFiles = _ref => {
14
+ let {
15
+ editor,
16
+ insertLinkCallback,
17
+ closeDialog,
18
+ t
19
+ } = _ref;
20
+ const historyFilesRef = useRef();
21
+ const historyFilesInputRef = useRef();
22
+ const [files, setFiles] = useState([]);
23
+ const [position, setPosition] = useState({});
24
+ const [header, setHeader] = useState(t('Recent_previews'));
25
+ const [newFileName, setNewFileName] = useState('');
26
+ const getPosition = useCallback(() => {
27
+ const {
28
+ selection
29
+ } = editor;
30
+ const nodeEntry = Editor.node(editor, selection);
31
+ const domNode = ReactEditor.toDOMNode(editor, nodeEntry[0]);
32
+ if (domNode) {
33
+ const {
34
+ top,
35
+ right
36
+ } = domNode.getBoundingClientRect();
37
+ setPosition({
38
+ left: right + 5,
39
+ top: top + 20
40
+ });
41
+ }
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, []);
44
+ const onClick = useCallback(e => {
45
+ if (historyFilesRef.current.contains(e.target)) return;
46
+ closeDialog();
47
+ // eslint-disable-next-line react-hooks/exhaustive-deps
48
+ }, []);
49
+ const onScroll = useCallback(e => {
50
+ getPosition();
51
+ // eslint-disable-next-line react-hooks/exhaustive-deps
52
+ }, []);
53
+ const getHistoryFiles = useCallback(e => {
54
+ const files = LocalStorage.getItem('sdoc-recent-files') || [];
55
+ setFiles(files);
56
+ }, []);
57
+ useEffect(() => {
58
+ getPosition();
59
+ getHistoryFiles();
60
+ setTimeout(() => {
61
+ historyFilesInputRef.current.focus();
62
+ }, 0);
63
+ const sdocScrollContainer = document.getElementById('sdoc-scroll-container');
64
+ sdocScrollContainer.addEventListener('scroll', onScroll);
65
+ document.addEventListener('click', onClick);
66
+ return () => {
67
+ sdocScrollContainer.removeEventListener('scroll', onScroll);
68
+ document.removeEventListener('click', onClick);
69
+ };
70
+ // eslint-disable-next-line react-hooks/exhaustive-deps
71
+ }, []);
72
+ const onSearch = useCallback(e => {
73
+ let newFiles = LocalStorage.getItem('sdoc-recent-files') || [];
74
+ if (e.target.value) {
75
+ newFiles = newFiles.filter(item => item.file_name.includes(e.target.value));
76
+ if (newFiles.length === 0) {
77
+ setHeader(t('The_document_does_not_exist'));
78
+ setNewFileName(e.target.value);
79
+ } else {
80
+ setHeader(t('Recent_previews'));
81
+ setNewFileName('');
82
+ }
83
+ setFiles(newFiles);
84
+ return;
85
+ }
86
+ setHeader(t('Recent_previews'));
87
+ setNewFileName('');
88
+ setFiles(newFiles);
89
+ // eslint-disable-next-line react-hooks/exhaustive-deps
90
+ }, []);
91
+ const onSelect = useCallback(fileInfo => {
92
+ const {
93
+ file_uuid,
94
+ file_name
95
+ } = fileInfo;
96
+ const {
97
+ insertSdocFileLinkCallback
98
+ } = insertLinkCallback;
99
+ insertSdocFileLinkCallback(editor, file_name, file_uuid);
100
+ closeDialog();
101
+ // eslint-disable-next-line react-hooks/exhaustive-deps
102
+ }, []);
103
+ const onShowMore = useCallback(() => {
104
+ const eventBus = EventBus.getInstance();
105
+ eventBus.dispatch(INTERNAL_EVENT.INSERT_ELEMENT, {
106
+ type: SDOC_LINK,
107
+ insertSdocFileLinkCallback: insertSdocFileLink
108
+ });
109
+ }, []);
110
+ const onCreateFile = useCallback(() => {
111
+ const eventBus = EventBus.getInstance();
112
+ eventBus.dispatch(EXTERNAL_EVENT.CREATE_SDOC_FILE, {
113
+ newFileName: newFileName.trim()
114
+ });
115
+ closeDialog();
116
+ }, [closeDialog, newFileName]);
117
+ return /*#__PURE__*/React.createElement("div", {
118
+ ref: historyFilesRef,
119
+ className: "sdoc-history-files-wrapper popover",
120
+ style: _objectSpread({}, position)
121
+ }, /*#__PURE__*/React.createElement("input", {
122
+ id: "sdoc-history-files-search-input",
123
+ className: "sdoc-history-files-search-input",
124
+ ref: historyFilesInputRef,
125
+ autoComplete: "off",
126
+ onChange: onSearch,
127
+ onCompositionStart: e => {
128
+ e.stopPropagation();
129
+ }
130
+ }), /*#__PURE__*/React.createElement("div", {
131
+ className: "sdoc-history-files-content"
132
+ }, /*#__PURE__*/React.createElement("div", {
133
+ className: "sdoc-history-files-header"
134
+ }, header), /*#__PURE__*/React.createElement("div", {
135
+ className: "sdoc-history-files"
136
+ }, files.map(item => {
137
+ return /*#__PURE__*/React.createElement("div", {
138
+ key: item.file_uuid,
139
+ className: "sdoc-history-files-item",
140
+ onClick: () => {
141
+ onSelect(item);
142
+ }
143
+ }, /*#__PURE__*/React.createElement("i", {
144
+ className: "sdocfont sdoc-document"
145
+ }), /*#__PURE__*/React.createElement("span", null, item.file_name));
146
+ }), /*#__PURE__*/React.createElement("div", {
147
+ className: "sdoc-history-files-item",
148
+ onClick: onShowMore
149
+ }, "...", t('More'))), /*#__PURE__*/React.createElement("div", {
150
+ className: "sdoc-history-files-add",
151
+ onClick: onCreateFile
152
+ }, /*#__PURE__*/React.createElement("i", {
153
+ className: "sdocfont sdoc-append"
154
+ }), /*#__PURE__*/React.createElement("span", null, newFileName ? t("Create ".concat(newFileName, ".sdoc")) : t('Create_a_new_sdoc_file')))));
155
+ };
156
+ export default withTranslation('sdoc-editor')(HistoryFiles);
@@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useState, useRef } from 'react';
2
2
  import { CustomTableSizeDialog, SplitCellSettingDialog } from '../../plugins/table/dialogs';
3
3
  import AddLinkDialog from '../../plugins/link/dialog/add-link-dialog';
4
4
  import SelectFileDialog from '../select-file-dialog/index.js';
5
+ import HistoryFiles from '../history-files';
5
6
  import EventBus from '../../../utils/event-bus';
6
7
  import { INTERNAL_EVENT } from '../../../constants';
7
8
  import { ELEMENT_TYPE, INSERT_POSITION, LOCAL_IMAGE } from '../../constants';
@@ -16,6 +17,7 @@ const InsertElementDialog = _ref => {
16
17
  const [insertPosition, setInsertPosition] = useState(INSERT_POSITION.CURRENT);
17
18
  const [slateNode, setSlateNode] = useState(null);
18
19
  const [insertLinkCallback, setInsertLinkCallback] = useState(null);
20
+ const [isShowHistoryFiles, setIsShowHistoryFiles] = useState(false);
19
21
  const uploadLocalImageInputRef = useRef();
20
22
  const onFileChanged = useCallback(event => {
21
23
  const files = event.target.files;
@@ -42,7 +44,8 @@ const InsertElementDialog = _ref => {
42
44
  insertPosition = INSERT_POSITION.CURRENT,
43
45
  slateNode,
44
46
  insertFileLinkCallback,
45
- insertSdocFileLinkCallback
47
+ insertSdocFileLinkCallback,
48
+ isShowHistoryFiles
46
49
  } = _ref2;
47
50
  setInsertPosition(insertPosition);
48
51
  setSlateNode(slateNode);
@@ -52,6 +55,7 @@ const InsertElementDialog = _ref => {
52
55
  insertSdocFileLinkCallback,
53
56
  insertFileLinkCallback
54
57
  });
58
+ setIsShowHistoryFiles(isShowHistoryFiles);
55
59
  if (type === LOCAL_IMAGE) {
56
60
  setTimeout(() => {
57
61
  uploadLocalImageInputRef.current && uploadLocalImageInputRef.current.click();
@@ -64,6 +68,7 @@ const InsertElementDialog = _ref => {
64
68
  setElement('');
65
69
  setDialogType('');
66
70
  setInsertLinkCallback(null);
71
+ setIsShowHistoryFiles(false);
67
72
  }, []);
68
73
  const props = {
69
74
  insertPosition,
@@ -93,6 +98,9 @@ const InsertElementDialog = _ref => {
93
98
  insertLinkCallback,
94
99
  closeDialog
95
100
  };
101
+ if (isShowHistoryFiles) {
102
+ return /*#__PURE__*/React.createElement(HistoryFiles, sdocLinkProps);
103
+ }
96
104
  return /*#__PURE__*/React.createElement(SelectFileDialog, sdocLinkProps);
97
105
  }
98
106
  case ELEMENT_TYPE.FILE_LINK:
@@ -1,44 +1,9 @@
1
1
  .sdoc-file-select-dialog {
2
- max-width: 620px;
2
+ max-width: 520px;
3
3
  }
4
4
 
5
5
  .sdoc-file-select-dialog .sdoc-file-select-modal {
6
- width: 620px;
7
- }
8
-
9
- .sdoc-file-select-dialog .sdoc-file-select-container {
10
- display: flex;
11
- }
12
-
13
- .sdoc-file-select-dialog .sdoc-file-select-left {
14
- border-right: 1px solid #e9ecef;
15
- width: 150px;
16
- padding: 12px 8px;
17
- }
18
-
19
- .sdoc-file-select-dialog .sdoc-file-select-left .sdoc-file-select-nav-item {
20
- padding: 5px 0 5px 8px;
21
- border-radius: 3px;
22
- display: inline-block;
23
- cursor: pointer;
24
- width: 100%;
25
- }
26
-
27
- .sdoc-file-select-dialog .sdoc-file-select-left .sdoc-file-select-nav-item:hover {
28
- background-color: #f5f5f5;
29
- }
30
-
31
- .sdoc-file-select-dialog .sdoc-file-select-container .sdoc-file-select-left .selected-sdoc-file-select-nav-item {
32
- background-color: #ff8000;
33
- color: #fff;
34
- }
35
-
36
- .sdoc-file-select-dialog .sdoc-file-select-right {
37
- height: 440px;
38
- width: 468px;
39
- display: flex;
40
- padding: 0;
41
- flex-direction: column;
6
+ width: 520px;
42
7
  }
43
8
 
44
9
  .sdoc-file-select-dialog .sdoc-file-select-footer {
@@ -73,14 +73,6 @@ const SelectSdocFileDialog = _ref => {
73
73
  className: "p-0"
74
74
  }, /*#__PURE__*/React.createElement("div", {
75
75
  className: "sdoc-file-select-container"
76
- }, /*#__PURE__*/React.createElement("div", {
77
- className: "sdoc-file-select-left"
78
- }, /*#__PURE__*/React.createElement("div", {
79
- className: "sdoc-file-select-nav"
80
- }, /*#__PURE__*/React.createElement("div", {
81
- className: "sdoc-file-select-nav-item selected-sdoc-file-select-nav-item"
82
- }, t('Local_file')))), /*#__PURE__*/React.createElement("div", {
83
- className: "sdoc-file-select-right"
84
76
  }, /*#__PURE__*/React.createElement(LocalFiles, {
85
77
  fileType: FILE_TYPE[dialogType],
86
78
  onSelectedFile: onSelectedFile,
@@ -96,6 +88,6 @@ const SelectSdocFileDialog = _ref => {
96
88
  className: "highlight-bg-color",
97
89
  disabled: !currentSelectedFile,
98
90
  onClick: onSubmit
99
- }, t('Confirm')))))));
91
+ }, t('Confirm'))))));
100
92
  };
101
93
  export default SelectSdocFileDialog;
@@ -1,16 +1,17 @@
1
1
  .sdoc-files-tree {
2
2
  flex: 1;
3
- padding: 16px;
4
- overflow: auto;
3
+ padding: 8px 16px;
5
4
  width: 100%;
5
+ height: 400px;
6
+ overflow-y: auto;
6
7
  display: flex;
7
8
  flex-direction: column;
8
9
  }
9
10
 
10
11
  .sdoc-files-tree .sdoc-file-info {
11
12
  border-radius: 2px;
12
- height: 1.5rem;
13
- line-height: 1.625;
13
+ height: 32px;
14
+ line-height: 32px;
14
15
  overflow: hidden;
15
16
  text-overflow: ellipsis;
16
17
  white-space: nowrap;
@@ -20,8 +21,7 @@
20
21
 
21
22
  .sdoc-files-tree .sdoc-file-info:hover {
22
23
  cursor: pointer;
23
- background: #fdefb9;
24
- box-shadow: inset 0 0 1px #999;
24
+ background-color: #f5f5f5;
25
25
  }
26
26
 
27
27
  .sdoc-files-tree .sdoc-file-info .sdoc-file-icon-container {
@@ -37,13 +37,7 @@
37
37
  }
38
38
 
39
39
  .sdoc-files-tree .sdoc-file-info.active {
40
- background: #ff8000;
41
- box-shadow: inset 0 0 1px #999;
42
- color: #fff;
43
- }
44
-
45
- .sdoc-files-tree .sdoc-file-info.active .sdoc-file-icon {
46
- color: #fff;
40
+ background-color: #f5f5f5;
47
41
  }
48
42
 
49
43
  .sdoc-files-tree .sdoc-file-icon-toggle {
@@ -4,8 +4,9 @@ import { Editor, Transforms, Range, Text } from '@seafile/slate';
4
4
  import slugid from 'slugid';
5
5
  import copy from 'copy-to-clipboard';
6
6
  import context from '../../../../context';
7
- import { SDOC_LINK, LINK, INSERT_FILE_DISPLAY_TYPE, CODE_BLOCK, CODE_LINE, PARAGRAPH } from '../../constants';
8
7
  import { focusEditor, getNodeType, getSelectedElems } from '../../core';
8
+ import { LocalStorage } from '../../../../utils';
9
+ import { SDOC_LINK, LINK, INSERT_FILE_DISPLAY_TYPE, CODE_BLOCK, CODE_LINE, PARAGRAPH } from '../../constants';
9
10
  export const isMenuDisabled = (editor, readonly) => {
10
11
  if (readonly) return true;
11
12
  if (editor.selection == null) return true;
@@ -55,12 +56,11 @@ export const insertSdocFileLink = (editor, text, uuid) => {
55
56
 
56
57
  // Remove shortcut symbol,if trigger by shortcut
57
58
  removeShortCutSymbol(editor);
59
+ const sdocFileNode = generateSdocFileNode(uuid, text);
58
60
  if (isCollapsed) {
59
61
  // Insert Spaces before and after sdoclinks for easy operation
60
62
  editor.insertText(' ');
61
- const sdocFileNode = generateSdocFileNode(uuid, text);
62
63
  Transforms.insertNodes(editor, sdocFileNode);
63
-
64
64
  // Not being able to use insertText directly causes the added Spaces to be added to the linked text, as in the issue above, replaced by insertFragment
65
65
  editor.insertFragment([{
66
66
  id: slugid.nice(),
@@ -71,11 +71,9 @@ export const insertSdocFileLink = (editor, text, uuid) => {
71
71
  if (selectedText !== text) {
72
72
  // If the selected text is different from the typed text, delete the text and insert the link
73
73
  editor.deleteFragment();
74
- const sdocFileNode = generateSdocFileNode(uuid, text);
75
74
  Transforms.insertNodes(editor, sdocFileNode);
76
75
  } else {
77
76
  // If the selected text is the same as the entered text, only the link can be wrapped
78
- const sdocFileNode = generateSdocFileNode(uuid, text);
79
77
  Transforms.wrapNodes(editor, sdocFileNode, {
80
78
  split: true
81
79
  });
@@ -55,7 +55,8 @@ const withSdocLink = editor => {
55
55
  if (isTriggeredByShortCut(newEditor)) {
56
56
  eventBus.dispatch(INTERNAL_EVENT.INSERT_ELEMENT, {
57
57
  type: ELEMENT_TYPE.SDOC_LINK,
58
- insertSdocFileLinkCallback: insertSdocFileLink
58
+ insertSdocFileLinkCallback: insertSdocFileLink,
59
+ isShowHistoryFiles: true
59
60
  });
60
61
  }
61
62
  return onHotKeyDown && onHotKeyDown(event);
@@ -16,7 +16,8 @@ export const EXTERNAL_EVENT = {
16
16
  REMOVE_DOCUMENT_ERROR: 'remove_document_error',
17
17
  NEW_NOTIFICATION: 'new_notification',
18
18
  PARTICIPANT_ADDED: 'participant-added',
19
- PARTICIPANT_REMOVED: 'participant-removed'
19
+ PARTICIPANT_REMOVED: 'participant-removed',
20
+ CREATE_SDOC_FILE: 'create_sdoc_file'
20
21
  };
21
22
  export const TIP_TYPE = {
22
23
  DELETE_NO_CHANGES_REVISION: 'delete_no_changes_revision',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.4.16",
3
+ "version": "0.4.17",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -440,5 +440,9 @@
440
440
  "Replace_all": "Replace all",
441
441
  "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "Are you sure to replace all {{number}} '{{originalWord}}' in this document with '{{replacedWord}}'?",
442
442
  "Are_you_sure_to_clear_all_number_xxx_in_this_document": "Are you sure to clear all {{number}} '{{originalWord}}' in this document?",
443
- "Search_not_found": "Not found"
443
+ "Search_not_found": "Not found",
444
+ "Recent_previews": "Recent previews",
445
+ "The_document_does_not_exist": "The document does not exist",
446
+ "Create_a_new_sdoc_file": "Create a new sdoc file",
447
+ "Create": "Create"
444
448
  }
@@ -440,5 +440,9 @@
440
440
  "Replace_all": "替换全部",
441
441
  "Are_you_sure_to_replace_all_number_xxx_in_this_document_with_yyy": "确定要将此文档内的 {{number}} 处 \"{{originalWord}} \" 替换为 \"{{replacedWord}} \" 吗?",
442
442
  "Are_you_sure_to_clear_all_number_xxx_in_this_document": "确定将此文档内的 {{number}} 处 \"{{originalWord}}\" 全部清除吗?",
443
- "Search_not_found": "未找到"
443
+ "Search_not_found": "未找到",
444
+ "Recent_previews": "最近浏览",
445
+ "The_document_does_not_exist": "不存在该文档",
446
+ "Create_a_new_sdoc_file": "新建sdoc文件",
447
+ "Create": "新建"
444
448
  }