@seafile/sdoc-editor 0.2.3 → 0.2.5-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/api/seafile-api.js +8 -0
  2. package/dist/basic-sdk/assets/css/sdoc-editor-plugins.css +9 -0
  3. package/dist/basic-sdk/comment/comment/comment-editor.js +58 -21
  4. package/dist/basic-sdk/comment/comment/comment-list.css +27 -0
  5. package/dist/basic-sdk/comment/comment/comment-list.js +16 -0
  6. package/dist/basic-sdk/comment/comment/editor-comment.js +21 -26
  7. package/dist/basic-sdk/constants/index.js +2 -1
  8. package/dist/basic-sdk/extension/commons/tooltip/index.js +4 -2
  9. package/dist/basic-sdk/extension/plugins/check-list/render-elem.js +3 -4
  10. package/dist/basic-sdk/extension/plugins/image/helpers.js +19 -1
  11. package/dist/basic-sdk/extension/plugins/image/hover-menu/index.css +0 -18
  12. package/dist/basic-sdk/extension/plugins/image/hover-menu/index.js +23 -7
  13. package/dist/basic-sdk/extension/plugins/image/plugin.js +11 -3
  14. package/dist/basic-sdk/extension/plugins/image/render-elem.js +13 -11
  15. package/dist/basic-sdk/layout/article-container.js +9 -2
  16. package/dist/components/doc-operations/revision-operations/index.js +2 -1
  17. package/dist/components/doc-operations/revision-operations/revisions/revisions-dialog/index.css +12 -0
  18. package/dist/components/doc-operations/revision-operations/revisions/revisions-dialog/index.js +93 -12
  19. package/dist/components/doc-operations/revision-operations/revisions/revisions-dialog/revision-operation/index.css +20 -0
  20. package/dist/components/doc-operations/revision-operations/revisions/revisions-dialog/revision-operation/index.js +57 -0
  21. package/dist/components/tip-dialog/index.js +6 -3
  22. package/dist/constants/index.js +4 -3
  23. package/dist/context.js +6 -0
  24. package/package.json +1 -1
  25. package/public/locales/en/sdoc-editor.json +3 -1
  26. package/public/locales/zh_CN/sdoc-editor.json +3 -1
@@ -9,6 +9,12 @@ var SeafileAPI = /*#__PURE__*/function () {
9
9
  var url = 'api/v2.1/seadoc/revision/' + docUuid + '/';
10
10
  return _this.req.delete(url);
11
11
  };
12
+ this.deleteSdocOtherRevision = function (docUuid, revisionId) {
13
+ var url = 'api/v2.1/seadoc/delete-revision/' + docUuid + '/';
14
+ var formData = new FormData();
15
+ formData.append('revision_id', revisionId);
16
+ return _this.req.delete(url, formData);
17
+ };
12
18
  this.req = axios.create({
13
19
  baseURL: server,
14
20
  headers: {
@@ -51,6 +57,8 @@ var SeafileAPI = /*#__PURE__*/function () {
51
57
  var url = '/api/v2.1/seadoc/download-image/' + docUuid + '/' + encodeURIComponent(imageName);
52
58
  return this.req.get(url);
53
59
  }
60
+
61
+ // revision
54
62
  }, {
55
63
  key: "startRevise",
56
64
  value: function startRevise(repoID, fileUuid, path) {
@@ -27,6 +27,15 @@
27
27
  padding-inline-start: 24px;
28
28
  }
29
29
 
30
+ /* check list */
31
+ .sdoc-editor-container .article .sdoc-checkbox-container .sdoc-checkbox-input-wrapper {
32
+ margin-right: 6px;
33
+ }
34
+
35
+ .sdoc-editor-container .article .sdoc-checkbox-container .sdoc-checkbox-input-wrapper :first-child {
36
+ vertical-align: middle;
37
+ }
38
+
30
39
  /* image */
31
40
  .sdoc-editor-container .article .sdoc-image-wrapper {
32
41
  position: relative;
@@ -1,8 +1,11 @@
1
- import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
- import classNames from 'classnames';
3
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useRef } from 'react';
4
2
  import { useTranslation } from 'react-i18next';
5
3
  import { Button } from 'reactstrap';
4
+ import classNames from 'classnames';
5
+ import { useScrollContext } from '../../hooks/use-scroll-context';
6
+ import context from '../../../context';
7
+ import EventBus from '../../utils/event-bus';
8
+ import { INTERNAL_EVENT } from '../../constants';
6
9
  var getSubmitTip = function getSubmitTip(type, content) {
7
10
  if (content) return 'Save';
8
11
  return type === 'comment' ? 'Comment' : 'Reply';
@@ -17,18 +20,44 @@ var CommentEditor = function CommentEditor(_ref) {
17
20
  setIsEditing = _ref.setIsEditing,
18
21
  hiddenComment = _ref.hiddenComment;
19
22
  var commentRef = useRef();
23
+ var commentWrapperRef = useRef();
20
24
  var _useTranslation = useTranslation(),
21
25
  t = _useTranslation.t;
22
- var _useState = useState(false),
23
- _useState2 = _slicedToArray(_useState, 2),
24
- isFocus = _useState2[0],
25
- setIsFocus = _useState2[1];
26
+ var scrollRef = useScrollContext();
26
27
 
27
- // onMount
28
+ // onMount: comment content
28
29
  useEffect(function () {
29
- if (content) {
30
- commentRef.current.textContent = content;
31
- }
30
+ if (!content) return;
31
+ commentRef.current.textContent = content;
32
+ // eslint-disable-next-line react-hooks/exhaustive-deps
33
+ }, []);
34
+
35
+ // onMount: set input focus
36
+ useEffect(function () {
37
+ if (type !== 'comment') return;
38
+ commentRef.current && commentRef.current.focus();
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ }, []);
41
+
42
+ // onMount: set scrollLeft
43
+ useEffect(function () {
44
+ if (!commentWrapperRef.current) return;
45
+ var _commentWrapperRef$cu = commentWrapperRef.current.getBoundingClientRect(),
46
+ right = _commentWrapperRef$cu.right,
47
+ width = _commentWrapperRef$cu.width;
48
+ if (right <= window.innerWidth) return;
49
+ if (!scrollRef.current) return;
50
+ scrollRef.current.scrollLeft = scrollRef.current.scrollLeft + width;
51
+ // eslint-disable-next-line react-hooks/exhaustive-deps
52
+ }, []);
53
+
54
+ // onMount: hidden comment
55
+ useEffect(function () {
56
+ var eventBus = EventBus.getInstance();
57
+ var unsubscribe = eventBus.subscribe(INTERNAL_EVENT.ARTICLE_CLICK, hiddenComment);
58
+ return function () {
59
+ unsubscribe();
60
+ };
32
61
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
62
  }, []);
34
63
  var updateValue = useCallback(function (value) {
@@ -47,7 +76,6 @@ var CommentEditor = function CommentEditor(_ref) {
47
76
  }, [updateValue]);
48
77
  var onCancel = useCallback(function (event) {
49
78
  event.stopPropagation();
50
- setIsFocus(false);
51
79
  commentRef.current.textContent = '';
52
80
  setIsEditing && setIsEditing(false);
53
81
  hiddenComment && hiddenComment(false);
@@ -65,23 +93,32 @@ var CommentEditor = function CommentEditor(_ref) {
65
93
  onCancel();
66
94
  }
67
95
  }, [onCancel, onSubmit]);
68
- placeholder = t(placeholder);
69
96
  var submitTip = useMemo(function () {
70
97
  return getSubmitTip(type, content);
71
98
  }, [content, type]);
99
+ var userInfo = context.getUserInfo();
72
100
  return /*#__PURE__*/React.createElement("div", {
73
- className: classNames('comment-editor-wrapper', className)
101
+ className: classNames('comment-editor-wrapper', className),
102
+ ref: commentWrapperRef
103
+ }, type === 'comment' && /*#__PURE__*/React.createElement("div", {
104
+ className: "comment-editor-user-info"
74
105
  }, /*#__PURE__*/React.createElement("div", {
106
+ className: "comment-editor-user-img"
107
+ }, /*#__PURE__*/React.createElement("img", {
108
+ src: userInfo.avatar_url,
109
+ alt: "",
110
+ height: "100%",
111
+ width: "100%"
112
+ })), /*#__PURE__*/React.createElement("div", {
113
+ className: "comment-editor-user-name"
114
+ }, userInfo.name)), /*#__PURE__*/React.createElement("div", {
75
115
  ref: commentRef,
76
116
  contentEditable: "true",
77
117
  className: "comment-editor",
78
- placeholder: placeholder,
79
- onKeyDown: onKeyDown,
80
- onFocus: function onFocus() {
81
- return setIsFocus(true);
82
- }
83
- }), isFocus && /*#__PURE__*/React.createElement("div", {
84
- className: "editor-operations"
118
+ placeholder: t(placeholder),
119
+ onKeyDown: onKeyDown
120
+ }), /*#__PURE__*/React.createElement("div", {
121
+ className: "comment-operations"
85
122
  }, /*#__PURE__*/React.createElement(Button, {
86
123
  className: "mr-2",
87
124
  onClick: onCancel
@@ -191,3 +191,30 @@
191
191
  .sdoc-comment-list-container .comment-editor-wrapper .comment-editor:focus {
192
192
  border: 1px solid rgba(0, 0, 0, .12);
193
193
  }
194
+
195
+ .sdoc-comment-list-container .comment-editor-wrapper .comment-editor-user-info {
196
+ display: flex;
197
+ align-items: center;
198
+ margin-bottom: 10px;
199
+ }
200
+
201
+ .sdoc-comment-list-container .comment-editor-wrapper .comment-editor-user-info .comment-editor-user-img {
202
+ height: 30px;
203
+ width: 30px;
204
+ border-radius: 50%;
205
+ overflow: hidden;
206
+ margin-right: 8px;
207
+ }
208
+
209
+ .sdoc-comment-list-container .comment-editor-wrapper .comment-editor-user-info .comment-editor-user-name {
210
+ flex: 1;
211
+ overflow: hidden;
212
+ text-overflow: ellipsis;
213
+ white-space: nowrap;
214
+ user-select: none;
215
+ }
216
+
217
+ .sdoc-comment-list-container .comment-editor-wrapper .comment-operations {
218
+ display: flex;
219
+ justify-content: flex-end;
220
+ }
@@ -9,6 +9,8 @@ import { useCommentListPosition } from '../../hooks/use-selection-position';
9
9
  import { useCommentContext } from '../hooks/use-comment-context';
10
10
  import CommentEditor from './comment-editor';
11
11
  import CommentItemWrapper from './comment-item-wrapper';
12
+ import EventBus from '../../utils/event-bus';
13
+ import { INTERNAL_EVENT } from '../../constants';
12
14
  import './comment-list.css';
13
15
  var CommentList = function CommentList(_ref) {
14
16
  var comments = _ref.comments,
@@ -20,6 +22,20 @@ var CommentList = function CommentList(_ref) {
20
22
  _useState2 = _slicedToArray(_useState, 2),
21
23
  activeComment = _useState2[0],
22
24
  setActiveComment = _useState2[1];
25
+ var handelArticleClick = useCallback(function (event) {
26
+ if (event.target.className !== 'article') return;
27
+ hiddenComment();
28
+ }, [hiddenComment]);
29
+
30
+ // onMount: hidden comment
31
+ useEffect(function () {
32
+ var eventBus = EventBus.getInstance();
33
+ var unsubscribe = eventBus.subscribe(INTERNAL_EVENT.ARTICLE_CLICK, handelArticleClick);
34
+ return function () {
35
+ unsubscribe();
36
+ };
37
+ // eslint-disable-next-line react-hooks/exhaustive-deps
38
+ }, []);
23
39
  var onCommentClick = useCallback(function (comment) {
24
40
  if (activeComment && activeComment.id === comment.id) return;
25
41
  setActiveComment(comment);
@@ -19,18 +19,6 @@ var EditorComment = function EditorComment() {
19
19
  var onAddCommentToggle = useCallback(function () {
20
20
  setIsShowComments(true);
21
21
  }, []);
22
- var cursor = useCursorPosition();
23
- var style = useMemo(function () {
24
- var _Node$string;
25
- if (selectionElement && ((_Node$string = Node.string(selectionElement)) === null || _Node$string === void 0 ? void 0 : _Node$string.length) === 0) {
26
- return {
27
- top: '-99999px'
28
- };
29
- }
30
- return {
31
- top: cursor.y === 0 || isShowComments ? '-99999px' : cursor.y
32
- };
33
- }, [cursor, isShowComments, selectionElement]);
34
22
 
35
23
  // When selectionElement update, recalculate comment's panel state
36
24
  var _useState3 = useState([]),
@@ -52,24 +40,31 @@ var EditorComment = function EditorComment() {
52
40
  setComments([]);
53
41
  setIsShowComments(false);
54
42
  }, [element_comments_map, selectionElement, editor.selection]);
43
+ var cursor = useCursorPosition();
44
+ var style = useMemo(function () {
45
+ var _Node$string;
46
+ if (selectionElement && ((_Node$string = Node.string(selectionElement)) === null || _Node$string === void 0 ? void 0 : _Node$string.length) === 0) return {
47
+ top: '-99999px'
48
+ };
49
+ var comments = element_comments_map[selectionElement === null || selectionElement === void 0 ? void 0 : selectionElement.id];
50
+ var unresolvedComments = comments && comments.filter(function (item) {
51
+ return !item.resolved;
52
+ });
53
+ var hasComments = unresolvedComments && unresolvedComments.length > 0;
54
+ if (hasComments) return {
55
+ top: '-99999px'
56
+ };
57
+ if (cursor.y === 0 || isShowComments) return {
58
+ top: '-99999px'
59
+ };
60
+ return {
61
+ top: cursor.y
62
+ };
63
+ }, [cursor, isShowComments, selectionElement, element_comments_map]);
55
64
  var hiddenComment = useCallback(function () {
56
65
  setComments([]);
57
66
  setIsShowComments(false);
58
67
  }, []);
59
- var onHiddenComment = useCallback(function (e) {
60
- if (e.target.className === 'article') {
61
- hiddenComment();
62
- }
63
-
64
- // eslint-disable-next-line react-hooks/exhaustive-deps
65
- }, []);
66
- useEffect(function () {
67
- window.addEventListener('click', onHiddenComment);
68
- return function () {
69
- window.removeEventListener('click', onHiddenComment);
70
- };
71
- // eslint-disable-next-line react-hooks/exhaustive-deps
72
- }, []);
73
68
  return /*#__PURE__*/React.createElement("div", {
74
69
  className: "sdoc-comment-container"
75
70
  }, /*#__PURE__*/React.createElement("div", {
@@ -5,7 +5,8 @@ export var INTERNAL_EVENT = {
5
5
  ON_MOUSE_ENTER_BLOCK: 'on_mouse_enter_block',
6
6
  INSERT_ELEMENT: 'insert_element',
7
7
  OUTLINE_STATE_CHANGED: 'outline_state_changed',
8
- RELOAD_IMAGE: 'reload_image'
8
+ RELOAD_IMAGE: 'reload_image',
9
+ ARTICLE_CLICK: 'hidden_comment'
9
10
  };
10
11
  export var PAGE_EDIT_AREA_WIDTH = 672; // 672 = 794 - 2[borderLeft + borderRight] - 120[paddingLeft + paddingRight]
11
12
 
@@ -6,12 +6,14 @@ var Tooltip = function Tooltip(_ref) {
6
6
  var target = _ref.target,
7
7
  children = _ref.children,
8
8
  className = _ref.className,
9
- placement = _ref.placement;
9
+ placement = _ref.placement,
10
+ _ref$fade = _ref.fade,
11
+ fade = _ref$fade === void 0 ? false : _ref$fade;
10
12
  var popperClassName = classnames('sdoc-tooltip', className);
11
13
  return /*#__PURE__*/React.createElement(UncontrolledTooltip, {
12
14
  popperClassName: popperClassName,
13
15
  target: target,
14
- fade: false,
16
+ fade: fade,
15
17
  placement: placement || 'bottom',
16
18
  delay: 0
17
19
  }, children);
@@ -45,15 +45,14 @@ var CheckListItem = /*#__PURE__*/function (_React$PureComponent) {
45
45
  textAlign: align
46
46
  };
47
47
  return /*#__PURE__*/React.createElement("div", Object.assign({
48
+ className: "sdoc-checkbox-container",
48
49
  "data-id": id,
49
50
  "data-root": "true"
50
51
  }, attributes, {
51
52
  style: style
52
53
  }), /*#__PURE__*/React.createElement("span", {
53
- contentEditable: false,
54
- style: {
55
- marginRight: 6
56
- }
54
+ className: "sdoc-checkbox-input-wrapper",
55
+ contentEditable: false
57
56
  }, /*#__PURE__*/React.createElement("input", {
58
57
  type: "checkbox",
59
58
  onChange: this.onChange,
@@ -3,7 +3,7 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
3
3
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
4
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(typeof e + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
5
5
  import urlJoin from 'url-join';
6
- import { Editor, Range, Transforms, Path } from '@seafile/slate';
6
+ import { Editor, Range, Transforms, Path, Node } from '@seafile/slate';
7
7
  import { ReactEditor } from '@seafile/slate-react';
8
8
  import context from '../../../../context';
9
9
  import EventBus from '../../../utils/event-bus';
@@ -145,4 +145,22 @@ export var queryCopyMoveProgressView = function queryCopyMoveProgressView(taskId
145
145
  };
146
146
  }();
147
147
  start();
148
+ };
149
+ export var resetCursor = function resetCursor(editor) {
150
+ var selection = editor.selection;
151
+ var currentPath = selection.focus.path;
152
+ var targetPath = Path.next(Path.next(currentPath));
153
+
154
+ // Set cursor after image insertion
155
+ queueMicrotask(function () {
156
+ Transforms.select(editor, targetPath);
157
+ });
158
+ };
159
+ export var isSingleImage = function isSingleImage(data) {
160
+ if (data.length !== 1) return false;
161
+ if (Node.string(data[0]).length !== 0) return false;
162
+ if (data[0].children.filter(function (item) {
163
+ return (item === null || item === void 0 ? void 0 : item.type) === IMAGE;
164
+ }).length !== 1) return false;
165
+ return true;
148
166
  };
@@ -49,24 +49,6 @@
49
49
  background: #f1f1f1;
50
50
  }
51
51
 
52
- .sdoc-image-hover-menu-container .hover-menu-container .op-tooltip:hover::after {
53
- position: absolute;
54
- color: #212529;
55
- content: attr(op-item-tooltip);
56
- top: -40px;
57
- left: -20px;
58
- width: 100px;
59
- height: 30px;
60
- display: flex;
61
- justify-content: center;
62
- align-items: center;
63
- background-color: #fff;
64
- border-radius: 3px;
65
- border: 1px solid #e8e8e8;
66
- font-size: 12px;
67
- box-shadow: 0 0 5px #ccc;
68
- }
69
-
70
52
  .sdoc-image-hover-menu-container .hover-menu-container .icon-font {
71
53
  font-size: 12px;
72
54
  color: #999999;
@@ -1,11 +1,12 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3
- import React, { useCallback, useState } from 'react';
3
+ import React, { useCallback, useEffect, useState } from 'react';
4
4
  import { Transforms } from '@seafile/slate';
5
5
  import { ReactEditor } from '@seafile/slate-react';
6
6
  import { withTranslation } from 'react-i18next';
7
7
  import classnames from 'classnames';
8
8
  import { ElementPopover } from '../../../commons';
9
+ import Tooltip from '../../../commons/tooltip';
9
10
  import ImagePreviewer from '../dialogs/image-previewer';
10
11
  import { getImageURL } from '../helpers';
11
12
  import { IMAGE_DISPLAY_TYPE, IMAGE_BORDER_TYPE } from '../constants';
@@ -35,6 +36,13 @@ var ImageHoverMenu = function ImageHoverMenu(_ref) {
35
36
  _useState4 = _slicedToArray(_useState3, 2),
36
37
  isShowImagePreview = _useState4[0],
37
38
  setIsShowImagePreview = _useState4[1];
39
+ var _useState5 = useState(false),
40
+ _useState6 = _slicedToArray(_useState5, 2),
41
+ isShowTooltip = _useState6[0],
42
+ setIsShowTooltip = _useState6[1];
43
+ useEffect(function () {
44
+ setIsShowTooltip(true);
45
+ }, []);
38
46
  var onShowProver = useCallback(function (event, showProverKey) {
39
47
  event.stopPropagation();
40
48
  var newPopoverState = popoverState;
@@ -92,9 +100,9 @@ var ImageHoverMenu = function ImageHoverMenu(_ref) {
92
100
  }), /*#__PURE__*/React.createElement("i", {
93
101
  className: "sdocfont sdoc-drop-down icon-font"
94
102
  })), /*#__PURE__*/React.createElement("span", {
103
+ id: "sdoc_image_border",
95
104
  role: "button",
96
- "op-item-tooltip": t('Image_border'),
97
- className: classnames('op-item', 'op-tooltip', 'ml-1', {
105
+ className: classnames('op-item', 'ml-1', {
98
106
  'active': popoverState.borderPopover
99
107
  }),
100
108
  onClick: function onClick(e) {
@@ -104,19 +112,27 @@ var ImageHoverMenu = function ImageHoverMenu(_ref) {
104
112
  className: "sdocfont sdoc-image icon-font mr-1"
105
113
  }), /*#__PURE__*/React.createElement("i", {
106
114
  className: "sdocfont sdoc-drop-down icon-font"
107
- }))), /*#__PURE__*/React.createElement("span", {
115
+ }), isShowTooltip && /*#__PURE__*/React.createElement(Tooltip, {
116
+ target: "sdoc_image_border",
117
+ placement: "top",
118
+ fade: true
119
+ }, t('Image_border')))), /*#__PURE__*/React.createElement("span", {
108
120
  className: "op-group-item"
109
121
  }, /*#__PURE__*/React.createElement("span", {
122
+ id: "sdoc_image_full_screen_mode",
110
123
  role: "button",
111
- "op-item-tooltip": t('Full_screen_mode'),
112
- className: "op-item op-tooltip",
124
+ className: "op-item",
113
125
  onClick: function onClick(e) {
114
126
  e.stopPropagation();
115
127
  setIsShowImagePreview(!isShowImagePreview);
116
128
  }
117
129
  }, /*#__PURE__*/React.createElement("i", {
118
130
  className: "sdocfont sdoc-fullscreen icon-font"
119
- })))), popoverState.displayPopover && /*#__PURE__*/React.createElement("div", {
131
+ }), isShowTooltip && /*#__PURE__*/React.createElement(Tooltip, {
132
+ target: "sdoc_image_full_screen_mode",
133
+ placement: "top",
134
+ fade: true
135
+ }, t('Full_screen_mode'))))), popoverState.displayPopover && /*#__PURE__*/React.createElement("div", {
120
136
  className: "sdoc-image-popover sdoc-dropdown-menu"
121
137
  }, IMAGE_DISPLAY_TYPE.map(function (item) {
122
138
  return /*#__PURE__*/React.createElement("div", {
@@ -1,8 +1,8 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
- import { Transforms, Path, Editor, Element } from '@seafile/slate';
2
+ import { Transforms, Path, Editor, Element, Node } from '@seafile/slate';
3
3
  import toaster from '../../../../components/toast';
4
4
  import context from '../../../../context';
5
- import { insertImage, hasSdocImages, getImageData, queryCopyMoveProgressView } from './helpers';
5
+ import { insertImage, hasSdocImages, getImageData, queryCopyMoveProgressView, resetCursor, isSingleImage } from './helpers';
6
6
  import { focusEditor } from '../../core';
7
7
  import { getErrorMsg } from '../../../../utils';
8
8
  import { getSlateFragmentAttribute } from '../../../utils/document-utils';
@@ -11,7 +11,8 @@ var withImage = function withImage(editor) {
11
11
  var isInline = editor.isInline,
12
12
  isVoid = editor.isVoid,
13
13
  insertData = editor.insertData,
14
- deleteBackward = editor.deleteBackward;
14
+ deleteBackward = editor.deleteBackward,
15
+ insertFragment = editor.insertFragment;
15
16
  var newEditor = editor;
16
17
 
17
18
  // rewrite isInline
@@ -52,11 +53,18 @@ var withImage = function withImage(editor) {
52
53
  if (data.types && data.types.includes('Files') && data.files[0].type.includes(IMAGE)) {
53
54
  context.uploadLocalImage(data.files[0]).then(function (fileUrl) {
54
55
  insertImage(newEditor, fileUrl, editor.selection, INSERT_POSITION.CURRENT);
56
+ resetCursor(newEditor);
55
57
  });
56
58
  return;
57
59
  }
58
60
  insertData(data);
59
61
  };
62
+ newEditor.insertFragment = function (data) {
63
+ if (isSingleImage(data)) {
64
+ resetCursor(newEditor);
65
+ }
66
+ return insertFragment(data);
67
+ };
60
68
  newEditor.imageOnKeyDown = function (e) {
61
69
  if (e.keyCode === 13) {
62
70
  var selection = newEditor.selection;
@@ -40,8 +40,8 @@ var Image = function Image(_ref) {
40
40
  var scrollRef = useScrollContext();
41
41
  var _useState = useState(null),
42
42
  _useState2 = _slicedToArray(_useState, 2),
43
- width = _useState2[0],
44
- setWidth = _useState2[1];
43
+ movingWidth = _useState2[0],
44
+ setMovingWidth = _useState2[1];
45
45
  var _useState3 = useState(false),
46
46
  _useState4 = _slicedToArray(_useState3, 2),
47
47
  isResizing = _useState4[0],
@@ -75,7 +75,8 @@ var Image = function Image(_ref) {
75
75
  var changeX = event.clientX - ((_resizerRef$current = resizerRef.current) === null || _resizerRef$current === void 0 ? void 0 : _resizerRef$current.getBoundingClientRect().left) - 5;
76
76
  var imageWidth = imageRef.current.width + changeX;
77
77
  if (imageWidth < 20) return;
78
- setWidth(imageWidth);
78
+ imageRef.current.width = imageWidth;
79
+ setMovingWidth(imageWidth);
79
80
  }, []);
80
81
  var onResizeEnd = useCallback(function (event) {
81
82
  event.preventDefault();
@@ -88,12 +89,12 @@ var Image = function Image(_ref) {
88
89
  'event': onResizeEnd
89
90
  }]);
90
91
  var newData = _objectSpread(_objectSpread({}, element.data), {}, {
91
- width: width
92
+ width: imageRef.current.width
92
93
  });
93
94
  updateImage(editor, newData);
94
95
  setIsResizing(false);
95
96
  // eslint-disable-next-line react-hooks/exhaustive-deps
96
- }, [editor, element.data, width]);
97
+ }, [editor, element.data]);
97
98
  var onResizeStart = useCallback(function (event) {
98
99
  event.preventDefault();
99
100
  event.stopPropagation();
@@ -108,18 +109,19 @@ var Image = function Image(_ref) {
108
109
  }, [onMouseMove, onResizeEnd, registerEvent]);
109
110
  var getImageStyle = useCallback(function () {
110
111
  var imageWidth = element.data.width || '';
111
- if (width) imageWidth = width;
112
+ if (movingWidth) imageWidth = movingWidth;
112
113
  return {
113
114
  width: imageWidth
114
115
  };
115
- }, [element.data, width]);
116
+ }, [element.data, movingWidth]);
116
117
  var onScroll = useCallback(function () {
117
118
  setPosition(imageRef.current);
118
119
  // eslint-disable-next-line react-hooks/exhaustive-deps
119
120
  }, []);
120
121
  var onHideImageHoverMenu = useCallback(function (e) {
122
+ var _imagePreviewer$;
121
123
  var imagePreviewer = document.getElementsByClassName('sf-editor-image-previewer');
122
- if (e.target === imageRef.current || imagePreviewer[0].contains(e.target)) return;
124
+ if (e.target === imageRef.current || ((_imagePreviewer$ = imagePreviewer[0]) === null || _imagePreviewer$ === void 0 ? void 0 : _imagePreviewer$.contains(e.target))) return;
123
125
  setIsShowImageHoverMenu(false);
124
126
  }, []);
125
127
  useEffect(function () {
@@ -154,9 +156,9 @@ var Image = function Image(_ref) {
154
156
  var _elem$getBoundingClie = elem.getBoundingClientRect(),
155
157
  top = _elem$getBoundingClie.top,
156
158
  left = _elem$getBoundingClie.left,
157
- _width = _elem$getBoundingClie.width;
159
+ width = _elem$getBoundingClie.width;
158
160
  var menuTop = top - 42;
159
- var menuLeft = left - 222 / 2 + _width / 2; // left = left distance - (menu width / 2) + (image with / 2)
161
+ var menuLeft = left - 222 / 2 + width / 2; // left = left distance - (menu width / 2) + (image with / 2)
160
162
  setMenuPosition({
161
163
  top: menuTop,
162
164
  left: menuLeft
@@ -215,7 +217,7 @@ var Image = function Image(_ref) {
215
217
  }), isResizing && /*#__PURE__*/React.createElement("span", {
216
218
  className: "image-size",
217
219
  contentEditable: false
218
- }, /*#__PURE__*/React.createElement("span", null, t('Width'), ':', parseInt(width || imageRef.current.clientWidth)), /*#__PURE__*/React.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/React.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), children), isShowImageHoverMenu && !readOnly && /*#__PURE__*/React.createElement(ImageHoverMenu, {
220
+ }, /*#__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))), children), isShowImageHoverMenu && !readOnly && /*#__PURE__*/React.createElement(ImageHoverMenu, {
219
221
  editor: editor,
220
222
  menuPosition: menuPosition,
221
223
  element: element,
@@ -31,6 +31,11 @@ export default function ArticleContainer(_ref) {
31
31
  setContainerStyle({});
32
32
  }
33
33
  }, [scrollRef]);
34
+ var handelArticleClick = useCallback(function (event) {
35
+ if (!articleRef.current.contains(event.target)) return;
36
+ var eventBus = EventBus.getInstance();
37
+ eventBus.dispatch(INTERNAL_EVENT.ARTICLE_CLICK, event);
38
+ }, []);
34
39
  useEffect(function () {
35
40
  var eventBus = EventBus.getInstance();
36
41
  var unsubscribeOutline = eventBus.subscribe(INTERNAL_EVENT.OUTLINE_STATE_CHANGED, handleWindowResize);
@@ -49,9 +54,11 @@ export default function ArticleContainer(_ref) {
49
54
  style: containerStyle
50
55
  }, React.Children.count(children) === 1 && /*#__PURE__*/React.createElement("div", {
51
56
  className: "article",
52
- ref: articleRef
57
+ ref: articleRef,
58
+ onClick: handelArticleClick
53
59
  }, children), React.Children.count(children) > 1 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
54
60
  className: "article",
55
- ref: articleRef
61
+ ref: articleRef,
62
+ onClick: handelArticleClick
56
63
  }, children[0]), _toConsumableArray(children.slice(1))));
57
64
  }
@@ -199,7 +199,8 @@ var RevisionOperations = function RevisionOperations(_ref) {
199
199
  }), isShowTip && /*#__PURE__*/React.createElement(TipDialog, {
200
200
  tipType: tipType,
201
201
  onSubmit: onSubmit,
202
- onClose: onClose
202
+ onClose: onClose,
203
+ zIndex: 1072
203
204
  }));
204
205
  };
205
206
  export default RevisionOperations;
@@ -60,6 +60,10 @@
60
60
  border-bottom: 1px solid rgba(0, 40, 100, 0.12);
61
61
  }
62
62
 
63
+ .revisions-dialog .revisions-body .sdoc-revision.operating {
64
+ background-color: #f5f5f5;
65
+ }
66
+
63
67
  .revisions-dialog .revisions-body .sdoc-revision:hover {
64
68
  cursor: pointer;
65
69
  background-color: #f5f5f5;
@@ -112,3 +116,11 @@
112
116
  .revisions-dialog .sdoc-revision.loading:hover {
113
117
  background-color: unset;
114
118
  }
119
+
120
+ .revisions-dialog .sdoc-revision-operations {
121
+ height: 100%;
122
+ width: 100%;
123
+ display: flex;
124
+ align-items: center;
125
+ justify-content: center;
126
+ }
@@ -3,12 +3,17 @@ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3
3
  import React, { useState, useEffect, useCallback, useRef } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { Modal, ModalHeader, ModalBody } from 'reactstrap';
6
+ import classnames from 'classnames';
6
7
  import CommonLoading from '../../../../common-loading';
7
8
  import context from '../../../../../context';
8
9
  import { Revision } from '../../../../../model';
9
10
  import { getErrorMsg } from '../../../../../utils';
10
11
  import toaster from '../../../../toast';
12
+ import RevisionOperation from './revision-operation';
13
+ import { eventStopPropagation } from '../../../../../basic-sdk/utils/mouse-event';
14
+ import TipDialog from '../../../../tip-dialog';
11
15
  import './index.css';
16
+ import { TIP_CONTENT, TIP_TYPE } from '../../../../../constants';
12
17
  var RevisionsDialog = function RevisionsDialog(_ref) {
13
18
  var _revisionListRef$curr;
14
19
  var updateRevisionsCount = _ref.updateRevisionsCount,
@@ -39,6 +44,18 @@ var RevisionsDialog = function RevisionsDialog(_ref) {
39
44
  var perPage = 25;
40
45
  var repoID = context.getSetting('repoID');
41
46
  var siteRoot = context.getSetting('siteRoot');
47
+ var _useState11 = useState(''),
48
+ _useState12 = _slicedToArray(_useState11, 2),
49
+ activeRevisionId = _useState12[0],
50
+ setActiveRevision = _useState12[1];
51
+ var _useState13 = useState(''),
52
+ _useState14 = _slicedToArray(_useState13, 2),
53
+ operatingRevisionId = _useState14[0],
54
+ setOperatingRevision = _useState14[1];
55
+ var _useState15 = useState(false),
56
+ _useState16 = _slicedToArray(_useState15, 2),
57
+ showDeleteTipDialog = _useState16[0],
58
+ setShowDeleteTipDialog = _useState16[1];
42
59
 
43
60
  // did mount
44
61
  useEffect(function () {
@@ -72,7 +89,9 @@ var RevisionsDialog = function RevisionsDialog(_ref) {
72
89
 
73
90
  // eslint-disable-next-line react-hooks/exhaustive-deps
74
91
  }, [revisions, page, perPage]);
75
- var openRevision = useCallback(function (revisionId) {
92
+ var openRevision = useCallback(function (event, revisionId) {
93
+ eventStopPropagation(event);
94
+ if (event.target.className.includes('sdoc-revision-operation-toggle')) return;
76
95
  window.location.href = "".concat(siteRoot, "lib/").concat(repoID, "/revisions/").concat(revisionId, "/");
77
96
 
78
97
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -94,6 +113,34 @@ var RevisionsDialog = function RevisionsDialog(_ref) {
94
113
 
95
114
  // eslint-disable-next-line react-hooks/exhaustive-deps
96
115
  }, [(_revisionListRef$curr = revisionListRef.current) === null || _revisionListRef$curr === void 0 ? void 0 : _revisionListRef$curr.clientHeight, isLoading, hasMore]);
116
+ var onDeleteOtherRevision = useCallback(function () {
117
+ setShowDeleteTipDialog(true);
118
+ }, []);
119
+ var closeDeleteTipDialog = useCallback(function () {
120
+ setOperatingRevision('');
121
+ setShowDeleteTipDialog(false);
122
+ }, []);
123
+ var deleteOtherRevision = useCallback(function () {
124
+ var revisionIndex = revisions.findIndex(function (revision) {
125
+ return revision.id === operatingRevisionId;
126
+ });
127
+ if (revisionIndex === -1) {
128
+ closeDeleteTipDialog();
129
+ return;
130
+ }
131
+ var revision = revisions[revisionIndex];
132
+ context.deleteSdocOtherRevision(revision.docUuid).then(function (res) {
133
+ var newRevisions = revisions.slice(0);
134
+ newRevisions.splice(revisionIndex, 1);
135
+ updateRevisionsCount(newRevisions.length);
136
+ setRevisions(newRevisions);
137
+ closeDeleteTipDialog();
138
+ }).catch(function (error) {
139
+ toaster.danger(t('Delete_failed'));
140
+ });
141
+
142
+ // eslint-disable-next-line react-hooks/exhaustive-deps
143
+ }, [operatingRevisionId, revisions, closeDeleteTipDialog]);
97
144
  var renderContent = useCallback(function () {
98
145
  if (page === 1 && isLoading) {
99
146
  return /*#__PURE__*/React.createElement("div", {
@@ -117,25 +164,41 @@ var RevisionsDialog = function RevisionsDialog(_ref) {
117
164
  }, t('ID')), /*#__PURE__*/React.createElement("div", {
118
165
  className: "sdoc-revision-user-header",
119
166
  style: {
120
- width: '30%'
167
+ width: '25%'
121
168
  }
122
169
  }, t('Creator')), /*#__PURE__*/React.createElement("div", {
123
170
  className: "sdoc-revision-time-header",
124
171
  style: {
125
172
  width: '30%'
126
173
  }
127
- }, t('Created_time'))), /*#__PURE__*/React.createElement("div", {
174
+ }, t('Created_time')), /*#__PURE__*/React.createElement("div", {
175
+ className: "sdoc-revision-time-header",
176
+ style: {
177
+ width: '5%'
178
+ }
179
+ })), /*#__PURE__*/React.createElement("div", {
128
180
  className: "sdoc-revisions-content",
129
181
  onScroll: onScroll
130
182
  }, /*#__PURE__*/React.createElement("div", {
131
183
  className: "sdoc-revisions-list",
132
184
  ref: revisionListRef
133
185
  }, revisions.map(function (revision) {
186
+ var revisionId = revision.id;
187
+ var isOperating = operatingRevisionId === revisionId;
188
+ var isActive = activeRevisionId === revisionId;
134
189
  return /*#__PURE__*/React.createElement("div", {
135
- className: "sdoc-revision",
136
190
  key: revision.id,
137
- onClick: function onClick() {
138
- return openRevision(revision.id);
191
+ className: classnames('sdoc-revision', {
192
+ 'operating': isOperating
193
+ }),
194
+ onClick: function onClick(event) {
195
+ return openRevision(event, revisionId);
196
+ },
197
+ onMouseEnter: function onMouseEnter() {
198
+ return setActiveRevision(revisionId);
199
+ },
200
+ onMouseLeave: function onMouseLeave() {
201
+ return setActiveRevision('');
139
202
  }
140
203
  }, /*#__PURE__*/React.createElement("div", {
141
204
  className: "sdoc-revision-name",
@@ -144,24 +207,35 @@ var RevisionsDialog = function RevisionsDialog(_ref) {
144
207
  }
145
208
  }, /*#__PURE__*/React.createElement("div", {
146
209
  className: "sdoc-revision-name-content"
147
- }, t('Revision') + ' ' + revision.id)), /*#__PURE__*/React.createElement("div", {
210
+ }, t('Revision') + ' ' + revisionId)), /*#__PURE__*/React.createElement("div", {
148
211
  className: "sdoc-revision-user",
149
212
  style: {
150
- width: '30%'
213
+ width: '25%'
151
214
  }
152
215
  }, revision.nickname), /*#__PURE__*/React.createElement("div", {
153
216
  className: "sdoc-revision-time",
154
217
  style: {
155
218
  width: '30%'
156
219
  }
157
- }, revision.createdTime));
220
+ }, revision.createdTime), /*#__PURE__*/React.createElement("div", {
221
+ className: "sdoc-revision-operations",
222
+ style: {
223
+ width: '5%'
224
+ }
225
+ }, /*#__PURE__*/React.createElement(RevisionOperation, {
226
+ isActive: isActive,
227
+ isOperating: isOperating,
228
+ revision: revision,
229
+ updateOperatingRevision: setOperatingRevision,
230
+ onDeleteOtherRevision: onDeleteOtherRevision
231
+ })));
158
232
  }), isLoading && /*#__PURE__*/React.createElement("div", {
159
233
  className: "sdoc-revision loading"
160
234
  }, /*#__PURE__*/React.createElement(CommonLoading, null)))));
161
235
 
162
236
  // eslint-disable-next-line react-hooks/exhaustive-deps
163
- }, [page, revisions, isLoading, errorMessage]);
164
- return /*#__PURE__*/React.createElement(Modal, {
237
+ }, [page, revisions, isLoading, errorMessage, activeRevisionId, operatingRevisionId]);
238
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Modal, {
165
239
  isOpen: true,
166
240
  toggle: toggle,
167
241
  className: "revisions-dialog"
@@ -169,6 +243,13 @@ var RevisionsDialog = function RevisionsDialog(_ref) {
169
243
  toggle: toggle
170
244
  }, t('Revision')), /*#__PURE__*/React.createElement(ModalBody, {
171
245
  className: "revisions-body"
172
- }, renderContent()));
246
+ }, renderContent())), showDeleteTipDialog && /*#__PURE__*/React.createElement(TipDialog, {
247
+ tipType: TIP_TYPE.DELETE_REVISION,
248
+ onSubmit: deleteOtherRevision,
249
+ onClose: closeDeleteTipDialog,
250
+ zIndex: 1071
251
+ }, t(TIP_CONTENT[TIP_TYPE.DELETE_REVISION], {
252
+ content: "".concat(t('Revision'), " ").concat(operatingRevisionId)
253
+ })));
173
254
  };
174
255
  export default RevisionsDialog;
@@ -0,0 +1,20 @@
1
+ .sdoc-revision-operation-toggle {
2
+ display: none;
3
+ font-size: 16px;
4
+ color: #999;
5
+ }
6
+
7
+ .revisions-body .sdoc-revision:hover .sdoc-revision-operation-toggle,
8
+ .revisions-dialog .revisions-body .sdoc-revision.operating .sdoc-revision-operation-toggle {
9
+ display: inline-block;
10
+ }
11
+
12
+ .sdoc-revision-operation-toggle:hover {
13
+ cursor: pointer;
14
+ color: #333;
15
+ }
16
+
17
+ .sdoc-revision-menu-popover .popover {
18
+ margin-top: 0;
19
+ }
20
+
@@ -0,0 +1,57 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import React, { useCallback, useRef, useState } from 'react';
3
+ import { UncontrolledPopover } from 'reactstrap';
4
+ import DropdownMenuItem from '../../../../../../basic-sdk/extension/commons/dropdown-menu-item';
5
+ import { eventStopPropagation } from '../../../../../../basic-sdk/utils/mouse-event';
6
+ import './index.css';
7
+ var RevisionOperation = function RevisionOperation(_ref) {
8
+ var isActive = _ref.isActive,
9
+ isOperating = _ref.isOperating,
10
+ revision = _ref.revision,
11
+ updateOperatingRevision = _ref.updateOperatingRevision,
12
+ onDeleteOtherRevision = _ref.onDeleteOtherRevision;
13
+ var targetId = "sdoc-revision-".concat(revision.id);
14
+ var popoverRef = useRef(null);
15
+ var _useState = useState(false),
16
+ _useState2 = _slicedToArray(_useState, 2),
17
+ isPopoverShow = _useState2[0],
18
+ setPopoverShow = _useState2[1];
19
+ var toggle = useCallback(function () {
20
+ popoverRef.current.toggle();
21
+ var nextPopoverShow = !isPopoverShow;
22
+ setPopoverShow(nextPopoverShow);
23
+ updateOperatingRevision(nextPopoverShow ? revision.id : '');
24
+ }, [isPopoverShow, updateOperatingRevision, revision]);
25
+ var deleteRevision = useCallback(function (event) {
26
+ eventStopPropagation(event);
27
+ onDeleteOtherRevision();
28
+ }, [onDeleteOtherRevision]);
29
+ if (!isActive && !isOperating) return null;
30
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("i", {
31
+ className: "sdocfont sdoc-more sdoc-revision-operation-toggle",
32
+ id: targetId
33
+ }), /*#__PURE__*/React.createElement(UncontrolledPopover, {
34
+ target: targetId,
35
+ className: "sdoc-menu-popover sdoc-dropdown-menu sdoc-revision-menu-popover",
36
+ trigger: "legacy",
37
+ placement: "bottom-start",
38
+ hideArrow: true,
39
+ toggle: toggle,
40
+ fade: false,
41
+ modifiers: {
42
+ preventOverflow: {
43
+ boundariesElement: document.body
44
+ }
45
+ },
46
+ ref: popoverRef
47
+ }, /*#__PURE__*/React.createElement("div", {
48
+ className: "sdoc-dropdown-menu-container"
49
+ }, /*#__PURE__*/React.createElement(DropdownMenuItem, {
50
+ onClick: deleteRevision,
51
+ menuConfig: {
52
+ iconClass: 'sdocfont sdoc-delete',
53
+ text: 'Delete'
54
+ }
55
+ }))));
56
+ };
57
+ export default RevisionOperation;
@@ -12,7 +12,10 @@ var TipDialog = function TipDialog(_ref) {
12
12
  var className = _ref.className,
13
13
  tipType = _ref.tipType,
14
14
  onClose = _ref.onClose,
15
- propsOnSubmit = _ref.onSubmit;
15
+ propsOnSubmit = _ref.onSubmit,
16
+ _ref$zIndex = _ref.zIndex,
17
+ zIndex = _ref$zIndex === void 0 ? 1071 : _ref$zIndex,
18
+ children = _ref.children;
16
19
  var _useTranslation = useTranslation(),
17
20
  t = _useTranslation.t;
18
21
  var _useState = useState(),
@@ -46,7 +49,7 @@ var TipDialog = function TipDialog(_ref) {
46
49
  return /*#__PURE__*/React.createElement(Modal, {
47
50
  isOpen: true,
48
51
  autoFocus: false,
49
- zIndex: 1071,
52
+ zIndex: zIndex,
50
53
  returnFocusAfterClose: false,
51
54
  toggle: closeDialog,
52
55
  className: classnames('sdoc-tip-dialog', className),
@@ -55,7 +58,7 @@ var TipDialog = function TipDialog(_ref) {
55
58
  toggle: NOT_CLOSE_DIALOG_TIP_TYPE.includes(tipType) ? undefined : closeDialog
56
59
  }, t(TIP_TITLE[tipType])), /*#__PURE__*/React.createElement(ModalBody, {
57
60
  className: "sdoc-tip-body"
58
- }, /*#__PURE__*/React.createElement(TipContent, {
61
+ }, children ? children : /*#__PURE__*/React.createElement(TipContent, {
59
62
  tipType: tipType
60
63
  })), !NOT_CLOSE_DIALOG_TIP_TYPE.includes(tipType) && /*#__PURE__*/React.createElement(ModalFooter, null, /*#__PURE__*/React.createElement(Button, {
61
64
  color: "secondary",
@@ -23,7 +23,8 @@ export var TIP_TYPE = {
23
23
  HAS_CONFLICT_BEFORE_VIEW_CHANGES: 'has_conflict_before_view_changes',
24
24
  HAS_BEEN_REMOVED: 'has_been_removed',
25
25
  CHECKING: 'checking',
26
- PUBLISHING: 'publishing'
26
+ PUBLISHING: 'publishing',
27
+ DELETE_REVISION: 'delete_revision'
27
28
  };
28
- export var TIP_TITLE = (_TIP_TITLE = {}, _defineProperty(_TIP_TITLE, TIP_TYPE.DELETE_NO_CHANGES_REVISION, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.MERGE, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_CONFLICT_BEFORE_PUBLISH, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_BEEN_PUBLISHED, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_BEEN_REPLACED, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_CONFLICT_BEFORE_VIEW_CHANGES, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_BEEN_REMOVED, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.CHECKING, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.PUBLISHING, 'Tip'), _TIP_TITLE);
29
- export var TIP_CONTENT = (_TIP_CONTENT = {}, _defineProperty(_TIP_CONTENT, TIP_TYPE.DELETE_NO_CHANGES_REVISION, 'Rebase_delete_no_change_revision_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.MERGE, 'Merge_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_CONFLICT_BEFORE_PUBLISH, 'Has_conflict_before_publish_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_BEEN_PUBLISHED, 'Has_been_published_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_BEEN_REPLACED, 'Has_been_replaced_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_CONFLICT_BEFORE_VIEW_CHANGES, 'Has_conflict_before_view_changes_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_BEEN_REMOVED, 'Has_been_removed_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.CHECKING, 'Checking'), _defineProperty(_TIP_CONTENT, TIP_TYPE.PUBLISHING, 'Publishing'), _TIP_CONTENT);
29
+ export var TIP_TITLE = (_TIP_TITLE = {}, _defineProperty(_TIP_TITLE, TIP_TYPE.DELETE_NO_CHANGES_REVISION, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.MERGE, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_CONFLICT_BEFORE_PUBLISH, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_BEEN_PUBLISHED, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_BEEN_REPLACED, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_CONFLICT_BEFORE_VIEW_CHANGES, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.HAS_BEEN_REMOVED, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.CHECKING, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.PUBLISHING, 'Tip'), _defineProperty(_TIP_TITLE, TIP_TYPE.DELETE_REVISION, 'Delete_revision'), _TIP_TITLE);
30
+ export var TIP_CONTENT = (_TIP_CONTENT = {}, _defineProperty(_TIP_CONTENT, TIP_TYPE.DELETE_NO_CHANGES_REVISION, 'Rebase_delete_no_change_revision_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.MERGE, 'Merge_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_CONFLICT_BEFORE_PUBLISH, 'Has_conflict_before_publish_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_BEEN_PUBLISHED, 'Has_been_published_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_BEEN_REPLACED, 'Has_been_replaced_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_CONFLICT_BEFORE_VIEW_CHANGES, 'Has_conflict_before_view_changes_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.HAS_BEEN_REMOVED, 'Has_been_removed_tip'), _defineProperty(_TIP_CONTENT, TIP_TYPE.CHECKING, 'Checking'), _defineProperty(_TIP_CONTENT, TIP_TYPE.PUBLISHING, 'Publishing'), _defineProperty(_TIP_CONTENT, TIP_TYPE.DELETE_REVISION, 'Delete_tip'), _TIP_CONTENT);
package/dist/context.js CHANGED
@@ -204,6 +204,12 @@ var Context = /*#__PURE__*/function () {
204
204
  var docUuid = this.getSetting('docUuid');
205
205
  return this.api.deleteSdocRevision(docUuid);
206
206
  }
207
+ }, {
208
+ key: "deleteSdocOtherRevision",
209
+ value: function deleteSdocOtherRevision(revisionId) {
210
+ var docUuid = this.getSetting('docUuid');
211
+ return this.api.deleteSdocOtherRevision(docUuid, revisionId);
212
+ }
207
213
  }, {
208
214
  key: "getRevisionBaseVersionContent",
209
215
  value: function getRevisionBaseVersionContent() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.2.3",
3
+ "version": "0.2.5beta",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -382,5 +382,7 @@
382
382
  "Inline": "Inline",
383
383
  "Block": "Block",
384
384
  "Full_screen_mode": "Full screen mode",
385
- "Image_border": "Image border"
385
+ "Image_border": "Image border",
386
+ "Delete_revision": "Delete revision",
387
+ "Delete_tip": "Are you sure you want to delete {{content}}?"
386
388
  }
@@ -382,5 +382,7 @@
382
382
  "Inline": "嵌入行内",
383
383
  "Block": "独占一行",
384
384
  "Full_screen_mode": "全屏查看",
385
- "Image_border": "图片边框"
385
+ "Image_border": "图片边框",
386
+ "Delete_revision": "删除修订稿",
387
+ "Delete_tip": "确定要删除 {{content}}?"
386
388
  }