diff --git a/frontend/config/webpack.config.dev.js b/frontend/config/webpack.config.dev.js
index 2456afcc2d..d213587064 100644
--- a/frontend/config/webpack.config.dev.js
+++ b/frontend/config/webpack.config.dev.js
@@ -109,6 +109,31 @@ module.exports = {
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appSrc + "/shared-file-view-pdf.js",
],
+ sharedFileViewSVG: [
+ require.resolve('./polyfills'),
+ require.resolve('react-dev-utils/webpackHotDevClient'),
+ paths.appSrc + "/shared-file-view-svg.js",
+ ],
+ sharedFileViewAudio: [
+ require.resolve('./polyfills'),
+ require.resolve('react-dev-utils/webpackHotDevClient'),
+ paths.appSrc + "/shared-file-view-audio.js",
+ ],
+ sharedFileViewDocument: [
+ require.resolve('./polyfills'),
+ require.resolve('react-dev-utils/webpackHotDevClient'),
+ paths.appSrc + "/shared-file-view-document.js",
+ ],
+ sharedFileViewSpreadsheet: [
+ require.resolve('./polyfills'),
+ require.resolve('react-dev-utils/webpackHotDevClient'),
+ paths.appSrc + "/shared-file-view-spreadsheet.js",
+ ],
+ sharedFileViewUnknown: [
+ require.resolve('./polyfills'),
+ require.resolve('react-dev-utils/webpackHotDevClient'),
+ paths.appSrc + "/shared-file-view-unknown.js",
+ ],
viewFileText: [
require.resolve('./polyfills'),
require.resolve('react-dev-utils/webpackHotDevClient'),
diff --git a/frontend/config/webpack.config.prod.js b/frontend/config/webpack.config.prod.js
index 7d8ffcb3a1..160f5f07e9 100644
--- a/frontend/config/webpack.config.prod.js
+++ b/frontend/config/webpack.config.prod.js
@@ -70,6 +70,11 @@ module.exports = {
sharedFileViewImage: [require.resolve('./polyfills'), paths.appSrc + "/shared-file-view-image.js"],
sharedFileViewVideo: [require.resolve('./polyfills'), paths.appSrc + "/shared-file-view-video.js"],
sharedFileViewPDF: [require.resolve('./polyfills'), paths.appSrc + "/shared-file-view-pdf.js"],
+ sharedFileViewSVG: [require.resolve('./polyfills'), paths.appSrc + "/shared-file-view-svg.js"],
+ sharedFileViewAudio: [require.resolve('./polyfills'), paths.appSrc + "/shared-file-view-audio.js"],
+ sharedFileViewDocument: [require.resolve('./polyfills'), paths.appSrc + "/shared-file-view-document.js"],
+ sharedFileViewSpreadsheet: [require.resolve('./polyfills'), paths.appSrc + "/shared-file-view-spreadsheet.js"],
+ sharedFileViewUnknown: [require.resolve('./polyfills'), paths.appSrc + "/shared-file-view-unknown.js"],
viewFileText: [require.resolve('./polyfills'), paths.appSrc + "/view-file-text.js"],
viewFileImage: [require.resolve('./polyfills'), paths.appSrc + "/view-file-image.js"],
viewFileXmind: [require.resolve('./polyfills'), paths.appSrc + "/view-file-xmind.js"],
diff --git a/frontend/src/components/shared-file-view/shared-file-view-tip.js b/frontend/src/components/shared-file-view/shared-file-view-tip.js
index e5d31c998b..90170bf150 100644
--- a/frontend/src/components/shared-file-view/shared-file-view-tip.js
+++ b/frontend/src/components/shared-file-view/shared-file-view-tip.js
@@ -1,7 +1,12 @@
import React from 'react';
+import PropTypes from 'prop-types';
import { gettext } from '../../utils/constants';
-const { err } = window.shared.pageOptions;
+const { err, trafficOverLimit } = window.shared.pageOptions;
+
+const propTypes = {
+ errorMsg: PropTypes.string
+};
class SharedFileViewTip extends React.Component {
render() {
@@ -9,16 +14,21 @@ class SharedFileViewTip extends React.Component {
if (err == 'File preview unsupported') {
errorMsg =
{gettext('Online view is not applicable to this file format')}
;
} else {
- errorMsg = {err}
;
+ errorMsg = {err || this.props.errorMsg}
;
}
return (
);
}
}
+SharedFileViewTip.propTypes = propTypes;
+
export default SharedFileViewTip;
diff --git a/frontend/src/components/shared-file-view/shared-file-view.js b/frontend/src/components/shared-file-view/shared-file-view.js
index e644f21864..33e3d32469 100644
--- a/frontend/src/components/shared-file-view/shared-file-view.js
+++ b/frontend/src/components/shared-file-view/shared-file-view.js
@@ -45,7 +45,7 @@ class SharedFileView extends React.Component {
}
componentDidMount() {
- if (trafficOverLimit == 'True') {
+ if (trafficOverLimit) {
toaster.danger(gettext('File download is disabled: the share link traffic of owner is used up.'), {
duration: 3
});
@@ -76,7 +76,7 @@ class SharedFileView extends React.Component {
onClick={this.handleSaveSharedFileDialog}>{gettext('Save as ...')}
}{' '}
- {(trafficOverLimit === 'False') &&
+ {!trafficOverLimit &&
diff --git a/frontend/src/shared-file-view-audio.js b/frontend/src/shared-file-view-audio.js
new file mode 100644
index 0000000000..0b7a8d7dab
--- /dev/null
+++ b/frontend/src/shared-file-view-audio.js
@@ -0,0 +1,44 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import SharedFileView from './components/shared-file-view/shared-file-view';
+import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
+import AudioPlayer from './components/audio-player';
+
+import './css/audio-file-view.css';
+
+const { rawPath, err } = window.shared.pageOptions;
+
+class SharedFileViewAudio extends React.Component {
+ render() {
+ return } />;
+ }
+}
+
+class FileContent extends React.Component {
+ render() {
+ if (err) {
+ return ;
+ }
+
+ const videoJsOptions = {
+ autoplay: false,
+ controls: true,
+ preload: 'auto',
+ sources: [{
+ src: rawPath
+ }]
+ };
+ return (
+
+ );
+ }
+}
+
+ReactDOM.render(
+ ,
+ document.getElementById('wrapper')
+);
diff --git a/frontend/src/shared-file-view-document.js b/frontend/src/shared-file-view-document.js
new file mode 100644
index 0000000000..11f4a792db
--- /dev/null
+++ b/frontend/src/shared-file-view-document.js
@@ -0,0 +1,109 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { seafileAPI } from './utils/seafile-api';
+import { gettext, mediaUrl} from './utils/constants';
+import SharedFileView from './components/shared-file-view/shared-file-view';
+import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
+import Loading from './components/loading';
+import PDFViewer from './components/pdf-viewer';
+
+import './css/pdf-file-view.css';
+
+const {
+ repoID, filePath, err,
+ commitID, fileType, sharedToken
+} = window.shared.pageOptions;
+
+class SharedFileViewDocument extends React.Component {
+ render() {
+ return } />;
+ }
+}
+
+class FileContent extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isLoading: !err,
+ errorMsg: ''
+ };
+ }
+
+ componentDidMount() {
+ if (err) {
+ return;
+ }
+
+ let queryStatus = () => {
+ seafileAPI.queryOfficeFileConvertStatus(repoID, commitID, filePath, fileType.toLowerCase(), sharedToken).then((res) => {
+ const convertStatus = res.data['status'];
+ switch (convertStatus) {
+ case 'PROCESSING':
+ this.setState({
+ isLoading: true
+ });
+ setTimeout(queryStatus, 2000);
+ break;
+ case 'ERROR':
+ this.setState({
+ isLoading: false,
+ errorMsg: gettext('Document convertion failed.')
+ });
+ break;
+ case 'DONE':
+ this.setState({
+ isLoading: false,
+ errorMsg: ''
+ });
+
+ let scriptNode = document.createElement('script');
+ scriptNode.type = 'text/javascript';
+ scriptNode.src = `${mediaUrl}js/pdf/viewer.js`;
+ document.body.append(scriptNode);
+ }
+ }).catch((error) => {
+ if (error.response) {
+ this.setState({
+ isLoading: false,
+ errorMsg: gettext('Document convertion failed.')
+ });
+ } else {
+ this.setState({
+ isLoading: false,
+ errorMsg: gettext('Please check the network.')
+ });
+ }
+ });
+ };
+
+ queryStatus();
+ }
+
+ render() {
+ const { isLoading, errorMsg } = this.state;
+
+ if (err) {
+ return ;
+ }
+
+ if (isLoading) {
+ return ;
+ }
+
+ if (errorMsg) {
+ return ;
+ }
+
+ return (
+
+ );
+ }
+}
+
+ReactDOM.render (
+ ,
+ document.getElementById('wrapper')
+);
diff --git a/frontend/src/shared-file-view-spreadsheet.js b/frontend/src/shared-file-view-spreadsheet.js
new file mode 100644
index 0000000000..7ced8b29fc
--- /dev/null
+++ b/frontend/src/shared-file-view-spreadsheet.js
@@ -0,0 +1,111 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { seafileAPI } from './utils/seafile-api';
+import { siteRoot, gettext } from './utils/constants';
+import SharedFileView from './components/shared-file-view/shared-file-view';
+import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
+import Loading from './components/loading';
+
+import './css/spreadsheet-file-view.css';
+
+const {
+ repoID, filePath, err,
+ commitID, fileType, fileName, sharedToken
+} = window.shared.pageOptions;
+
+class SharedFileViewSpreadsheet extends React.Component {
+ render() {
+ return (
+ } />
+ );
+ }
+}
+
+class FileContent extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isLoading: !err,
+ errorMsg: ''
+ };
+ }
+
+ componentDidMount() {
+ if (err) {
+ return;
+ }
+
+ let queryStatus = () => {
+ seafileAPI.queryOfficeFileConvertStatus(repoID, commitID, filePath, fileType.toLowerCase(), sharedToken).then((res) => {
+ const convertStatus = res.data['status'];
+ switch (convertStatus) {
+ case 'QUEUED':
+ case 'PROCESSING':
+ this.setState({
+ isLoading: true
+ });
+ setTimeout(queryStatus, 2000);
+ break;
+ case 'ERROR':
+ this.setState({
+ isLoading: false,
+ errorMsg: gettext('Document convertion failed.')
+ });
+ break;
+ case 'DONE':
+ this.setState({
+ isLoading: false,
+ errorMsg: ''
+ });
+ }
+ }).catch((error) => {
+ if (error.response) {
+ this.setState({
+ isLoading: false,
+ errorMsg: gettext('Document convertion failed.')
+ });
+ } else {
+ this.setState({
+ isLoading: false,
+ errorMsg: gettext('Please check the network.')
+ });
+ }
+ });
+ };
+
+ queryStatus();
+ }
+
+ setIframeHeight = (e) => {
+ const iframe = e.currentTarget;
+ iframe.height = iframe.contentDocument.body.scrollHeight;
+ }
+
+ render() {
+ const { isLoading, errorMsg } = this.state;
+
+ if (err) {
+ return ;
+ }
+
+ if (isLoading) {
+ return ;
+ }
+
+ if (errorMsg) {
+ return ;
+ }
+
+ return (
+
+
+
+ );
+ }
+}
+
+ReactDOM.render (
+ ,
+ document.getElementById('wrapper')
+);
diff --git a/frontend/src/shared-file-view-svg.js b/frontend/src/shared-file-view-svg.js
new file mode 100644
index 0000000000..94c5fe7ef3
--- /dev/null
+++ b/frontend/src/shared-file-view-svg.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import SharedFileView from './components/shared-file-view/shared-file-view';
+import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
+
+import './css/svg-file-view.css';
+
+const { fileName, rawPath, err } = window.shared.pageOptions;
+
+class SharedFileViewSVG extends React.Component {
+ render() {
+ return } />;
+ }
+}
+
+class FileContent extends React.Component {
+ render() {
+ if (err) {
+ return ;
+ }
+
+ return (
+
+
+

+
+
+ );
+ }
+}
+
+ReactDOM.render(
+ ,
+ document.getElementById('wrapper')
+);
diff --git a/frontend/src/shared-file-view-unknown.js b/frontend/src/shared-file-view-unknown.js
new file mode 100644
index 0000000000..03ee5f60db
--- /dev/null
+++ b/frontend/src/shared-file-view-unknown.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import SharedFileView from './components/shared-file-view/shared-file-view';
+import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
+
+const { err } = window.shared.pageOptions;
+
+class SharedFileViewImage extends React.Component {
+ render() {
+ return } />;
+ }
+}
+
+class FileContent extends React.Component {
+ render() {
+ if (err) {
+ return ;
+ }
+ }
+}
+
+ReactDOM.render(
+ ,
+ document.getElementById('wrapper')
+);
diff --git a/frontend/src/shared-file-view-video.js b/frontend/src/shared-file-view-video.js
index ff201d73a0..73a7ff3c93 100644
--- a/frontend/src/shared-file-view-video.js
+++ b/frontend/src/shared-file-view-video.js
@@ -1,150 +1,44 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import Account from './components/common/account';
-import { gettext, siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from './utils/constants';
-import { Button } from 'reactstrap';
-import { Utils } from './utils/utils';
-import SaveSharedFileDialog from './components/dialog/save-shared-file-dialog';
-import toaster from './components/toast';
+import SharedFileView from './components/shared-file-view/shared-file-view';
+import SharedFileViewTip from './components/shared-file-view/shared-file-view-tip';
import VideoPlayer from './components/video-player';
-import watermark from 'watermark-dom';
-import './css/shared-file-view.css';
import './css/video-file-view.css';
-let loginUser = window.app.pageOptions.name;
-const { repoID, sharedToken, trafficOverLimit, fileName, fileSize, rawPath, sharedBy, siteName, enableWatermark, download, err } = window.shared.pageOptions;
-
-class SharedFileViewVideo extends React.Component {
-
- constructor(props) {
- super(props);
- this.state = {
- showSaveSharedFileDialog: false
- };
- }
-
- handleSaveSharedFileDialog = () => {
- this.setState({
- showSaveSharedFileDialog: true
- });
- }
-
- toggleCancel = () => {
- this.setState({
- showSaveSharedFileDialog: false
- });
- }
-
- handleSaveSharedFile = () => {
- toaster.success(gettext('Successfully saved'), {
- duration: 3
- });
- }
-
- componentDidMount() {
- if (trafficOverLimit == 'True') {
- toaster.danger(gettext('File download is disabled: the share link traffic of owner is used up.'), {
- duration: 3
- });
- }
- }
-
- getContent() {
- if (err) {
- let errorMsg;
- if (err == 'File preview unsupported') {
- errorMsg = {gettext('Online view is not applicable to this file format')}
;
- } else {
- errorMsg = {err}
;
- }
- return (
-
- );
- } else {
- const videoJsOptions = {
- autoplay: false,
- controls: true,
- preload: 'auto',
- sources: [{
- src: rawPath
- }]
- };
- return (
-
- );
- }
- }
+const { rawPath, err } = window.shared.pageOptions;
+class SharedFileViewImage extends React.Component {
render() {
+ return } />;
+ }
+}
+
+class FileContent extends React.Component {
+ render() {
+ if (err) {
+ return ;
+ }
+
+ const videoJsOptions = {
+ autoplay: false,
+ controls: true,
+ preload: 'auto',
+ sources: [{
+ src: rawPath
+ }]
+ };
return (
-
-
-
-
-
-
-
- { loginUser &&
}
+
+
+
-
-
-
-
{fileName}
-
{gettext('Shared by:')}{' '}{sharedBy}
-
- {download &&
-
- }
-
- {this.getContent()}
-
- {this.state.showSaveSharedFileDialog &&
-
- }
);
}
}
-if (enableWatermark) {
- let watermark_txt;
- if (loginUser) {
- watermark_txt = siteName + ' ' + loginUser;
- } else {
- watermark_txt = gettext('Anonymous User');
- }
- watermark.init({
- watermark_txt: watermark_txt,
- watermark_alpha: 0.075
- });
-}
-
ReactDOM.render(
-
,
+
,
document.getElementById('wrapper')
);
diff --git a/seahub/templates/shared_file_view_react.html b/seahub/templates/shared_file_view_react.html
index 98db73858c..2f62490d80 100644
--- a/seahub/templates/shared_file_view_react.html
+++ b/seahub/templates/shared_file_view_react.html
@@ -9,11 +9,22 @@
{% render_bundle 'sharedFileViewText' 'css' %}
{% elif filetype == 'Image' %}
{% render_bundle 'sharedFileViewImage' 'css' %}
+{% elif filetype == 'SVG' %}
+ {% render_bundle 'sharedFileViewSVG' 'css' %}
{% elif filetype == 'Video' %}
{% render_bundle 'sharedFileViewVideo' 'css' %}
+{% elif filetype == 'Audio' %}
+ {% render_bundle 'sharedFileViewAudio' 'css' %}
{% elif filetype == 'PDF' %}
{% render_bundle 'sharedFileViewPDF' 'css' %}
+{% elif filetype == 'Document' %}
+
+ {% render_bundle 'sharedFileViewDocument' 'css' %}
+{% elif filetype == 'SpreadSheet' %}
+ {% render_bundle 'sharedFileViewSpreadsheet' 'css' %}
+{% elif filetype == 'Unknown' %}
+ {% render_bundle 'sharedFileViewUnknown' 'css' %}
{% endif %}
{% endblock %}
@@ -22,21 +33,21 @@
window.shared = {
pageOptions: {
repoID: '{{ repo.id }}',
- path: '{{ path|escapejs }}',
+ filePath: '{{ path|escapejs }}',
sharedToken: '{{ shared_token }}',
- trafficOverLimit: '{{ traffic_over_limit }}',
+ trafficOverLimit: {% if traffic_over_limit %}true{% else %}false{% endif %},
fileName: '{{ file_name|escapejs }}',
- fileSize: '{{ file_size }}',
+ fileSize: {{ file_size }},
rawPath: '{{ raw_path|escapejs }}',
sharedBy: '{{ shared_by|email2nickname }}',
siteName: '{{ site_name }}',
- enableWatermark: '{{ enable_watermark }}' == 'True',
+ enableWatermark: {% if enable_watermark %}true{% else %}false{% endif %},
download: '{{ permissions.can_download }}' == 'True',
- fileEncodingList: '{{ file_encoding_list|escapejs }}',
- encoding: '{{ encoding }}',
fileContent: '{{ file_content|escapejs }}',
- err: '{{ err }}',
+ err: {% if err %}'{{ err }}'{% else %}''{% endif %},
+ fileType: '{{ filetype }}',
fileExt: '{{ fileext }}',
+ commitID: '{{ current_commit.id }}' || '{{ repo.head_cmmt_id }}'
}
};
@@ -46,8 +57,12 @@
{% render_bundle 'sharedFileViewText' 'js' %}
{% elif filetype == 'Image' %}
{% render_bundle 'sharedFileViewImage' 'js' %}
+{% elif filetype == 'SVG' %}
+ {% render_bundle 'sharedFileViewSVG' 'js' %}
{% elif filetype == 'Video' %}
{% render_bundle 'sharedFileViewVideo' 'js' %}
+{% elif filetype == 'Audio' %}
+ {% render_bundle 'sharedFileViewAudio' 'js' %}
{% elif filetype == 'PDF' %}
{% render_bundle 'sharedFileViewPDF' 'js' %}
+{% elif filetype == 'Document' %}
+ {% render_bundle 'sharedFileViewDocument' 'js' %}
+
+
+{% elif filetype == 'SpreadSheet' %}
+ {% render_bundle 'sharedFileViewSpreadsheet' 'js' %}
+{% elif filetype == 'Unknown' %}
+ {% render_bundle 'sharedFileViewUnknown' 'js' %}
{% endif %}
{% endblock %}
diff --git a/seahub/templates/spreadsheet_file_view_react.html b/seahub/templates/spreadsheet_file_view_react.html
index 2294da62c1..b62f64a23a 100644
--- a/seahub/templates/spreadsheet_file_view_react.html
+++ b/seahub/templates/spreadsheet_file_view_react.html
@@ -12,7 +12,4 @@
{% block render_bundle %}
{% render_bundle 'viewFileSpreadsheet' 'js' %}
-
{% endblock %}
diff --git a/seahub/views/file.py b/seahub/views/file.py
index 03a4691e54..e67d1d22ce 100644
--- a/seahub/views/file.py
+++ b/seahub/views/file.py
@@ -1232,7 +1232,7 @@ def view_shared_file(request, fileshare):
template = 'shared_file_view.html'
- if is_textual_file(file_type=filetype) or filetype in (IMAGE, VIDEO, PDF):
+ if filetype != XMIND:
template = 'shared_file_view_react.html'
return render(request, template, {