mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 23:48:47 +00:00
Update public wiki (#2868)
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import MarkdownViewer from '@seafile/seafile-editor/dist/viewer/markdown-viewer';
|
import MarkdownViewer from '@seafile/seafile-editor/dist/viewer/markdown-viewer';
|
||||||
import { gettext } from '../utils/constants';
|
import { gettext, repoID, slug, serviceURL, isPublicWiki } from '../utils/constants';
|
||||||
import Loading from './loading';
|
import Loading from './loading';
|
||||||
|
import { Utils } from '../utils/utils';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
children: PropTypes.object,
|
children: PropTypes.object,
|
||||||
@@ -10,7 +11,8 @@ const propTypes = {
|
|||||||
markdownContent: PropTypes.string.isRequired,
|
markdownContent: PropTypes.string.isRequired,
|
||||||
latestContributor: PropTypes.string.isRequired,
|
latestContributor: PropTypes.string.isRequired,
|
||||||
lastModified: PropTypes.string.isRequired,
|
lastModified: PropTypes.string.isRequired,
|
||||||
onLinkClick: PropTypes.func.isRequired
|
onLinkClick: PropTypes.func.isRequired,
|
||||||
|
isWiki: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
const contentClass = 'wiki-page-content';
|
const contentClass = 'wiki-page-content';
|
||||||
@@ -102,6 +104,76 @@ class WikiMarkdownViewer extends React.Component {
|
|||||||
this.setState({activeTitleIndex: activeTitleIndex});
|
this.setState({activeTitleIndex: activeTitleIndex});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeInlineNode = (item) => {
|
||||||
|
if (item.object == 'inline') {
|
||||||
|
let url;
|
||||||
|
|
||||||
|
// change image url
|
||||||
|
if (item.type == 'image' && isPublicWiki) {
|
||||||
|
url = item.data.src;
|
||||||
|
const re = new RegExp(serviceURL + '/lib/' + repoID +'/file.*raw=1');
|
||||||
|
// different repo
|
||||||
|
if (!re.test(url)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// get image path
|
||||||
|
let index = url.indexOf('/file');
|
||||||
|
let index2 = url.indexOf('?');
|
||||||
|
const imagePath = url.substring(index + 5, index2);
|
||||||
|
// replace url
|
||||||
|
item.data.src = serviceURL + '/view-image-via-public-wiki/?slug=' + slug + '&path=' + imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (item.type == 'link') {
|
||||||
|
url = item.data.href;
|
||||||
|
// change file url
|
||||||
|
if (Utils.isInternalMarkdownLink(url, repoID)) {
|
||||||
|
let path = Utils.getPathFromInternalMarkdownLink(url, repoID);
|
||||||
|
// replace url
|
||||||
|
item.data.href = serviceURL + '/wikis/' + slug + path;
|
||||||
|
}
|
||||||
|
// change dir url
|
||||||
|
else if (Utils.isInternalDirLink(url, repoID)) {
|
||||||
|
let path = Utils.getPathFromInternalDirLink(url, repoID, slug);
|
||||||
|
// replace url
|
||||||
|
item.data.href = serviceURL + '/wikis/' + slug + path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifyValueBeforeRender = (value) => {
|
||||||
|
let nodes = value.document.nodes;
|
||||||
|
let newNodes = Utils.changeMarkdownNodes(nodes, this.changeInlineNode);
|
||||||
|
value.document.nodes = newNodes;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMarkdown = () => {
|
||||||
|
if (this.props.isWiki) {
|
||||||
|
return (
|
||||||
|
<MarkdownViewer
|
||||||
|
showTOC={true}
|
||||||
|
markdownContent={this.props.markdownContent}
|
||||||
|
activeTitleIndex={this.state.activeTitleIndex}
|
||||||
|
onContentRendered={this.onContentRendered}
|
||||||
|
modifyValueBeforeRender={this.modifyValueBeforeRender}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MarkdownViewer
|
||||||
|
showTOC={true}
|
||||||
|
markdownContent={this.props.markdownContent}
|
||||||
|
activeTitleIndex={this.state.activeTitleIndex}
|
||||||
|
onContentRendered={this.onContentRendered}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.props.isFileLoading) {
|
if (this.props.isFileLoading) {
|
||||||
return <Loading />
|
return <Loading />
|
||||||
@@ -110,12 +182,7 @@ class WikiMarkdownViewer extends React.Component {
|
|||||||
<div ref={this.markdownContainer} className="wiki-page-container" onScroll={this.onScrollHandler.bind(this)}>
|
<div ref={this.markdownContainer} className="wiki-page-container" onScroll={this.onScrollHandler.bind(this)}>
|
||||||
<div className={contentClass}>
|
<div className={contentClass}>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
<MarkdownViewer
|
{this.renderMarkdown()}
|
||||||
showTOC={true}
|
|
||||||
markdownContent={this.props.markdownContent}
|
|
||||||
activeTitleIndex={this.state.activeTitleIndex}
|
|
||||||
onContentRendered={this.onContentRendered}
|
|
||||||
/>
|
|
||||||
<p id="wiki-page-last-modified">{gettext('Last modified by')} {this.props.latestContributor}, <span>{this.props.lastModified}</span></p>
|
<p id="wiki-page-last-modified">{gettext('Last modified by')} {this.props.latestContributor}, <span>{this.props.lastModified}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -123,6 +190,11 @@ class WikiMarkdownViewer extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
isWiki: false,
|
||||||
|
}
|
||||||
|
|
||||||
WikiMarkdownViewer.propTypes = propTypes;
|
WikiMarkdownViewer.propTypes = propTypes;
|
||||||
|
MarkdownViewer.defaultProps = defaultProps;
|
||||||
|
|
||||||
export default WikiMarkdownViewer;
|
export default WikiMarkdownViewer;
|
||||||
|
@@ -117,6 +117,7 @@ class MainPanel extends Component {
|
|||||||
lastModified = {this.props.lastModified}
|
lastModified = {this.props.lastModified}
|
||||||
latestContributor={this.props.latestContributor}
|
latestContributor={this.props.latestContributor}
|
||||||
onLinkClick={this.props.onLinkClick}
|
onLinkClick={this.props.onLinkClick}
|
||||||
|
isWiki={true}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{!this.props.isViewFileState &&
|
{!this.props.isViewFileState &&
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import Account from './components/common/account';
|
import Account from './components/common/account';
|
||||||
import { gettext, siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from './utils/constants';
|
import { serviceURL, gettext, siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from './utils/constants';
|
||||||
import { Button } from 'reactstrap';
|
import { Button } from 'reactstrap';
|
||||||
import { seafileAPI } from './utils/seafile-api';
|
import { seafileAPI } from './utils/seafile-api';
|
||||||
import { Utils } from './utils/utils';
|
import { Utils } from './utils/utils';
|
||||||
@@ -17,7 +17,7 @@ import './assets/css/fa-regular.css';
|
|||||||
import './assets/css/fontawesome.css';
|
import './assets/css/fontawesome.css';
|
||||||
|
|
||||||
let loginUser = window.app.pageOptions.name;
|
let loginUser = window.app.pageOptions.name;
|
||||||
const { serviceURL, repoID, sharedToken, trafficOverLimit, fileName, fileSize, rawPath, sharedBy, siteName, enableWatermark, download } = window.shared.pageOptions;
|
const { repoID, sharedToken, trafficOverLimit, fileName, fileSize, rawPath, sharedBy, siteName, enableWatermark, download } = window.shared.pageOptions;
|
||||||
|
|
||||||
class SharedFileViewMarkdown extends React.Component {
|
class SharedFileViewMarkdown extends React.Component {
|
||||||
|
|
||||||
@@ -62,6 +62,33 @@ class SharedFileViewMarkdown extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeImageURL = (innerNode) => {
|
||||||
|
if (innerNode.type == 'image') {
|
||||||
|
let imageUrl = innerNode.data.src;
|
||||||
|
|
||||||
|
const re = new RegExp(serviceURL + '/lib/' + repoID +'/file.*raw=1');
|
||||||
|
|
||||||
|
// different repo
|
||||||
|
if (!re.test(imageUrl)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// get image path
|
||||||
|
let index = imageUrl.indexOf('/file');
|
||||||
|
let index2 = imageUrl.indexOf('?');
|
||||||
|
const imagePath = imageUrl.substring(index + 5, index2);
|
||||||
|
// change image url
|
||||||
|
innerNode.data.src = serviceURL + '/view-image-via-share-link/?token=' + sharedToken + '&path=' + imagePath;
|
||||||
|
}
|
||||||
|
return innerNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifyValueBeforeRender = (value) => {
|
||||||
|
let nodes = value.document.nodes;
|
||||||
|
let newNodes = Utils.changeMarkdownNodes(nodes, this.changeImageURL);
|
||||||
|
value.document.nodes = newNodes;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.loading) {
|
if (this.state.loading) {
|
||||||
return <Loading />
|
return <Loading />
|
||||||
@@ -102,9 +129,9 @@ class SharedFileViewMarkdown extends React.Component {
|
|||||||
<MarkdownViewer markdownContent={this.state.markdownContent}
|
<MarkdownViewer markdownContent={this.state.markdownContent}
|
||||||
showTOC={false}
|
showTOC={false}
|
||||||
serviceURL={serviceURL}
|
serviceURL={serviceURL}
|
||||||
isShared={true}
|
|
||||||
sharedToken={sharedToken}
|
sharedToken={sharedToken}
|
||||||
repoID={repoID}
|
repoID={repoID}
|
||||||
|
modifyValueBeforeRender={this.modifyValueBeforeRender}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -13,6 +13,7 @@ export const isPro = window.app.config.isPro === 'True';
|
|||||||
export const lang = window.app.config.lang;
|
export const lang = window.app.config.lang;
|
||||||
export const fileServerRoot = window.app.config.fileServerRoot;
|
export const fileServerRoot = window.app.config.fileServerRoot;
|
||||||
export const seafileVersion = window.app.config.seafileVersion;
|
export const seafileVersion = window.app.config.seafileVersion;
|
||||||
|
export const serviceURL = window.app.config.serviceURL;
|
||||||
|
|
||||||
//pageOptions
|
//pageOptions
|
||||||
export const seafileCollabServer = window.app.pageOptions.seafileCollabServer;
|
export const seafileCollabServer = window.app.pageOptions.seafileCollabServer;
|
||||||
@@ -46,6 +47,7 @@ export const initialPath = window.wiki ? window.wiki.config.initial_path : '';
|
|||||||
export const permission = window.wiki ? window.wiki.config.permission === 'True' : '';
|
export const permission = window.wiki ? window.wiki.config.permission === 'True' : '';
|
||||||
export const isDir = window.wiki ? window.wiki.config.isDir : '';
|
export const isDir = window.wiki ? window.wiki.config.isDir : '';
|
||||||
export const serviceUrl = window.wiki ? window.wiki.config.serviceUrl : '';
|
export const serviceUrl = window.wiki ? window.wiki.config.serviceUrl : '';
|
||||||
|
export const isPublicWiki = window.wiki ? window.wiki.config.isPublicWiki === 'True': '';
|
||||||
|
|
||||||
// file history
|
// file history
|
||||||
export const PER_PAGE = 25;
|
export const PER_PAGE = 25;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { mediaUrl, gettext, siteRoot } from './constants';
|
import { mediaUrl, gettext, serviceURL } from './constants';
|
||||||
import { strChineseFirstPY } from './pinyin-by-unicode';
|
import { strChineseFirstPY } from './pinyin-by-unicode';
|
||||||
|
|
||||||
export const Utils = {
|
export const Utils = {
|
||||||
@@ -404,30 +404,59 @@ export const Utils = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
isInternalMarkdownLink: function(url, repoID) {
|
isInternalMarkdownLink: function(url, repoID) {
|
||||||
var re = new RegExp(siteRoot + 'lib/' + repoID + '.*\.md$');
|
var re = new RegExp(serviceURL + '/lib/' + repoID + '.*\.md$');
|
||||||
return re.test(url);
|
return re.test(url);
|
||||||
},
|
},
|
||||||
|
|
||||||
isInternalDirLink: function(url, repoID) {
|
isInternalDirLink: function(url, repoID) {
|
||||||
var re = new RegExp(siteRoot + 'library/' + repoID + '.*');
|
var re = new RegExp(serviceURL + '/library/' + repoID + '.*');
|
||||||
return re.test(url);
|
return re.test(url);
|
||||||
},
|
},
|
||||||
|
|
||||||
getPathFromInternalMarkdownLink: function(url, repoID) {
|
getPathFromInternalMarkdownLink: function(url, repoID) {
|
||||||
var re = new RegExp(siteRoot + 'lib/' + repoID + '/file' + '(.*\.md)');
|
var re = new RegExp(serviceURL + '/lib/' + repoID + '/file' + '(.*\.md)');
|
||||||
var array = re.exec(url);
|
var array = re.exec(url);
|
||||||
var path = decodeURIComponent(array[1]);
|
var path = decodeURIComponent(array[1]);
|
||||||
return path;
|
return path;
|
||||||
},
|
},
|
||||||
|
|
||||||
getPathFromInternalDirLink: function(url, repoID, repoName) {
|
getPathFromInternalDirLink: function(url, repoID, repoName) {
|
||||||
var re = new RegExp(siteRoot + 'library/' + repoID + '/' + repoName + '(/.*)');
|
var repoName = encodeURIComponent(repoName);
|
||||||
|
var re = new RegExp(serviceURL + '/library/' + repoID + '/' + repoName + '(/.*)');
|
||||||
var array = re.exec(url);
|
var array = re.exec(url);
|
||||||
var path = decodeURIComponent(array[1]);
|
var path = decodeURIComponent(array[1]);
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isWikiInternalMarkdownLink: function(url, slug) {
|
||||||
|
var slug = encodeURIComponent(slug);
|
||||||
|
var re = new RegExp(serviceURL + '/wikis/' + slug + '.*\.md$');
|
||||||
|
return re.test(url);
|
||||||
|
},
|
||||||
|
|
||||||
|
isWikiInternalDirLink: function(url, slug) {
|
||||||
|
var slug = encodeURIComponent(slug);
|
||||||
|
var re = new RegExp(serviceURL + '/wikis/' + slug + '.*');
|
||||||
|
return re.test(url);
|
||||||
|
},
|
||||||
|
|
||||||
|
getPathFromWikiInternalMarkdownLink: function(url, slug) {
|
||||||
|
var slug = encodeURIComponent(slug);
|
||||||
|
var re = new RegExp(serviceURL + '/wikis/' + slug + '(.*\.md)');
|
||||||
|
var array = re.exec(url);
|
||||||
|
var path = decodeURIComponent(array[1]);
|
||||||
|
return path;
|
||||||
|
},
|
||||||
|
|
||||||
|
getPathFromWikiInternalDirLink: function(url, slug) {
|
||||||
|
var slug = encodeURIComponent(slug);
|
||||||
|
var re = new RegExp(serviceURL + '/wikis/' + slug+ '(/.*)');
|
||||||
|
var array = re.exec(url);
|
||||||
|
var path = decodeURIComponent(array[1]);
|
||||||
|
return path;
|
||||||
|
},
|
||||||
|
|
||||||
compareTwoWord: function(wordA, wordB) {
|
compareTwoWord: function(wordA, wordB) {
|
||||||
// compare wordA and wordB at lower case
|
// compare wordA and wordB at lower case
|
||||||
// if wordA >= wordB, return 1
|
// if wordA >= wordB, return 1
|
||||||
@@ -577,6 +606,17 @@ export const Utils = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return items;
|
return items;
|
||||||
|
},
|
||||||
|
|
||||||
|
changeMarkdownNodes: function(nodes, fn) {
|
||||||
|
nodes.map((item) => {
|
||||||
|
fn(item);
|
||||||
|
if (item.nodes && item.nodes.length > 0){
|
||||||
|
Utils.changeMarkdownNodes(item.nodes, fn);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -119,11 +119,11 @@ class Wiki extends Component {
|
|||||||
|
|
||||||
onLinkClick = (link) => {
|
onLinkClick = (link) => {
|
||||||
const url = link;
|
const url = link;
|
||||||
if (Utils.isInternalMarkdownLink(url, repoID)) {
|
if (Utils.isWikiInternalMarkdownLink(url, slug)) {
|
||||||
let path = Utils.getPathFromInternalMarkdownLink(url, repoID);
|
let path = Utils.getPathFromWikiInternalMarkdownLink(url, slug);
|
||||||
this.initMainPanelData(path);
|
this.initMainPanelData(path);
|
||||||
} else if (Utils.isInternalDirLink(url, repoID)) {
|
} else if (Utils.isWikiInternalDirLink(url, slug)) {
|
||||||
let path = Utils.getPathFromInternalDirLink(url, repoID, slug);
|
let path = Utils.getPathFromWikiInternalDirLink(url, slug);
|
||||||
this.initWikiData(path);
|
this.initWikiData(path);
|
||||||
} else {
|
} else {
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
|
@@ -22,7 +22,7 @@ from seahub.settings import SEAFILE_VERSION, SITE_TITLE, SITE_NAME, \
|
|||||||
MEDIA_ROOT, SHOW_LOGOUT_ICON, CUSTOM_LOGO_PATH, CUSTOM_FAVICON_PATH
|
MEDIA_ROOT, SHOW_LOGOUT_ICON, CUSTOM_LOGO_PATH, CUSTOM_FAVICON_PATH
|
||||||
|
|
||||||
from seahub.constants import DEFAULT_ADMIN
|
from seahub.constants import DEFAULT_ADMIN
|
||||||
from seahub.utils import get_site_name
|
from seahub.utils import get_site_name, get_service_url
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from seahub.settings import SEACLOUD_MODE
|
from seahub.settings import SEACLOUD_MODE
|
||||||
@@ -118,7 +118,8 @@ def base(request):
|
|||||||
'is_pro': True if is_pro_version() else False,
|
'is_pro': True if is_pro_version() else False,
|
||||||
'enable_repo_wiki_mode': dj_settings.ENABLE_REPO_WIKI_MODE,
|
'enable_repo_wiki_mode': dj_settings.ENABLE_REPO_WIKI_MODE,
|
||||||
'enable_upload_folder': dj_settings.ENABLE_UPLOAD_FOLDER,
|
'enable_upload_folder': dj_settings.ENABLE_UPLOAD_FOLDER,
|
||||||
'enable_resumable_fileupload': dj_settings.ENABLE_RESUMABLE_FILEUPLOAD
|
'enable_resumable_fileupload': dj_settings.ENABLE_RESUMABLE_FILEUPLOAD,
|
||||||
|
'service_url': get_service_url().rstrip('/'),
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.user.is_staff:
|
if request.user.is_staff:
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
isPro: '{{ is_pro }}',
|
isPro: '{{ is_pro }}',
|
||||||
lang: '{{ LANGUAGE_CODE }}',
|
lang: '{{ LANGUAGE_CODE }}',
|
||||||
fileServerRoot: '{{ FILE_SERVER_ROOT }}',
|
fileServerRoot: '{{ FILE_SERVER_ROOT }}',
|
||||||
|
serviceURL: '{{ service_url }}',
|
||||||
seafileVersion: '{{ seafile_version }}',
|
seafileVersion: '{{ seafile_version }}',
|
||||||
},
|
},
|
||||||
pageOptions: {
|
pageOptions: {
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
siteName: '{{ site_name }}',
|
siteName: '{{ site_name }}',
|
||||||
enableWatermark: '{{ enable_watermark }}' == 'True',
|
enableWatermark: '{{ enable_watermark }}' == 'True',
|
||||||
download: '{{ permissions.can_download}}' == 'True',
|
download: '{{ permissions.can_download}}' == 'True',
|
||||||
serviceURL: '{{ serviceUrl }}',
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
slug: "{{ wiki.slug }}",
|
slug: "{{ wiki.slug }}",
|
||||||
repoId: "{{ wiki.repo_id }}",
|
repoId: "{{ wiki.repo_id }}",
|
||||||
initial_path: "{{ file_path }}",
|
initial_path: "{{ file_path }}",
|
||||||
permission: "{{ user_can_write }}",
|
isPublicWiki: "{{ is_public_wiki }}",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@@ -12,7 +12,8 @@ from seahub.views.sso import *
|
|||||||
from seahub.views.file import view_history_file, view_trash_file,\
|
from seahub.views.file import view_history_file, view_trash_file,\
|
||||||
view_snapshot_file, file_edit, view_shared_file, view_file_via_shared_dir,\
|
view_snapshot_file, file_edit, view_shared_file, view_file_via_shared_dir,\
|
||||||
text_diff, view_raw_file, download_file, view_lib_file, \
|
text_diff, view_raw_file, download_file, view_lib_file, \
|
||||||
file_access, view_lib_file_via_smart_link, view_media_file_via_share_link
|
file_access, view_lib_file_via_smart_link, view_media_file_via_share_link, \
|
||||||
|
view_media_file_via_public_wiki
|
||||||
from seahub.views.repo import repo_history_view, view_shared_dir, \
|
from seahub.views.repo import repo_history_view, view_shared_dir, \
|
||||||
view_shared_upload_link, view_lib_as_wiki
|
view_shared_upload_link, view_lib_as_wiki
|
||||||
from notifications.views import notification_list
|
from notifications.views import notification_list
|
||||||
@@ -362,6 +363,7 @@ urlpatterns = [
|
|||||||
url(r'^api/v2.1/wikis/(?P<slug>[^/]+)/dir/$', WikiPagesDirView.as_view(), name='api-v2.1-wiki-pages-dir'),
|
url(r'^api/v2.1/wikis/(?P<slug>[^/]+)/dir/$', WikiPagesDirView.as_view(), name='api-v2.1-wiki-pages-dir'),
|
||||||
url(r'^api/v2.1/wikis/(?P<slug>[^/]+)/content/$', WikiPageContentView.as_view(), name='api-v2.1-wiki-pages-content'),
|
url(r'^api/v2.1/wikis/(?P<slug>[^/]+)/content/$', WikiPageContentView.as_view(), name='api-v2.1-wiki-pages-content'),
|
||||||
url(r'^api/v2.1/wikis/(?P<slug>[^/]+)/pages/(?P<page_name>[^/]+)/$', WikiPageView.as_view(), name='api-v2.1-wiki-page'),
|
url(r'^api/v2.1/wikis/(?P<slug>[^/]+)/pages/(?P<page_name>[^/]+)/$', WikiPageView.as_view(), name='api-v2.1-wiki-page'),
|
||||||
|
url(r'^view-image-via-public-wiki/$', view_media_file_via_public_wiki, name='view_media_file_via_public_wiki'),
|
||||||
|
|
||||||
## user::drafts
|
## user::drafts
|
||||||
url(r'^api/v2.1/drafts/$', DraftsView.as_view(), name='api-v2.1-drafts'),
|
url(r'^api/v2.1/drafts/$', DraftsView.as_view(), name='api-v2.1-drafts'),
|
||||||
|
@@ -48,7 +48,7 @@ from seahub.base.accounts import ANONYMOUS_EMAIL
|
|||||||
from seahub.share.models import FileShare, check_share_link_common
|
from seahub.share.models import FileShare, check_share_link_common
|
||||||
from seahub.share.decorators import share_link_audit, share_link_login_required
|
from seahub.share.decorators import share_link_audit, share_link_login_required
|
||||||
from seahub.wiki.utils import get_wiki_dirent
|
from seahub.wiki.utils import get_wiki_dirent
|
||||||
from seahub.wiki.models import WikiDoesNotExist, WikiPageMissing
|
from seahub.wiki.models import Wiki, WikiDoesNotExist, WikiPageMissing
|
||||||
from seahub.utils import render_error, is_org_context, \
|
from seahub.utils import render_error, is_org_context, \
|
||||||
get_file_type_and_ext, gen_file_get_url, gen_file_share_link, \
|
get_file_type_and_ext, gen_file_get_url, gen_file_share_link, \
|
||||||
render_permission_error, is_pro_version, is_textual_file, \
|
render_permission_error, is_pro_version, is_textual_file, \
|
||||||
@@ -1213,7 +1213,6 @@ def view_shared_file(request, fileshare):
|
|||||||
'traffic_over_limit': traffic_over_limit,
|
'traffic_over_limit': traffic_over_limit,
|
||||||
'permissions': permissions,
|
'permissions': permissions,
|
||||||
'enable_watermark': ENABLE_WATERMARK,
|
'enable_watermark': ENABLE_WATERMARK,
|
||||||
'serviceUrl': get_service_url().rstrip('/'),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@share_link_audit
|
@share_link_audit
|
||||||
@@ -2041,22 +2040,11 @@ def view_media_file_via_share_link(request):
|
|||||||
return render_error(request, 'File does not exist')
|
return render_error(request, 'File does not exist')
|
||||||
|
|
||||||
# read file from cache, if hit
|
# read file from cache, if hit
|
||||||
cache_key = normalize_cache_key(file_id, token=token)
|
err_msg, file_content = get_file_content_from_cache(file_id, repo_id, shared_file_name)
|
||||||
file_content = cache.get(cache_key)
|
|
||||||
if not file_content:
|
|
||||||
# otherwise, read file from database and update cache
|
|
||||||
access_token = seafile_api.get_fileserver_access_token(repo_id,
|
|
||||||
file_id, 'view', '', use_onetime=False)
|
|
||||||
|
|
||||||
if not access_token:
|
if err_msg:
|
||||||
err_msg = 'Unable to view file'
|
|
||||||
return render_error(request, err_msg)
|
return render_error(request, err_msg)
|
||||||
|
|
||||||
shared_file_raw_path = gen_inner_file_get_url(access_token, shared_file_name)
|
|
||||||
|
|
||||||
err, file_content, encode = repo_file_get(shared_file_raw_path, 'auto')
|
|
||||||
cache.set(cache_key, file_content, 24 * 60 * 60)
|
|
||||||
|
|
||||||
# If the image does not exist in markdown
|
# If the image does not exist in markdown
|
||||||
serviceURL = get_service_url().rstrip('/')
|
serviceURL = get_service_url().rstrip('/')
|
||||||
image_file_name = os.path.basename(image_path)
|
image_file_name = os.path.basename(image_path)
|
||||||
@@ -2077,3 +2065,69 @@ def view_media_file_via_share_link(request):
|
|||||||
dl_or_raw_url = gen_file_get_url(access_token, image_file_name)
|
dl_or_raw_url = gen_file_get_url(access_token, image_file_name)
|
||||||
|
|
||||||
return HttpResponseRedirect(dl_or_raw_url)
|
return HttpResponseRedirect(dl_or_raw_url)
|
||||||
|
|
||||||
|
|
||||||
|
def view_media_file_via_public_wiki(request):
|
||||||
|
image_path = request.GET.get('path', '')
|
||||||
|
slug = request.GET.get('slug', '')
|
||||||
|
if not image_path or not slug:
|
||||||
|
return HttpResponseBadRequest('invalid params')
|
||||||
|
|
||||||
|
# check file type
|
||||||
|
image_file_name = os.path.basename(image_path)
|
||||||
|
file_type, file_ext = get_file_type_and_ext(image_file_name)
|
||||||
|
if file_type != IMAGE:
|
||||||
|
err_msg = 'Invalid file type'
|
||||||
|
return render_error(request, err_msg)
|
||||||
|
|
||||||
|
# get wiki object or 404
|
||||||
|
try:
|
||||||
|
wiki = Wiki.objects.get(slug=slug)
|
||||||
|
except Wiki.DoesNotExist:
|
||||||
|
err_msg = "Wiki not found."
|
||||||
|
return render_error(request, err_msg)
|
||||||
|
|
||||||
|
if wiki.permission != 'public':
|
||||||
|
return render_permission_error(request, 'Permission denied')
|
||||||
|
|
||||||
|
# recourse check
|
||||||
|
repo_id = wiki.repo_id
|
||||||
|
repo = seafile_api.get_repo(repo_id)
|
||||||
|
if not repo:
|
||||||
|
return render_error(request, 'Repo does not exist')
|
||||||
|
|
||||||
|
# get image
|
||||||
|
obj_id = seafile_api.get_file_id_by_path(repo_id, image_path)
|
||||||
|
if not obj_id:
|
||||||
|
return render_error(request, 'Image does not exist')
|
||||||
|
|
||||||
|
access_token = seafile_api.get_fileserver_access_token(repo_id,
|
||||||
|
obj_id, 'view', '', use_onetime=False)
|
||||||
|
|
||||||
|
dl_or_raw_url = gen_file_get_url(access_token, image_file_name)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(dl_or_raw_url)
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_content_from_cache(file_id, repo_id, file_name):
|
||||||
|
err_msg = ''
|
||||||
|
file_content = ''
|
||||||
|
|
||||||
|
cache_key = normalize_cache_key(file_id)
|
||||||
|
# read file from cache, if hit
|
||||||
|
file_content = cache.get(cache_key)
|
||||||
|
if not file_content:
|
||||||
|
# otherwise, read file from database and update cache
|
||||||
|
access_token = seafile_api.get_fileserver_access_token(repo_id,
|
||||||
|
file_id, 'view', '', use_onetime=False)
|
||||||
|
|
||||||
|
if not access_token:
|
||||||
|
err_msg = 'Unable to view file'
|
||||||
|
return err_msg, file_content
|
||||||
|
|
||||||
|
file_raw_path = gen_inner_file_get_url(access_token, file_name)
|
||||||
|
|
||||||
|
err_msg, file_content, encode = repo_file_get(file_raw_path, 'auto')
|
||||||
|
cache.set(cache_key, file_content, 24 * 60 * 60)
|
||||||
|
|
||||||
|
return err_msg, file_content
|
||||||
|
@@ -65,22 +65,18 @@ def slug(request, slug, file_path="home.md"):
|
|||||||
file_url = reverse('view_lib_file', args=[wiki.repo_id, file_path])
|
file_url = reverse('view_lib_file', args=[wiki.repo_id, file_path])
|
||||||
return HttpResponseRedirect(file_url + "?raw=1")
|
return HttpResponseRedirect(file_url + "?raw=1")
|
||||||
|
|
||||||
if not req_user:
|
is_public_wiki = False
|
||||||
user_can_write = False
|
if wiki.permission == 'public':
|
||||||
elif req_user == wiki.username or check_folder_permission(
|
is_public_wiki = True
|
||||||
request, wiki.repo_id, '/') == 'rw':
|
|
||||||
user_can_write = True
|
|
||||||
else:
|
|
||||||
user_can_write = False
|
|
||||||
|
|
||||||
return render(request, "wiki/wiki.html", {
|
return render(request, "wiki/wiki.html", {
|
||||||
"wiki": wiki,
|
"wiki": wiki,
|
||||||
"page_name": file_path,
|
"page_name": file_path,
|
||||||
"user_can_write": user_can_write,
|
|
||||||
"file_path": file_path,
|
"file_path": file_path,
|
||||||
"repo_id": wiki.repo_id,
|
"repo_id": wiki.repo_id,
|
||||||
"search_repo_id": wiki.repo_id,
|
"search_repo_id": wiki.repo_id,
|
||||||
"search_wiki": True,
|
"search_wiki": True,
|
||||||
|
"is_public_wiki": is_public_wiki,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user