mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-16 23:29:49 +00:00
support rename Wiki (#6142)
* 01 UI support rename Wiki * rename wiki * old wiki support rename * fix wiki-v1 and wiki-v2 have same id * fix format --------- Co-authored-by: ‘JoinTyang’ <yangtong1009@163.com>
This commit is contained in:
@@ -75,7 +75,7 @@ class App extends Component {
|
||||
}
|
||||
|
||||
navigateClientUrlToLib = () =>{
|
||||
if(window.location.hash && window.location.hash.indexOf('common/lib') != -1){
|
||||
if (window.location.hash && window.location.hash.indexOf('common/lib') != -1){
|
||||
let splitUrlArray = window.location.hash.split('/');
|
||||
let repoID = splitUrlArray[splitUrlArray.length - 2];
|
||||
let url = siteRoot + 'library/' + repoID + '/';
|
||||
|
@@ -32,7 +32,7 @@ class ImportMembersDialog extends React.Component {
|
||||
}
|
||||
// check file extension
|
||||
let fileName = this.fileInputRef.current.files[0].name;
|
||||
if(fileName.substr(fileName.lastIndexOf('.') + 1) != 'xlsx') {
|
||||
if (fileName.substr(fileName.lastIndexOf('.') + 1) != 'xlsx') {
|
||||
this.setState({
|
||||
errorMsg: gettext('Please choose a .xlsx file.')
|
||||
});
|
||||
|
@@ -32,7 +32,7 @@ class ImportOrgUsersDialog extends React.Component {
|
||||
}
|
||||
// check file extension
|
||||
let fileName = this.fileInputRef.current.files[0].name;
|
||||
if(fileName.substr(fileName.lastIndexOf('.') + 1) != 'xlsx') {
|
||||
if (fileName.substr(fileName.lastIndexOf('.') + 1) != 'xlsx') {
|
||||
this.setState({
|
||||
errorMsg: gettext('Please choose a .xlsx file.')
|
||||
});
|
||||
|
93
frontend/src/components/dialog/rename-wiki-dialog.js
Normal file
93
frontend/src/components/dialog/rename-wiki-dialog.js
Normal file
@@ -0,0 +1,93 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { Button, Modal, ModalHeader, Input, ModalBody, ModalFooter, Alert } from 'reactstrap';
|
||||
|
||||
const propTypes = {
|
||||
wiki: PropTypes.object,
|
||||
onRename: PropTypes.func.isRequired,
|
||||
toggleCancel: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class RenameWikiDialog extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
newName: props.wiki.name,
|
||||
errMessage: '',
|
||||
isSubmitBtnActive: false,
|
||||
};
|
||||
this.newInput = React.createRef();
|
||||
}
|
||||
|
||||
handleChange = (e) => {
|
||||
this.setState({
|
||||
isSubmitBtnActive: !!e.target.value.trim(),
|
||||
newName: e.target.value
|
||||
});
|
||||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
let { isValid, errMessage } = this.validateInput();
|
||||
if (!isValid) {
|
||||
this.setState({ errMessage : errMessage });
|
||||
} else {
|
||||
this.props.onRename(this.state.newName.trim());
|
||||
}
|
||||
};
|
||||
|
||||
handleKeyDown = (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.handleSubmit();
|
||||
}
|
||||
};
|
||||
|
||||
toggle = () => {
|
||||
this.props.toggleCancel();
|
||||
};
|
||||
|
||||
validateInput = () => {
|
||||
let newName = this.state.newName.trim();
|
||||
let isValid = true;
|
||||
let errMessage = '';
|
||||
if (!newName) {
|
||||
isValid = false;
|
||||
errMessage = gettext('Name is required.');
|
||||
return { isValid, errMessage };
|
||||
}
|
||||
if (newName.indexOf('/') > -1) {
|
||||
isValid = false;
|
||||
errMessage = gettext('Name should not include ' + '\'/\'' + '.');
|
||||
return { isValid, errMessage };
|
||||
}
|
||||
return { isValid, errMessage };
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.toggle}>
|
||||
<ModalHeader toggle={this.toggle}>{gettext('Rename Wiki')}</ModalHeader>
|
||||
<ModalBody>
|
||||
<p>{gettext('New Wiki name')}</p>
|
||||
<Input
|
||||
onKeyDown={this.handleKeyDown}
|
||||
innerRef={this.newInput}
|
||||
placeholder="newName"
|
||||
value={this.state.newName}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
{this.state.errMessage && <Alert color="danger" className="mt-2">{this.state.errMessage}</Alert>}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={this.toggle}>{gettext('Cancel')}</Button>
|
||||
<Button color="primary" onClick={this.handleSubmit} disabled={!this.state.isSubmitBtnActive}>{gettext('Submit')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
RenameWikiDialog.propTypes = propTypes;
|
||||
|
||||
export default RenameWikiDialog;
|
@@ -179,7 +179,7 @@ class ShareToGroup extends React.Component {
|
||||
let path = this.props.itemPath;
|
||||
let repoID = this.props.repoID;
|
||||
seafileAPI.listSharedItems(repoID, path, 'group').then((res) => {
|
||||
if(res.data.length !== 0) {
|
||||
if (res.data.length !== 0) {
|
||||
this.setState({
|
||||
sharedItems: res.data
|
||||
});
|
||||
|
@@ -188,7 +188,7 @@ class ShareToUser extends React.Component {
|
||||
let path = this.props.itemPath;
|
||||
let repoID = this.props.repoID;
|
||||
seafileAPI.listSharedItems(repoID, path, 'user').then((res) => {
|
||||
if(res.data.length !== 0) {
|
||||
if (res.data.length !== 0) {
|
||||
this.setState({sharedItems: res.data});
|
||||
}
|
||||
}).catch(error => {
|
||||
|
@@ -33,7 +33,7 @@ class SysAdminImportUserDialog extends React.Component {
|
||||
}
|
||||
// check file extension
|
||||
let fileName = this.fileInputRef.current.files[0].name;
|
||||
if(fileName.substr(fileName.lastIndexOf('.') + 1) != 'xlsx') {
|
||||
if (fileName.substr(fileName.lastIndexOf('.') + 1) != 'xlsx') {
|
||||
this.setState({
|
||||
errorMsg: gettext('Please choose a .xlsx file.')
|
||||
});
|
||||
|
@@ -154,7 +154,7 @@ class SysAdminShareToGroup extends React.Component {
|
||||
listSharedGroups = () => {
|
||||
let repoID = this.props.repoID;
|
||||
seafileAPI.sysAdminListRepoSharedItems(repoID, 'group').then((res) => {
|
||||
if(res.data.length !== 0) {
|
||||
if (res.data.length !== 0) {
|
||||
this.setState({
|
||||
sharedItems: res.data
|
||||
});
|
||||
|
@@ -133,7 +133,7 @@ class SysAdminShareToUser extends React.Component {
|
||||
componentDidMount() {
|
||||
let repoID = this.props.repoID;
|
||||
seafileAPI.sysAdminListRepoSharedItems(repoID, 'user').then((res) => {
|
||||
if(res.data.length !== 0) {
|
||||
if (res.data.length !== 0) {
|
||||
this.setState({sharedItems: res.data});
|
||||
}
|
||||
}).catch(error => {
|
||||
|
@@ -615,7 +615,7 @@ class FileUploader extends React.Component {
|
||||
resumableFile.bootstrap();
|
||||
var firedRetry = false;
|
||||
resumableFile.resumableObj.on('chunkingComplete', () => {
|
||||
if(!firedRetry) {
|
||||
if (!firedRetry) {
|
||||
seafileAPI.getFileUploadedBytes(repoID, path, fileName).then(res => {
|
||||
let uploadedBytes = res.data.uploadedBytes;
|
||||
let blockSize = parseInt(resumableUploadFileBlockSize) * 1024 * 1024 || 1024 * 1024;
|
||||
|
@@ -85,7 +85,7 @@ class Search extends Component {
|
||||
|
||||
getSearchResult(queryData) {
|
||||
|
||||
if(this.source){
|
||||
if (this.source){
|
||||
this.cancelRequest();
|
||||
}
|
||||
this.setState({
|
||||
|
@@ -615,7 +615,7 @@ class FileUploader extends React.Component {
|
||||
resumableFile.bootstrap();
|
||||
var firedRetry = false;
|
||||
resumableFile.resumableObj.on('chunkingComplete', () => {
|
||||
if(!firedRetry) {
|
||||
if (!firedRetry) {
|
||||
seafileAPI.getFileUploadedBytes(repoID, path, fileName).then(res => {
|
||||
let uploadedBytes = res.data.uploadedBytes;
|
||||
let blockSize = parseInt(resumableUploadFileBlockSize) * 1024 * 1024 || 1024 * 1024;
|
||||
|
@@ -7,6 +7,7 @@ const propTypes = {
|
||||
deleteWiki: PropTypes.func.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
isDepartment: PropTypes.bool.isRequired,
|
||||
renameWiki: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class WikiCardGroup extends Component {
|
||||
@@ -22,10 +23,11 @@ class WikiCardGroup extends Component {
|
||||
{wikis.map((wiki, index) => {
|
||||
return (
|
||||
<WikiCardItem
|
||||
key={index}
|
||||
key={index + wiki.id}
|
||||
wiki={wiki}
|
||||
deleteWiki={this.props.deleteWiki}
|
||||
isDepartment={isDepartment}
|
||||
renameWiki={this.props.renameWiki}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@@ -6,10 +6,12 @@ import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { siteRoot, gettext } from '../../utils/constants';
|
||||
import ModalPortal from '../modal-portal';
|
||||
import WikiDeleteDialog from '../dialog/wiki-delete-dialog';
|
||||
import RenameWikiDialog from '../dialog/rename-wiki-dialog';
|
||||
|
||||
const propTypes = {
|
||||
wiki: PropTypes.object.isRequired,
|
||||
deleteWiki: PropTypes.func.isRequired,
|
||||
renameWiki: PropTypes.func.isRequired,
|
||||
isDepartment: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
@@ -18,6 +20,7 @@ class WikiCardItem extends Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
isShowDeleteDialog: false,
|
||||
isShowRenameDialog: false,
|
||||
isItemMenuShow: false,
|
||||
ownerAvatar: '',
|
||||
};
|
||||
@@ -32,6 +35,12 @@ class WikiCardItem extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
onRenameToggle = (e) => {
|
||||
this.setState({
|
||||
isShowRenameDialog: !this.state.isShowRenameDialog,
|
||||
});
|
||||
};
|
||||
|
||||
onDeleteToggle = (e) => {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
@@ -53,6 +62,13 @@ class WikiCardItem extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
renameWiki = (newName) => {
|
||||
if (this.props.wiki.name !== newName) {
|
||||
this.props.renameWiki(this.props.wiki, newName);
|
||||
}
|
||||
this.setState({ isShowRenameDialog: false });
|
||||
};
|
||||
|
||||
clickWikiCard = (link) => {
|
||||
window.open(link);
|
||||
};
|
||||
@@ -94,7 +110,10 @@ class WikiCardItem extends Component {
|
||||
let wikiName = isOldVersion ? `${wiki.name} (old version)` : wiki.name;
|
||||
return (
|
||||
<>
|
||||
<div className="wiki-card-item" onClick={this.clickWikiCard.bind(this, isOldVersion ? publishedUrl : editUrl )}>
|
||||
<div
|
||||
className={`wiki-card-item ${this.state.isItemMenuShow ? 'wiki-card-item-menu-open' : ''}`}
|
||||
onClick={this.clickWikiCard.bind(this, isOldVersion ? publishedUrl : editUrl )}
|
||||
>
|
||||
<div className="wiki-card-item-top">
|
||||
<div className="d-flex align-items-center" style={{width: 'calc(100% - 46px)'}}>
|
||||
<span className="sf3-font-wiki sf3-font" aria-hidden="true"></span>
|
||||
@@ -114,7 +133,7 @@ class WikiCardItem extends Component {
|
||||
style={{'minWidth': '0'}}
|
||||
/>
|
||||
<DropdownMenu right={true} className="dtable-dropdown-menu">
|
||||
{/* <DropdownItem onClick={}>{gettext('Rename')}</DropdownItem> */}
|
||||
<DropdownItem onClick={this.onRenameToggle}>{gettext('Rename')}</DropdownItem>
|
||||
<DropdownItem onClick={this.onDeleteToggle}>{gettext('Unpublish')}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
@@ -132,6 +151,15 @@ class WikiCardItem extends Component {
|
||||
/>
|
||||
</ModalPortal>
|
||||
}
|
||||
{this.state.isShowRenameDialog &&
|
||||
<ModalPortal>
|
||||
<RenameWikiDialog
|
||||
toggleCancel={this.onRenameToggle}
|
||||
onRename={this.renameWiki}
|
||||
wiki={wiki}
|
||||
/>
|
||||
</ModalPortal>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@@ -59,6 +59,7 @@
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.wiki-card-item.wiki-card-item-menu-open .wiki-card-item-top .dropdown .sf-dropdown-toggle,
|
||||
.wiki-card-item:hover .wiki-card-item-top .dropdown .sf-dropdown-toggle {
|
||||
opacity: 1;
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ import './wiki-card-view.css';
|
||||
const propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
deleteWiki: PropTypes.func.isRequired,
|
||||
renameWiki: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class WikiCardView extends Component {
|
||||
@@ -45,6 +46,7 @@ class WikiCardView extends Component {
|
||||
<WikiCardGroup
|
||||
key='my-Wikis'
|
||||
deleteWiki={this.props.deleteWiki}
|
||||
renameWiki={this.props.renameWiki}
|
||||
wikis={myWikis}
|
||||
title={gettext('My Wikis')}
|
||||
isDepartment={false}
|
||||
@@ -55,6 +57,7 @@ class WikiCardView extends Component {
|
||||
<WikiCardGroup
|
||||
key={'department-Wikis' + key}
|
||||
deleteWiki={this.props.deleteWiki}
|
||||
renameWiki={this.props.renameWiki}
|
||||
wikis={department2WikisMap[key]}
|
||||
title={department2WikisMap[key][0].owner_nickname}
|
||||
isDepartment={true}
|
||||
@@ -65,6 +68,7 @@ class WikiCardView extends Component {
|
||||
<WikiCardGroup
|
||||
key='old-Wikis'
|
||||
deleteWiki={this.props.deleteWiki}
|
||||
renameWiki={this.props.renameWiki}
|
||||
wikis={v1Wikis}
|
||||
title={gettext('Old Wikis')}
|
||||
isDepartment={false}
|
||||
|
@@ -321,7 +321,7 @@ class OrgAllRepos extends Component {
|
||||
return new OrgAdminRepo(item);
|
||||
});
|
||||
let page_info = {};
|
||||
if(res.data.page_info === undefined){
|
||||
if (res.data.page_info === undefined){
|
||||
let page = res.data.page;
|
||||
let has_next_page = res.data.page_next;
|
||||
page_info = {
|
||||
|
@@ -90,7 +90,7 @@ class StatisticCommonTool extends React.Component {
|
||||
|
||||
onSubmit = () => {
|
||||
let { startValue, endValue } = this.state;
|
||||
if(!startValue || !endValue) {
|
||||
if (!startValue || !endValue) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
|
@@ -90,7 +90,7 @@ class StatisticCommonTool extends React.Component {
|
||||
|
||||
onSubmit = () => {
|
||||
let { startValue, endValue } = this.state;
|
||||
if(!startValue || !endValue) {
|
||||
if (!startValue || !endValue) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
|
@@ -578,7 +578,7 @@ class FileUploader extends React.Component {
|
||||
resumableFile.bootstrap();
|
||||
var firedRetry = false;
|
||||
resumableFile.resumableObj.on('chunkingComplete', () => {
|
||||
if(!firedRetry) {
|
||||
if (!firedRetry) {
|
||||
seafileAPI.getFileUploadedBytes(repoID, path, fileName).then(res => {
|
||||
let uploadedBytes = res.data.uploadedBytes;
|
||||
let blockSize = parseInt(resumableUploadFileBlockSize) * 1024 * 1024 || 1024 * 1024;
|
||||
|
@@ -103,7 +103,7 @@ class Wikis extends Component {
|
||||
});
|
||||
this.setState({wikis: wikis});
|
||||
}).catch((error) => {
|
||||
if(error.response) {
|
||||
if (error.response) {
|
||||
let errorMsg = error.response.data.error_msg;
|
||||
toaster.danger(errorMsg);
|
||||
}
|
||||
@@ -115,7 +115,41 @@ class Wikis extends Component {
|
||||
});
|
||||
this.setState({wikis: wikis});
|
||||
}).catch((error) => {
|
||||
if(error.response) {
|
||||
if (error.response) {
|
||||
let errorMsg = error.response.data.error_msg;
|
||||
toaster.danger(errorMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
renameWiki = (wiki, newName) => {
|
||||
if (wiki.version === 'v1') {
|
||||
wikiAPI.renameWiki(wiki.id, newName).then(() => {
|
||||
let wikis = this.state.wikis.map(item => {
|
||||
if (item.id === wiki.id && item.version === 'v1') {
|
||||
item.name = newName;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setState({wikis: wikis});
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
let errorMsg = error.response.data.error_msg;
|
||||
toaster.danger(errorMsg);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
wikiAPI.renameWiki2(wiki.id, newName).then(() => {
|
||||
let wikis = this.state.wikis.map(item => {
|
||||
if (item.id === wiki.id && item.version === 'v2') {
|
||||
item.name = newName;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setState({wikis: wikis});
|
||||
}).catch((error) => {
|
||||
if (error.response) {
|
||||
let errorMsg = error.response.data.error_msg;
|
||||
toaster.danger(errorMsg);
|
||||
}
|
||||
@@ -161,6 +195,7 @@ class Wikis extends Component {
|
||||
<WikiCardView
|
||||
data={this.state}
|
||||
deleteWiki={this.deleteWiki}
|
||||
renameWiki={this.renameWiki}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ export const Utils = {
|
||||
bytesToSize: function(bytes) {
|
||||
if (typeof(bytes) == 'undefined') return ' ';
|
||||
|
||||
if(bytes < 0) return '--';
|
||||
if (bytes < 0) return '--';
|
||||
const sizes = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
||||
|
||||
if (bytes === 0) return bytes + ' ' + sizes[0];
|
||||
|
@@ -105,6 +105,13 @@ class WikiAPI {
|
||||
return this._sendPostRequest(url, form);
|
||||
}
|
||||
|
||||
renameWiki(wikiId, wikiName) {
|
||||
const url = this.server + '/api/v2.1/wikis/' + wikiId + '/';
|
||||
let form = new FormData();
|
||||
form.append('wiki_name', wikiName);
|
||||
return this._sendPostRequest(url, form);
|
||||
}
|
||||
|
||||
deleteWiki(wikiId) {
|
||||
const url = this.server + '/api/v2.1/wikis/' + wikiId + '/';
|
||||
return this.req.delete(url);
|
||||
@@ -191,6 +198,14 @@ class WikiAPI {
|
||||
return this.req.get(url);
|
||||
}
|
||||
|
||||
renameWiki2(wikiId, wikiName) {
|
||||
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/';
|
||||
let params = {
|
||||
wiki_name: wikiName
|
||||
};
|
||||
return this.req.put(url, params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let wikiAPI = new WikiAPI();
|
||||
|
@@ -202,6 +202,67 @@ class Wiki2View(APIView):
|
||||
permission_classes = (IsAuthenticated, )
|
||||
throttle_classes = (UserRateThrottle, )
|
||||
|
||||
def put(self, request, wiki_id):
|
||||
wiki_name = request.data.get('wiki_name')
|
||||
if not wiki_name:
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, 'wiki name is required.')
|
||||
|
||||
if not is_valid_dirent_name(wiki_name):
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.')
|
||||
|
||||
username = request.user.username
|
||||
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)
|
||||
|
||||
if not check_wiki_admin_permission(wiki, username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
if wiki_name == wiki.name:
|
||||
return Response({"success": True})
|
||||
|
||||
repo_id = wiki.repo_id
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
error_msg = "Wiki library not found."
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
if not check_wiki_admin_permission(wiki, username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
if not is_group_wiki(wiki):
|
||||
if is_org_context(request):
|
||||
repo_owner = seafile_api.get_org_repo_owner(repo.id)
|
||||
else:
|
||||
repo_owner = seafile_api.get_repo_owner(repo.id)
|
||||
|
||||
is_owner = True if username == repo_owner else False
|
||||
if not is_owner:
|
||||
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')
|
||||
|
||||
# check repo status
|
||||
repo_status = repo.status
|
||||
if repo_status != 0:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
try:
|
||||
# desc is ''
|
||||
seafile_api.edit_repo(repo_id, wiki_name, '', username)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Internal Server Error'
|
||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||
|
||||
wiki.name = wiki_name
|
||||
wiki.save()
|
||||
|
||||
return Response({"success": True})
|
||||
|
||||
def delete(self, request, wiki_id):
|
||||
"""Delete a wiki.
|
||||
"""
|
||||
@@ -432,6 +493,10 @@ class Wiki2PageView(APIView):
|
||||
path = page_info.get('path')
|
||||
doc_uuid = page_info.get('docUuid')
|
||||
|
||||
if not page_info:
|
||||
error_msg = 'page %s not found.' % page_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
permission = check_folder_permission(request, wiki.repo_id, '/')
|
||||
if not permission:
|
||||
error_msg = 'Permission denied.'
|
||||
|
Reference in New Issue
Block a user