From 17114eb2fc5e8f690ebcb4948e804c9c2ca6e027 Mon Sep 17 00:00:00 2001 From: Michael An <2331806369@qq.com> Date: Wed, 3 Jul 2024 17:57:10 +0800 Subject: [PATCH] 12.0 refactor wiki folder (#6290) * 01 remove wiki folder * remove folder * 03 remove wiki folder css * 04 optimise codes --- frontend/src/assets/icons/wiki-folder.svg | 24 -- frontend/src/pages/wiki2/constant.js | 4 - frontend/src/pages/wiki2/css/wiki-nav.css | 145 +-------- frontend/src/pages/wiki2/index.js | 11 +- frontend/src/pages/wiki2/models/folder.js | 8 - .../src/pages/wiki2/models/wiki-config.js | 44 ++- frontend/src/pages/wiki2/side-panel.js | 255 ++-------------- frontend/src/pages/wiki2/top-nav/index.jsx | 2 +- .../wiki2/wiki-nav/add-page-dropdownmenu.js | 52 ---- frontend/src/pages/wiki2/wiki-nav/constant.js | 2 - .../wiki-nav/folders/dragged-folder-item.js | 103 ------- .../wiki2/wiki-nav/folders/folder-item.js | 284 ------------------ .../folders/folder-operation-dropdownmenu.js | 75 ----- .../pages/wiki2/wiki-nav/new-folder-dialog.js | 98 ------ .../src/pages/wiki2/wiki-nav/page-utils.js | 169 +---------- .../wiki2/wiki-nav/pages/dragged-page-item.js | 42 +-- .../wiki2/wiki-nav/pages/page-dropdownmenu.js | 98 +----- .../pages/wiki2/wiki-nav/pages/page-item.js | 46 +-- .../pages/wiki2/wiki-nav/wiki-nav-footer.js | 48 --- frontend/src/pages/wiki2/wiki-nav/wiki-nav.js | 124 +------- 20 files changed, 119 insertions(+), 1515 deletions(-) delete mode 100644 frontend/src/assets/icons/wiki-folder.svg delete mode 100644 frontend/src/pages/wiki2/constant.js delete mode 100644 frontend/src/pages/wiki2/models/folder.js delete mode 100644 frontend/src/pages/wiki2/wiki-nav/add-page-dropdownmenu.js delete mode 100644 frontend/src/pages/wiki2/wiki-nav/constant.js delete mode 100644 frontend/src/pages/wiki2/wiki-nav/folders/dragged-folder-item.js delete mode 100644 frontend/src/pages/wiki2/wiki-nav/folders/folder-item.js delete mode 100644 frontend/src/pages/wiki2/wiki-nav/folders/folder-operation-dropdownmenu.js delete mode 100644 frontend/src/pages/wiki2/wiki-nav/new-folder-dialog.js delete mode 100644 frontend/src/pages/wiki2/wiki-nav/wiki-nav-footer.js diff --git a/frontend/src/assets/icons/wiki-folder.svg b/frontend/src/assets/icons/wiki-folder.svg deleted file mode 100644 index 2bb0e7eb9a..0000000000 --- a/frontend/src/assets/icons/wiki-folder.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - -folder - - - - - - diff --git a/frontend/src/pages/wiki2/constant.js b/frontend/src/pages/wiki2/constant.js deleted file mode 100644 index 1d1b537b08..0000000000 --- a/frontend/src/pages/wiki2/constant.js +++ /dev/null @@ -1,4 +0,0 @@ -const FOLDER = 'folder'; -const PAGE = 'page'; - -export { FOLDER, PAGE }; diff --git a/frontend/src/pages/wiki2/css/wiki-nav.css b/frontend/src/pages/wiki2/css/wiki-nav.css index 0516740bed..f3c134e548 100644 --- a/frontend/src/pages/wiki2/css/wiki-nav.css +++ b/frontend/src/pages/wiki2/css/wiki-nav.css @@ -15,14 +15,11 @@ padding-bottom: 0.5rem; overflow: auto; user-select: none; + max-height: 100%; } -.wiki-nav .page-folder { - position: relative; -} - -.wiki-nav .page-folder.can-drop::after, -.wiki-nav .page-folder.can-drop-top::after { +.wiki-nav .can-drop::after, +.wiki-nav .can-drop-top::after { content: ''; width: 100%; height: 1px; @@ -32,7 +29,16 @@ background-color: #666; } -.wiki-nav .page-folder .page-folder-children { +.wiki-nav .can-drop::after { + top: unset; + bottom: 0; +} + +.wiki-nav .can-drop-top::after { + top: 0; +} + +.wiki-nav .page-children { transition: height 0.25s ease-in-out 0s; } @@ -44,16 +50,6 @@ border-bottom: 1px solid #666; } -.wiki-nav .page-folder.can-drop::after { - top: unset; - bottom: 0; -} - -.wiki-nav .page-folder.can-drop-top::after { - top: 0; -} - -.wiki-nav .page-folder-wrapper, .wiki-nav .wiki-page-item { position: relative; display: flex; @@ -72,7 +68,6 @@ background-color: #EDEDEA; } -.wiki-nav .page-folder-wrapper:hover, .wiki-nav .wiki-page-item:hover { background-color: #EFEFED; } @@ -81,7 +76,6 @@ background-color: #E6E6E4; } -.wiki-nav .folder-main, .wiki-nav .wiki-page-item-main { flex: 1; display: flex; @@ -90,15 +84,6 @@ overflow: hidden; } -.wiki-nav .icon-expand-folder { - display: inline-block; - font-size: 12px; - transform: scale(0.8); - color: #b5b5b5; - cursor: pointer; -} - -.wiki-nav .folder-content, .wiki-nav .wiki-page-content { height: 100%; padding-right: 8px; @@ -109,29 +94,25 @@ overflow: hidden; } -.wiki-nav .in-folder .wiki-page-content { +.wiki-nav .wiki-page-content { padding-left: calc(12 * 0.8px + 0.5rem); } -.wiki-nav .folder-content:hover, .wiki-nav .wiki-page-content:hover { cursor: pointer; } -.wiki-nav .folder-content .dtable-font, .wiki-nav .wiki-page-content .dtable-font { margin-right: 6px; font-size: 14px; } -.wiki-nav .folder-content .folder-name, .wiki-nav .wiki-page-content .wiki-page-title { height: 40px; line-height: 40px; flex: 1; } -.wiki-nav .folder-operation-dropdownmenu, .wiki-nav .more-wiki-page-operation { width: 24px; height: 24px; @@ -141,37 +122,31 @@ } .wiki-nav .wiki-add-page-btn:hover, -.wiki-nav .folder-operation:hover, .wiki-nav .more-wiki-page-operation:hover { border-radius: 3px; background-color: #DFDFDD; } .wiki-nav .wiki-page-item .sf3-font.sf3-font-enlarge, -.wiki-nav .page-folder-wrapper .folder-operation-dropdownmenu .seafile-multicolor-icon-more-level, .wiki-nav .wiki-page-item .more-wiki-page-operation .seafile-multicolor-icon-more-level { cursor: pointer; opacity: 0; } .wiki-nav .wiki-page-item:hover .sf3-font.sf3-font-enlarge, -.wiki-nav .page-folder-wrapper:hover .folder-operation-dropdownmenu .seafile-multicolor-icon-more-level, .wiki-nav .wiki-page-item:hover .more-wiki-page-operation .seafile-multicolor-icon-more-level { opacity: 1; } -.wiki-nav .folder-operation-dropdownmenu:hover, .wiki-nav .more-wiki-page-operation:hover { cursor: pointer; } -.wiki-nav .folder-operation-dropdownmenu .dtable-font, .wiki-nav .more-wiki-page-operation .dtable-font { font-size: 14px; margin-right: 10px; } -.wiki-nav .folder-list .page-folder.fold-freezed .btn-folder-operation, .wiki-nav .wiki-page-item.wiki-page-freezed .sf3-font.sf3-font-enlarge, .wiki-nav .wiki-page-item.wiki-page-freezed .seafile-multicolor-icon-more-level { opacity: 1; @@ -254,69 +229,6 @@ margin: 0.2rem 0; } -/* folders dropdown */ -.wiki-nav .more-wiki-page-operation .btn-move-to-folder { - display: flex; - align-items: center; -} - -.wiki-nav .more-wiki-page-operation .move-to-folders-toggle { - opacity: 0; - width: 0; - min-width: 0; - margin-left: -12px; - padding: 0; -} - -.wiki-nav .more-wiki-page-operation .folders-dropdown-menu { - margin-top: -16px; - margin-left: 10px; -} - -.wiki-nav .folders-dropdown-menu .dropdown-item { - display: flex; - align-items: center; -} - -.wiki-nav .more-wiki-page-operation .btn-move-to-folder:focus .dtable-icon-insert-right { - color: #fff; -} - -.wiki-nav .folders-dropdown { - width: 100%; -} - -.wiki-nav .folders-dropdown-toggle { - display: flex; - align-items: center; -} - -.wiki-nav .folders-dropdown .item-text { - flex: 1; -} - -.wiki-nav .folders-dropdown .dropdown-menu { - max-height: 300px; - overflow-y: auto; -} - -.wiki-nav .folders-dropdown .dropdown-menu .folder-name { - display: inline-block; - width: 100%; -} - -.wiki-nav .folders-dropdown .icon-dropdown-toggle { - display: inline-flex; - align-items: center; - width: 12px; - height: 12px; - margin-right: 12px; -} - -.wiki-nav .folders-dropdown .icon-dropdown-toggle .item-icon { - transform: scale(0.8); -} - .wiki-nav .wiki-page-item.page-can-drop::after, .wiki-nav .wiki-page-item.page-can-drop-top::after { content: ''; @@ -351,40 +263,15 @@ .wiki-nav, .wiki-nav .wiki-page-item .sf3-font.sf3-font-enlarge:hover, -.wiki-nav .wiki-page-item .seafile-multicolor-icon-more-level:hover, -.wiki-nav .page-folder .seafile-multicolor-icon-more-level:hover, -.wiki-nav .icon-expand-folder:hover { +.wiki-nav .wiki-page-item .seafile-multicolor-icon-more-level:hover { color: #212529; } .wiki-nav .wiki-page-item .sf3-font.sf3-font-enlarge, -.wiki-nav .wiki-page-item .seafile-multicolor-icon-more-level, -.wiki-nav .page-folder .seafile-multicolor-icon-more-level, -.wiki-nav .icon-expand-folder { +.wiki-nav .wiki-page-item .seafile-multicolor-icon-more-level { color: #666; } -.wiki-nav .page-folder-wrapper.can-drop-top::before { - content: ''; - width: 100%; - height: 1px; - position: absolute; - left: 0; - top: 0; - background-color: #666; -} - -.wiki-nav .page-folder-wrapper.can-drop::after { - content: ''; - width: 100%; - height: 1px; - position: absolute; - left: 0; - background-color: #666; - top: unset; - bottom: 0; -} - .svg-item { width: 1em; height: 1em; diff --git a/frontend/src/pages/wiki2/index.js b/frontend/src/pages/wiki2/index.js index d55a0a1af9..b61d42697e 100644 --- a/frontend/src/pages/wiki2/index.js +++ b/frontend/src/pages/wiki2/index.js @@ -103,15 +103,8 @@ class Wiki extends Component { getFirstPageId = (config) => { if (!config || !Array.isArray(config.navigation)) return ''; - for (let i = 0; i < config.navigation.length; i++) { - const item = config.navigation[i] || {}; - if (item.type === 'page') { - return item.id; - } - if (item.type === 'folder' && item.children[0]) { - return item.children[0].id; - } - } + const firstPage = config.navigation[0] || {}; + return firstPage.id; }; getSdocFileContent = (docUuid, accessToken) => { diff --git a/frontend/src/pages/wiki2/models/folder.js b/frontend/src/pages/wiki2/models/folder.js deleted file mode 100644 index ade6d65d23..0000000000 --- a/frontend/src/pages/wiki2/models/folder.js +++ /dev/null @@ -1,8 +0,0 @@ -export default class Folder { - constructor(object) { - this.type = 'folder'; - this.id = object.id; - this.name = object.name; - this.children = Array.isArray(object.children) ? object.children : []; - } -} diff --git a/frontend/src/pages/wiki2/models/wiki-config.js b/frontend/src/pages/wiki2/models/wiki-config.js index cd814932c0..ba90a0c470 100644 --- a/frontend/src/pages/wiki2/models/wiki-config.js +++ b/frontend/src/pages/wiki2/models/wiki-config.js @@ -1,21 +1,37 @@ import Page from './page'; -import Folder from './folder'; export default class WikiConfig { constructor(object) { - this.version = object.version || 1; - this.navigation = (Array.isArray(object.navigation) ? object.navigation : []).map(item => { - if (item.type === 'folder') { - return new Folder(item); - } else if (item.type === 'page') { - return { - id: item.id, - type: item.type, - children: item.children || [], - }; + const { version = 1, pages = [], navigation = [] } = object; + this.version = version; + this.pages = pages.map(page => new Page(page)); + this.navigation = navigation.filter(item => { + return item.type === 'page'; + }); + // Render pages in folder to navigation root + const page_id_map = {}; + this.pages.forEach(page => { + page_id_map[page.id] = false; + }); + function traversePage(node) { + if (!node) return; + if (node.id) { + page_id_map[node.id] = true; } - return null; - }).filter(item => !!item); - this.pages = Array.isArray(object.pages) ? object.pages.map(page => new Page(page)) : []; + if (Array.isArray(node.children)) { + node.children.forEach(child => traversePage(child)); + } + } + traversePage({ children: this.navigation }); + for (let key in page_id_map) { + if (page_id_map[key] === false) { + const page = this.pages.find(item => item.id === key); + this.navigation.push({ + id: page.id, + type: 'page', + children: page.children || [], + }); + } + } } } diff --git a/frontend/src/pages/wiki2/side-panel.js b/frontend/src/pages/wiki2/side-panel.js index 075e6f8f93..b724139c8a 100644 --- a/frontend/src/pages/wiki2/side-panel.js +++ b/frontend/src/pages/wiki2/side-panel.js @@ -7,14 +7,9 @@ import toaster from '../../components/toast'; import Loading from '../../components/loading'; import WikiNav from './wiki-nav/index'; import PageUtils from './wiki-nav/page-utils'; -import NewFolderDialog from './wiki-nav/new-folder-dialog'; -import AddNewPageDialog from './wiki-nav/add-new-page-dialog'; -import WikiNavFooter from './wiki-nav/wiki-nav-footer'; import { generateUniqueId, isObjectNotEmpty } from './utils'; -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 WikiExternalOperations from './wiki-external-operations'; @@ -37,10 +32,6 @@ class SidePanel extends Component { constructor(props) { super(props); - this.state = { - isShowNewFolderDialog: false, - isShowAddNewPageDialog: false, - }; } confirmDeletePage = (pageId) => { @@ -50,7 +41,7 @@ class SidePanel extends Component { config.pages.splice(index, 1); PageUtils.deletePage(navigation, pageId); this.props.saveWikiConfig(config); - // TODO: To delete a page, do you need to delete all subpages at once (requires a new API) + // TODO: delete a page, then delete all subpages wikiAPI.deleteWiki2Page(wikiId, pageId); if (config.pages.length > 0) { this.props.setCurrentPage(config.pages[0].id); @@ -72,7 +63,7 @@ class SidePanel extends Component { const navigation = config.navigation; const pageId = generateUniqueId(navigation); const newPage = new Page({ id: pageId, name, icon, path, docUuid }); - this.addPage(newPage, this.current_folder_id, successCallback, errorCallback, jumpToNewPage); + this.addPage(newPage, '', successCallback, errorCallback, jumpToNewPage); }; duplicatePage = async (fromPageConfig, successCallback, errorCallback) => { @@ -102,240 +93,32 @@ class SidePanel extends Component { this.props.saveWikiConfig(config, onSuccess, errorCallback); }; - movePage = ({ moved_page_id, target_page_id, source_page_folder_id, target_page_folder_id, move_position }) => { + movePage = ({ moved_page_id, target_page_id, move_position }) => { let config = deepCopy(this.props.config); let { navigation } = config; - PageUtils.movePage(navigation, moved_page_id, target_page_id, source_page_folder_id, target_page_folder_id, move_position); + PageUtils.movePage(navigation, moved_page_id, target_page_id, move_position); config.navigation = navigation; this.props.saveWikiConfig(config); }; - movePageOut = (moved_page_id, source_id, target_id, move_position) => { - let config = deepCopy(this.props.config); - let { navigation } = config; - PageUtils.movePageOut(navigation, moved_page_id, source_id, target_id, move_position); - config.navigation = navigation; - this.props.saveWikiConfig(config); - }; - - // Create a new folder in the root directory (not supported to create a new subfolder in the folder) - addPageFolder = (folder_data, parent_folder_id) => { - const { config } = this.props; - const { navigation } = config; - let folder_id = generateUniqueId(navigation); - let newFolder = new Folder({ id: folder_id, ...folder_data }); - // No parent folder, directly add to the root directory - if (!parent_folder_id) { - config.navigation.push(newFolder); - } else { // Recursively find the parent folder and add - navigation.forEach(item => { - if (item.type === FOLDER) { - this._addFolder(item, newFolder, parent_folder_id); - } - }); - } - this.props.saveWikiConfig(config); - }; - - _addFolder(folder, newFolder, parent_folder_id) { - if (folder.id === parent_folder_id) { - folder.children.push(newFolder); - return; - } - folder.children.forEach(item => { - if (item.type === FOLDER) { - this._addFolder(item, newFolder, parent_folder_id); - } - }); - } - - onModifyFolder = (folder_id, folder_data) => { - const { config } = this.props; - const { navigation } = config; - PageUtils.modifyFolder(navigation, folder_id, folder_data); - config.navigation = navigation; - this.props.saveWikiConfig(config); - }; - - onDeleteFolder = (page_folder_id) => { - const { config } = this.props; - const { navigation, pages } = config; - PageUtils.deleteFolder(navigation, pages, page_folder_id); - // TODO: delete all pages inside the folder, A new API is required - config.navigation = navigation; - this.props.saveWikiConfig(config); - }; - - // Drag a folder to the front and back of another folder - onMoveFolder = (moved_folder_id, target_id, move_position) => { - const { config } = this.props; - const { navigation } = config; - let updatedNavigation = deepCopy(navigation); - - // Get the moved folder first and delete the original location - let moved_folder; - let moved_folder_index = PageUtils.getFolderIndexById(updatedNavigation, moved_folder_id); - if (moved_folder_index === -1) { - updatedNavigation.forEach(item => { - if (item.type === FOLDER) { - moved_folder_index = PageUtils.getFolderIndexById(item.children, moved_folder_id); - if (moved_folder_index > -1) { - moved_folder = item.children[moved_folder_index]; - item.children.splice(moved_folder_index, 1); - } - } - }); - } else { - moved_folder = updatedNavigation[moved_folder_index]; - updatedNavigation.splice(moved_folder_index, 1); - } - let indexOffset = 0; - if (move_position === 'move_below') { - indexOffset++; - } - // Get the location of the release - let target_folder_index = PageUtils.getFolderIndexById(updatedNavigation, target_id); - if (target_folder_index === -1) { - updatedNavigation.forEach(item => { - if (item.type === FOLDER) { - target_folder_index = PageUtils.getFolderIndexById(item.children, target_id); - if (target_folder_index > -1) { - item.children.splice(target_folder_index + indexOffset, 0, moved_folder); - } - } else { - // not changed - updatedNavigation = navigation; - } - }); - } else { - updatedNavigation.splice(target_folder_index + indexOffset, 0, moved_folder); - } - config.navigation = updatedNavigation; - this.props.saveWikiConfig(config); - }; - - // Not support yet: Move a folder into another folder - moveFolderToFolder = (moved_folder_id, target_id) => { - let { config } = this.props; - let { navigation } = config; - - // Find the folder and move it to this new folder - let target_folder = PageUtils.getFolderById(navigation, target_id); - if (!target_folder) { - toaster.danger('Only_support_two_level_folders'); - return; - } - - let moved_folder; - let moved_folder_index = PageUtils.getFolderIndexById(navigation, moved_folder_id); - - // The original directory is in the root directory - if (moved_folder_index > -1) { - moved_folder = PageUtils.getFolderById(navigation, moved_folder_id); - // If moved folder There are other directories under the ID, and dragging is not supported - if (moved_folder.children.some(item => item.type === FOLDER)) { - toaster.danger('Only_support_two_level_folders'); - return; - } - target_folder.children.push(moved_folder); - navigation.splice(moved_folder_index, 1); - } else { // The original directory is not in the root directory - navigation.forEach(item => { - if (item.type === FOLDER) { - let moved_folder_index = PageUtils.getFolderIndexById(item.children, moved_folder_id); - if (moved_folder_index > -1) { - moved_folder = item.children[moved_folder_index]; - target_folder.children.push(moved_folder); - item.children.splice(moved_folder_index, 1); - } - } - }); - } - config.navigation = navigation; - this.props.saveWikiConfig(config); - }; - - onToggleAddFolder = () => { - this.setState({ isShowNewFolderDialog: !this.state.isShowNewFolderDialog }); - }; - - openAddPageDialog = (folder_id) => { - this.current_folder_id = folder_id; - this.setState({ isShowAddNewPageDialog: true }); - }; - - closeAddNewPageDialog = () => { - this.current_folder_id = null; - this.setState({ isShowAddNewPageDialog: false }); - }; - - onSetFolderId = (folder_id) => { - this.current_folder_id = folder_id; - }; - - renderFolderView = () => { + renderWikiNav = () => { const { config, onUpdatePage } = this.props; const { pages, navigation } = config; return (
- - {this.state.isShowNewFolderDialog && - - } - {this.state.isShowAddNewPageDialog && - - } -
- ); - }; - - renderNoFolder = () => { - return ( -
- {isWiki2 && - - } - {this.state.isShowNewFolderDialog && - - } - {this.state.isShowAddNewPageDialog && - }
@@ -364,7 +147,7 @@ class SidePanel extends Component { }; render() { - const { isLoading, config } = this.props; + const { isLoading } = this.props; return (
@@ -377,7 +160,7 @@ class SidePanel extends Component {
- {isLoading ? : (isObjectNotEmpty(config) ? this.renderFolderView() : this.renderNoFolder())} + {isLoading ? : this.renderWikiNav()}
diff --git a/frontend/src/pages/wiki2/top-nav/index.jsx b/frontend/src/pages/wiki2/top-nav/index.jsx index 2e45cbd005..94ac31a68e 100644 --- a/frontend/src/pages/wiki2/top-nav/index.jsx +++ b/frontend/src/pages/wiki2/top-nav/index.jsx @@ -46,7 +46,7 @@ function WikiTopNav({ config, currentPageId }) { return (
- + {item.name}
{index !== paths.length - 1 &&
/
} diff --git a/frontend/src/pages/wiki2/wiki-nav/add-page-dropdownmenu.js b/frontend/src/pages/wiki2/wiki-nav/add-page-dropdownmenu.js deleted file mode 100644 index 7a6ae73de5..0000000000 --- a/frontend/src/pages/wiki2/wiki-nav/add-page-dropdownmenu.js +++ /dev/null @@ -1,52 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Dropdown, DropdownMenu, DropdownItem, DropdownToggle } from 'reactstrap'; -import { gettext } from '../../../utils/constants'; - -class AddPageDropdownMenu extends Component { - - toggle = event => { - this.onStopPropagation(event); - this.props.toggleDropdown(); - }; - - addPage = event => { - this.onStopPropagation(event); - this.props.onToggleAddPage(null); - }; - - onToggleAddFolder = event => { - this.onStopPropagation(event); - this.props.onToggleAddFolder(); - }; - - onStopPropagation = event => { - event && event.nativeEvent && event.nativeEvent.stopImmediatePropagation(); - }; - - render() { - return ( - - - - - - {gettext('Add page')} - - - - {gettext('Add folder')} - - - - ); - } -} - -AddPageDropdownMenu.propTypes = { - toggleDropdown: PropTypes.func, - onToggleAddPage: PropTypes.func, - onToggleAddFolder: PropTypes.func, -}; - -export default AddPageDropdownMenu; diff --git a/frontend/src/pages/wiki2/wiki-nav/constant.js b/frontend/src/pages/wiki2/wiki-nav/constant.js deleted file mode 100644 index 46f924a576..0000000000 --- a/frontend/src/pages/wiki2/wiki-nav/constant.js +++ /dev/null @@ -1,2 +0,0 @@ -export const DRAGGED_FOLDER_MODE = 'wiki-folder'; -export const DRAGGED_PAGE_MODE = 'wiki-page'; diff --git a/frontend/src/pages/wiki2/wiki-nav/folders/dragged-folder-item.js b/frontend/src/pages/wiki2/wiki-nav/folders/dragged-folder-item.js deleted file mode 100644 index 6052c04a31..0000000000 --- a/frontend/src/pages/wiki2/wiki-nav/folders/dragged-folder-item.js +++ /dev/null @@ -1,103 +0,0 @@ -import { DragSource, DropTarget } from 'react-dnd'; -import { DRAGGED_FOLDER_MODE, DRAGGED_PAGE_MODE } from '../constant'; -import FolderItem from './folder-item'; - -const dragSource = { - beginDrag(props, monitor) { - const { folderIndex, folder } = props; - return { - idx: folderIndex, - data: folder, - mode: DRAGGED_FOLDER_MODE, - }; - }, - endDrag(props, monitor) { - const sourceRow = monitor.getItem(); - const didDrop = monitor.didDrop(); - let targetRow = {}; - if (!didDrop) { - return { sourceRow, targetRow }; - } - }, - isDragging(props, monitor) { - const { folderIndex: currentIndex, draggedPage } = props; - const { idx } = draggedPage; - return idx > currentIndex; - }, -}; - -const dropTarget = { - drop(props, monitor) { - const sourceRow = monitor.getItem(); - const { folder: targetFolder } = props; - const targetFolderId = targetFolder.id; - const className = props.getClassName(); - if (!className) return; - let move_position; - if (className.includes('can-drop')) { - move_position = 'move_below'; - } - if (className.includes('can-drop-top')) { - move_position = 'move_above'; - } - let moveInto = className.includes('dragged-page-over'); - - // 1. drag source is page - if (sourceRow.mode === DRAGGED_PAGE_MODE) { - const sourceFolderId = sourceRow.folderId; - const draggedPageId = sourceRow.data.id; - // 1.1 move page into folder - if (moveInto) { - props.onMovePage({ - moved_page_id: draggedPageId, - target_page_id: null, - source_page_folder_id: sourceFolderId, - target_page_folder_id: targetFolderId, - move_position, - }); - return; - } else { // 1.2 Drag the page above or below the folder - props.movePageOut(draggedPageId, sourceFolderId, targetFolderId, move_position); - return; - } - } - // 2. drag source is folder - if (sourceRow.mode === DRAGGED_FOLDER_MODE) { - const draggedFolderId = sourceRow.data.id; - // 2.0 If dragged folder and target folder are the same folder, return - if (targetFolderId === draggedFolderId) { - return; - } - // 2.1 Do not support drag folder into another folder - if (moveInto) { - // props.moveFolderToFolder(draggedFolderId, targetFolderId); - return; - } else { - // 2.2 Drag folder above or below another folder - props.onMoveFolder(draggedFolderId, targetFolderId, move_position); - } - return; - } - // 3. Drag other dom - return; - } -}; - -const dragCollect = (connect, monitor) => ({ - connectDragSource: connect.dragSource(), - connectDragPreview: connect.dragPreview(), - isDragging: monitor.isDragging(), -}); - -const dropCollect = (connect, monitor) => ({ - connectDropTarget: connect.dropTarget(), - isOver: monitor.isOver(), - canDrop: monitor.canDrop(), - draggedPage: monitor.getItem(), - connect, - monitor, -}); - -export default DropTarget('WikiNav', dropTarget, dropCollect)( - DragSource('WikiNav', dragSource, dragCollect)(FolderItem) -); diff --git a/frontend/src/pages/wiki2/wiki-nav/folders/folder-item.js b/frontend/src/pages/wiki2/wiki-nav/folders/folder-item.js deleted file mode 100644 index 4dbe611438..0000000000 --- a/frontend/src/pages/wiki2/wiki-nav/folders/folder-item.js +++ /dev/null @@ -1,284 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; -import FolderOperationDropdownMenu from './folder-operation-dropdownmenu'; -import DraggedPageItem from '../pages/dragged-page-item'; -import DraggedFolderItem from './dragged-folder-item'; -import NameEditPopover from '../../common/name-edit-popover'; -import NavItemIcon from '../../common/nav-item-icon'; - -class FolderItem extends Component { - - constructor(props) { - super(props); - const { name, icon } = props.folder; - this.state = { - isEditing: false, - icon: icon || '', - name: name || '', - isMouseEnter: false, - }; - } - - toggleExpand = (e) => { - e.nativeEvent.stopImmediatePropagation(); - this.props.toggleExpand(this.props.folder.id); - this.forceUpdate(); - }; - - onClickFolderChildren = (e) => { - e.stopPropagation(); - e.nativeEvent.stopImmediatePropagation(); - }; - - openFolderEditor = () => { - this.setState({ isEditing: true }); - }; - - closeFolderEditor = () => { - if (this.state.isEditing) { - const { name, icon } = this.state; - this.props.onModifyFolder(this.props.folder.id, { name, icon }); - this.setState({ isEditing: false }); - } - }; - - onChangeName = (name) => { - this.setState({ name }); - }; - - onChangeIcon = (icon) => { - this.setState({ icon }); - }; - - changeItemFreeze = (isFreeze) => { - this.isFreeze = true; - }; - - renderFolder = (folder, index, pagesLength, isOnlyOnePage, id_page_map) => { - const { isEditMode, pages, pathStr } = this.props; - const { id: folderId } = folder; - return ( - - ); - }; - - renderPage = (page, index, pagesLength, isOnlyOnePage) => { - const { isEditMode, pages, folder, pathStr } = this.props; - const id = page.id; - if (!pages.find(item => item.id === id)) return; - return ( - item.id === id), page)} - pageIndex={index} - folderId={folder.id} - isEditMode={isEditMode} - renderFolderMenuItems={this.props.renderFolderMenuItems} - duplicatePage={this.props.duplicatePage} - onSetFolderId={this.props.onSetFolderId} - setCurrentPage={this.props.setCurrentPage} - onUpdatePage={this.props.onUpdatePage} - onDeletePage={this.props.onDeletePage} - onMovePageToFolder={(targetFolderId) => { - this.props.onMovePageToFolder(folder.id, page.id, targetFolderId); - }} - onMovePage={this.props.onMovePage} - onMoveFolder={this.props.onMoveFolder} - pages={pages} - pathStr={pathStr + '-' + page.id} - currentPageId={this.props.currentPageId} - addPageInside={this.props.addPageInside} - getFoldState={this.props.getFoldState} - toggleExpand={this.props.toggleExpand} - /> - ); - }; - - getFolderClassName = (layerDragProps, state) => { - if (!state || ! layerDragProps || !layerDragProps.clientOffset) { - return 'page-folder-wrapper'; - } - let y = layerDragProps.clientOffset.y; - let top = this.foldWrapprRef.getBoundingClientRect().y; - let className = ''; - // middle - if (top + 10 < y && y < top + 30) { - className += ' dragged-page-over '; - } - // top - if (top + 10 > y) { - className += ' can-drop-top '; - } - // bottom - if (top + 30 < y) { - className += ' can-drop '; - } - this.props.setClassName(className); - return className + 'page-folder-wrapper'; - }; - - getFolderChildrenHeight = () => { - const folded = this.props.getFoldState(this.props.folder.id); - if (folded) return 0; - return 'auto'; - }; - - onMouseEnter = () => { - this.setState({ isMouseEnter: true }); - }; - - onMouseLeave = () => { - this.setState({ isMouseEnter: false }); - }; - - render() { - const { - connectDropTarget, connectDragPreview, connectDragSource, isOver, canDrop, - isEditMode, folder, pagesLength, id_page_map, isOnlyOnePage, layerDragProps, - } = this.props; - const { isEditing } = this.state; - const { id: folderId, name, children } = folder; - const folded = this.props.getFoldState(folderId); - let navItemId = `folder-item-${folderId}`; - let fn = isEditMode ? connectDragSource : (argu) => {argu;}; - return ( -
this.foldRef = ref} - onClick={this.toggleExpand} - > - {fn(connectDropTarget( - connectDragPreview( -
this.foldWrapprRef = ref} - onMouseEnter={this.onMouseEnter} - onMouseLeave={this.onMouseLeave} - > -
-
- {this.state.isMouseEnter ? -
- -
- : - - } - {name} - {isEditing && - - } -
-
- {isEditMode && - - } -
- ) - )) - } -
- {!folded && children && - children.map((item, index) => { - return item.type === 'folder' ? this.renderFolder(item, index, pagesLength, isOnlyOnePage, id_page_map) : this.renderPage(item, index, pagesLength, isOnlyOnePage); - }) - } -
-
- ); - } -} - -FolderItem.propTypes = { - isEditMode: PropTypes.bool, - folder: PropTypes.object, - folderIndex: PropTypes.number, - pagesLength: PropTypes.number, - id_page_map: PropTypes.object, - isOver: PropTypes.bool, - canDrop: PropTypes.bool, - isDragging: PropTypes.bool, - connectDropTarget: PropTypes.func, - connectDragPreview: PropTypes.func, - connectDragSource: PropTypes.func, - renderFolderMenuItems: PropTypes.func, - duplicatePage: PropTypes.func, - onSetFolderId: PropTypes.func, - toggleExpand: PropTypes.func, - onToggleAddPage: PropTypes.func, - onModifyFolder: PropTypes.func, - onDeleteFolder: PropTypes.func, - setCurrentPage: PropTypes.func, - onUpdatePage: PropTypes.func, - onDeletePage: PropTypes.func, - onMovePageToFolder: PropTypes.func, - onMovePage: PropTypes.func, - isOnlyOnePage: PropTypes.bool, - pages: PropTypes.array, - onMoveFolder: PropTypes.func, - moveFolderToFolder: PropTypes.func, - pathStr: PropTypes.string, - setClassName: PropTypes.func, - getClassName: PropTypes.func, - movePageOut: PropTypes.func, - layerDragProps: PropTypes.object, - getFoldState: PropTypes.func, - currentPageId: PropTypes.string, - addPageInside: PropTypes.func, -}; - -export default FolderItem; diff --git a/frontend/src/pages/wiki2/wiki-nav/folders/folder-operation-dropdownmenu.js b/frontend/src/pages/wiki2/wiki-nav/folders/folder-operation-dropdownmenu.js deleted file mode 100644 index e9372e0d75..0000000000 --- a/frontend/src/pages/wiki2/wiki-nav/folders/folder-operation-dropdownmenu.js +++ /dev/null @@ -1,75 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; -import { gettext } from '../../../../utils/constants'; -import Icon from '../../../../components/icon'; - -export default class FolderOperationDropdownMenu extends Component { - - static propTypes = { - changeItemFreeze: PropTypes.func, - openFolderEditor: PropTypes.func, - onDeleteFolder: PropTypes.func, - onToggleAddPage: PropTypes.func, - folderId: PropTypes.string, - }; - - constructor(props) { - super(props); - this.state = { - isMenuShow: false, - }; - } - - onDropdownToggle = (e) => { - e.stopPropagation(); - const isMenuShow = !this.state.isMenuShow; - this.props.changeItemFreeze(isMenuShow); - this.setState({ isMenuShow }); - }; - - openFolderEditor = (evt) => { - evt.nativeEvent.stopImmediatePropagation(); - this.props.openFolderEditor(); - }; - - onDeleteFolder = (evt) => { - evt.nativeEvent.stopImmediatePropagation(); - this.props.onDeleteFolder(this.props.folderId); - }; - - render() { - return ( - <> - - - - - - - - {gettext('Add page')} - - - - {gettext('Modify name')} - - - - {gettext('Delete folder')} - - - - - ); - } -} diff --git a/frontend/src/pages/wiki2/wiki-nav/new-folder-dialog.js b/frontend/src/pages/wiki2/wiki-nav/new-folder-dialog.js deleted file mode 100644 index 38f41b3ed4..0000000000 --- a/frontend/src/pages/wiki2/wiki-nav/new-folder-dialog.js +++ /dev/null @@ -1,98 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input, Button, Alert } from 'reactstrap'; -import { gettext } from '../../../utils/constants'; - -export default class NewFolderDialog extends Component { - - static propTypes = { - onAddFolder: PropTypes.func, - onToggleAddFolderDialog: PropTypes.func, - }; - - constructor(props) { - super(props); - this.state = { - folderName: '', - errMessage: '', - iconClassName: '', - }; - } - - componentDidMount() { - document.addEventListener('keydown', this.onHotKey); - } - - componentWillUnmount() { - document.removeEventListener('keydown', this.onHotKey); - } - - onHotKey = (e) => { - if (e.keyCode === 13) { - e.preventDefault(); - this.handleSubmit(); - } - }; - - handleChange = (event) => { - let { folderName } = this.state; - let value = event.target.value; - if (value === folderName) { - return; - } - this.setState({ folderName: value }); - }; - - handleSubmit = () => { - let { folderName, iconClassName } = this.state; - if (!folderName) { - this.setState({ errMessage: gettext('Name_is_required') }); - return; - } - this.props.onAddFolder({ name: folderName, icon: iconClassName }); - this.props.onToggleAddFolderDialog(); - }; - - toggle = () => { - this.props.onToggleAddFolderDialog(); - }; - - onIconChange = (className) => { - this.setState({ iconClassName: className }); - }; - - render() { - const { folderName, errMessage } = this.state; - return ( - - {gettext('New folder')} - -
- - - { - this.newInput = input; - }} - onChange={this.handleChange} - autoFocus={true} - /> - -
- {errMessage && {errMessage}} -
- - - - -
- ); - } -} diff --git a/frontend/src/pages/wiki2/wiki-nav/page-utils.js b/frontend/src/pages/wiki2/wiki-nav/page-utils.js index 4c1ee58b79..898af9237f 100644 --- a/frontend/src/pages/wiki2/wiki-nav/page-utils.js +++ b/frontend/src/pages/wiki2/wiki-nav/page-utils.js @@ -1,10 +1,16 @@ -import { FOLDER, PAGE } from '../constant'; +class NewPage { + constructor(id) { + this.id = id; + this.type = 'page'; + this.children = []; + } +} export default class PageUtils { static addPage(navigation, page_id, parentId) { if (!parentId) { - navigation.push({ id: page_id, type: PAGE }); + navigation.push(new NewPage(page_id)); } else { navigation.forEach(item => { this._addPageRecursion(page_id, item, parentId); @@ -17,10 +23,10 @@ export default class PageUtils { item.children = []; } if (item.id === parentId) { - item.children.push({ id: page_id, type: PAGE }); + item.children.push(new NewPage(page_id)); return true; } - item.children.forEach(item => { + item.children && item.children.forEach(item => { this._addPageRecursion(page_id, item, parentId); }); } @@ -43,7 +49,7 @@ export default class PageUtils { item.children.splice(pageIndex, 1); return true; } - item.children.forEach(item => { + item.children && item.children.forEach(item => { this._deletePageRecursion(item, page_id); }); } @@ -57,76 +63,7 @@ export default class PageUtils { return pages.findIndex(page => page.id === pageId); }; - static getFolderById = (list, folder_id) => { - if (!folder_id || !Array.isArray(list)) return null; - return list.find(item => item.type === FOLDER && item.id === folder_id); - }; - - static getFolderIndexById = (list, folder_id) => { - if (!folder_id || !Array.isArray(list)) return -1; - return list.findIndex(folder => folder.id === folder_id); - }; - - static modifyFolder(navigation, folder_id, folder_data) { - navigation.forEach(item => { - if (item.type === FOLDER) { - this._modifyFolder(item, folder_id, folder_data); - } - }); - } - - static _modifyFolder(folder, folder_id, folder_data) { - if (folder.id === folder_id) { - for (let key in folder_data) { - folder[key] = folder_data[key]; - } - return; - } - folder.children.forEach(item => { - if (item.type === FOLDER) { - this._modifyFolder(item, folder_id, folder_data); - } - }); - } - - static deleteFolder(navigation, pages, folder_id) { - // delete folder and pages within it - const folderIndex = this.getFolderIndexById(navigation, folder_id); - if (folderIndex > -1) { - this._deletePagesInFolder(pages, navigation[folderIndex]); - navigation.splice(folderIndex, 1); - return true; - } - - // delete subfolder and pages within it - navigation.forEach(item => { - if (item.type === FOLDER) { - const folderIndex = this.getFolderIndexById(item.children, folder_id); - if (folderIndex > -1) { - const subfolder = item.children[folderIndex]; - this._deletePagesInFolder(pages, subfolder); - item.children.splice(folderIndex, 1); - return true; - } - } - }); - return false; - } - - static _deletePagesInFolder(pages, folder) { - folder.children.forEach(item => { - if (item.type === FOLDER) { - this._deletePagesInFolder(pages, item); - } - if (item.type === PAGE) { - let index = this.getPageIndexById(item.id, pages); - pages.splice(index, 1); - } - }); - } - static insertPage(navigation, page_id, target_page_id, target_id, move_position) { - // 1. No folder, insert page in root directory if (!target_id) { let insertIndex = target_page_id ? navigation.findIndex(item => item.id === target_page_id) : -1; if (insertIndex < 0) { @@ -136,34 +73,12 @@ export default class PageUtils { if (move_position === 'move_below') { insertIndex++; } - navigation.splice(insertIndex, 0, { id: page_id, type: PAGE }); + navigation.splice(insertIndex, 0, new NewPage(page_id)); return; } - // 2. If there is a folder, find it and insert it - navigation.forEach(item => { - if (item.type === FOLDER) { - this._insertPageIntoFolder(item, page_id, target_page_id, target_id, move_position); - } - }); } - static _insertPageIntoFolder(folder, page_id, target_page_id, target_id, move_position) { - if (folder.id === target_id) { - let insertIndex = target_page_id ? folder.children.findIndex(item => item.id === target_page_id) : -1; - if (move_position === 'move_below') { - insertIndex++; - } - folder.children.splice(insertIndex, 0, { id: page_id, type: PAGE }); - return; - } - folder.children.forEach(item => { - if (item.type === FOLDER) { - this._insertPageIntoFolder(item, page_id, target_page_id, target_id, move_position); - } - }); - } - - static movePage(navigation, moved_page_id, target_page_id, source_id, target_id, move_position) { + static movePage(navigation, moved_page_id, target_page_id, move_position) { let movedPage = null; function _cutPageRecursion(item, page_id) { if (!item || !Array.isArray(item.children) || movedPage) return; @@ -171,7 +86,7 @@ export default class PageUtils { if (pageIndex > -1) { movedPage = item.children.splice(pageIndex, 1)[0]; } else { - item.children.forEach(item => { + item.children && item.children.forEach(item => { _cutPageRecursion(item, page_id); }); } @@ -195,7 +110,7 @@ export default class PageUtils { item.children.splice(insertIndex, 0, movedPage); return; } - item.children.forEach(item => { + item.children && item.children.forEach(item => { _insertPageRecursion(item, page_id, target_page_id, target_id, move_position); }); } @@ -217,58 +132,6 @@ export default class PageUtils { }); } _cutPage(navigation, moved_page_id); - _insertPage(navigation, moved_page_id, target_page_id, target_id, move_position); - } - - // move Page Outside Folder - static movePageOut(navigation, moved_page_id, source_id, target_id, move_position) { - let movedPage = null; - function getFolderIndexById(list, folder_id) { - if (!folder_id || !Array.isArray(list)) return -1; - return list.findIndex(folder => folder.id === folder_id); - } - // Move the page to the top or bottom of the folder - function _insertPage(navigation, page_id, target_id, move_position) { - let indexOffset = 0; - if (move_position === 'move_below') { - indexOffset++; - } - let folder_index = getFolderIndexById(navigation, target_id); - if (folder_index > -1) { - navigation.splice(folder_index + indexOffset, 0, movedPage); - } else { - navigation.forEach((item) => { - if (item.type === FOLDER) { - let folder_index = getFolderIndexById(item.children, target_id); - if (folder_index > -1) { - item.children.splice(folder_index + indexOffset, 0, movedPage); - } - } - }); - } - } - function _cutPageRecursion(item, page_id) { - if (!item || !Array.isArray(item.children) || movedPage) return; - let pageIndex = item.children.findIndex(item => item.id === page_id); - if (pageIndex > -1) { - movedPage = item.children.splice(pageIndex, 1)[0]; - } else { - item.children.forEach(item => { - _cutPageRecursion(item, page_id); - }); - } - } - function _cutPage(navigation, page_id) { - const pageIndex = navigation.findIndex(item => item.id === page_id); - if (pageIndex > -1) { - movedPage = navigation.splice(pageIndex, 1)[0]; - } else { - navigation.forEach(item => { - _cutPageRecursion(item, page_id); - }); - } - } - _cutPage(navigation, moved_page_id, source_id); - _insertPage(navigation, moved_page_id, target_id, move_position); + _insertPage(navigation, moved_page_id, target_page_id, target_page_id, move_position); } } diff --git a/frontend/src/pages/wiki2/wiki-nav/pages/dragged-page-item.js b/frontend/src/pages/wiki2/wiki-nav/pages/dragged-page-item.js index 9b5efb86f4..799c4576b6 100644 --- a/frontend/src/pages/wiki2/wiki-nav/pages/dragged-page-item.js +++ b/frontend/src/pages/wiki2/wiki-nav/pages/dragged-page-item.js @@ -1,5 +1,4 @@ import { DragSource, DropTarget } from 'react-dnd'; -import { DRAGGED_FOLDER_MODE, DRAGGED_PAGE_MODE } from '../constant'; import PageItem from './page-item'; const dragSource = { @@ -7,8 +6,7 @@ const dragSource = { return { idx: props.pageIndex, data: { ...props.page, index: props.pageIndex }, - folderId: props.folderId, - mode: DRAGGED_PAGE_MODE, + mode: 'wiki-page', }; }, endDrag(props, monitor) { @@ -28,48 +26,22 @@ const dragSource = { const dropTarget = { drop(props, monitor) { - const sourceRow = monitor.getItem(); - // 1 drag page - if (sourceRow.mode === DRAGGED_PAGE_MODE) { - const { infolder, pageIndex: targetIndex, page: targetPage, folderId: targetFolderId } = props; - const sourceFolderId = sourceRow.folderId; - const draggedPageId = sourceRow.data.id; + const dragSource = monitor.getItem(); + if (dragSource.mode === 'wiki-page') { + const { pageIndex: targetIndex, page: targetPage } = props; + const draggedPageId = dragSource.data.id; const targetPageId = targetPage.id; - if (draggedPageId !== targetPageId) { - const sourceIndex = sourceRow.idx; - let move_position; - if (infolder) { - move_position = 'move_below'; - } else { - move_position = sourceIndex > targetIndex ? 'move_above' : 'move_below'; - } - + const sourceIndex = dragSource.idx; + const move_position = sourceIndex > targetIndex ? 'move_above' : 'move_below'; props.onMovePage({ moved_page_id: draggedPageId, target_page_id: targetPageId, - source_page_folder_id: sourceFolderId, - target_page_folder_id: targetFolderId, move_position, }); } return; } - // 1 drag folder - if (sourceRow.mode === DRAGGED_FOLDER_MODE) { - const { pageIndex: targetIndex, page: targetPage } = props; - const draggedFolderId = sourceRow.data.id; - const targetPageId = targetPage.id; - const sourceIndex = sourceRow.idx; - // Drag the parent folder to the child page, return - if (props.pathStr.split('-').includes(draggedFolderId)) return; - props.onMoveFolder( - draggedFolderId, - targetPageId, - sourceIndex > targetIndex ? 'move_above' : 'move_below', - ); - return; - } } }; diff --git a/frontend/src/pages/wiki2/wiki-nav/pages/page-dropdownmenu.js b/frontend/src/pages/wiki2/wiki-nav/pages/page-dropdownmenu.js index 7da29da58d..f944c1c183 100644 --- a/frontend/src/pages/wiki2/wiki-nav/pages/page-dropdownmenu.js +++ b/frontend/src/pages/wiki2/wiki-nav/pages/page-dropdownmenu.js @@ -11,24 +11,15 @@ export default class PageDropdownMenu extends Component { page: PropTypes.object.isRequired, pages: PropTypes.array, pagesLength: PropTypes.number, - folderId: PropTypes.string, - canDelete: PropTypes.bool, - canDuplicate: PropTypes.bool, - renderFolderMenuItems: PropTypes.func, toggle: PropTypes.func, toggleNameEditor: PropTypes.func, duplicatePage: PropTypes.func, - onSetFolderId: PropTypes.func, onDeletePage: PropTypes.func, - onMovePageToFolder: PropTypes.func, isOnlyOnePage: PropTypes.bool, }; constructor(props) { super(props); - this.state = { - isShowMenu: false, - }; this.pageNameMap = this.calculateNameMap(); } @@ -41,9 +32,6 @@ export default class PageDropdownMenu extends Component { }; onDropdownToggle = (evt) => { - if (evt.target && this.foldersDropdownToggle && this.foldersDropdownToggle.contains(evt.target)) { - return; - } evt.stopPropagation(); this.props.toggle(); }; @@ -58,22 +46,8 @@ export default class PageDropdownMenu extends Component { this.props.onDeletePage(); }; - onMovePageToFolder = (targetFolderId) => { - this.props.onMovePageToFolder(targetFolderId); - }; - - onRemoveFromFolder = (evt) => { - evt.nativeEvent.stopImmediatePropagation(); - this.props.onMovePageToFolder(null); - }; - - onToggleFoldersMenu = () => { - this.setState({ isShowMenu: !this.state.isShowMenu }); - }; - duplicatePage = () => { - const { page, folderId } = this.props; - this.props.onSetFolderId(folderId); + const { page } = this.props; this.props.duplicatePage({ from_page_id: page.id }, () => {}, this.duplicatePageFailure); }; @@ -81,14 +55,6 @@ export default class PageDropdownMenu extends Component { toaster.danger(gettext('Failed_to_duplicate_page')); }; - showMenu = () => { - this.setState({ isShowMenu: true }); - }; - - hideMenu = () => { - this.setState({ isShowMenu: false }); - }; - handleCopyLink = () => { const { page } = this.props; const wikiLink = getWikPageLink(page.id); @@ -109,10 +75,7 @@ export default class PageDropdownMenu extends Component { }; render() { - const { - folderId, canDelete, canDuplicate, renderFolderMenuItems, pagesLength, isOnlyOnePage, - } = this.props; - const folderMenuItems = renderFolderMenuItems && renderFolderMenuItems({ currentFolderId: folderId, onMovePageToFolder: this.onMovePageToFolder }); + const { pagesLength, isOnlyOnePage } = this.props; return ( {gettext('Modify name')} - {canDuplicate && - - - {gettext('Duplicate page')} - - } - {(isOnlyOnePage || pagesLength === 1 || !canDelete) ? '' : ( + + + {gettext('Duplicate page')} + + {(isOnlyOnePage || pagesLength === 1) ? '' : ( {gettext('Delete page')} )} - {folderId && - - - {gettext('Remove from folder')} - - } - {renderFolderMenuItems && folderMenuItems.length > 0 && - { - evt.stopPropagation(); - evt.nativeEvent.stopImmediatePropagation(); - this.showMenu(); - }} - onMouseEnter={this.showMenu} - onMouseLeave={this.hideMenu} - > - -
this.foldersDropdownToggle = ref}> - - {gettext('Move to')} - - - - -
- {this.state.isShowMenu && - - {folderMenuItems} - - } -
-
- } < hr className='divider' /> diff --git a/frontend/src/pages/wiki2/wiki-nav/pages/page-item.js b/frontend/src/pages/wiki2/wiki-nav/pages/page-item.js index 6df3b79b48..b51866b261 100644 --- a/frontend/src/pages/wiki2/wiki-nav/pages/page-item.js +++ b/frontend/src/pages/wiki2/wiki-nav/pages/page-item.js @@ -113,20 +113,20 @@ class PageItem extends Component { window.seafile['docUuid'] = docUuid; }; - getFolderChildrenHeight = () => { + getPageChildrenHeight = () => { const folded = this.props.getFoldState(this.props.page.id); if (folded) return 0; return 'auto'; }; - onClickFolderChildren = (e) => { + onClickPageChildren = (e) => { e.stopPropagation(); e.nativeEvent.stopImmediatePropagation(); }; renderPage = (page, index, pagesLength, isOnlyOnePage) => { if (!page) return; - const { isEditMode, pages, folderId, pathStr } = this.props; + const { isEditMode, pages, pathStr } = this.props; const id = page.id; if (!pages.find(item => item.id === id)) return; return ( @@ -134,22 +134,14 @@ class PageItem extends Component { key={id} pagesLength={pagesLength} isOnlyOnePage={isOnlyOnePage} - infolder={false} page={Object.assign({}, pages.find(item => item.id === id), page)} pageIndex={index} - folderId={folderId} isEditMode={isEditMode} - renderFolderMenuItems={this.props.renderFolderMenuItems} duplicatePage={this.props.duplicatePage} - onSetFolderId={this.props.onSetFolderId} setCurrentPage={this.props.setCurrentPage} onUpdatePage={this.props.onUpdatePage} onDeletePage={this.props.onDeletePage} - onMovePageToFolder={(targetFolderId) => { - this.props.onMovePageToFolder(folderId, page.id, targetFolderId); - }} onMovePage={this.props.onMovePage} - onMoveFolder={this.props.onMoveFolder} pages={pages} pathStr={pathStr + '-' + page.id} currentPageId={this.props.currentPageId} @@ -173,21 +165,14 @@ class PageItem extends Component { render() { const { connectDragSource, connectDragPreview, connectDropTarget, isOver, canDrop, isDragging, - infolder, page, pagesLength, isEditMode, folderId, isOnlyOnePage, pathStr, + page, pagesLength, isEditMode, isOnlyOnePage, pathStr, } = this.props; const { isShowNameEditor, pageName, isSelected } = this.state; const isOverPage = isOver && canDrop; if (isSelected) this.setDocUuid(page.docUuid); - let pageCanDropTop; - let pageCanDrop; - if (infolder) { - pageCanDropTop = false; - pageCanDrop = isOverPage; - } else { - pageCanDropTop = isOverPage && isDragging; - pageCanDrop = isOverPage && !isDragging; - } + let pageCanDropTop = isOverPage && isDragging; + let pageCanDrop = isOverPage && !isDragging; let navItemId = `page-editor-${page.id}`; let fn = isEditMode ? connectDragSource : (argu) => {argu;}; let childNumber = Array.isArray(page.children) ? page.children.length : 0; @@ -246,16 +231,10 @@ class PageItem extends Component { pages={this.props.pages} pagesLength={pagesLength} isOnlyOnePage={isOnlyOnePage} - folderId={folderId} - canDelete={true} - canDuplicate={true} toggle={this.toggleDropdown} - renderFolderMenuItems={this.props.renderFolderMenuItems} toggleNameEditor={this.toggleNameEditor} duplicatePage={this.props.duplicatePage} - onSetFolderId={this.props.onSetFolderId} onDeletePage={this.openDeleteDialog} - onMovePageToFolder={this.props.onMovePageToFolder} /> } @@ -283,9 +262,9 @@ class PageItem extends Component { )) }
{page.children && page.children.map((item, index) => { @@ -304,26 +283,19 @@ PageItem.propTypes = { isDragging: PropTypes.bool, draggedPage: PropTypes.object, isEditMode: PropTypes.bool, - infolder: PropTypes.bool, page: PropTypes.object, - folder: PropTypes.object, pages: PropTypes.array, pageIndex: PropTypes.number, - folderId: PropTypes.string, pagesLength: PropTypes.number, connectDragSource: PropTypes.func, connectDragPreview: PropTypes.func, connectDropTarget: PropTypes.func, - renderFolderMenuItems: PropTypes.func, duplicatePage: PropTypes.func, - onSetFolderId: PropTypes.func, setCurrentPage: PropTypes.func, onUpdatePage: PropTypes.func, onDeletePage: PropTypes.func, - onMovePageToFolder: PropTypes.func, onMovePage: PropTypes.func, isOnlyOnePage: PropTypes.bool, - onMoveFolder: PropTypes.func, pathStr: PropTypes.string, currentPageId: PropTypes.string, addPageInside: PropTypes.func, diff --git a/frontend/src/pages/wiki2/wiki-nav/wiki-nav-footer.js b/frontend/src/pages/wiki2/wiki-nav/wiki-nav-footer.js deleted file mode 100644 index 376e80b288..0000000000 --- a/frontend/src/pages/wiki2/wiki-nav/wiki-nav-footer.js +++ /dev/null @@ -1,48 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import CommonAddTool from '../../../components/common/common-add-tool'; -import AddPageDropdownMenu from './add-page-dropdownmenu'; -import { gettext } from '../../../utils/constants'; - -class WikiNavFooter extends Component { - - constructor(props) { - super(props); - this.state = { - isShowDropdownMenu: false, - }; - } - - toggleDropdown = (event) => { - event && event.stopPropagation(); - this.setState({ isShowDropdownMenu: !this.state.isShowDropdownMenu }); - }; - - render() { - return ( -
-
- - {this.state.isShowDropdownMenu && - - } -
-
- ); - } -} - -WikiNavFooter.propTypes = { - onToggleAddPage: PropTypes.func, - onToggleAddFolder: PropTypes.func, -}; - -export default WikiNavFooter; diff --git a/frontend/src/pages/wiki2/wiki-nav/wiki-nav.js b/frontend/src/pages/wiki2/wiki-nav/wiki-nav.js index de76f6ea70..c8d7ea7211 100644 --- a/frontend/src/pages/wiki2/wiki-nav/wiki-nav.js +++ b/frontend/src/pages/wiki2/wiki-nav/wiki-nav.js @@ -1,11 +1,8 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { DropdownItem } from 'reactstrap'; import { DropTarget, DragLayer } from 'react-dnd'; import html5DragDropContext from './html5DragDropContext'; -import DraggedFolderItem from './folders/dragged-folder-item'; import DraggedPageItem from './pages/dragged-page-item'; -import WikiNavFooter from './wiki-nav-footer'; import { repoID } from '../../../utils/constants'; import '../css/wiki-nav.css'; @@ -17,26 +14,17 @@ class WikiNav extends Component { navigation: PropTypes.array, pages: PropTypes.array, onTogglePinViewList: PropTypes.func, - onToggleAddPage: PropTypes.func, - onToggleAddFolder: PropTypes.func, - onModifyFolder: PropTypes.func, - onDeleteFolder: PropTypes.func, - onMoveFolder: PropTypes.func, setCurrentPage: PropTypes.func, onUpdatePage: PropTypes.func, onDeletePage: PropTypes.func, onMovePage: PropTypes.func, - moveFolderToFolder: PropTypes.func, - movePageOut: PropTypes.func, duplicatePage: PropTypes.func, - onSetFolderId: PropTypes.func, currentPageId: PropTypes.string, addPageInside: PropTypes.func, }; constructor(props) { super(props); - this.folderClassNameCache = ''; this.idFoldedStatusMap = this.getFoldedFromLocal(); } @@ -49,145 +37,63 @@ class WikiNav extends Component { window.localStorage.setItem(`wiki-folded-${repoID}`, JSON.stringify(items)); }; - getFoldState = (folderId) => { - return this.idFoldedStatusMap[folderId]; + getFoldState = (pageId) => { + return this.idFoldedStatusMap[pageId]; }; - toggleExpand = (folderId) => { + toggleExpand = (pageId) => { const idFoldedStatusMap = this.getFoldedFromLocal(); - if (idFoldedStatusMap[folderId]) { - delete idFoldedStatusMap[folderId]; + if (idFoldedStatusMap[pageId]) { + delete idFoldedStatusMap[pageId]; } else { - idFoldedStatusMap[folderId] = true; + idFoldedStatusMap[pageId] = true; } this.saveFoldedToLocal(idFoldedStatusMap); this.idFoldedStatusMap = idFoldedStatusMap; }; - onMovePageToFolder = (source_page_folder_id, moved_page_id, target_page_folder_id) => { - this.props.onMovePage({ - moved_page_id, - source_page_folder_id, - target_page_folder_id, - target_page_id: null, - move_position: 'move_below' - }); - }; - - renderFolderMenuItems = ({ currentFolderId, onMovePageToFolder }) => { - // folder lists (in the root directory) - const { navigation } = this.props; - let renderFolders = navigation.filter(item => item.type === 'folder' && item.id !== currentFolderId); - return renderFolders.map(folder => { - const { id, name } = folder; - return ( - - {name} - - ); - }); - }; - - setClassName = (name) => { - this.folderClassNameCache = name; - }; - - getClassName = () => { - return this.folderClassNameCache; - }; - - renderFolder = (folder, index, pagesLength, isOnlyOnePage, id_page_map, layerDragProps) => { - const { isEditMode, pages } = this.props; - const folderId = folder.id; - return ( - - ); - }; - - renderPage = (page, index, pagesLength, isOnlyOnePage, id_page_map) => { + renderPage = (page, index, pagesLength, isOnlyOnePage, id_page_map, layerDragProps) => { const { isEditMode, pages } = this.props; const id = page.id; if (!pages.find(item => item.id === id)) return; - const folderId = null; // Pages in the root directory, no folders, use null return ( item.id === id), page)} pages={pages} pageIndex={index} - folderId={folderId} isEditMode={isEditMode} - renderFolderMenuItems={this.renderFolderMenuItems} duplicatePage={this.props.duplicatePage} - onSetFolderId={this.props.onSetFolderId} setCurrentPage={this.props.setCurrentPage} onUpdatePage={this.props.onUpdatePage} onDeletePage={this.props.onDeletePage} - onMovePageToFolder={(targetFolderId) => { - this.onMovePageToFolder(folderId, page.id, targetFolderId); - }} onMovePage={this.props.onMovePage} - onMoveFolder={this.props.onMoveFolder} pathStr={page.id} currentPageId={this.props.currentPageId} addPageInside={this.props.addPageInside} getFoldState={this.getFoldState} toggleExpand={this.toggleExpand} + id_page_map={id_page_map} + layerDragProps={layerDragProps} /> ); }; // eslint-disable-next-line renderStructureBody = React.forwardRef((layerDragProps, ref) => { - const { navigation, pages, isEditMode } = this.props; + const { navigation, pages } = this.props; let isOnlyOnePage = false; if (pages.length === 1) { isOnlyOnePage = true; } - const pagesLength = pages.length; let id_page_map = {}; pages.forEach(page => id_page_map[page.id] = page); - const style = { maxHeight: isEditMode ? 'calc(100% - 40px)' : '100%' }; return ( -
+
{navigation.map((item, index) => { - return item.type === 'folder' ? - this.renderFolder(item, index, pagesLength, isOnlyOnePage, id_page_map, layerDragProps) : - this.renderPage(item, index, pagesLength, isOnlyOnePage, id_page_map); + return this.renderPage(item, index, pages.length, isOnlyOnePage, id_page_map, layerDragProps); })}
); @@ -211,12 +117,6 @@ class WikiNav extends Component { return (
- {(this.props.isEditMode) && - - }
); }