1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-10 03:17:39 +00:00

Wiki add new page below or above (#7118)

* Wiki add new page below or above

* change var name

* remove sibling page

* update create wiki page logic

* fix page does not exist

---------

Co-authored-by: 孙永强 <11704063+s-yongqiang@user.noreply.gitee.com>
This commit is contained in:
Michael An 2024-11-29 22:03:59 +08:00 committed by GitHub
parent 51d5706aa6
commit d63b68e8ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 185 additions and 48 deletions

View File

@ -132,7 +132,7 @@
background-color: #DFDFDD; background-color: #DFDFDD;
} }
.wiki-nav .wiki-page-item .sf3-font.sf3-font-enlarge, .wiki-nav .wiki-page-item .wiki-add-page-btn .sf3-font.sf3-font-enlarge,
.wiki-nav .wiki-page-item .more-wiki-page-operation .seafile-multicolor-icon-more-level { .wiki-nav .wiki-page-item .more-wiki-page-operation .seafile-multicolor-icon-more-level {
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
@ -270,13 +270,13 @@
} }
.wiki-nav, .wiki-nav,
.wiki-nav .wiki-page-item .sf3-font.sf3-font-enlarge:hover, .wiki-nav .wiki-page-item .wiki-add-page-btn .sf3-font.sf3-font-enlarge:hover,
.wiki-nav .wiki-page-item .seafile-multicolor-icon-more-level:hover { .wiki-nav .wiki-page-item .seafile-multicolor-icon-more-level:hover {
color: #212529; color: #212529;
} }
.wiki-nav .wiki2-trash .sf3-font, .wiki-nav .wiki2-trash .sf3-font,
.wiki-nav .wiki-page-item .sf3-font.sf3-font-enlarge, .wiki-nav .wiki-page-item .wiki-add-page-btn .sf3-font.sf3-font-enlarge,
.wiki-nav .wiki-page-item .seafile-multicolor-icon-more-level { .wiki-nav .wiki-page-item .seafile-multicolor-icon-more-level {
color: #666; color: #666;
} }

View File

@ -83,16 +83,16 @@ class SidePanel extends PureComponent {
}); });
}; };
addPage = (page, parentId, successCallback, errorCallback, jumpToNewPage = true) => { addPage = (page, parent_id, successCallback, errorCallback, jumpToNewPage = true) => {
const { config } = this.props; const { config } = this.props;
const navigation = config.navigation; const navigation = config.navigation;
const pageId = page.id; const page_id = page.id;
config.pages.push(page); config.pages.push(page);
PageUtils.addPage(navigation, pageId, parentId); PageUtils.addPage({ navigation, page_id, parent_id });
config.navigation = navigation; config.navigation = navigation;
JSON.stringify(config); JSON.stringify(config);
this.props.updateWikiConfig(config); this.props.updateWikiConfig(config);
jumpToNewPage && this.props.setCurrentPage(pageId, successCallback); jumpToNewPage && this.props.setCurrentPage(page_id, successCallback);
successCallback && successCallback(); successCallback && successCallback();
}; };
@ -104,6 +104,19 @@ class SidePanel extends PureComponent {
this.props.updateWikiConfig(config); this.props.updateWikiConfig(config);
}; };
addSiblingPage = (page, parent_id, insert_position, sibling_page_id, successCallback) => {
const { config } = this.props;
const navigation = config.navigation;
const page_id = page.page_id;
config.pages.push(page);
PageUtils.addPage({ navigation, page_id, parent_id, insert_position, sibling_page_id });
config.navigation = navigation;
JSON.stringify(config);
this.props.updateWikiConfig(config);
this.props.setCurrentPage(page_id, successCallback);
successCallback && successCallback();
};
toggleTrashDialog = () => { toggleTrashDialog = () => {
this.setState({ isShowTrashDialog: !this.state.isShowTrashDialog }); this.setState({ isShowTrashDialog: !this.state.isShowTrashDialog });
}; };
@ -128,6 +141,7 @@ class SidePanel extends PureComponent {
getCurrentPageId={this.props.getCurrentPageId} getCurrentPageId={this.props.getCurrentPageId}
addPageInside={this.addPageInside} addPageInside={this.addPageInside}
toggleTrashDialog={this.toggleTrashDialog} toggleTrashDialog={this.toggleTrashDialog}
addSiblingPage={this.addSiblingPage}
/> />
} }
</div> </div>

View File

@ -6,14 +6,16 @@ import { Utils } from '../../../utils/utils';
import toaster from '../../../components/toast'; import toaster from '../../../components/toast';
import Loading from '../../../components/loading'; import Loading from '../../../components/loading';
import wikiAPI from '../../../utils/wiki-api'; import wikiAPI from '../../../utils/wiki-api';
import { INSERT_POSITION } from './constants';
import '../css/add-new-page-dialog.css'; import '../css/add-new-page-dialog.css';
const propTypes = { const propTypes = {
page: PropTypes.object,
title: PropTypes.node, title: PropTypes.node,
toggle: PropTypes.func.isRequired, toggle: PropTypes.func.isRequired,
onAddNewPage: PropTypes.func, onAddNewPage: PropTypes.func,
getCurrentPageId: PropTypes.func.isRequired, insertPosition: PropTypes.string,
}; };
@ -71,9 +73,11 @@ class AddNewPageDialog extends React.Component {
}; };
createPage = (pageName) => { createPage = (pageName) => {
wikiAPI.createWiki2Page(wikiId, pageName, this.props.getCurrentPageId()).then(res => { const { insertPosition, page } = this.props;
wikiAPI.createWiki2Page(wikiId, pageName, page.id, insertPosition).then(res => {
const { page_id, obj_name, doc_uuid, parent_dir } = res.data.file_info; const { page_id, obj_name, doc_uuid, parent_dir } = res.data.file_info;
this.props.onAddNewPage({ this.props.onAddNewPage({
id: page_id,
page_id: page_id, page_id: page_id,
name: pageName, name: pageName,
icon: '', icon: '',
@ -126,4 +130,8 @@ class AddNewPageDialog extends React.Component {
AddNewPageDialog.propTypes = propTypes; AddNewPageDialog.propTypes = propTypes;
AddNewPageDialog.defaultProps = {
insertPosition: INSERT_POSITION.INNER,
};
export default AddNewPageDialog; export default AddNewPageDialog;

View File

@ -0,0 +1,5 @@
export const INSERT_POSITION = {
ABOVE: 'above',
BELOW: 'below',
INNER: 'inner',
};

View File

@ -1,3 +1,5 @@
import { INSERT_POSITION } from './constants';
class NewPage { class NewPage {
constructor(id) { constructor(id) {
this.id = id; this.id = id;
@ -8,26 +10,52 @@ class NewPage {
export default class PageUtils { export default class PageUtils {
static addPage(navigation, page_id, parentId) { static addPage({ navigation, page_id, parent_id, insert_position, sibling_page_id }) {
if (!parentId) { if (!parent_id) {
navigation.push(new NewPage(page_id)); const newPage = new NewPage(page_id);
if (sibling_page_id) {
let insertIndex = navigation.findIndex(item => item.id === sibling_page_id);
if (insertIndex > -1) {
if (insert_position === INSERT_POSITION.ABOVE) {
insertIndex -= 1;
}
navigation.splice(insertIndex + 1, 0, newPage);
} else {
navigation.push(newPage);
}
} else {
navigation.push(newPage);
}
} else { } else {
navigation.forEach(item => { navigation.forEach(item => {
this._addPageRecursion(page_id, item, parentId); this._addPageRecursion({ page_id, item, parent_id, insert_position, sibling_page_id });
}); });
} }
} }
static _addPageRecursion(page_id, item, parentId) { static _addPageRecursion({ page_id, item, parent_id, insert_position, sibling_page_id }) {
if (!Array.isArray(item.children)) { if (!Array.isArray(item.children)) {
item.children = []; item.children = [];
} }
if (item.id === parentId) { if (item.id === parent_id) {
item.children.push(new NewPage(page_id)); const newPage = new NewPage(page_id);
if (sibling_page_id) {
let insertIndex = item.children.findIndex(item => item.id === sibling_page_id);
if (insertIndex > -1) {
if (insert_position === INSERT_POSITION.ABOVE) {
insertIndex -= 1;
}
item.children.splice(insertIndex + 1, 0, newPage);
} else {
item.children.push(newPage);
}
} else {
item.children.push(newPage);
}
return true; return true;
} }
item.children && item.children.forEach(item => { item.children && item.children.forEach(item => {
this._addPageRecursion(page_id, item, parentId); this._addPageRecursion({ page_id, item, parent_id, insert_position, sibling_page_id });
}); });
} }

View File

@ -4,6 +4,7 @@ import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap
import toaster from '../../../../components/toast'; import toaster from '../../../../components/toast';
import { gettext } from '../../../../utils/constants'; import { gettext } from '../../../../utils/constants';
import { getWikPageLink } from '../../utils'; import { getWikPageLink } from '../../utils';
import { INSERT_POSITION } from '../constants';
export default class PageDropdownMenu extends Component { export default class PageDropdownMenu extends Component {
@ -13,6 +14,7 @@ export default class PageDropdownMenu extends Component {
pagesLength: PropTypes.number, pagesLength: PropTypes.number,
toggle: PropTypes.func, toggle: PropTypes.func,
toggleNameEditor: PropTypes.func, toggleNameEditor: PropTypes.func,
toggleInsertSiblingPage: PropTypes.func,
duplicatePage: PropTypes.func, duplicatePage: PropTypes.func,
onDeletePage: PropTypes.func, onDeletePage: PropTypes.func,
isOnlyOnePage: PropTypes.bool, isOnlyOnePage: PropTypes.bool,
@ -46,6 +48,14 @@ export default class PageDropdownMenu extends Component {
this.props.onDeletePage(); this.props.onDeletePage();
}; };
addPageAbove = () => {
this.props.toggleInsertSiblingPage(INSERT_POSITION.ABOVE);
};
addPageBelow = () => {
this.props.toggleInsertSiblingPage(INSERT_POSITION.BELOW);
};
duplicatePage = () => { duplicatePage = () => {
const { page } = this.props; const { page } = this.props;
this.props.duplicatePage({ from_page_id: page.id }, () => {}, this.duplicatePageFailure); this.props.duplicatePage({ from_page_id: page.id }, () => {}, this.duplicatePageFailure);
@ -98,6 +108,14 @@ export default class PageDropdownMenu extends Component {
<i className="sf3-font sf3-font-rename" /> <i className="sf3-font sf3-font-rename" />
<span className="item-text">{gettext('Modify name')}</span> <span className="item-text">{gettext('Modify name')}</span>
</DropdownItem> </DropdownItem>
<DropdownItem onClick={this.addPageAbove}>
<i className="sf3-font sf3-font-enlarge" />
<span className="item-text">{gettext('Add page above')}</span>
</DropdownItem>
<DropdownItem onClick={this.addPageBelow}>
<i className="sf3-font sf3-font-enlarge" />
<span className="item-text">{gettext('Add page below')}</span>
</DropdownItem>
<DropdownItem onClick={this.duplicatePage}> <DropdownItem onClick={this.duplicatePage}>
<i className="sf3-font sf3-font-copy1" /> <i className="sf3-font sf3-font-copy1" />
<span className="item-text">{gettext('Duplicate page')}</span> <span className="item-text">{gettext('Duplicate page')}</span>

View File

@ -11,6 +11,7 @@ import Icon from '../../../../components/icon';
import DraggedPageItem from './dragged-page-item'; import DraggedPageItem from './dragged-page-item';
import CustomIcon from '../../custom-icon'; import CustomIcon from '../../custom-icon';
import { eventBus } from '../../../../components/common/event-bus'; import { eventBus } from '../../../../components/common/event-bus';
import { INSERT_POSITION } from '../constants';
class PageItem extends Component { class PageItem extends Component {
@ -21,6 +22,8 @@ class PageItem extends Component {
isShowOperationDropdown: false, isShowOperationDropdown: false,
isShowDeleteDialog: false, isShowDeleteDialog: false,
isShowInsertPage: false, isShowInsertPage: false,
isShowAddSiblingPage: false,
insertPosition: '',
pageName: props.page.name || '', pageName: props.page.name || '',
isSelected: props.getCurrentPageId() === props.page.id, isSelected: props.getCurrentPageId() === props.page.id,
isMouseEnter: false, isMouseEnter: false,
@ -73,6 +76,17 @@ class PageItem extends Component {
this.setState({ isShowInsertPage: !this.state.isShowInsertPage }); this.setState({ isShowInsertPage: !this.state.isShowInsertPage });
}; };
toggleInsertSiblingPage = (position) => {
let insertPosition = null;
if (position === INSERT_POSITION.BELOW || position === INSERT_POSITION.ABOVE) {
insertPosition = position;
}
this.setState({
insertPosition,
isShowAddSiblingPage: !this.state.isShowAddSiblingPage,
});
};
savePageProperties = () => { savePageProperties = () => {
const { name, id } = this.props.page; const { name, id } = this.props.page;
const pageName = this.state.pageName.trim(); const pageName = this.state.pageName.trim();
@ -134,6 +148,7 @@ class PageItem extends Component {
isOnlyOnePage={isOnlyOnePage} isOnlyOnePage={isOnlyOnePage}
page={Object.assign({}, pages.find(item => item.id === id), page)} page={Object.assign({}, pages.find(item => item.id === id), page)}
pageIndex={index} pageIndex={index}
parentPageId={this.props.page.id}
isEditMode={isEditMode} isEditMode={isEditMode}
duplicatePage={this.props.duplicatePage} duplicatePage={this.props.duplicatePage}
setCurrentPage={this.props.setCurrentPage} setCurrentPage={this.props.setCurrentPage}
@ -150,6 +165,7 @@ class PageItem extends Component {
setClassName={this.props.setClassName} setClassName={this.props.setClassName}
getClassName={this.props.getClassName} getClassName={this.props.getClassName}
layerDragProps={this.props.layerDragProps} layerDragProps={this.props.layerDragProps}
addSiblingPage={this.props.addSiblingPage}
/> />
); );
}; };
@ -176,6 +192,11 @@ class PageItem extends Component {
this.props.addPageInside(Object.assign({ parentPageId: this.props.page.id }, newPage)); this.props.addPageInside(Object.assign({ parentPageId: this.props.page.id }, newPage));
}; };
onAddSiblingPage = (newPage) => {
const { page } = this.props;
this.props.addSiblingPage(newPage, this.props.parentPageId, this.state.insertPosition, page.id, this.toggleInsertSiblingPage);
};
getPageClassName = () => { getPageClassName = () => {
const { isOver, canDrop, isEditMode, layerDragProps } = this.props; const { isOver, canDrop, isEditMode, layerDragProps } = this.props;
const isOverPage = isOver && canDrop; const isOverPage = isOver && canDrop;
@ -257,6 +278,7 @@ class PageItem extends Component {
toggleNameEditor={this.toggleNameEditor} toggleNameEditor={this.toggleNameEditor}
duplicatePage={this.props.duplicatePage} duplicatePage={this.props.duplicatePage}
onDeletePage={this.openDeleteDialog} onDeletePage={this.openDeleteDialog}
toggleInsertSiblingPage={this.toggleInsertSiblingPage}
/> />
} }
</div> </div>
@ -275,9 +297,18 @@ class PageItem extends Component {
{this.state.isShowInsertPage && {this.state.isShowInsertPage &&
<AddNewPageDialog <AddNewPageDialog
toggle={this.toggleInsertPage} toggle={this.toggleInsertPage}
getCurrentPageId={this.props.getCurrentPageId}
onAddNewPage={this.onAddNewPage} onAddNewPage={this.onAddNewPage}
title={gettext('Add page inside')} title={gettext('Add page inside')}
page={this.props.page}
/>
}
{this.state.isShowAddSiblingPage &&
<AddNewPageDialog
toggle={this.toggleInsertSiblingPage}
onAddNewPage={this.onAddSiblingPage}
title={gettext('Add page')}
insertPosition={this.state.insertPosition}
page={this.props.page}
/> />
} }
</div> </div>

View File

@ -19,6 +19,7 @@ class WikiNav extends Component {
onDeletePage: PropTypes.func, onDeletePage: PropTypes.func,
onMovePage: PropTypes.func, onMovePage: PropTypes.func,
duplicatePage: PropTypes.func, duplicatePage: PropTypes.func,
addSiblingPage: PropTypes.func,
getCurrentPageId: PropTypes.func, getCurrentPageId: PropTypes.func,
addPageInside: PropTypes.func, addPageInside: PropTypes.func,
updateWikiConfig: PropTypes.func.isRequired, updateWikiConfig: PropTypes.func.isRequired,
@ -91,6 +92,7 @@ class WikiNav extends Component {
pathStr={page.id} pathStr={page.id}
getCurrentPageId={this.props.getCurrentPageId} getCurrentPageId={this.props.getCurrentPageId}
addPageInside={this.props.addPageInside} addPageInside={this.props.addPageInside}
addSiblingPage={this.props.addSiblingPage}
getFoldState={this.getFoldState} getFoldState={this.getFoldState}
toggleExpand={this.toggleExpand} toggleExpand={this.toggleExpand}
id_page_map={id_page_map} id_page_map={id_page_map}

View File

@ -181,13 +181,16 @@ class WikiAPI {
return this.req.get(url); return this.req.get(url);
} }
createWiki2Page(wikiId, pageName, currentId) { createWiki2Page(wikiId, pageName, currentId, insertPosition) {
const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/pages/'; const url = this.server + '/api/v2.1/wiki2/' + wikiId + '/pages/';
let form = new FormData(); let form = new FormData();
form.append('page_name', pageName); form.append('page_name', pageName);
if (currentId) { if (currentId) {
form.append('current_id', currentId); form.append('current_id', currentId);
} }
if (insertPosition) {
form.append('insert_position', insertPosition);
}
return this._sendPostRequest(url, form); return this._sendPostRequest(url, form);
} }

View File

@ -500,6 +500,12 @@ class Wiki2PagesView(APIView):
error_msg = 'page_name invalid.' error_msg = 'page_name invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
current_id = request.data.get('current_id', None)
insert_position = request.data.get('insert_position', None)
positions = ['above', 'below', 'inner']
if insert_position and insert_position not in positions:
error_msg = 'insert_position invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
wiki = Wiki.objects.get(wiki_id=wiki_id) wiki = Wiki.objects.get(wiki_id=wiki_id)
if not wiki: if not wiki:
@ -514,16 +520,15 @@ class Wiki2PagesView(APIView):
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
repo_id = wiki.repo_id repo_id = wiki.repo_id
# resource check # resource check
repo = seafile_api.get_repo(repo_id) repo = seafile_api.get_repo(repo_id)
if not repo: if not repo:
error_msg = 'Library %s not found.' % repo_id error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
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', [])
# side panel create Untitled page
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:
@ -537,22 +542,6 @@ class Wiki2PagesView(APIView):
new_file_name = page_name + '.sdoc' new_file_name = page_name + '.sdoc'
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)
# create new empty file
if not is_valid_dirent_name(new_file_name):
return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.')
try:
seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, request.user.username)
except Exception as e:
if str(e) == 'Too many files in library.':
error_msg = _("The number of files in library exceeds the limit")
return api_error(HTTP_447_TOO_MANY_FILES_IN_LIBRARY, error_msg)
else:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
new_file_path = posixpath.join(parent_dir, new_file_name) new_file_path = posixpath.join(parent_dir, new_file_name)
file_info = self.get_file_info(repo_id, new_file_path) file_info = self.get_file_info(repo_id, new_file_path)
file_info['doc_uuid'] = sdoc_uuid file_info['doc_uuid'] = sdoc_uuid
@ -565,7 +554,27 @@ class Wiki2PagesView(APIView):
id_set = get_all_wiki_ids(navigation) id_set = get_all_wiki_ids(navigation)
new_page_id = gen_unique_id(id_set) new_page_id = gen_unique_id(id_set)
file_info['page_id'] = new_page_id file_info['page_id'] = new_page_id
gen_new_page_nav_by_id(navigation, new_page_id, current_id) is_find = [False]
gen_new_page_nav_by_id(navigation, new_page_id, current_id, insert_position, is_find)
if not is_find[0]:
error_msg = 'Current page does not exist'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# create new empty file
seafile_api.mkdir_with_parents(repo_id, '/', parent_dir.strip('/'), request.user.username)
if not is_valid_dirent_name(new_file_name):
return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.')
try:
seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, request.user.username)
except Exception as e:
if str(e) == 'Too many files in library.':
error_msg = _("The number of files in library exceeds the limit")
return api_error(HTTP_447_TOO_MANY_FILES_IN_LIBRARY, error_msg)
else:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
new_page = { new_page = {
'id': new_page_id, 'id': new_page_id,
'name': page_name, 'name': page_name,

View File

@ -173,22 +173,41 @@ 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): def gen_new_page_nav_by_id(navigation, page_id, current_id, insert_position, is_find):
new_nav = { new_nav = {
'id': page_id, 'id': page_id,
'type': 'page', 'type': 'page',
} }
if current_id: if current_id:
for nav in navigation: if insert_position == 'inner':
if nav.get('type') == 'page' and nav.get('id') == current_id: for nav in navigation:
sub_nav = nav.get('children', []) if nav.get('type') == 'page' and nav.get('id') == current_id:
sub_nav.append(new_nav) sub_nav = nav.get('children', [])
nav['children'] = sub_nav sub_nav.append(new_nav)
return nav['children'] = sub_nav
else: is_find[0] = True
gen_new_page_nav_by_id(nav.get('children', []), page_id, current_id) return True
else:
gen_new_page_nav_by_id(nav.get('children', []), page_id, current_id, insert_position, is_find)
elif insert_position == 'above':
for index, nav in enumerate(navigation):
if nav.get('type') == 'page' and nav.get('id') == current_id:
navigation.insert(index, new_nav)
is_find[0] = True
return True
else:
gen_new_page_nav_by_id(nav.get('children', []), page_id, current_id, insert_position, is_find)
elif insert_position == 'below':
for index, nav in enumerate(navigation):
if nav.get('type') == 'page' and nav.get('id') == current_id:
navigation.insert(index+1, new_nav)
is_find[0] = True
return True
else:
gen_new_page_nav_by_id(nav.get('children', []), page_id, current_id, insert_position, is_find)
else: else:
navigation.append(new_nav) navigation.append(new_nav)
return True
def get_current_level_page_ids(navigation, page_id, ids=[]): def get_current_level_page_ids(navigation, page_id, ids=[]):