diff --git a/frontend/src/pages/wiki2/side-panel.css b/frontend/src/pages/wiki2/side-panel.css index ba349fb54c..01cc137544 100644 --- a/frontend/src/pages/wiki2/side-panel.css +++ b/frontend/src/pages/wiki2/side-panel.css @@ -3,18 +3,29 @@ display: flex; flex-direction: column; overflow: hidden; - background-color: #F7F7F5;; + background-color: #F7F7F5; border-right: 1px solid #F1F1EF; } .wiki2-side-panel .wiki2-side-panel-top { padding: 8px 20px; display: flex; + justify-content: space-between; align-items: center; flex-shrink: 0; height: 44px; } +.wiki2-side-panel .wiki2-side-panel-top .add-new-page { + padding: 0 4px; + cursor: pointer; + border-radius: 4px; +} + +.wiki2-side-panel .wiki2-side-panel-top .add-new-page:hover { + background-color: #DFDFDD; +} + .wiki2-side-panel .wiki2-side-nav { flex: auto; display: flex; diff --git a/frontend/src/pages/wiki2/side-panel.js b/frontend/src/pages/wiki2/side-panel.js index f68300d2d9..dc01abb621 100644 --- a/frontend/src/pages/wiki2/side-panel.js +++ b/frontend/src/pages/wiki2/side-panel.js @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import deepCopy from 'deep-copy'; +import { UncontrolledTooltip } from 'reactstrap'; import { gettext, isWiki2, wikiId } from '../../utils/constants'; import toaster from '../../components/toast'; import Loading from '../../components/loading'; @@ -14,6 +15,7 @@ import Folder from './models/folder'; import Page from './models/page'; import wikiAPI from '../../utils/wiki-api'; import { FOLDER } from './constant'; +import { Utils } from '../../utils/utils'; import './side-panel.css'; @@ -339,12 +341,38 @@ class SidePanel extends Component { ); }; + handleAddNewPage = () => { + const pageName = 'Untitled'; // default page name + const voidFn = () => void 0; + wikiAPI.createWiki2Page(wikiId, pageName).then(res => { + const { obj_name, parent_dir, doc_uuid,page_name } = res.data; + this.onAddNewPage({ + name: page_name, + icon: '', + path: parent_dir === '/' ? `/${obj_name}` : `${parent_dir}/${obj_name}`, + docUuid: doc_uuid, + successCallback: voidFn, + errorCallback: voidFn, + }); + }).catch((error) => { + let errMessage = Utils.getErrorMsg(error); + toaster.danger(errMessage); + this.onError(); + }); + }; + render() { const { isLoading, config } = this.props; return (

{repoName}

+
+ +
+ + {gettext('New page')} +
{isLoading ? : (isObjectNotEmpty(config) ? this.renderFolderView() : this.renderNoFolder())} diff --git a/media/css/sf_font3/iconfont.css b/media/css/sf_font3/iconfont.css index d60f4f60eb..03043c8000 100644 --- a/media/css/sf_font3/iconfont.css +++ b/media/css/sf_font3/iconfont.css @@ -1,11 +1,11 @@ @font-face { font-family: "sf3-font"; /* Project id 1230969 */ - src: url('iconfont.eot?t=1716779999367'); /* IE9 */ - src: url('iconfont.eot?t=1716779999367#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('iconfont.woff2?t=1716779999367') format('woff2'), - url('iconfont.woff?t=1716779999367') format('woff'), - url('iconfont.ttf?t=1716779999367') format('truetype'), - url('iconfont.svg?t=1716779999367#sf3-font') format('svg'); + src: url('iconfont.eot?t=1716950761276'); /* IE9 */ + src: url('iconfont.eot?t=1716950761276#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('iconfont.woff2?t=1716950761276') format('woff2'), + url('iconfont.woff?t=1716950761276') format('woff'), + url('iconfont.ttf?t=1716950761276') format('truetype'), + url('iconfont.svg?t=1716950761276#sf3-font') format('svg'); } .sf3-font { @@ -16,6 +16,10 @@ -moz-osx-font-smoothing: grayscale; } +.sf3-font-new-page:before { + content: "\e823"; +} + .sf3-font-upload-files:before { content: "\e821"; } diff --git a/media/css/sf_font3/iconfont.eot b/media/css/sf_font3/iconfont.eot index 1ffbf7357e..cc08c124d2 100644 Binary files a/media/css/sf_font3/iconfont.eot and b/media/css/sf_font3/iconfont.eot differ diff --git a/media/css/sf_font3/iconfont.js b/media/css/sf_font3/iconfont.js index 807191c58f..f355507d33 100644 --- a/media/css/sf_font3/iconfont.js +++ b/media/css/sf_font3/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_1230969='',function(h){var c=(c=document.getElementsByTagName("script"))[c.length-1],l=c.getAttribute("data-injectcss"),c=c.getAttribute("data-disable-injectsvg");if(!c){var s,o,t,v,i,m=function(c,l){l.parentNode.insertBefore(c,l)};if(l&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}s=function(){var c,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_1230969,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(c=document.body).firstChild?m(l,c.firstChild):c.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(s,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),s()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(t=s,v=h.document,i=!1,f(),v.onreadystatechange=function(){"complete"==v.readyState&&(v.onreadystatechange=null,z())})}function z(){i||(i=!0,t())}function f(){try{v.documentElement.doScroll("left")}catch(c){return void setTimeout(f,50)}z()}}(window); \ No newline at end of file +window._iconfont_svg_string_1230969='',function(h){var c=(c=document.getElementsByTagName("script"))[c.length-1],l=c.getAttribute("data-injectcss"),c=c.getAttribute("data-disable-injectsvg");if(!c){var s,o,t,v,i,m=function(c,l){l.parentNode.insertBefore(c,l)};if(l&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}s=function(){var c,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_1230969,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(c=document.body).firstChild?m(l,c.firstChild):c.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(s,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),s()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(t=s,v=h.document,i=!1,f(),v.onreadystatechange=function(){"complete"==v.readyState&&(v.onreadystatechange=null,z())})}function z(){i||(i=!0,t())}function f(){try{v.documentElement.doScroll("left")}catch(c){return void setTimeout(f,50)}z()}}(window); \ No newline at end of file diff --git a/media/css/sf_font3/iconfont.svg b/media/css/sf_font3/iconfont.svg index 64de3e564c..d047c168dc 100644 --- a/media/css/sf_font3/iconfont.svg +++ b/media/css/sf_font3/iconfont.svg @@ -14,6 +14,8 @@ /> + + diff --git a/media/css/sf_font3/iconfont.ttf b/media/css/sf_font3/iconfont.ttf index 24db2185bf..ba46c15d02 100644 Binary files a/media/css/sf_font3/iconfont.ttf and b/media/css/sf_font3/iconfont.ttf differ diff --git a/media/css/sf_font3/iconfont.woff b/media/css/sf_font3/iconfont.woff index 13cbc24a06..cf8c7a4429 100644 Binary files a/media/css/sf_font3/iconfont.woff and b/media/css/sf_font3/iconfont.woff differ diff --git a/media/css/sf_font3/iconfont.woff2 b/media/css/sf_font3/iconfont.woff2 index c766abc1f1..50af2462be 100644 Binary files a/media/css/sf_font3/iconfont.woff2 and b/media/css/sf_font3/iconfont.woff2 differ diff --git a/seahub/api2/endpoints/wiki2.py b/seahub/api2/endpoints/wiki2.py index dc10b066e9..497fcf05be 100644 --- a/seahub/api2/endpoints/wiki2.py +++ b/seahub/api2/endpoints/wiki2.py @@ -24,9 +24,9 @@ from seahub.api2.utils import api_error, to_python_boolean 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, \ get_wiki_config, WIKI_PAGES_DIR, WIKI_CONFIG_PATH, WIKI_CONFIG_FILE_NAME, is_group_wiki, \ - check_wiki_admin_permission, check_wiki_permission + check_wiki_admin_permission, check_wiki_permission, get_page_ids_in_folder 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 + 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.file import send_file_access_msg from seahub.base.templatetags.seahub_tags import email2nickname @@ -424,19 +424,29 @@ class Wiki2PagesView(APIView): error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) - sdoc_uuid = uuid.uuid4() - file_name = page_name + '.sdoc' - parent_dir = os.path.join(WIKI_PAGES_DIR, str(sdoc_uuid)) - path = os.path.join(parent_dir, file_name) + folder_id = request.data.get('folder_id', None) + wiki_config = get_wiki_config(repo_id, request.user.username) + navigation = wiki_config.get('navigation') + if not folder_id: + page_ids = {element.get('id') for element in navigation if element.get('type') != 'folder'} + else: + page_ids = get_page_ids_in_folder(navigation, folder_id) + + pages = wiki_config.get('pages', []) + 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) + + sdoc_uuid = uuid.uuid4() + new_file_name = page_name + '.sdoc' + parent_dir = os.path.join(WIKI_PAGES_DIR, str(sdoc_uuid)) + path = os.path.join(parent_dir, new_file_name) seafile_api.mkdir_with_parents(repo_id, '/', parent_dir.strip('/'), request.user.username) - new_file_name = check_filename_with_rename(repo_id, parent_dir, file_name) # create new empty file if not is_valid_dirent_name(new_file_name): return api_error(status.HTTP_400_BAD_REQUEST, 'name invalid.') - new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name) try: seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, request.user.username) except Exception as e: @@ -451,6 +461,7 @@ class Wiki2PagesView(APIView): new_file_path = posixpath.join(parent_dir, new_file_name) file_info = self.get_file_info(repo_id, new_file_path) file_info['doc_uuid'] = sdoc_uuid + file_info['page_name'] = page_name filename = os.path.basename(path) try: diff --git a/seahub/wiki2/utils.py b/seahub/wiki2/utils.py index 82838e2053..cf3226a721 100644 --- a/seahub/wiki2/utils.py +++ b/seahub/wiki2/utils.py @@ -88,3 +88,14 @@ def check_wiki_permission(wiki, username): if username == wiki.owner: return True return False + + +def get_page_ids_in_folder(navigation, folder_id): + for directory in navigation: + if directory.get('type') == 'folder' and directory.get('id') == folder_id: + children = directory.get('children', []) + page_ids = {child.get('id') for child in children if child.get('type') == 'page'} + return page_ids + elif directory.get('type') == 'folder': + navigation = directory.get('children', []) + return get_page_ids_in_folder(navigation, folder_id)