1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-08 18:30:53 +00:00

12.0 change sdoc content (#6121)

* fix warnings in 12.0

* get wiki sdoc content from sdoc server

* optimize code

* change page search params

* Add repo_name for wiki name

---------

Co-authored-by: ‘JoinTyang’ <yangtong1009@163.com>
This commit is contained in:
Michael An
2024-05-29 11:51:52 +08:00
committed by GitHub
parent b76bad303a
commit 96aa207802
9 changed files with 177 additions and 58 deletions

View File

@@ -4,7 +4,8 @@ import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap'; import { Modal } from 'reactstrap';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import wikiAPI from '../../utils/wiki-api'; import wikiAPI from '../../utils/wiki-api';
import { slug, wikiId, siteRoot, initialPath, isDir, sharedToken, hasIndex, lang, isWiki2, gettext } from '../../utils/constants'; import SDocServerApi from '../../utils/sdoc-server-api';
import { slug, wikiId, siteRoot, initialPath, isDir, sharedToken, hasIndex, lang, isWiki2, seadocServerUrl } from '../../utils/constants';
import Dirent from '../../models/dirent'; import Dirent from '../../models/dirent';
import WikiConfig from './models/wiki-config'; import WikiConfig from './models/wiki-config';
import TreeNode from '../../components/tree-view/tree-node'; import TreeNode from '../../components/tree-view/tree-node';
@@ -33,7 +34,7 @@ class Wiki extends Component {
isViewFile: true, isViewFile: true,
isDataLoading: false, isDataLoading: false,
direntList: [], direntList: [],
content: '', editorContent: {},
permission: '', permission: '',
lastModified: '', lastModified: '',
latestContributor: '', latestContributor: '',
@@ -47,7 +48,6 @@ class Wiki extends Component {
config: new WikiConfig({}), config: new WikiConfig({}),
repoId: '', repoId: '',
seadoc_access_token: '', seadoc_access_token: '',
docUuid: '',
assets_url: '', assets_url: '',
}; };
@@ -200,24 +200,41 @@ class Wiki extends Component {
window.history.pushState({ url: fileUrl, path: dirPath }, dirPath, fileUrl); window.history.pushState({ url: fileUrl, path: dirPath }, dirPath, fileUrl);
}; };
getSdocFileContent = (docUuid, accessToken) => {
const config = {
docUuid,
sdocServer: seadocServerUrl,
accessToken,
};
const sdocServerApi = new SDocServerApi(config);
sdocServerApi.getDocContent().then(res => {
this.setState({
isDataLoading: false,
editorContent: res.data,
});
}).catch(error => {
let errorMsg = Utils.getErrorMsg(error);
toaster.danger(errorMsg);
});
};
showFile = (filePath) => { showFile = (filePath) => {
this.setState({ this.setState({
isDataLoading: true, isDataLoading: true,
}); });
this.removePythonWrapper();
wikiAPI.getWiki2FileContent(wikiId, filePath).then(res => { wikiAPI.getWiki2FileContent(wikiId, filePath).then(res => {
let data = res.data; const { permission, last_modified, latest_contributor, seadoc_access_token, assets_url } = res.data;
this.setState({ this.setState({
isDataLoading: false, permission,
content: data.content, lastModified: moment.unix(last_modified).fromNow(),
permission: data.permission, latestContributor: latest_contributor,
lastModified: moment.unix(data.last_modified).fromNow(), seadoc_access_token,
latestContributor: data.latest_contributor, assets_url,
seadoc_access_token: data.seadoc_access_token,
assets_url: data.assets_url,
isViewFile: true, isViewFile: true,
path: filePath, path: filePath,
}); });
const docUuid = assets_url.slice(assets_url.lastIndexOf('/') + 1);
this.getSdocFileContent(docUuid, seadoc_access_token);
}).catch(error => { }).catch(error => {
let errorMsg = Utils.getErrorMsg(error); let errorMsg = Utils.getErrorMsg(error);
toaster.danger(errorMsg); toaster.danger(errorMsg);
@@ -541,6 +558,36 @@ class Wiki extends Component {
node.addChildren(nodeList); node.addChildren(nodeList);
}; };
showPage = (pageId, filePath) => {
this.setState({
isDataLoading: true,
});
this.removePythonWrapper();
wikiAPI.getWiki2Page(wikiId, pageId).then(res => {
const { permission, last_modified, latest_contributor, seadoc_access_token, assets_url } = res.data;
this.setState({
permission,
lastModified: moment.unix(last_modified).fromNow(),
latestContributor: latest_contributor,
seadoc_access_token,
assets_url,
isViewFile: true,
path: filePath,
});
const docUuid = assets_url.slice(assets_url.lastIndexOf('/') + 1);
this.getSdocFileContent(docUuid, seadoc_access_token);
}).catch(error => {
let errorMsg = Utils.getErrorMsg(error);
toaster.danger(errorMsg);
});
const params = new URLSearchParams(window.location.search);
params.set('page_id', pageId);
const fileUrl = `${siteRoot}${this.handlePath()}${wikiId}/?${params.toString()}`;
window.history.pushState({ url: fileUrl, path: filePath }, filePath, fileUrl);
};
setCurrentPage = (pageId, callback) => { setCurrentPage = (pageId, callback) => {
const { currentPageId, config } = this.state; const { currentPageId, config } = this.state;
if (pageId === currentPageId) { if (pageId === currentPageId) {
@@ -552,7 +599,7 @@ class Wiki extends Component {
const path = currentPage.path; const path = currentPage.path;
if (Utils.isMarkdownFile(path) || Utils.isSdocFile(path)) { if (Utils.isMarkdownFile(path) || Utils.isSdocFile(path)) {
if (path !== this.state.path) { if (path !== this.state.path) {
this.showFile(path); this.showPage(pageId, path);
} }
this.onCloseSide(); this.onCloseSide();
} else { } else {
@@ -602,7 +649,7 @@ class Wiki extends Component {
pathExist={this.state.pathExist} pathExist={this.state.pathExist}
isViewFile={this.state.isViewFile} isViewFile={this.state.isViewFile}
isDataLoading={this.state.isDataLoading} isDataLoading={this.state.isDataLoading}
content={this.state.content} editorContent={this.state.editorContent}
permission={this.state.permission} permission={this.state.permission}
lastModified={this.state.lastModified} lastModified={this.state.lastModified}
latestContributor={this.state.latestContributor} latestContributor={this.state.latestContributor}

View File

@@ -12,7 +12,7 @@ const propTypes = {
pathExist: PropTypes.bool.isRequired, pathExist: PropTypes.bool.isRequired,
isViewFile: PropTypes.bool.isRequired, isViewFile: PropTypes.bool.isRequired,
isDataLoading: PropTypes.bool.isRequired, isDataLoading: PropTypes.bool.isRequired,
content: PropTypes.string, editorContent: PropTypes.object,
permission: PropTypes.string, permission: PropTypes.string,
lastModified: PropTypes.string, lastModified: PropTypes.string,
latestContributor: PropTypes.string, latestContributor: PropTypes.string,
@@ -103,13 +103,11 @@ class MainPanel extends Component {
render() { render() {
const errMessage = (<div className="message err-tip">{gettext('Folder does not exist.')}</div>); const errMessage = (<div className="message err-tip">{gettext('Folder does not exist.')}</div>);
const { content, permission, pathExist, isDataLoading, isViewFile } = this.props; const { permission, pathExist, isDataLoading, isViewFile } = this.props;
const isViewingFile = pathExist && !isDataLoading && isViewFile; const isViewingFile = pathExist && !isDataLoading && isViewFile;
const editorContent = content && JSON.parse(content);
const isReadOnly = !(permission === 'rw'); const isReadOnly = !(permission === 'rw');
return ( return (
<div className="wiki2-main-panel"> <div className="wiki2-main-panel">
<div className="main-panel-hide hide">{this.props.content}</div>
<div className='wiki2-main-panel-north'> <div className='wiki2-main-panel-north'>
<WikiTopNav <WikiTopNav
config={this.props.config} config={this.props.config}
@@ -125,7 +123,7 @@ class MainPanel extends Component {
{this.props.pathExist && this.props.isDataLoading && <Loading />} {this.props.pathExist && this.props.isDataLoading && <Loading />}
{isViewingFile && Utils.isSdocFile(this.props.path) && ( {isViewingFile && Utils.isSdocFile(this.props.path) && (
<SdocWikiViewer <SdocWikiViewer
document={editorContent} document={this.props.editorContent}
showOutline={false} showOutline={false}
showToolbar={false} showToolbar={false}
docUuid={this.state.docUuid} docUuid={this.state.docUuid}

View File

@@ -122,6 +122,8 @@ export const sharedType = window.wiki ? window.wiki.config.sharedType : '';
export const hasIndex = window.wiki ? window.wiki.config.hasIndex : ''; export const hasIndex = window.wiki ? window.wiki.config.hasIndex : '';
export const assetsUrl = window.wiki ? window.wiki.config.assetsUrl : ''; export const assetsUrl = window.wiki ? window.wiki.config.assetsUrl : '';
export const isWiki2 = window.wiki ? window.wiki.config.isWiki2 : false; export const isWiki2 = window.wiki ? window.wiki.config.isWiki2 : false;
export const seadocServerUrl = window.wiki ? window.wiki.config.seadocServerUrl : '';
export const seadocAccessToken = window.wiki ? window.wiki.config.seadocAccessToken : '';
// file history // file history
export const PER_PAGE = 25; export const PER_PAGE = 25;

View File

@@ -0,0 +1,19 @@
import axios from 'axios';
class SDocServerApi {
constructor(options) {
this.server = options.sdocServer;
this.docUuid = options.docUuid;
this.accessToken = options.accessToken;
}
getDocContent() {
const { server, docUuid, accessToken } = this;
const url = `${server}/api/v1/docs/${docUuid}/`;
return axios.get(url, { headers: { Authorization: `Token ${accessToken}` } });
}
}
export default SDocServerApi;

View File

@@ -189,7 +189,6 @@ class WikiAPI {
} }
deleteWiki2Page(wikiId, pageId) { deleteWiki2Page(wikiId, pageId) {
// const path = encodeURIComponent(pagePath);
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/page/' + pageId + '/'; const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/page/' + pageId + '/';
return this.req.delete(url); return this.req.delete(url);
} }
@@ -199,6 +198,11 @@ class WikiAPI {
return this.req.delete(url); return this.req.delete(url);
} }
getWiki2Page(wikiId, pageId) {
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/page/' + pageId + '/';
return this.req.get(url);
}
} }
let wikiAPI = new WikiAPI(); let wikiAPI = new WikiAPI();

View File

@@ -556,6 +556,70 @@ class Wiki2PageView(APIView):
permission_classes = (IsAuthenticated, ) permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, ) throttle_classes = (UserRateThrottle, )
def get(self, request, wiki_id, page_id):
try:
wiki = Wiki.objects.get(id=wiki_id)
except Wiki.DoesNotExist:
error_msg = "Wiki not found."
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
username = request.user.username
if not check_wiki_permission(wiki, username):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
repo_id = wiki.repo_id
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
wiki_config = get_wiki_config(repo_id, username)
pages = wiki_config.get('pages', [])
page_info = next(filter(lambda t: t['id'] == page_id, pages), {})
path = page_info.get('path')
doc_uuid = page_info.get('docUuid')
permission = check_folder_permission(request, wiki.repo_id, '/')
if not permission:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
file_id = seafile_api.get_file_id_by_path(repo.repo_id, path)
except SearpcError as e:
logger.error(e)
return api_error(HTTP_520_OPERATION_FAILED,
"Failed to get file id by path.")
if not file_id:
return api_error(status.HTTP_404_NOT_FOUND, "File not found")
# send stats message
send_file_access_msg(request, repo, path, 'api')
filename = os.path.basename(path)
try:
dirent = seafile_api.get_dirent_by_path(repo.repo_id, path)
if dirent:
latest_contributor, last_modified = dirent.modifier, dirent.mtime
else:
latest_contributor, last_modified = None, 0
except SearpcError as e:
logger.error(e)
latest_contributor, last_modified = None, 0
assets_url = '/api/v2.1/seadoc/download-image/' + doc_uuid
seadoc_access_token = gen_seadoc_access_token(doc_uuid, filename, request.user.username, permission=permission)
return Response({
"latest_contributor": email2nickname(latest_contributor),
"last_modified": last_modified,
"permission": permission,
"seadoc_access_token": seadoc_access_token,
"assets_url": assets_url,
})
def delete(self, request, wiki_id, page_id): def delete(self, request, wiki_id, page_id):
try: try:
wiki = Wiki.objects.get(id=wiki_id) wiki = Wiki.objects.get(id=wiki_id)
@@ -579,6 +643,10 @@ class Wiki2PageView(APIView):
page_info = next(filter(lambda t: t['id'] == page_id, pages), {}) page_info = next(filter(lambda t: t['id'] == page_id, pages), {})
path = page_info.get('path') path = page_info.get('path')
if not page_info:
error_msg = 'page %s not found.' % page_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# check file lock # check file lock
try: try:
is_locked, locked_by_me = check_file_lock(repo_id, path, username) is_locked, locked_by_me = check_file_lock(repo_id, path, username)

View File

@@ -43,12 +43,9 @@
window.wiki = { window.wiki = {
config: { config: {
wikiId: "{{ wiki.id }}", wikiId: "{{ wiki.id }}",
repoId: "{{ wiki.repo_id }}",
repoName: "{{ wiki.name }}", repoName: "{{ wiki.name }}",
initial_path: "{{ file_path|escapejs }}", initial_path: "{{ file_path|escapejs }}",
isDir: "{{ is_dir }}",
isWiki2: true, isWiki2: true,
assetsUrl: "{{ assets_url }}",
seadocServerUrl: "{{ seadoc_server_url }}", seadocServerUrl: "{{ seadoc_server_url }}",
seadocAccessToken: "{{ seadoc_access_token }}", seadocAccessToken: "{{ seadoc_access_token }}",
permission: "{{ permission }}", permission: "{{ permission }}",

View File

@@ -712,7 +712,7 @@ urlpatterns = [
re_path(r'^api/v2.1/admin/invitations/$', AdminInvitations.as_view(), name='api-v2.1-admin-invitations'), re_path(r'^api/v2.1/admin/invitations/$', AdminInvitations.as_view(), name='api-v2.1-admin-invitations'),
re_path(r'^api/v2.1/admin/invitations/(?P<token>[a-f0-9]{32})/$', AdminInvitation.as_view(), name='api-v2.1-admin-invitation'), re_path(r'^api/v2.1/admin/invitations/(?P<token>[a-f0-9]{32})/$', AdminInvitation.as_view(), name='api-v2.1-admin-invitation'),
re_path(r'^wikis/(?P<wiki_id>[^/]+)/(?P<file_path>.*)$', wiki_view, name='wiki'), re_path(r'^wikis/(?P<wiki_id>[^/]+)/$', wiki_view, name='wiki'),
path('avatar/', include('seahub.avatar.urls')), path('avatar/', include('seahub.avatar.urls')),
path('notice/', include('seahub.notifications.urls')), path('notice/', include('seahub.notifications.urls')),

View File

@@ -18,7 +18,7 @@ from seahub.utils import get_file_type_and_ext, render_permission_error, is_pro_
from seahub.utils.file_types import IMAGE, SEADOC from seahub.utils.file_types import IMAGE, SEADOC
from seahub.seadoc.utils import get_seadoc_file_uuid, gen_seadoc_access_token from seahub.seadoc.utils import get_seadoc_file_uuid, gen_seadoc_access_token
from seahub.auth.decorators import login_required from seahub.auth.decorators import login_required
from seahub.wiki2.utils import can_edit_wiki, check_wiki_permission from seahub.wiki2.utils import can_edit_wiki, check_wiki_permission, get_wiki_config
from seahub.utils.file_op import check_file_lock, ONLINE_OFFICE_LOCK_OWNER, if_locked_by_online_office from seahub.utils.file_op import check_file_lock, ONLINE_OFFICE_LOCK_OWNER, if_locked_by_online_office
from seahub.utils.repo import parse_repo_perm from seahub.utils.repo import parse_repo_perm
@@ -29,41 +29,35 @@ logger = logging.getLogger(__name__)
@login_required @login_required
def wiki_view(request, wiki_id, file_path): def wiki_view(request, wiki_id):
""" edit wiki page. for wiki2 """ edit wiki page. for wiki2
""" """
# get wiki object or 404 # get wiki object or 404
wiki = get_object_or_404(Wiki, id=wiki_id) wiki = get_object_or_404(Wiki, id=wiki_id)
file_path = "/" + file_path
page_id = request.GET.get('page_id')
file_path = ''
if page_id:
wiki_config = get_wiki_config(wiki.repo_id, request.user.username)
pages = wiki_config.get('pages', [])
page_info = next(filter(lambda t: t['id'] == page_id, pages), {})
file_path = page_info.get('path', '')
is_page = False
if file_path:
is_page = True
# perm check # perm check
req_user = request.user.username req_user = request.user.username
if not check_wiki_permission(wiki, req_user): if not check_wiki_permission(wiki, req_user):
return render_permission_error(request, 'Permission denied.') return render_permission_error(request, 'Permission denied.')
permission = check_folder_permission(request, wiki.repo_id, '/')
if not permission:
return render_permission_error(request, 'Permission denied.')
is_dir = None
file_id = seafile_api.get_file_id_by_path(wiki.repo_id, file_path)
if file_id:
is_dir = False
dir_id = seafile_api.get_dir_id_by_path(wiki.repo_id, file_path)
if dir_id:
is_dir = True
outlines = []
latest_contributor = '' latest_contributor = ''
last_modified = 0 last_modified = 0
assets_url = ''
seadoc_access_token = ''
file_type, ext = get_file_type_and_ext(posixpath.basename(file_path)) file_type, ext = get_file_type_and_ext(posixpath.basename(file_path))
repo = seafile_api.get_repo(wiki.repo_id) repo = seafile_api.get_repo(wiki.repo_id)
if is_dir is False and file_type == SEADOC: if is_page and file_type == SEADOC:
file_uuid = get_seadoc_file_uuid(repo, file_path)
assets_url = '/api/v2.1/seadoc/download-image/' + file_uuid
try: try:
dirent = seafile_api.get_dirent_by_path(wiki.repo_id, file_path) dirent = seafile_api.get_dirent_by_path(wiki.repo_id, file_path)
if dirent: if dirent:
@@ -71,23 +65,13 @@ def wiki_view(request, wiki_id, file_path):
except Exception as e: except Exception as e:
logger.warning(e) logger.warning(e)
filename = os.path.basename(file_path)
seadoc_access_token = gen_seadoc_access_token(file_uuid, filename, req_user, permission=permission)
last_modified = datetime.fromtimestamp(last_modified) last_modified = datetime.fromtimestamp(last_modified)
return render(request, "wiki/wiki_edit.html", { return render(request, "wiki/wiki_edit.html", {
"wiki": wiki, "wiki": wiki,
"repo_name": repo.name if repo else '',
"file_path": file_path, "file_path": file_path,
"filename": os.path.splitext(os.path.basename(file_path))[0], "repo_name": repo.name if repo else '',
"outlines": outlines,
"modifier": latest_contributor, "modifier": latest_contributor,
"modify_time": last_modified, "modify_time": last_modified,
"repo_id": wiki.repo_id, "seadoc_server_url": SEADOC_SERVER_URL
"is_dir": is_dir,
"assets_url": assets_url,
"seadoc_server_url": SEADOC_SERVER_URL,
"seadoc_access_token": seadoc_access_token,
"permission": permission,
}) })