mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 15:38:15 +00:00
Update wiki page (#6298)
* add wiki page * delete wiki page * update * move wiki page * optimize code * update * fix code format change error message --------- Co-authored-by: 孙永强 <11704063+s-yongqiang@user.noreply.gitee.com> Co-authored-by: Michael An <2331806369@qq.com>
This commit is contained in:
@@ -7,8 +7,8 @@ import toaster from '../../components/toast';
|
|||||||
import Loading from '../../components/loading';
|
import Loading from '../../components/loading';
|
||||||
import WikiNav from './wiki-nav/index';
|
import WikiNav from './wiki-nav/index';
|
||||||
import PageUtils from './wiki-nav/page-utils';
|
import PageUtils from './wiki-nav/page-utils';
|
||||||
import { generateUniqueId, isObjectNotEmpty } from './utils';
|
|
||||||
import Page from './models/page';
|
import Page from './models/page';
|
||||||
|
import { isObjectNotEmpty } from './utils';
|
||||||
import wikiAPI from '../../utils/wiki-api';
|
import wikiAPI from '../../utils/wiki-api';
|
||||||
import { Utils } from '../../utils/utils';
|
import { Utils } from '../../utils/utils';
|
||||||
import WikiExternalOperations from './wiki-external-operations';
|
import WikiExternalOperations from './wiki-external-operations';
|
||||||
@@ -36,13 +36,16 @@ class SidePanel extends Component {
|
|||||||
|
|
||||||
confirmDeletePage = (pageId) => {
|
confirmDeletePage = (pageId) => {
|
||||||
const config = deepCopy(this.props.config);
|
const config = deepCopy(this.props.config);
|
||||||
const { pages, navigation } = config;
|
const { pages } = config;
|
||||||
const index = PageUtils.getPageIndexById(pageId, pages);
|
const index = PageUtils.getPageIndexById(pageId, pages);
|
||||||
config.pages.splice(index, 1);
|
config.pages.splice(index, 1);
|
||||||
PageUtils.deletePage(navigation, pageId);
|
// TODO: To delete a page, do you need to delete all subpages at once(update PageUtils delete a page)
|
||||||
this.props.saveWikiConfig(config);
|
wikiAPI.deleteWiki2Page(wikiId, pageId).then((res) => {
|
||||||
// TODO: delete a page, then delete all subpages
|
this.props.updateWikiConfig(config);
|
||||||
wikiAPI.deleteWiki2Page(wikiId, pageId);
|
}).catch((error) => {
|
||||||
|
let errMessage = Utils.getErrorMsg(error);
|
||||||
|
toaster.danger(errMessage);
|
||||||
|
});
|
||||||
if (config.pages.length > 0) {
|
if (config.pages.length > 0) {
|
||||||
this.props.setCurrentPage(config.pages[0].id);
|
this.props.setCurrentPage(config.pages[0].id);
|
||||||
} else {
|
} else {
|
||||||
@@ -50,19 +53,13 @@ class SidePanel extends Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
addPageInside = async ({ parentPageId, name, icon, path, docUuid, successCallback, errorCallback }) => {
|
addPageInside = async ({ parentPageId, page_id, name, icon, path, docUuid, successCallback, errorCallback}) => {
|
||||||
const { config } = this.props;
|
const newPage = new Page({ id: page_id, name, icon, path, docUuid });
|
||||||
const navigation = config.navigation;
|
|
||||||
const pageId = generateUniqueId(navigation);
|
|
||||||
const newPage = new Page({ id: pageId, name, icon, path, docUuid });
|
|
||||||
this.addPage(newPage, parentPageId, successCallback, errorCallback);
|
this.addPage(newPage, parentPageId, successCallback, errorCallback);
|
||||||
};
|
};
|
||||||
|
|
||||||
onAddNewPage = async ({ name, icon, path, docUuid, successCallback, errorCallback, jumpToNewPage = true }) => {
|
onAddNewPage = async ({ name, icon, path, page_id, docUuid, successCallback, errorCallback, jumpToNewPage = true }) => {
|
||||||
const { config } = this.props;
|
const newPage = new Page({ id: page_id, name, icon, path, docUuid });
|
||||||
const navigation = config.navigation;
|
|
||||||
const pageId = generateUniqueId(navigation);
|
|
||||||
const newPage = new Page({ id: pageId, name, icon, path, docUuid });
|
|
||||||
this.addPage(newPage, '', successCallback, errorCallback, jumpToNewPage);
|
this.addPage(newPage, '', successCallback, errorCallback, jumpToNewPage);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,11 +83,10 @@ class SidePanel extends Component {
|
|||||||
config.pages.push(page);
|
config.pages.push(page);
|
||||||
PageUtils.addPage(navigation, pageId, parentId);
|
PageUtils.addPage(navigation, pageId, parentId);
|
||||||
config.navigation = navigation;
|
config.navigation = navigation;
|
||||||
const onSuccess = () => {
|
JSON.stringify(config);
|
||||||
jumpToNewPage && this.props.setCurrentPage(pageId, successCallback);
|
this.props.updateWikiConfig(config);
|
||||||
successCallback();
|
jumpToNewPage && this.props.setCurrentPage(pageId, successCallback);
|
||||||
};
|
successCallback && successCallback();
|
||||||
this.props.saveWikiConfig(config, onSuccess, errorCallback);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
movePage = ({ moved_page_id, target_page_id, move_position }) => {
|
movePage = ({ moved_page_id, target_page_id, move_position }) => {
|
||||||
@@ -98,7 +94,8 @@ class SidePanel extends Component {
|
|||||||
let { navigation } = config;
|
let { navigation } = config;
|
||||||
PageUtils.movePage(navigation, moved_page_id, target_page_id, move_position);
|
PageUtils.movePage(navigation, moved_page_id, target_page_id, move_position);
|
||||||
config.navigation = navigation;
|
config.navigation = navigation;
|
||||||
this.props.saveWikiConfig(config);
|
JSON.stringify(config);
|
||||||
|
this.props.updateWikiConfig(config);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderWikiNav = () => {
|
renderWikiNav = () => {
|
||||||
@@ -115,6 +112,7 @@ class SidePanel extends Component {
|
|||||||
onUpdatePage={onUpdatePage}
|
onUpdatePage={onUpdatePage}
|
||||||
setCurrentPage={this.props.setCurrentPage}
|
setCurrentPage={this.props.setCurrentPage}
|
||||||
onMovePage={this.movePage}
|
onMovePage={this.movePage}
|
||||||
|
updateWikiConfig={this.props.updateWikiConfig}
|
||||||
onAddNewPage={this.onAddNewPage}
|
onAddNewPage={this.onAddNewPage}
|
||||||
duplicatePage={this.duplicatePage}
|
duplicatePage={this.duplicatePage}
|
||||||
currentPageId={this.props.currentPageId}
|
currentPageId={this.props.currentPageId}
|
||||||
@@ -129,8 +127,9 @@ class SidePanel extends Component {
|
|||||||
handleAddNewPage = (jumpToNewPage = true, pageName = 'Untitled') => {
|
handleAddNewPage = (jumpToNewPage = true, pageName = 'Untitled') => {
|
||||||
const voidFn = () => void 0;
|
const voidFn = () => void 0;
|
||||||
wikiAPI.createWiki2Page(wikiId, pageName).then(res => {
|
wikiAPI.createWiki2Page(wikiId, pageName).then(res => {
|
||||||
const { obj_name, parent_dir, doc_uuid, page_name } = res.data;
|
const { page_id, obj_name, doc_uuid, parent_dir, page_name } = res.data.file_info;
|
||||||
this.onAddNewPage({
|
this.onAddNewPage({
|
||||||
|
page_id: page_id,
|
||||||
name: page_name,
|
name: page_name,
|
||||||
icon: '',
|
icon: '',
|
||||||
path: parent_dir === '/' ? `/${obj_name}` : `${parent_dir}/${obj_name}`,
|
path: parent_dir === '/' ? `/${obj_name}` : `${parent_dir}/${obj_name}`,
|
||||||
@@ -142,7 +141,6 @@ class SidePanel extends Component {
|
|||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
let errMessage = Utils.getErrorMsg(error);
|
let errMessage = Utils.getErrorMsg(error);
|
||||||
toaster.danger(errMessage);
|
toaster.danger(errMessage);
|
||||||
this.onError();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@ const propTypes = {
|
|||||||
title: PropTypes.node,
|
title: PropTypes.node,
|
||||||
toggle: PropTypes.func.isRequired,
|
toggle: PropTypes.func.isRequired,
|
||||||
onAddNewPage: PropTypes.func,
|
onAddNewPage: PropTypes.func,
|
||||||
|
currentPageId: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -70,9 +71,10 @@ class AddNewPageDialog extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
createPage = (pageName) => {
|
createPage = (pageName) => {
|
||||||
wikiAPI.createWiki2Page(wikiId, pageName).then(res => {
|
wikiAPI.createWiki2Page(wikiId, pageName, this.props.currentPageId).then(res => {
|
||||||
const { obj_name, parent_dir, doc_uuid } = res.data;
|
const { page_id, obj_name, doc_uuid, parent_dir } = res.data.file_info;
|
||||||
this.props.onAddNewPage({
|
this.props.onAddNewPage({
|
||||||
|
page_id: page_id,
|
||||||
name: pageName,
|
name: pageName,
|
||||||
icon: '',
|
icon: '',
|
||||||
path: parent_dir === '/' ? `/${obj_name}` : `${parent_dir}/${obj_name}`,
|
path: parent_dir === '/' ? `/${obj_name}` : `${parent_dir}/${obj_name}`,
|
||||||
|
@@ -103,11 +103,16 @@ export default class PageUtils {
|
|||||||
}
|
}
|
||||||
function _insertPageRecursion(item, page_id, target_page_id, target_id, move_position) {
|
function _insertPageRecursion(item, page_id, target_page_id, target_id, move_position) {
|
||||||
if (item.id === target_id) {
|
if (item.id === target_id) {
|
||||||
let insertIndex = target_page_id ? item.children.findIndex(item => item.id === target_page_id) : -1;
|
if (item.children) {
|
||||||
if (move_position === 'move_below') {
|
let insertIndex = target_page_id ? item.children.findIndex(item => item.id === target_page_id) : -1;
|
||||||
insertIndex++;
|
if (move_position === 'move_below') {
|
||||||
|
insertIndex++;
|
||||||
|
}
|
||||||
|
item.children.splice(insertIndex, 0, movedPage);
|
||||||
|
} else {
|
||||||
|
item.children = [];
|
||||||
|
item.children.push(movedPage);
|
||||||
}
|
}
|
||||||
item.children.splice(insertIndex, 0, movedPage);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
item.children && item.children.forEach(item => {
|
item.children && item.children.forEach(item => {
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
import { DragSource, DropTarget } from 'react-dnd';
|
import { DragSource, DropTarget } from 'react-dnd';
|
||||||
import PageItem from './page-item';
|
import PageItem from './page-item';
|
||||||
|
import wikiAPI from '../../../../utils/wiki-api';
|
||||||
|
import { wikiId, gettext } from '../../../../utils/constants';
|
||||||
|
import { Utils } from '../../../../utils/utils';
|
||||||
|
import toaster from '../../../../components/toast';
|
||||||
|
|
||||||
const dragSource = {
|
const dragSource = {
|
||||||
beginDrag: props => {
|
beginDrag: props => {
|
||||||
@@ -34,10 +38,19 @@ const dropTarget = {
|
|||||||
if (draggedPageId !== targetPageId) {
|
if (draggedPageId !== targetPageId) {
|
||||||
const sourceIndex = dragSource.idx;
|
const sourceIndex = dragSource.idx;
|
||||||
const move_position = sourceIndex > targetIndex ? 'move_above' : 'move_below';
|
const move_position = sourceIndex > targetIndex ? 'move_above' : 'move_below';
|
||||||
props.onMovePage({
|
wikiAPI.moveWiki2Page(wikiId, draggedPageId, targetPageId, move_position).then(res => {
|
||||||
moved_page_id: draggedPageId,
|
props.onMovePage({
|
||||||
target_page_id: targetPageId,
|
moved_page_id: draggedPageId,
|
||||||
move_position,
|
target_page_id: targetPageId,
|
||||||
|
move_position,
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response && error.response.status === 400 && error.response.data.error_msg === 'Internal Server Error') {
|
||||||
|
toaster.danger(gettext('Cannot move parent page to child page'));
|
||||||
|
} else {
|
||||||
|
let errMessage = Utils.getErrorMsg(error);
|
||||||
|
toaster.danger(errMessage);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@@ -143,6 +143,7 @@ class PageItem extends Component {
|
|||||||
onUpdatePage={this.props.onUpdatePage}
|
onUpdatePage={this.props.onUpdatePage}
|
||||||
onDeletePage={this.props.onDeletePage}
|
onDeletePage={this.props.onDeletePage}
|
||||||
onMovePage={this.props.onMovePage}
|
onMovePage={this.props.onMovePage}
|
||||||
|
updateWikiConfig={this.props.updateWikiConfig}
|
||||||
pages={pages}
|
pages={pages}
|
||||||
pathStr={pathStr + '-' + page.id}
|
pathStr={pathStr + '-' + page.id}
|
||||||
currentPageId={this.props.currentPageId}
|
currentPageId={this.props.currentPageId}
|
||||||
@@ -252,6 +253,7 @@ class PageItem extends Component {
|
|||||||
{this.state.isShowInsertPage &&
|
{this.state.isShowInsertPage &&
|
||||||
<AddNewPageDialog
|
<AddNewPageDialog
|
||||||
toggle={this.toggleInsertPage}
|
toggle={this.toggleInsertPage}
|
||||||
|
currentPageId={this.props.page.id}
|
||||||
onAddNewPage={this.onAddNewPage}
|
onAddNewPage={this.onAddNewPage}
|
||||||
title={gettext('Add page inside')}
|
title={gettext('Add page inside')}
|
||||||
/>
|
/>
|
||||||
@@ -300,6 +302,7 @@ PageItem.propTypes = {
|
|||||||
addPageInside: PropTypes.func,
|
addPageInside: PropTypes.func,
|
||||||
getFoldState: PropTypes.func,
|
getFoldState: PropTypes.func,
|
||||||
toggleExpand: PropTypes.func,
|
toggleExpand: PropTypes.func,
|
||||||
|
updateWikiConfig: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PageItem;
|
export default PageItem;
|
||||||
|
@@ -21,6 +21,7 @@ class WikiNav extends Component {
|
|||||||
duplicatePage: PropTypes.func,
|
duplicatePage: PropTypes.func,
|
||||||
currentPageId: PropTypes.string,
|
currentPageId: PropTypes.string,
|
||||||
addPageInside: PropTypes.func,
|
addPageInside: PropTypes.func,
|
||||||
|
updateWikiConfig: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -70,6 +71,7 @@ class WikiNav extends Component {
|
|||||||
onUpdatePage={this.props.onUpdatePage}
|
onUpdatePage={this.props.onUpdatePage}
|
||||||
onDeletePage={this.props.onDeletePage}
|
onDeletePage={this.props.onDeletePage}
|
||||||
onMovePage={this.props.onMovePage}
|
onMovePage={this.props.onMovePage}
|
||||||
|
updateWikiConfig={this.props.updateWikiConfig}
|
||||||
pathStr={page.id}
|
pathStr={page.id}
|
||||||
currentPageId={this.props.currentPageId}
|
currentPageId={this.props.currentPageId}
|
||||||
addPageInside={this.props.addPageInside}
|
addPageInside={this.props.addPageInside}
|
||||||
|
@@ -191,6 +191,16 @@ class WikiAPI {
|
|||||||
return this.req.delete(url);
|
return this.req.delete(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moveWiki2Page(wikiId, moved_id, target_id, move_position) {
|
||||||
|
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/pages/';
|
||||||
|
let params = {
|
||||||
|
'moved_id': moved_id,
|
||||||
|
'target_id': target_id,
|
||||||
|
'move_position': move_position
|
||||||
|
};
|
||||||
|
return this.req.put(url, params);
|
||||||
|
}
|
||||||
|
|
||||||
deleteWiki2Folder(wikiId, folderId) {
|
deleteWiki2Folder(wikiId, folderId) {
|
||||||
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/folder/' + folderId + '/';
|
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/folder/' + folderId + '/';
|
||||||
return this.req.delete(url);
|
return this.req.delete(url);
|
||||||
|
@@ -26,8 +26,10 @@ from seahub.utils.db_api import SeafileDB
|
|||||||
from seahub.wiki2.models import Wiki2 as Wiki
|
from seahub.wiki2.models import Wiki2 as Wiki
|
||||||
from seahub.wiki2.utils import is_valid_wiki_name, can_edit_wiki, get_wiki_dirs_by_path, \
|
from seahub.wiki2.utils import is_valid_wiki_name, can_edit_wiki, get_wiki_dirs_by_path, \
|
||||||
get_wiki_config, WIKI_PAGES_DIR, WIKI_CONFIG_PATH, WIKI_CONFIG_FILE_NAME, is_group_wiki, \
|
get_wiki_config, WIKI_PAGES_DIR, WIKI_CONFIG_PATH, WIKI_CONFIG_FILE_NAME, is_group_wiki, \
|
||||||
check_wiki_admin_permission, check_wiki_permission, get_page_ids_in_folder, get_all_wiki_ids, \
|
check_wiki_admin_permission, check_wiki_permission, get_all_wiki_ids, get_and_gen_page_nav_by_id, \
|
||||||
get_and_gen_page_nav_by_id, get_current_level_page_ids, save_wiki_config
|
get_current_level_page_ids, save_wiki_config, gen_unique_id, gen_new_page_nav_by_id, pop_nav, \
|
||||||
|
delete_page, move_nav
|
||||||
|
|
||||||
from seahub.utils import is_org_context, get_user_repos, gen_inner_file_get_url, gen_file_upload_url, \
|
from seahub.utils import is_org_context, get_user_repos, gen_inner_file_get_url, gen_file_upload_url, \
|
||||||
normalize_dir_path, is_pro_version, check_filename_with_rename, is_valid_dirent_name, get_no_duplicate_obj_name
|
normalize_dir_path, is_pro_version, check_filename_with_rename, is_valid_dirent_name, get_no_duplicate_obj_name
|
||||||
from seahub.views import check_folder_permission
|
from seahub.views import check_folder_permission
|
||||||
@@ -415,14 +417,12 @@ class Wiki2PagesView(APIView):
|
|||||||
|
|
||||||
current_id = request.data.get('current_id', None)
|
current_id = request.data.get('current_id', None)
|
||||||
wiki_config = get_wiki_config(repo_id, request.user.username)
|
wiki_config = get_wiki_config(repo_id, request.user.username)
|
||||||
|
|
||||||
navigation = wiki_config.get('navigation', [])
|
navigation = wiki_config.get('navigation', [])
|
||||||
if not current_id:
|
if not current_id:
|
||||||
page_ids = {element.get('id') for element in navigation if element.get('type') != 'folder'}
|
page_ids = {element.get('id') for element in navigation if element.get('type') != 'folder'}
|
||||||
else:
|
else:
|
||||||
page_ids = []
|
page_ids = []
|
||||||
get_current_level_page_ids(navigation, current_id, page_ids)
|
get_current_level_page_ids(navigation, current_id, page_ids)
|
||||||
|
|
||||||
pages = wiki_config.get('pages', [])
|
pages = wiki_config.get('pages', [])
|
||||||
exist_page_names = [page.get('name') for page in pages if page.get('id') in page_ids]
|
exist_page_names = [page.get('name') for page in pages if page.get('id') in page_ids]
|
||||||
page_name = get_no_duplicate_obj_name(page_name, exist_page_names)
|
page_name = get_no_duplicate_obj_name(page_name, exist_page_names)
|
||||||
@@ -432,7 +432,6 @@ class Wiki2PagesView(APIView):
|
|||||||
parent_dir = os.path.join(WIKI_PAGES_DIR, str(sdoc_uuid))
|
parent_dir = os.path.join(WIKI_PAGES_DIR, str(sdoc_uuid))
|
||||||
path = os.path.join(parent_dir, new_file_name)
|
path = os.path.join(parent_dir, new_file_name)
|
||||||
seafile_api.mkdir_with_parents(repo_id, '/', parent_dir.strip('/'), request.user.username)
|
seafile_api.mkdir_with_parents(repo_id, '/', parent_dir.strip('/'), request.user.username)
|
||||||
|
|
||||||
# create new empty file
|
# create new empty file
|
||||||
if not is_valid_dirent_name(new_file_name):
|
if not is_valid_dirent_name(new_file_name):
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.')
|
return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.')
|
||||||
@@ -456,12 +455,85 @@ class Wiki2PagesView(APIView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
FileUUIDMap.objects.create_fileuuidmap_by_uuid(sdoc_uuid, repo_id, parent_dir, filename, is_dir=False)
|
FileUUIDMap.objects.create_fileuuidmap_by_uuid(sdoc_uuid, repo_id, parent_dir, filename, is_dir=False)
|
||||||
|
# update wiki_config
|
||||||
|
id_set = get_all_wiki_ids(navigation)
|
||||||
|
new_page_id = gen_unique_id(id_set)
|
||||||
|
file_info['page_id'] = new_page_id
|
||||||
|
gen_new_page_nav_by_id(navigation, new_page_id, current_id)
|
||||||
|
new_page = {
|
||||||
|
'id': new_page_id,
|
||||||
|
'name': page_name,
|
||||||
|
'path': path,
|
||||||
|
'icon': '',
|
||||||
|
'docUuid': str(sdoc_uuid)
|
||||||
|
}
|
||||||
|
pages.append(new_page)
|
||||||
|
|
||||||
|
if len(wiki_config) == 0:
|
||||||
|
wiki_config['version'] = 1
|
||||||
|
|
||||||
|
wiki_config['navigation'] = navigation
|
||||||
|
wiki_config['pages'] = pages
|
||||||
|
wiki_config = json.dumps(wiki_config)
|
||||||
|
save_wiki_config(wiki, request.user.username, wiki_config)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
error_msg = 'Internal Server Error'
|
error_msg = 'Internal Server Error'
|
||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
return Response(file_info)
|
wiki = wiki.to_dict()
|
||||||
|
wiki['wiki_config'] = wiki_config
|
||||||
|
|
||||||
|
return Response({'file_info': file_info})
|
||||||
|
|
||||||
|
def put(self, request, wiki_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)
|
||||||
|
navigation = wiki_config.get('navigation', [])
|
||||||
|
|
||||||
|
id_set = get_all_wiki_ids(navigation)
|
||||||
|
target_page_id = request.data.get('target_id', '')
|
||||||
|
moved_page_id = request.data.get('moved_id', '')
|
||||||
|
if (target_page_id not in id_set) or (moved_page_id not in id_set):
|
||||||
|
error_msg = 'Page not found'
|
||||||
|
logger.error(error_msg)
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
moved_nav = pop_nav(navigation, moved_page_id)
|
||||||
|
# Move one into one's own subset
|
||||||
|
judge_navs = get_all_wiki_ids([moved_nav])
|
||||||
|
if target_page_id in judge_navs:
|
||||||
|
error_msg = 'Internal Server Error'
|
||||||
|
logger.error(error_msg)
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
move_nav(navigation, target_page_id, moved_nav)
|
||||||
|
wiki_config['navigation'] = navigation
|
||||||
|
wiki_config = json.dumps(wiki_config)
|
||||||
|
|
||||||
|
try:
|
||||||
|
save_wiki_config(wiki, username, wiki_config)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
error_msg = 'Internal Server Error'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
return Response({'success': True})
|
||||||
|
|
||||||
|
|
||||||
class Wiki2PageView(APIView):
|
class Wiki2PageView(APIView):
|
||||||
@@ -576,29 +648,63 @@ class Wiki2PageView(APIView):
|
|||||||
error_msg = _("File is locked")
|
error_msg = _("File is locked")
|
||||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
sdoc_dir_path = os.path.dirname(path)
|
# check page
|
||||||
parent_dir = os.path.dirname(sdoc_dir_path)
|
navigation = wiki_config.get('navigation', [])
|
||||||
dir_name = os.path.basename(sdoc_dir_path)
|
id_set = get_all_wiki_ids(navigation)
|
||||||
|
if page_id not in id_set:
|
||||||
|
error_msg = 'Page not found'
|
||||||
|
logger.error(error_msg)
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
# update navigation and page
|
||||||
|
pop_nav(navigation, page_id)
|
||||||
|
id_set = get_all_wiki_ids(navigation)
|
||||||
|
new_pages, old_pages = delete_page(pages, id_set)
|
||||||
|
for old_page in old_pages:
|
||||||
|
sdoc_dir_path = os.path.dirname(old_page['path'])
|
||||||
|
parent_dir = os.path.dirname(sdoc_dir_path)
|
||||||
|
dir_name = os.path.basename(sdoc_dir_path)
|
||||||
|
old_page['sdoc_dir_path'] = sdoc_dir_path
|
||||||
|
old_page['parent_dir'] = parent_dir
|
||||||
|
old_page['dir_name'] = dir_name
|
||||||
|
|
||||||
# delete the folder where the sdoc is located
|
# delete the folder where the sdoc is located
|
||||||
try:
|
try:
|
||||||
seafile_api.del_file(repo_id, parent_dir, json.dumps([dir_name]), username)
|
for old_page in old_pages:
|
||||||
|
seafile_api.del_file(repo_id, old_page['parent_dir'], json.dumps([old_page['dir_name']]), username)
|
||||||
except SearpcError as e:
|
except SearpcError as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
error_msg = 'Internal Server Error'
|
error_msg = 'Internal Server Error'
|
||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
try: # rm sdoc fileuuid
|
try: # rm sdoc fileuuid
|
||||||
file_name = os.path.basename(path)
|
for old_page in old_pages:
|
||||||
file_uuid = get_seadoc_file_uuid(repo, path)
|
file_name = os.path.basename(old_page['path'])
|
||||||
FileComment.objects.filter(uuid=file_uuid).delete()
|
file_uuid = get_seadoc_file_uuid(repo, old_page['path'])
|
||||||
FileUUIDMap.objects.delete_fileuuidmap_by_path(repo_id, sdoc_dir_path, file_name, is_dir=False)
|
FileComment.objects.filter(uuid=file_uuid).delete()
|
||||||
SeadocHistoryName.objects.filter(doc_uuid=file_uuid).delete()
|
FileUUIDMap.objects.delete_fileuuidmap_by_path(repo_id, old_page['sdoc_dir_path'], file_name, is_dir=False)
|
||||||
SeadocDraft.objects.filter(doc_uuid=file_uuid).delete()
|
SeadocHistoryName.objects.filter(doc_uuid=file_uuid).delete()
|
||||||
SeadocCommentReply.objects.filter(doc_uuid=file_uuid).delete()
|
SeadocDraft.objects.filter(doc_uuid=file_uuid).delete()
|
||||||
|
SeadocCommentReply.objects.filter(doc_uuid=file_uuid).delete()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
|
||||||
|
# update wiki_config
|
||||||
|
try:
|
||||||
|
wiki_config['navigation'] = navigation
|
||||||
|
wiki_config['pages'] = new_pages
|
||||||
|
# TODO: add trash.
|
||||||
|
if 'trash_pages' in wiki_config:
|
||||||
|
wiki_config['trash_pages'].extend(old_pages)
|
||||||
|
else:
|
||||||
|
wiki_config['trash_pages'] = old_pages
|
||||||
|
wiki_config = json.dumps(wiki_config)
|
||||||
|
save_wiki_config(wiki, request.user.username, wiki_config)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
error_msg = 'Internal Server Error'
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
return Response({'success': True})
|
return Response({'success': True})
|
||||||
|
|
||||||
|
|
||||||
@@ -646,7 +752,6 @@ class Wiki2DuplicatePageView(APIView):
|
|||||||
# old page to new page
|
# old page to new page
|
||||||
old_to_new = {}
|
old_to_new = {}
|
||||||
get_and_gen_page_nav_by_id(id_set, navigation, page_id, old_to_new)
|
get_and_gen_page_nav_by_id(id_set, navigation, page_id, old_to_new)
|
||||||
|
|
||||||
# page_id not exist in wiki
|
# page_id not exist in wiki
|
||||||
if not old_to_new:
|
if not old_to_new:
|
||||||
error_msg = 'page %s not found.' % page_id
|
error_msg = 'page %s not found.' % page_id
|
||||||
|
@@ -16,7 +16,6 @@ from seahub.group.utils import is_group_admin, is_group_member
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
WIKI_PAGES_DIR = '/wiki-pages'
|
WIKI_PAGES_DIR = '/wiki-pages'
|
||||||
WIKI_CONFIG_PATH = '_Internal/Wiki'
|
WIKI_CONFIG_PATH = '_Internal/Wiki'
|
||||||
WIKI_CONFIG_FILE_NAME = 'index.json'
|
WIKI_CONFIG_FILE_NAME = 'index.json'
|
||||||
@@ -173,6 +172,24 @@ def get_and_gen_page_nav_by_id(id_set, navigation, page_id, old_to_new):
|
|||||||
get_and_gen_page_nav_by_id(id_set, new_navigation, page_id, old_to_new)
|
get_and_gen_page_nav_by_id(id_set, new_navigation, page_id, old_to_new)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_new_page_nav_by_id(navigation, page_id, current_id):
|
||||||
|
new_nav = {
|
||||||
|
'id': page_id,
|
||||||
|
'type': 'page',
|
||||||
|
}
|
||||||
|
if current_id:
|
||||||
|
for nav in navigation:
|
||||||
|
if nav.get('type') == 'page' and nav.get('id') == current_id:
|
||||||
|
sub_nav = nav.get('children', [])
|
||||||
|
sub_nav.append(new_nav)
|
||||||
|
nav['children'] = sub_nav
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
gen_new_page_nav_by_id(nav.get('children', []), page_id, current_id)
|
||||||
|
else:
|
||||||
|
navigation.append(new_nav)
|
||||||
|
|
||||||
|
|
||||||
def get_current_level_page_ids(navigation, page_id, ids=[]):
|
def get_current_level_page_ids(navigation, page_id, ids=[]):
|
||||||
for item in navigation:
|
for item in navigation:
|
||||||
if item.get('id') == page_id:
|
if item.get('id') == page_id:
|
||||||
@@ -207,3 +224,39 @@ def save_wiki_config(wiki, username, wiki_config):
|
|||||||
resp = requests.post(upload_link, files=files, data=data)
|
resp = requests.post(upload_link, files=files, data=data)
|
||||||
if not resp.ok:
|
if not resp.ok:
|
||||||
raise Exception(resp.text)
|
raise Exception(resp.text)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_page(pages, id_set):
|
||||||
|
new_pages = []
|
||||||
|
old_pages = []
|
||||||
|
for page in pages:
|
||||||
|
if page['id'] in id_set:
|
||||||
|
new_pages.append(page)
|
||||||
|
else:
|
||||||
|
old_pages.append(page)
|
||||||
|
return new_pages, old_pages
|
||||||
|
|
||||||
|
|
||||||
|
def pop_nav(navigation, page_id):
|
||||||
|
for nav in navigation:
|
||||||
|
if nav['id'] == page_id:
|
||||||
|
navigation.remove(nav)
|
||||||
|
return nav
|
||||||
|
if 'children' in nav and nav['children']:
|
||||||
|
result = pop_nav(nav['children'], page_id)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def move_nav(navigation, target_id, moved_nav):
|
||||||
|
for nav in navigation:
|
||||||
|
if nav['id'] == target_id:
|
||||||
|
if 'children' in nav:
|
||||||
|
nav['children'].insert(0, moved_nav)
|
||||||
|
else:
|
||||||
|
nav['children'] = [moved_nav]
|
||||||
|
return
|
||||||
|
if 'children' in nav:
|
||||||
|
move_nav(nav['children'], target_id, moved_nav)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user