diff --git a/frontend/config/webpack.entry.js b/frontend/config/webpack.entry.js
index 575b9281da..7e46e2ce6a 100644
--- a/frontend/config/webpack.entry.js
+++ b/frontend/config/webpack.entry.js
@@ -9,6 +9,7 @@ const entryFiles = {
fileHistory: "/file-history.js",
fileHistoryOld: "/file-history-old.js",
sdocFileHistory: "/pages/sdoc-file-history/index.js",
+ sdocRevision: "/pages/sdoc-revision/index.js",
app: "/app.js",
draft: "/draft.js",
sharedDirView: "/shared-dir-view.js",
diff --git a/frontend/src/css/sdoc-revision.css b/frontend/src/css/sdoc-revision.css
new file mode 100644
index 0000000000..ac46fffb7d
--- /dev/null
+++ b/frontend/src/css/sdoc-revision.css
@@ -0,0 +1,51 @@
+.sdoc-revision .sdoc-revision-container {
+ flex: 1;
+ overflow-x: hidden;
+}
+
+.sdoc-revision .sdoc-revision-header {
+ height: 50px;
+ border-bottom: 1px solid #e5e5e5;
+ background-color: #fff;
+}
+
+.sdoc-revision .sdoc-revision-header .sdoc-revision-header-left {
+ font-size: 1.25rem;
+ flex: 1;
+}
+
+.sdoc-revision .sdoc-revision-header .file-name {
+ flex: 1;
+}
+
+.sdoc-revision .sdoc-revision-header .sdoc-revision-header-right {
+ height: 100%;
+ min-width: 100px;
+}
+
+.sdoc-revision .sdoc-revision-content {
+ flex: 1;
+ min-height: 0;
+ padding: 20px 40px;
+ background-color: #F5F5F5;
+ overflow-y: scroll;
+}
+
+.sdoc-revision .sdoc-revision-content .sdoc-revision-viewer {
+ width: 100%;
+ min-height: 120px;
+ flex: 1;
+ background-color: #fff;
+ word-break: break-word;
+ border: 1px solid #e6e6dd;
+}
+
+.sdoc-revision .sdoc-revision-content .sdoc-editor-content {
+ background-color: #fff;
+}
+
+.sdoc-revision .sdoc-revision-content .article {
+ width: 100%;
+ margin: 0;
+}
+
diff --git a/frontend/src/pages/sdoc-revision/index.js b/frontend/src/pages/sdoc-revision/index.js
new file mode 100644
index 0000000000..0b6f3fc28a
--- /dev/null
+++ b/frontend/src/pages/sdoc-revision/index.js
@@ -0,0 +1,124 @@
+import React from 'react';
+import ReactDom from 'react-dom';
+import classnames from 'classnames';
+import { Button } from 'reactstrap';
+import { DiffViewer } from '@seafile/sdoc-editor';
+import { gettext } from '../../utils/constants';
+import Loading from '../../components/loading';
+import GoBack from '../../components/common/go-back';
+import { Utils } from '../../utils/utils';
+import { seafileAPI } from '../../utils/seafile-api';
+
+import '../../css/layout.css';
+import '../../css/sdoc-revision.css';
+
+const { serviceURL, avatarURL, siteRoot } = window.app.config;
+const { username, name } = window.app.pageOptions;
+const { repoID, fileName, filePath, docUuid, assetsUrl, fileDownloadLink, originFileDownloadLink, isPublished } = window.sdocRevision;
+
+window.seafile = {
+ repoID,
+ docPath: filePath,
+ docName: fileName,
+ docUuid,
+ isOpenSocket: false,
+ serviceUrl: serviceURL,
+ name,
+ username,
+ avatarURL,
+ siteRoot,
+ assetsUrl,
+};
+
+class SdocRevision extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isLoading: true,
+ errorMessage: '',
+ revisionContent: '',
+ originContent: '',
+ };
+ }
+
+ componentDidMount() {
+ fetch(fileDownloadLink).then(res => {
+ return res.json();
+ }).then(revisionContent => {
+ fetch(originFileDownloadLink).then(res => {
+ return res.json();
+ }).then(originContent => {
+ this.setState({ revisionContent, originContent, isLoading: false, errorMessage: '' });
+ }).catch(error => {
+ const errorMessage = Utils.getErrorMsg(error, true);
+ this.setState({ isLoading: false, errorMessage });
+ });
+ }).catch(error => {
+ const errorMessage = Utils.getErrorMsg(error, true);
+ this.setState({ isLoading: false, errorMessage });
+ });
+ }
+
+ publishRevision = (event) => {
+ event.stopPropagation();
+ event.nativeEvent.stopImmediatePropagation();
+ seafileAPI.sdocPublishRevision(docUuid).then(res => {
+ console.log(res)
+ }).catch(error => {
+ console.log(error);
+ });
+ }
+
+ renderContent = () => {
+ const { isLoading, errorMessage, revisionContent, originContent } = this.state;
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ if (errorMessage) {
+ return (
+
+ {gettext(errorMessage)}
+
+ );
+ }
+
+ return (
+
+ );
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ {!isPublished && (
+
+ )}
+
+
+
+ {this.renderContent()}
+
+
+
+ );
+ }
+}
+
+ReactDom.render(, document.getElementById('wrapper'));
diff --git a/frontend/src/utils/utils.js b/frontend/src/utils/utils.js
index f63d6c440e..d680eee91d 100644
--- a/frontend/src/utils/utils.js
+++ b/frontend/src/utils/utils.js
@@ -1543,6 +1543,11 @@ export const Utils = {
generateHistoryURL: function(siteRoot, repoID, path) {
if (!siteRoot || !repoID || !path) return '';
return siteRoot + 'repo/file_revisions/' + repoID + '/?p=' + this.encodePath(path);
+ },
+
+ generateRevisionURL: function(siteRoot, repoID, path) {
+ if (!siteRoot || !repoID || !path) return '';
+ return siteRoot + 'repo/sdoc_revision/' + repoID + '/?p=' + this.encodePath(path);
}
};
diff --git a/frontend/src/view-file-sdoc.js b/frontend/src/view-file-sdoc.js
index 48bf8bd91a..f81c3a88ea 100644
--- a/frontend/src/view-file-sdoc.js
+++ b/frontend/src/view-file-sdoc.js
@@ -10,7 +10,7 @@ const { serviceURL, avatarURL, siteRoot } = window.app.config;
const { username, name } = window.app.userInfo;
const {
repoID, repoName, parentDir, filePerm,
- docPath, docName, docUuid, seadocAccessToken, seadocServerUrl, assetsUrl
+ docPath, docName, docUuid, seadocAccessToken, seadocServerUrl, assetsUrl,
} = window.app.pageOptions;
window.seafile = {
@@ -31,7 +31,8 @@ window.seafile = {
parentFolderURL: `${siteRoot}library/${repoID}/${Utils.encodePath(repoName + parentDir)}`,
assetsUrl,
isShowInternalLink: true,
- isStarIconShown: true // for star/unstar
+ isStarIconShown: true, // for star/unstar
+ revisionURL: Utils.generateRevisionURL(siteRoot, repoID, docPath),
};
ReactDom.render(
diff --git a/seahub/seadoc/urls.py b/seahub/seadoc/urls.py
index e9727e9276..e881488e60 100644
--- a/seahub/seadoc/urls.py
+++ b/seahub/seadoc/urls.py
@@ -3,6 +3,8 @@ from .apis import SeadocAccessToken, SeadocUploadLink, SeadocDownloadLink, Seado
SeadocUploadImage, SeadocDownloadImage, SeadocCopyHistoryFile, SeadocHistory, SeadocDrafts, SeadocMaskAsDraft, \
SeadocCommentsView, SeadocCommentView, SeadocRevisions, SeadocPublishRevision
+from .views import sdoc_revision
+
urlpatterns = [
re_path(r'^access-token/(?P[-0-9a-f]{36})/$', SeadocAccessToken.as_view(), name='seadoc_access_token'),
re_path(r'^upload-file/(?P[-0-9a-f]{36})/$', SeadocUploadFile.as_view(), name='seadoc_upload_file'),
diff --git a/seahub/seadoc/views.py b/seahub/seadoc/views.py
new file mode 100644
index 0000000000..8b4530dda2
--- /dev/null
+++ b/seahub/seadoc/views.py
@@ -0,0 +1,65 @@
+import os
+from django.shortcuts import render
+from django.utils.translation import gettext as _
+from seaserv import get_repo
+from seahub.auth.decorators import login_required
+from seahub.utils import render_error
+from seahub.views import check_folder_permission, validate_owner, get_seadoc_file_uuid
+from seahub.tags.models import FileUUIDMap
+
+from .utils import is_seadoc_revision, get_seadoc_download_link
+
+
+@login_required
+def sdoc_revision(request, repo_id):
+ """List file revisions in file version history page.
+ """
+ repo = get_repo(repo_id)
+ if not repo:
+ error_msg = _("Library does not exist")
+ return render_error(request, error_msg)
+
+ # perm check
+ if not check_folder_permission(request, repo_id, '/'):
+ error_msg = _("Permission denied.")
+ return render_error(request, error_msg)
+
+ path = request.GET.get('p', '/')
+ if not path:
+ return render_error(request)
+
+ if path[-1] == '/':
+ path = path[:-1]
+
+ u_filename = os.path.basename(path)
+
+ # Check whether user is repo owner
+ if validate_owner(request, repo_id):
+ is_owner = True
+ else:
+ is_owner = False
+
+ file_uuid = get_seadoc_file_uuid(repo, path)
+ uuid_map = FileUUIDMap.objects.get_fileuuidmap_by_uuid(file_uuid)
+ return_dict = {
+ 'repo': repo,
+ 'path': path,
+ 'u_filename': u_filename,
+ 'file_uuid': file_uuid,
+ 'is_owner': is_owner,
+ 'can_compare': True,
+ 'assets_url': '/api/v2.1/seadoc/download-image/' + file_uuid,
+ 'file_download_link': get_seadoc_download_link(uuid_map)
+ }
+
+ revision_info = is_seadoc_revision(file_uuid)
+ return_dict.update(revision_info)
+
+ origin_doc_uuid = return_dict.get('origin_doc_uuid', '')
+ is_published = return_dict.get('is_published', False)
+ if (origin_doc_uuid and not is_published):
+ uuid_map = FileUUIDMap.objects.get_fileuuidmap_by_uuid(origin_doc_uuid)
+ return_dict['origin_file_download_link'] = get_seadoc_download_link(uuid_map)
+
+ return render(request, 'sdoc_revision.html', return_dict)
+
diff --git a/seahub/templates/sdoc_revision.html b/seahub/templates/sdoc_revision.html
new file mode 100644
index 0000000000..f11c8d6fc1
--- /dev/null
+++ b/seahub/templates/sdoc_revision.html
@@ -0,0 +1,37 @@
+{% extends "base_for_react.html" %}
+{% load render_bundle from webpack_loader %}
+
+{% block extra_style %}
+{% render_bundle 'sdocRevision' 'css'%}
+{% endblock %}
+
+{% block extra_script %}
+
+ {% render_bundle 'sdocRevision' 'js'%}
+{% endblock %}
diff --git a/seahub/urls.py b/seahub/urls.py
index 61b148e473..e3b61d4412 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -194,6 +194,7 @@ from seahub.api2.endpoints.admin.virus_scan_records import AdminVirusFilesView,
from seahub.api2.endpoints.file_participants import FileParticipantsView, FileParticipantView
from seahub.api2.endpoints.repo_related_users import RepoRelatedUsersView
from seahub.api2.endpoints.repo_auto_delete import RepoAutoDeleteView
+from seahub.seadoc.views import sdoc_revision
from seahub.ocm.settings import OCM_ENDPOINT
@@ -220,6 +221,7 @@ urlpatterns = [
path('repo/upload_check/', validate_filename),
re_path(r'^repo/download_dir/(?P[-0-9a-f]{36})/$', repo_download_dir, name='repo_download_dir'),
re_path(r'^repo/file_revisions/(?P[-0-9a-f]{36})/$', file_revisions, name='file_revisions'),
+ re_path(r'^repo/sdoc_revision/(?P[-0-9a-f]{36})/$', sdoc_revision, name='sdoc_revision'),
re_path(r'^repo/file-access/(?P[-0-9a-f]{36})/$', file_access, name='file_access'),
re_path(r'^repo/text_diff/(?P[-0-9a-f]{36})/$', text_diff, name='text_diff'),
re_path(r'^repo/history/(?P[-0-9a-f]{36})/$', repo_history, name='repo_history'),