diff --git a/frontend/src/assets/icons/file.svg b/frontend/src/assets/icons/file.svg index 447119c1fc..cf122ab0d4 100644 --- a/frontend/src/assets/icons/file.svg +++ b/frontend/src/assets/icons/file.svg @@ -3,17 +3,16 @@ -file1 -Created with Sketch. - - - - - +file + + + + diff --git a/frontend/src/assets/icons/files.svg b/frontend/src/assets/icons/files.svg new file mode 100644 index 0000000000..dd9d0898e8 --- /dev/null +++ b/frontend/src/assets/icons/files.svg @@ -0,0 +1,22 @@ + + + + +files + + + + + + + + + diff --git a/frontend/src/pages/wiki2/css/view-structure.css b/frontend/src/pages/wiki2/css/view-structure.css index f9782481d3..622e130f39 100644 --- a/frontend/src/pages/wiki2/css/view-structure.css +++ b/frontend/src/pages/wiki2/css/view-structure.css @@ -94,7 +94,7 @@ padding-left: 20px; } -.view-structure .view-folder-wrapper .icon-expand-folder { +.view-structure .icon-expand-folder { display: inline-block; font-size: 12px; transform: scale(0.8); @@ -145,10 +145,13 @@ } .view-structure .view-folder-wrapper .more-view-folder-operation .seafile-multicolor-icon-more-level, +.view-structure .view-item .fas.fa-plus, .view-structure .view-item .more-view-operation .seafile-multicolor-icon-more-level { + cursor: pointer; opacity: 0; } +.view-structure .view-item:hover .fas.fa-plus, .view-structure .view-folder-wrapper:hover .more-view-folder-operation .seafile-multicolor-icon-more-level, .view-structure .view-item:hover .more-view-operation .seafile-multicolor-icon-more-level { opacity: 1; @@ -166,6 +169,7 @@ } .view-structure .folder-list .view-folder.fold-freezed .btn-folder-operation, +.view-structure .view-item.view-freezed .fas.fa-plus, .view-structure .view-item.view-freezed .seafile-multicolor-icon-more-level { opacity: 1; } @@ -358,21 +362,24 @@ /* dark mode */ .view-structure-dark.view-structure, -.view-structure-dark.view-structure .view-folder .icon-expand-folder { +.view-structure-dark.view-structure .icon-expand-folder { color: #fff; } /* light mode */ .view-structure-light.view-structure, +.view-structure-light.view-structure .view-item .fas.fa-plus:hover, .view-structure-light.view-structure .view-item .seafile-multicolor-icon-more-level:hover, .view-structure-light.view-structure .view-folder .seafile-multicolor-icon-more-level:hover, -.view-structure-light.view-structure .view-folder .icon-expand-folder:hover { +.view-structure-light.view-structure .icon-expand-folder:hover { color: #212529; } + +.view-structure-light.view-structure .view-item .fas.fa-plus, .view-structure-light.view-structure .view-item .seafile-multicolor-icon-more-level, .view-structure-light.view-structure .view-folder .seafile-multicolor-icon-more-level, -.view-structure-light.view-structure .view-folder .icon-expand-folder { +.view-structure-light.view-structure .icon-expand-folder { color: #666; } diff --git a/frontend/src/pages/wiki2/models/page.js b/frontend/src/pages/wiki2/models/page.js index 528861131e..e602394b57 100644 --- a/frontend/src/pages/wiki2/models/page.js +++ b/frontend/src/pages/wiki2/models/page.js @@ -1,9 +1,12 @@ -export default class Page { +class Page { constructor(object) { this.id = object.id; this.name = object.name; this.path = object.path; this.icon = object.icon; this.docUuid = object.docUuid; + this.children = Array.isArray(object.children) ? object.children.map(item => new Page(item)) : []; } } + +export default Page; diff --git a/frontend/src/pages/wiki2/models/wiki-config.js b/frontend/src/pages/wiki2/models/wiki-config.js index d08fc9ccd8..cd814932c0 100644 --- a/frontend/src/pages/wiki2/models/wiki-config.js +++ b/frontend/src/pages/wiki2/models/wiki-config.js @@ -11,6 +11,7 @@ export default class WikiConfig { return { id: item.id, type: item.type, + children: item.children || [], }; } return null; diff --git a/frontend/src/pages/wiki2/side-panel.js b/frontend/src/pages/wiki2/side-panel.js index dc01abb621..068bbf0ec3 100644 --- a/frontend/src/pages/wiki2/side-panel.js +++ b/frontend/src/pages/wiki2/side-panel.js @@ -47,6 +47,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) wikiAPI.deleteWiki2Page(wikiId, pageId); if (config.pages.length > 0) { this.props.setCurrentPage(config.pages[0].id); @@ -55,12 +56,20 @@ class SidePanel extends Component { } }; + addPageInside = async ({ parentPageId, name, icon, path, docUuid, successCallback, errorCallback }) => { + const { config } = this.props; + const navigation = config.navigation; + const pageId = generateUniqueId(navigation); + const newPage = new Page({ id: pageId, name, icon, path, docUuid }); + this.addPage(newPage, parentPageId, successCallback, errorCallback); + }; + onAddNewPage = async ({ name, icon, path, docUuid, successCallback, errorCallback }) => { const { config } = this.props; const navigation = config.navigation; const pageId = generateUniqueId(navigation); const newPage = new Page({ id: pageId, name, icon, path, docUuid }); - this.addPage(newPage, successCallback, errorCallback); + this.addPage(newPage, this.current_folder_id, successCallback, errorCallback); }; duplicatePage = async (fromPageConfig, successCallback, errorCallback) => { @@ -75,15 +84,15 @@ class SidePanel extends Component { name, }; const newPage = new Page({ ...newPageConfig }); - this.addPage(newPage, successCallback, errorCallback); + this.addPage(newPage, this.current_folder_id, successCallback, errorCallback); }; - addPage = (page, successCallback, errorCallback) => { + addPage = (page, parentId, successCallback, errorCallback) => { const { config } = this.props; const navigation = config.navigation; const pageId = page.id; config.pages.push(page); - PageUtils.addPage(navigation, pageId, this.current_folder_id); + PageUtils.addPage(navigation, pageId, parentId); config.navigation = navigation; const onSuccess = () => { this.props.setCurrentPage(pageId, successCallback); @@ -113,10 +122,10 @@ class SidePanel extends Component { this.props.saveWikiConfig(config); }; - movePageOut = (moved_page_id, source_folder_id, target_folder_id, move_position) => { + 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_folder_id, target_folder_id, move_position); + PageUtils.movePageOut(navigation, moved_page_id, source_id, target_id, move_position); config.navigation = navigation; this.props.saveWikiConfig(config); }; @@ -164,12 +173,13 @@ class SidePanel extends Component { 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_folder_id, move_position) => { + onMoveFolder = (moved_folder_id, target_id, move_position) => { const { config } = this.props; const { navigation } = config; let updatedNavigation = deepCopy(navigation); @@ -196,11 +206,11 @@ class SidePanel extends Component { indexOffset++; } // Get the location of the release - let target_folder_index = PageUtils.getFolderIndexById(updatedNavigation, target_folder_id); + 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_folder_id); + target_folder_index = PageUtils.getFolderIndexById(item.children, target_id); if (target_folder_index > -1) { item.children.splice(target_folder_index + indexOffset, 0, moved_folder); } @@ -217,12 +227,12 @@ class SidePanel extends Component { }; // Not support yet: Move a folder into another folder - moveFolderToFolder = (moved_folder_id, target_folder_id) => { + 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_folder_id); + let target_folder = PageUtils.getFolderById(navigation, target_id); if (!target_folder) { toaster.danger('Only_support_two_level_folders'); return; @@ -299,6 +309,7 @@ class SidePanel extends Component { duplicatePage={this.duplicatePage} onSetFolderId={this.onSetFolderId} currentPageId={this.props.currentPageId} + addPageInside={this.addPageInside} /> {this.state.isShowNewFolderDialog && } @@ -335,6 +347,7 @@ class SidePanel extends Component { } diff --git a/frontend/src/pages/wiki2/top-nav/index.jsx b/frontend/src/pages/wiki2/top-nav/index.jsx index a2c5a10e07..ba7256827c 100644 --- a/frontend/src/pages/wiki2/top-nav/index.jsx +++ b/frontend/src/pages/wiki2/top-nav/index.jsx @@ -1,31 +1,56 @@ -import React from 'react'; +import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import NavItemIcon from '../view-structure/nav-item-icon'; import './index.css'; +// Find the path array from the root to the leaf based on the currentPageId (leaf) +function getPaths(navigation, currentPageId, pages) { + let idPageMap = {}; + pages.forEach(page => idPageMap[page.id] = page); + navigation.forEach(item => { + if (!idPageMap[item.id]) { + idPageMap[item.id] = item; + } + }); + let pathStr = null; + function runNode(node) { + const newPath = node._path ? (node._path + '-' + node.id) : node.id; + if (node.id === currentPageId) { + pathStr = newPath; + return; + } + if (node.children) { + node.children.forEach(child => { + child._path = newPath; + runNode(child); + }); + } + } + let root = {}; + root.id = ''; + root._path = ''; + root.children = navigation; + runNode(root); + if (!pathStr) return []; + return pathStr.split('-').map(id => idPageMap[id]); +} + function WikiTopNav({ config, currentPageId }) { const { navigation, pages } = config; - const folder = navigation.find(item => { - return item.type === 'folder' && item.children && item.children.find(item => item.id === currentPageId); - }); - const page = pages.find(page => page.id === currentPageId); + const paths = getPaths(navigation, currentPageId, pages); return (
- {folder && - <> -
- - {folder.name} -
-
/
- - } - {page && -
- - {page.name} -
- } + {paths.map((item, index) => { + return ( + +
+ + {item.name} +
+ {index !== paths.length - 1 &&
/
} +
+ ); + })}
); } diff --git a/frontend/src/pages/wiki2/view-structure/add-new-page-dialog.js b/frontend/src/pages/wiki2/view-structure/add-new-page-dialog.js index 194f65b761..130942ddd0 100644 --- a/frontend/src/pages/wiki2/view-structure/add-new-page-dialog.js +++ b/frontend/src/pages/wiki2/view-structure/add-new-page-dialog.js @@ -10,6 +10,7 @@ import wikiAPI from '../../../utils/wiki-api'; import '../css/add-new-page-dialog.css'; const propTypes = { + title: PropTypes.node, toggle: PropTypes.func.isRequired, onAddNewPage: PropTypes.func, }; @@ -95,9 +96,10 @@ class AddNewPageDialog extends React.Component { }; render() { + const { title } = this.props; return ( - {gettext('Add page')} + {title} currentIndex; }, }; @@ -43,7 +43,7 @@ const dropTarget = { let moveInto = className.includes('dragged-view-over'); // 1. drag source is page - if (sourceRow.mode === DRAGGED_VIEW_MODE) { + if (sourceRow.mode === DRAGGED_PAGE_MODE) { const sourceFolderId = sourceRow.folderId; const draggedViewId = sourceRow.data.id; // 1.1 move page into folder @@ -93,7 +93,7 @@ const dropCollect = (connect, monitor) => ({ connectDropTarget: connect.dropTarget(), isOver: monitor.isOver(), canDrop: monitor.canDrop(), - draggedRow: monitor.getItem(), + draggedPage: monitor.getItem(), connect, monitor, }); diff --git a/frontend/src/pages/wiki2/view-structure/folders/folder-item.js b/frontend/src/pages/wiki2/view-structure/folders/folder-item.js index b60c224a6f..9c8a6c674d 100644 --- a/frontend/src/pages/wiki2/view-structure/folders/folder-item.js +++ b/frontend/src/pages/wiki2/view-structure/folders/folder-item.js @@ -2,10 +2,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import FolderOperationDropdownMenu from './folder-operation-dropdownmenu'; -import ViewItem from '../views/view-item'; +import DraggedViewItem from '../views/dragged-view-item'; import DraggedFolderItem from './dragged-folder-item'; import ViewEditPopover from '../../view-structure/views/view-edit-popover'; -import { FOLDER } from '../../constant'; import NavItemIcon from '../nav-item-icon'; class FolderItem extends Component { @@ -21,14 +20,9 @@ class FolderItem extends Component { }; } - onToggleExpandFolder = (e) => { + toggleExpand = (e) => { e.nativeEvent.stopImmediatePropagation(); - this.props.onToggleExpandFolder(this.props.folder.id); - this.forceUpdate(); - }; - - onToggleExpandSubfolder = (subfolderId) => { - this.props.onToggleExpandFolder(subfolderId); + this.props.toggleExpand(this.props.folder.id); this.forceUpdate(); }; @@ -66,8 +60,8 @@ class FolderItem extends Component { // } }; - renderFolder = (folder, index, tableGridsLength, isOnlyOneView, id_view_map) => { - const { isEditMode, views, foldersStr } = this.props; + renderFolder = (folder, index, pagesLength, isOnlyOneView, id_view_map) => { + const { isEditMode, views, pathStr } = this.props; const { id: folderId } = folder; return ( ); }; - renderView = (view, index, tableGridsLength, isOnlyOneView) => { - const { isEditMode, views, folder, foldersStr } = this.props; + renderView = (view, index, pagesLength, isOnlyOneView) => { + const { isEditMode, views, folder, pathStr } = this.props; const id = view.id; if (!views.find(item => item.id === id)) return; return ( - item.id === id)} + view={Object.assign({}, views.find(item => item.id === id), view)} viewIndex={index} folderId={folder.id} isEditMode={isEditMode} renderFolderMenuItems={this.props.renderFolderMenuItems} duplicatePage={this.props.duplicatePage} onSetFolderId={this.props.onSetFolderId} - onSelectView={() => this.props.onSelectView(id)} + onSelectView={this.props.onSelectView} onUpdatePage={this.props.onUpdatePage} - onDeleteView={this.props.onDeleteView.bind(this, id)} + onDeleteView={this.props.onDeleteView} onMoveViewToFolder={(targetFolderId) => { this.props.onMoveViewToFolder(folder.id, view.id, targetFolderId); }} onMoveView={this.props.onMoveView} onMoveFolder={this.props.onMoveFolder} views={views} - foldersStr={foldersStr} + pathStr={pathStr + '-' + view.id} currentPageId={this.props.currentPageId} + addPageInside={this.props.addPageInside} + getFoldState={this.props.getFoldState} + toggleExpand={this.props.toggleExpand} /> ); }; @@ -160,22 +158,9 @@ class FolderItem extends Component { }; getFolderChildrenHeight = () => { - const { id: folderId, children } = this.props.folder; - const folded = this.props.getFolderState(folderId); + const folded = this.props.getFoldState(this.props.folder.id); if (folded) return 0; - - let height = 0; - children.forEach((child) => { - // just support two levels - const { type, id: childId, children } = child; - if (type === FOLDER) { - height += (this.props.getFolderState(childId) || !Array.isArray(children)) - ? 40 : (children.length + 1) * 40; - } else { - height += 40; - } - }); - return height; + return 'auto'; }; onMouseEnter = () => { @@ -189,18 +174,18 @@ class FolderItem extends Component { render() { const { connectDropTarget, connectDragPreview, connectDragSource, isOver, canDrop, - isEditMode, folder, tableGridsLength, id_view_map, isOnlyOneView, layerDragProps, + isEditMode, folder, pagesLength, id_view_map, isOnlyOneView, layerDragProps, } = this.props; const { isEditing } = this.state; const { id: folderId, name, children } = folder; - const folded = this.props.getFolderState(folderId); + const folded = this.props.getFoldState(folderId); let viewEditorId = `folder-item-${folderId}`; let fn = isEditMode ? connectDragSource : (argu) => {argu;}; return (
this.foldRef = ref} - onClick={this.onToggleExpandFolder} + onClick={this.toggleExpand} > {fn(connectDropTarget( connectDragPreview( @@ -213,7 +198,7 @@ class FolderItem extends Component {
{this.state.isMouseEnter ? @@ -254,7 +239,7 @@ class FolderItem extends Component { > {!folded && children && children.map((item, index) => { - return item.type === 'folder' ? this.renderFolder(item, index, tableGridsLength, isOnlyOneView, id_view_map) : this.renderView(item, index, tableGridsLength, isOnlyOneView); + return item.type === 'folder' ? this.renderFolder(item, index, pagesLength, isOnlyOneView, id_view_map) : this.renderView(item, index, pagesLength, isOnlyOneView); }) }
@@ -267,19 +252,18 @@ FolderItem.propTypes = { isEditMode: PropTypes.bool, folder: PropTypes.object, folderIndex: PropTypes.number, - tableGridsLength: PropTypes.number, + pagesLength: PropTypes.number, id_view_map: PropTypes.object, isOver: PropTypes.bool, canDrop: PropTypes.bool, isDragging: PropTypes.bool, - draggedRow: PropTypes.object, connectDropTarget: PropTypes.func, connectDragPreview: PropTypes.func, connectDragSource: PropTypes.func, renderFolderMenuItems: PropTypes.func, duplicatePage: PropTypes.func, onSetFolderId: PropTypes.func, - onToggleExpandFolder: PropTypes.func, + toggleExpand: PropTypes.func, onToggleAddView: PropTypes.func, onModifyFolder: PropTypes.func, onDeleteFolder: PropTypes.func, @@ -292,13 +276,14 @@ FolderItem.propTypes = { views: PropTypes.array, onMoveFolder: PropTypes.func, moveFolderToFolder: PropTypes.func, - foldersStr: PropTypes.string, + pathStr: PropTypes.string, setClassName: PropTypes.func, getClassName: PropTypes.func, movePageOut: PropTypes.func, layerDragProps: PropTypes.object, - getFolderState: PropTypes.func, + getFoldState: PropTypes.func, currentPageId: PropTypes.string, + addPageInside: PropTypes.func, }; export default FolderItem; diff --git a/frontend/src/pages/wiki2/view-structure/nav-item-icon.jsx b/frontend/src/pages/wiki2/view-structure/nav-item-icon.jsx index 04c317dcce..0171b3574b 100644 --- a/frontend/src/pages/wiki2/view-structure/nav-item-icon.jsx +++ b/frontend/src/pages/wiki2/view-structure/nav-item-icon.jsx @@ -4,9 +4,9 @@ import Icon from '../../../components/icon'; import classNames from 'classnames'; import './nav-item-icon.css'; -function NavItemIcon({ symbol, className, disable }) { +function NavItemIcon({ symbol, className, disable, onClick }) { return ( -
+
); @@ -16,6 +16,7 @@ NavItemIcon.propTypes = { symbol: PropTypes.string.isRequired, className: PropTypes.string, disable: PropTypes.bool, + onClick: PropTypes.func, }; export default NavItemIcon; diff --git a/frontend/src/pages/wiki2/view-structure/page-utils.js b/frontend/src/pages/wiki2/view-structure/page-utils.js index a4d3b8aeb5..65121f446b 100644 --- a/frontend/src/pages/wiki2/view-structure/page-utils.js +++ b/frontend/src/pages/wiki2/view-structure/page-utils.js @@ -2,34 +2,57 @@ import { FOLDER, PAGE } from '../constant'; export default class PageUtils { + static addPage(navigation, page_id, parentId) { + if (!parentId) { + navigation.push({ id: page_id, type: PAGE }); + } else { + navigation.forEach(item => { + this._addPageRecursion(page_id, item, parentId); + }); + } + } + + static _addPageRecursion(page_id, item, parentId) { + if (!Array.isArray(item.children)) { + item.children = []; + } + if (item.id === parentId) { + item.children.push({ id: page_id, type: PAGE }); + return true; + } + item.children.forEach(item => { + this._addPageRecursion(page_id, item, parentId); + }); + } + + static deletePage(navigation, page_id) { + const pageIndex = navigation.findIndex(item => item.id === page_id); + if (pageIndex > -1) { + navigation.splice(pageIndex, 1); + return true; + } + navigation.forEach(item => { + this._deletePageRecursion(item, page_id); + }); + } + + static _deletePageRecursion(item, page_id) { + if (!item || !Array.isArray(item.children)) return; + let pageIndex = item.children.findIndex(item => item.id === page_id); + if (pageIndex > -1) { + item.children.splice(pageIndex, 1); + return true; + } + item.children.forEach(item => { + this._deletePageRecursion(item, page_id); + }); + } + static getPageById = (pages, page_id) => { if (!page_id || !Array.isArray(pages)) return null; return pages.find((page) => page.id === page_id) || null; }; - static getPageFromNavigationById = (navigation, page_id) => { - if (!page_id || !Array.isArray(navigation)) return null; - let page_index = navigation.indexOf(item => item.id === page_id); - if (page_index > -1) { - return navigation[page_index]; - } - for (let i = 0; i < navigation.length; i++) { - const currNavigation = navigation[i]; - if (currNavigation.id === page_id) { - return currNavigation; - } - - if (Array.isArray(currNavigation.children)) { - for (let j = 0; j < currNavigation.children.length; j++) { - if (currNavigation.children[j].id === page_id) { - return currNavigation.children[j]; - } - } - } - } - return null; - }; - static getPageIndexById = (pageId, pages) => { return pages.findIndex(page => page.id === pageId); }; @@ -102,39 +125,12 @@ export default class PageUtils { }); } - static addPage(navigation, page_id, target_folder_id) { - // 1. Add pages directly under the root directory - if (!target_folder_id) { - navigation.push({ id: page_id, type: PAGE }); - return; - } else { - // 2. Add pages to the folder - navigation.forEach(item => { - if (item.type === FOLDER) { - this._addPageInFolder(page_id, item, target_folder_id); - } - }); - } - } - - static _addPageInFolder(page_id, folder, target_folder_id) { - if (folder.id === target_folder_id) { - folder.children.push({ id: page_id, type: PAGE }); - return true; - } - folder.children.forEach(item => { - if (item.type === FOLDER) { - this._addPageInFolder(page_id, item, target_folder_id); - } - }); - } - - static insertPage(navigation, page_id, target_page_id, folder_id, move_position) { + static insertPage(navigation, page_id, target_page_id, target_id, move_position) { // 1. No folder, insert page in root directory - if (!folder_id) { + if (!target_id) { let insertIndex = target_page_id ? navigation.findIndex(item => item.id === target_page_id) : -1; if (insertIndex < 0) { - this.addPage(navigation, page_id, folder_id); + this.addPage(navigation, page_id, target_id); return true; } if (move_position === 'move_below') { @@ -146,13 +142,13 @@ export default class PageUtils { // 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, folder_id, move_position); + this._insertPageIntoFolder(item, page_id, target_page_id, target_id, move_position); } }); } - static _insertPageIntoFolder(folder, page_id, target_page_id, folder_id, move_position) { - if (folder.id === folder_id) { + 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++; @@ -162,70 +158,118 @@ export default class PageUtils { } folder.children.forEach(item => { if (item.type === FOLDER) { - this._insertPageIntoFolder(item, page_id, target_page_id, folder_id, move_position); + this._insertPageIntoFolder(item, page_id, target_page_id, target_id, move_position); } }); } - // Move the page to the top or bottom of the folder - static insertPageOut(navigation, page_id, folder_id, move_position) { - let indexOffset = 0; - if (move_position === 'move_below') { - indexOffset++; + // move page into folder or page(已解决) + static movePage(navigation, moved_page_id, target_page_id, source_id, target_id, move_position) { + let movedPage = null; + 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); + }); + } } - let page = { id: page_id, type: PAGE }; - let folder_index = this.getFolderIndexById(navigation, folder_id); - if (folder_index > -1) { - navigation.splice(folder_index + indexOffset, 0, page); - } else { - navigation.forEach((item) => { - if (item.type === FOLDER) { - let folder_index = this.getFolderIndexById(item.children, folder_id); - if (folder_index > -1) { - item.children.splice(folder_index + indexOffset, 0, page); - } + 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); + }); + } + } + function _insertPageRecursion(item, page_id, target_page_id, target_id, move_position) { + if (item.id === target_id) { + let insertIndex = target_page_id ? item.children.findIndex(item => item.id === target_page_id) : -1; + if (move_position === 'move_below') { + insertIndex++; } + item.children.splice(insertIndex, 0, movedPage); + return; + } + item.children.forEach(item => { + _insertPageRecursion(item, page_id, target_page_id, target_id, move_position); }); } - } - - static deletePage(navigation, page_id) { - // 1. Delete pages directly under the root directory - const pageIndex = navigation.findIndex(item => item.id === page_id); - if (pageIndex > -1) { - navigation.splice(pageIndex, 1); - return true; - } - // 2. Delete Page in Folder - navigation.forEach(item => { - if (item.type === FOLDER) { - this._deletePageInFolder(item, page_id); + function _insertPage(navigation, page_id, target_page_id, target_id, move_position) { + if (!target_id) { + let insertIndex = target_page_id ? navigation.findIndex(item => item.id === target_page_id) : -1; + if (insertIndex < 0) { + navigation.splice(0, 0, movedPage); + return; + } + if (move_position === 'move_below') { + insertIndex++; + } + navigation.splice(insertIndex, 0, movedPage); + return; } - }); - } - - static _deletePageInFolder(folder, page_id) { - let pageIndex = folder.children.findIndex(item => item.id === page_id); - if (pageIndex > -1) { - folder.children.splice(pageIndex, 1); - return true; + navigation.forEach(item => { + _insertPageRecursion(item, page_id, target_page_id, target_id, move_position); + }); } - folder.children.forEach(item => { - if (item.type === FOLDER) { - this._deletePageInFolder(item, page_id); + _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++; } - }); - } - - // movePageintoFolder - static movePage(navigation, moved_page_id, target_page_id, source_folder_id, target_folder_id, move_position) { - this.deletePage(navigation, moved_page_id, source_folder_id); - this.insertPage(navigation, moved_page_id, target_page_id, target_folder_id, move_position); - } - - // movePageOutsideFolder - static movePageOut(navigation, moved_page_id, source_folder_id, target_folder_id, move_position) { - this.deletePage(navigation, moved_page_id, source_folder_id); - this.insertPageOut(navigation, moved_page_id, target_folder_id, move_position); + 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); } } diff --git a/frontend/src/pages/wiki2/view-structure/view-structure.js b/frontend/src/pages/wiki2/view-structure/view-structure.js index 3fc0ef2c8b..a5fc1c3b62 100644 --- a/frontend/src/pages/wiki2/view-structure/view-structure.js +++ b/frontend/src/pages/wiki2/view-structure/view-structure.js @@ -1,11 +1,10 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import classnames from 'classnames'; import { DropdownItem } from 'reactstrap'; import { DropTarget, DragLayer } from 'react-dnd'; import html5DragDropContext from './html5DragDropContext'; import DraggedFolderItem from './folders/dragged-folder-item'; -import ViewItem from './views/view-item'; +import DraggedViewItem from './views/dragged-view-item'; import ViewStructureFooter from './view-structure-footer'; import { repoID } from '../../../utils/constants'; @@ -32,35 +31,36 @@ class ViewStructure extends Component { duplicatePage: PropTypes.func, onSetFolderId: PropTypes.func, currentPageId: PropTypes.string, + addPageInside: PropTypes.func, }; constructor(props) { super(props); this.folderClassNameCache = ''; - this.idFoldedStatusMap = this.getFoldedFoldersFromBase(); + this.idFoldedStatusMap = this.getFoldedFromLocal(); } - getFoldedFoldersFromBase = () => { - const foldedFolders = window.localStorage.getItem(`wiki-folded-folders-${repoID}`); - return foldedFolders ? JSON.parse(foldedFolders) : {}; + getFoldedFromLocal = () => { + const items = window.localStorage.getItem(`wiki-folded-${repoID}`); + return items ? JSON.parse(items) : {}; }; - setFoldedFolders = (foldedFolders) => { - window.localStorage.setItem(`wiki-folded-folders-${repoID}`, JSON.stringify(foldedFolders)); + saveFoldedToLocal = (items) => { + window.localStorage.setItem(`wiki-folded-${repoID}`, JSON.stringify(items)); }; - getFolderState = (folderId) => { + getFoldState = (folderId) => { return this.idFoldedStatusMap[folderId]; }; - onToggleExpandFolder = (folderId) => { - const idFoldedStatusMap = this.getFoldedFoldersFromBase(); + toggleExpand = (folderId) => { + const idFoldedStatusMap = this.getFoldedFromLocal(); if (idFoldedStatusMap[folderId]) { delete idFoldedStatusMap[folderId]; } else { idFoldedStatusMap[folderId] = true; } - this.setFoldedFolders(idFoldedStatusMap); + this.saveFoldedToLocal(idFoldedStatusMap); this.idFoldedStatusMap = idFoldedStatusMap; }; @@ -96,7 +96,7 @@ class ViewStructure extends Component { return this.folderClassNameCache; }; - renderFolder = (folder, index, tableGridsLength, isOnlyOneView, id_view_map, layerDragProps) => { + renderFolder = (folder, index, pagesLength, isOnlyOneView, id_view_map, layerDragProps) => { const { isEditMode, views } = this.props; const folderId = folder.id; return ( @@ -105,11 +105,11 @@ class ViewStructure extends Component { isEditMode={isEditMode} folder={folder} folderIndex={index} - tableGridsLength={tableGridsLength} + pagesLength={pagesLength} isOnlyOneView={isOnlyOneView} id_view_map={id_view_map} renderFolderMenuItems={this.renderFolderMenuItems} - onToggleExpandFolder={this.onToggleExpandFolder} + toggleExpand={this.toggleExpand} onToggleAddView={this.props.onToggleAddView} onDeleteFolder={this.props.onDeleteFolder} onMoveFolder={this.props.onMoveFolder} @@ -122,30 +122,31 @@ class ViewStructure extends Component { onMoveView={this.props.onMoveView} views={views} moveFolderToFolder={this.props.moveFolderToFolder} - foldersStr={folderId} + pathStr={folderId} layerDragProps={layerDragProps} setClassName={this.setClassName} getClassName={this.getClassName} movePageOut={this.props.movePageOut} onModifyFolder={this.props.onModifyFolder} - getFolderState={this.getFolderState} + getFoldState={this.getFoldState} currentPageId={this.props.currentPageId} + addPageInside={this.props.addPageInside} /> ); }; - renderView = (view, index, tableGridsLength, isOnlyOneView, id_view_map) => { + renderView = (view, index, pagesLength, isOnlyOneView, id_view_map) => { const { isEditMode, views } = this.props; const id = view.id; if (!views.find(item => item.id === id)) return; const folderId = null; // Pages in the root directory, no folders, use null return ( - item.id === id)} + view={Object.assign({}, views.find(item => item.id === id), view)} views={views} viewIndex={index} folderId={folderId} @@ -153,16 +154,19 @@ class ViewStructure extends Component { renderFolderMenuItems={this.renderFolderMenuItems} duplicatePage={this.props.duplicatePage} onSetFolderId={this.props.onSetFolderId} - onSelectView={() => this.props.onSelectView(id)} + onSelectView={this.props.onSelectView} onUpdatePage={this.props.onUpdatePage} - onDeleteView={this.props.onDeleteView.bind(this, id)} + onDeleteView={this.props.onDeleteView} onMoveViewToFolder={(targetFolderId) => { this.onMoveViewToFolder(folderId, view.id, targetFolderId); }} onMoveView={this.props.onMoveView} onMoveFolder={this.props.onMoveFolder} - foldersStr={''} + pathStr={view.id} currentPageId={this.props.currentPageId} + addPageInside={this.props.addPageInside} + getFoldState={this.getFoldState} + toggleExpand={this.toggleExpand} /> ); }; @@ -174,7 +178,7 @@ class ViewStructure extends Component { if (views.length === 1) { isOnlyOneView = true; } - const tableGridsLength = views.length; + const pagesLength = views.length; let id_view_map = {}; views.forEach(view => id_view_map[view.id] = view); const style = { maxHeight: isEditMode ? 'calc(100% - 40px)' : '100%' }; @@ -182,8 +186,8 @@ class ViewStructure extends Component {
{navigation.map((item, index) => { return item.type === 'folder' ? - this.renderFolder(item, index, tableGridsLength, isOnlyOneView, id_view_map, layerDragProps) : - this.renderView(item, index, tableGridsLength, isOnlyOneView, id_view_map); + this.renderFolder(item, index, pagesLength, isOnlyOneView, id_view_map, layerDragProps) : + this.renderView(item, index, pagesLength, isOnlyOneView, id_view_map); })}
); @@ -204,15 +208,10 @@ class ViewStructure extends Component { connectDropTarget: connect.dropTarget() }))(DragLayer(this.collect)(this.renderStructureBody)) ); - const isSpecialInstance = false; - const isDarkMode = false; return ( -
+
- {(this.props.isEditMode && !isSpecialInstance) && + {(this.props.isEditMode) && { + return { + idx: props.viewIndex, + data: { ...props.view, index: props.viewIndex }, + folderId: props.folderId, + mode: DRAGGED_PAGE_MODE, + }; + }, + endDrag(props, monitor) { + const viewSource = monitor.getItem(); + const didDrop = monitor.didDrop(); + let viewTarget = {}; + if (!didDrop) { + return { viewSource, viewTarget }; + } + }, + isDragging(props) { + const { draggedPage, viewIndex: targetIndex } = props; + const { idx } = draggedPage; + return idx > targetIndex; + } +}; + +const dropTarget = { + drop(props, monitor) { + const sourceRow = monitor.getItem(); + // 1 drag page + if (sourceRow.mode === DRAGGED_PAGE_MODE) { + const { infolder, viewIndex: targetIndex, view: targetView, folderId: targetFolderId } = props; + const sourceFolderId = sourceRow.folderId; + const draggedViewId = sourceRow.data.id; + const targetViewId = targetView.id; + + if (draggedViewId !== targetViewId) { + const sourceIndex = sourceRow.idx; + let move_position; + if (infolder) { + move_position = 'move_below'; + } else { + move_position = sourceIndex > targetIndex ? 'move_above' : 'move_below'; + } + + props.onMoveView({ + moved_view_id: draggedViewId, + target_view_id: targetViewId, + source_view_folder_id: sourceFolderId, + target_view_folder_id: targetFolderId, + move_position, + }); + } + return; + } + // 1 drag folder + if (sourceRow.mode === DRAGGED_FOLDER_MODE) { + const { viewIndex: targetIndex, view: targetView } = props; + const draggedFolderId = sourceRow.data.id; + const targetViewId = targetView.id; + const sourceIndex = sourceRow.idx; + // Drag the parent folder to the child page, return + if (props.pathStr.split('-').includes(draggedFolderId)) return; + props.onMoveFolder( + draggedFolderId, + targetViewId, + sourceIndex > targetIndex ? 'move_above' : 'move_below', + ); + 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() +}); + +export default DropTarget('ViewStructure', dropTarget, dropCollect)( + DragSource('ViewStructure', dragSource, dragCollect)(ViewItem) +); diff --git a/frontend/src/pages/wiki2/view-structure/views/drop-target-top-view.js b/frontend/src/pages/wiki2/view-structure/views/drop-target-top-view.js index 260474f998..2540445556 100644 --- a/frontend/src/pages/wiki2/view-structure/views/drop-target-top-view.js +++ b/frontend/src/pages/wiki2/view-structure/views/drop-target-top-view.js @@ -8,15 +8,15 @@ const DropTargetTopView = (Placeholder) => class extends React.Component { connectDropTarget: PropTypes.func.isRequired, isOver: PropTypes.bool, canDrop: PropTypes.bool, - draggedRow: PropTypes.object, + draggedPage: PropTypes.object, targetFolderId: PropTypes.string, targetViewId: PropTypes.string, onMoveView: PropTypes.func, }; render() { - const { connectDropTarget, isOver, canDrop, draggedRow } = this.props; - const { mode } = draggedRow || {}; + const { connectDropTarget, isOver, canDrop, draggedPage } = this.props; + const { mode } = draggedPage || {}; if (mode !== 'view') { return null; } @@ -61,7 +61,7 @@ function collect(connect, monitor) { connectDropTarget: connect.dropTarget(), isOver: monitor.isOver(), canDrop: monitor.canDrop(), - draggedRow: monitor.getItem(), + draggedPage: monitor.getItem(), }; } diff --git a/frontend/src/pages/wiki2/view-structure/views/page-dropdownmenu.js b/frontend/src/pages/wiki2/view-structure/views/page-dropdownmenu.js index ccdb25d125..b583a0b54d 100644 --- a/frontend/src/pages/wiki2/view-structure/views/page-dropdownmenu.js +++ b/frontend/src/pages/wiki2/view-structure/views/page-dropdownmenu.js @@ -10,7 +10,7 @@ export default class PageDropdownMenu extends Component { static propTypes = { view: PropTypes.object.isRequired, views: PropTypes.array, - tableGridsLength: PropTypes.number, + pagesLength: PropTypes.number, folderId: PropTypes.string, canDelete: PropTypes.bool, canDuplicate: PropTypes.bool, @@ -105,7 +105,7 @@ export default class PageDropdownMenu extends Component { render() { const { - folderId, canDelete, canDuplicate, renderFolderMenuItems, tableGridsLength, isOnlyOneView, + folderId, canDelete, canDuplicate, renderFolderMenuItems, pagesLength, isOnlyOneView, } = this.props; const folderMenuItems = renderFolderMenuItems && renderFolderMenuItems({ currentFolderId: folderId, onMoveViewToFolder: this.onMoveViewToFolder }); return ( @@ -132,7 +132,7 @@ export default class PageDropdownMenu extends Component { {gettext('Duplicate page')} } - {(isOnlyOneView || tableGridsLength === 1 || !canDelete) ? '' : ( + {(isOnlyOneView || pagesLength === 1 || !canDelete) ? '' : ( {gettext('Delete page')} diff --git a/frontend/src/pages/wiki2/view-structure/views/view-item.js b/frontend/src/pages/wiki2/view-structure/views/view-item.js index d5a773870c..b0bf4b1e09 100644 --- a/frontend/src/pages/wiki2/view-structure/views/view-item.js +++ b/frontend/src/pages/wiki2/view-structure/views/view-item.js @@ -1,100 +1,14 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import { DragSource, DropTarget } from 'react-dnd'; import ViewEditPopover from './view-edit-popover'; import PageDropdownMenu from './page-dropdownmenu'; import DeleteDialog from './delete-dialog'; -import { DRAGGED_FOLDER_MODE, DRAGGED_VIEW_MODE } from '../constant'; +import { gettext } from '../../../../utils/constants'; +import AddNewPageDialog from '../add-new-page-dialog'; import Icon from '../../../../components/icon'; import NavItemIcon from '../nav-item-icon'; - -const dragSource = { - beginDrag: props => { - return { - idx: props.viewIndex, - data: { ...props.view, index: props.viewIndex }, - folderId: props.folderId, - mode: DRAGGED_VIEW_MODE, - }; - }, - endDrag(props, monitor) { - const viewSource = monitor.getItem(); - const didDrop = monitor.didDrop(); - let viewTarget = {}; - if (!didDrop) { - return { viewSource, viewTarget }; - } - }, - isDragging(props) { - const { draggedRow, infolder, viewIndex: targetIndex } = props; - if (infolder) { - return false; - } - const { idx } = draggedRow; - return idx > targetIndex; - } -}; - -const dropTarget = { - drop(props, monitor) { - const sourceRow = monitor.getItem(); - // 1 drag page - if (sourceRow.mode === DRAGGED_VIEW_MODE) { - const { infolder, viewIndex: targetIndex, view: targetView, folderId: targetFolderId } = props; - const sourceFolderId = sourceRow.folderId; - const draggedViewId = sourceRow.data.id; - const targetViewId = targetView.id; - - if (draggedViewId !== targetViewId) { - const sourceIndex = sourceRow.idx; - let move_position; - if (infolder) { - move_position = 'move_below'; - } else { - move_position = sourceIndex > targetIndex ? 'move_above' : 'move_below'; - } - - props.onMoveView({ - moved_view_id: draggedViewId, - target_view_id: targetViewId, - source_view_folder_id: sourceFolderId, - target_view_folder_id: targetFolderId, - move_position, - }); - } - return; - } - // 1 drag folder - if (sourceRow.mode === DRAGGED_FOLDER_MODE) { - const { viewIndex: targetIndex, view: targetView } = props; - const draggedFolderId = sourceRow.data.id; - const targetViewId = targetView.id; - const sourceIndex = sourceRow.idx; - // Drag the parent folder to the child page, return - if (props.foldersStr.split('-').includes(draggedFolderId)) return; - props.onMoveFolder( - draggedFolderId, - targetViewId, - sourceIndex > targetIndex ? 'move_above' : 'move_below', - ); - 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(), - draggedRow: monitor.getItem() -}); +import DraggedViewItem from '../views/dragged-view-item'; class ViewItem extends Component { @@ -104,18 +18,26 @@ class ViewItem extends Component { isShowViewEditor: false, isShowViewOperationDropdown: false, isShowDeleteDialog: false, + isShowInsertPage: false, viewName: props.view.name || '', viewIcon: props.view.icon, isSelected: props.currentPageId === props.view.id, + isMouseEnter: false, }; this.viewItemRef = React.createRef(); } onMouseEnter = () => { + this.setState({ isMouseEnter: true }); if (this.state.isSelected) return; }; + onMouseMove = () => { + if (!this.state.isMouseEnter) this.setState({ isMouseEnter: true }); + }; + onMouseLeave = () => { + this.setState({ isMouseEnter: false }); if (this.state.isSelected) return; }; @@ -137,6 +59,10 @@ class ViewItem extends Component { }); }; + toggleInsertPage = () => { + this.setState({ isShowInsertPage: !this.state.isShowInsertPage }); + }; + saveViewProperties = () => { const { name, icon, id } = this.props.view; const { viewIcon } = this.state; @@ -198,15 +124,71 @@ class ViewItem extends Component { window.seafile['docUuid'] = docUuid; }; + getFolderChildrenHeight = () => { + const folded = this.props.getFoldState(this.props.view.id); + if (folded) return 0; + return 'auto'; + }; + + onClickFolderChildren = (e) => { + e.stopPropagation(); + e.nativeEvent.stopImmediatePropagation(); + }; + + renderView = (view, index, pagesLength, isOnlyOneView) => { + const { isEditMode, views, folderId, pathStr } = this.props; + const id = view.id; + if (!views.find(item => item.id === id)) return; + return ( + item.id === id), view)} + viewIndex={index} + folderId={folderId} + isEditMode={isEditMode} + renderFolderMenuItems={this.props.renderFolderMenuItems} + duplicatePage={this.props.duplicatePage} + onSetFolderId={this.props.onSetFolderId} + onSelectView={this.props.onSelectView} + onUpdatePage={this.props.onUpdatePage} + onDeleteView={this.props.onDeleteView} + onMoveViewToFolder={(targetFolderId) => { + this.props.onMoveViewToFolder(folderId, view.id, targetFolderId); + }} + onMoveView={this.props.onMoveView} + onMoveFolder={this.props.onMoveFolder} + views={views} + pathStr={pathStr + '-' + view.id} + currentPageId={this.props.currentPageId} + addPageInside={this.props.addPageInside} + getFoldState={this.props.getFoldState} + toggleExpand={this.props.toggleExpand} + /> + ); + }; + + toggleExpand = (e) => { + e.nativeEvent.stopImmediatePropagation(); + this.props.toggleExpand(this.props.view.id); + this.forceUpdate(); + }; + + onAddNewPage = (newPage) => { + const { view } = this.props; + this.props.addPageInside(Object.assign({ parentPageId: view.id }, newPage)); + }; + render() { const { connectDragSource, connectDragPreview, connectDropTarget, isOver, canDrop, isDragging, - infolder, view, tableGridsLength, isEditMode, folderId, isOnlyOneView, foldersStr, + infolder, view, pagesLength, isEditMode, folderId, isOnlyOneView, pathStr, } = this.props; const { isShowViewEditor, viewName, viewIcon, isSelected } = this.state; const isOverView = isOver && canDrop; if (isSelected) this.setDocUuid(view.docUuid); - const isSpecialInstance = false; let viewCanDropTop; let viewCanDrop; @@ -219,72 +201,116 @@ class ViewItem extends Component { } let viewEditorId = `view-editor-${view.id}`; let fn = isEditMode ? connectDragSource : (argu) => {argu;}; + let childNumber = Array.isArray(view.children) ? view.children.length : 0; - return fn(connectDropTarget( - connectDragPreview( -
this.viewItemRef = ref} - onMouseEnter={this.onMouseEnter} - onMouseLeave={this.onMouseLeave} - id={viewEditorId} - > -
{} : this.props.onSelectView}> -
- - {/* {this.renderIcon(view.icon)} */} - {view.name} - {isShowViewEditor && ( - - )} -
-
-
- {isEditMode && -
- - {this.state.isShowViewOperationDropdown && - + { + fn(connectDropTarget( + connectDragPreview( +
this.viewItemRef = ref} + onMouseEnter={this.onMouseEnter} + onMouseMove={this.onMouseMove} + onMouseLeave={this.onMouseLeave} + id={viewEditorId} + > +
{} : (e) => this.props.onSelectView(view.id)}> +
+ {childNumber === 0 && + + } + {(!this.state.isMouseEnter && childNumber > 0) && + + } + {(this.state.isMouseEnter && childNumber > 0) && + + } + {/* {this.renderIcon(view.icon)} */} + {view.name} + {isShowViewEditor && ( + + )} +
+
+
+ {isEditMode && + <> +
+ + {this.state.isShowViewOperationDropdown && + + } +
+
+ +
+ + } +
+ {this.state.isShowDeleteDialog && + + } + {this.state.isShowInsertPage && + }
- } -
- {this.state.isShowDeleteDialog && - + ) + )) + } +
+ {view.children && + view.children.map((item, index) => { + return this.renderView(item, index, pagesLength, isOnlyOneView); + }) }
- ) - )); +
+ ); } } @@ -292,14 +318,15 @@ ViewItem.propTypes = { isOver: PropTypes.bool, canDrop: PropTypes.bool, isDragging: PropTypes.bool, - draggedRow: PropTypes.object, + draggedPage: PropTypes.object, isEditMode: PropTypes.bool, infolder: PropTypes.bool, view: PropTypes.object, + folder: PropTypes.object, views: PropTypes.array, viewIndex: PropTypes.number, folderId: PropTypes.string, - tableGridsLength: PropTypes.number, + pagesLength: PropTypes.number, connectDragSource: PropTypes.func, connectDragPreview: PropTypes.func, connectDropTarget: PropTypes.func, @@ -313,10 +340,11 @@ ViewItem.propTypes = { onMoveView: PropTypes.func, isOnlyOneView: PropTypes.bool, onMoveFolder: PropTypes.func, - foldersStr: PropTypes.string, + pathStr: PropTypes.string, currentPageId: PropTypes.string, + addPageInside: PropTypes.func, + getFoldState: PropTypes.func, + toggleExpand: PropTypes.func, }; -export default DropTarget('ViewStructure', dropTarget, dropCollect)( - DragSource('ViewStructure', dragSource, dragCollect)(ViewItem) -); +export default ViewItem; diff --git a/frontend/src/pages/wikis/wikis.js b/frontend/src/pages/wikis/wikis.js index 69a78d1042..0fb3bc6ab4 100644 --- a/frontend/src/pages/wikis/wikis.js +++ b/frontend/src/pages/wikis/wikis.js @@ -55,10 +55,6 @@ class Wikis extends Component { errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403 }); }); - this.setState({ - loading: false, - wikis: wikis - }); }).catch((error) => { this.setState({ loading: false,