1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-04 08:28:11 +00:00

12.0 wiki page can add sub page (#6165)

* 00 add page.children

* 01 add delete inner page

* 02 change page indent and path

* 03 change top nav style

* 04 change svg and var name

* 05 move pages into or out folder

* 06 change codes
This commit is contained in:
Michael An
2024-06-07 09:45:05 +08:00
committed by GitHub
parent e5b696b098
commit 440fde0553
19 changed files with 632 additions and 416 deletions

View File

@@ -3,17 +3,16 @@
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve"> viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
<style type="text/css"> <style type="text/css">
.st0{fill:#949494;} .st0{fill:#999999;}
</style> </style>
<title>file1</title> <title>file</title>
<desc>Created with Sketch.</desc> <g id="file">
<g id="file1"> <g transform="translate(4.000000, 1.000000)">
<g id="编组-5"> <path id="形状" class="st0" d="M20,30H4c-2.3,0-4-1.8-4-4.1V4.1C0,1.8,1.7,0,4,0h9.3c0.4,0,0.7,0.1,0.9,0.4l9.3,9.5
<g id="文件" transform="translate(3.000000, 0.000000)"> c0.3,0.3,0.4,0.5,0.4,1v15C24,28.2,22.3,30,20,30z M4.3,3C3.5,3,3,3.5,3,4.3v21.3C3,26.5,3.5,27,4.3,27h15.4
<path id="形状" class="st0" d="M25.6,6.9l-6.7-6.6C18.6,0,18.3,0,18,0H4C2.1,0,1,2.3,1,3.9C1,4.9,1,13.3,1,29c0,1,1.3,3,3,3 c0.8,0,1.3-0.5,1.3-1.3V11.5L12.8,3H4.3z"/>
s17.4,0,19.1,0s2.9-1.4,2.9-3c0-1,0-8.2,0-21.3C26,7.4,25.7,7,25.6,6.9z M17.9,3.7L22.3,8H18V3.7H17.9z M22.8,29H4V3h11v5.3 <path id="路径" class="st0" d="M21.7,13h-9.3c-0.8,0-1.3-0.5-1.3-1.3V2.3C11,1.5,11.5,1,12.3,1s1.3,0.5,1.3,1.3v8h8
c0,1.8,0.8,2.7,2.9,2.7H23v18H22.8z"/> c0.8,0,1.3,0.5,1.3,1.3S22.5,13,21.7,13L21.7,13z"/>
</g>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 866 B

After

Width:  |  Height:  |  Size: 941 B

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
<style type="text/css">
.st0{fill:#999999;}
</style>
<title>files</title>
<g id="files">
<g id="file" transform="translate(4.000000, 1.000000)">
<path id="形状" class="st0" d="M20,30H4c-2.3,0-4-1.8-4-4.1V4.1C0,1.8,1.7,0,4,0h9.3c0.4,0,0.7,0.1,0.9,0.4l9.3,9.5
c0.3,0.3,0.4,0.5,0.4,1v15C24,28.2,22.3,30,20,30z M4.3,3C3.5,3,3,3.5,3,4.3v21.3C3,26.5,3.5,27,4.3,27h15.4
c0.8,0,1.3-0.5,1.3-1.3V11.5L12.8,3H4.3z"/>
<path id="路径" class="st0" d="M21.7,13h-9.3c-0.8,0-1.3-0.5-1.3-1.3V2.3C11,1.5,11.5,1,12.3,1s1.3,0.5,1.3,1.3v8h8
c0.8,0,1.3,0.5,1.3,1.3S22.5,13,21.7,13L21.7,13z"/>
<path id="矩形" class="st0" d="M7.5,16h9c0.8,0,1.5,0.7,1.5,1.5l0,0c0,0.8-0.7,1.5-1.5,1.5h-9C6.7,19,6,18.3,6,17.5l0,0
C6,16.7,6.7,16,7.5,16z"/>
<path id="矩形备份" class="st0" d="M7.5,21h9c0.8,0,1.5,0.7,1.5,1.5l0,0c0,0.8-0.7,1.5-1.5,1.5h-9C6.7,24,6,23.3,6,22.5l0,0
C6,21.7,6.7,21,7.5,21z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -94,7 +94,7 @@
padding-left: 20px; padding-left: 20px;
} }
.view-structure .view-folder-wrapper .icon-expand-folder { .view-structure .icon-expand-folder {
display: inline-block; display: inline-block;
font-size: 12px; font-size: 12px;
transform: scale(0.8); 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-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 { .view-structure .view-item .more-view-operation .seafile-multicolor-icon-more-level {
cursor: pointer;
opacity: 0; 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-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 { .view-structure .view-item:hover .more-view-operation .seafile-multicolor-icon-more-level {
opacity: 1; opacity: 1;
@@ -166,6 +169,7 @@
} }
.view-structure .folder-list .view-folder.fold-freezed .btn-folder-operation, .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 { .view-structure .view-item.view-freezed .seafile-multicolor-icon-more-level {
opacity: 1; opacity: 1;
} }
@@ -358,21 +362,24 @@
/* dark mode */ /* dark mode */
.view-structure-dark.view-structure, .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; color: #fff;
} }
/* light mode */ /* light mode */
.view-structure-light.view-structure, .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-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 .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; 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-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 .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; color: #666;
} }

View File

@@ -1,9 +1,12 @@
export default class Page { class Page {
constructor(object) { constructor(object) {
this.id = object.id; this.id = object.id;
this.name = object.name; this.name = object.name;
this.path = object.path; this.path = object.path;
this.icon = object.icon; this.icon = object.icon;
this.docUuid = object.docUuid; this.docUuid = object.docUuid;
this.children = Array.isArray(object.children) ? object.children.map(item => new Page(item)) : [];
} }
} }
export default Page;

View File

@@ -11,6 +11,7 @@ export default class WikiConfig {
return { return {
id: item.id, id: item.id,
type: item.type, type: item.type,
children: item.children || [],
}; };
} }
return null; return null;

View File

@@ -47,6 +47,7 @@ class SidePanel extends Component {
config.pages.splice(index, 1); config.pages.splice(index, 1);
PageUtils.deletePage(navigation, pageId); PageUtils.deletePage(navigation, pageId);
this.props.saveWikiConfig(config); 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); wikiAPI.deleteWiki2Page(wikiId, pageId);
if (config.pages.length > 0) { if (config.pages.length > 0) {
this.props.setCurrentPage(config.pages[0].id); 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 }) => { onAddNewPage = async ({ name, icon, path, docUuid, successCallback, errorCallback }) => {
const { config } = this.props; const { config } = this.props;
const navigation = config.navigation; const navigation = config.navigation;
const pageId = generateUniqueId(navigation); const pageId = generateUniqueId(navigation);
const newPage = new Page({ id: pageId, name, icon, path, docUuid }); 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) => { duplicatePage = async (fromPageConfig, successCallback, errorCallback) => {
@@ -75,15 +84,15 @@ class SidePanel extends Component {
name, name,
}; };
const newPage = new Page({ ...newPageConfig }); 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 { config } = this.props;
const navigation = config.navigation; const navigation = config.navigation;
const pageId = page.id; const pageId = page.id;
config.pages.push(page); config.pages.push(page);
PageUtils.addPage(navigation, pageId, this.current_folder_id); PageUtils.addPage(navigation, pageId, parentId);
config.navigation = navigation; config.navigation = navigation;
const onSuccess = () => { const onSuccess = () => {
this.props.setCurrentPage(pageId, successCallback); this.props.setCurrentPage(pageId, successCallback);
@@ -113,10 +122,10 @@ class SidePanel extends Component {
this.props.saveWikiConfig(config); 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 config = deepCopy(this.props.config);
let { navigation } = 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; config.navigation = navigation;
this.props.saveWikiConfig(config); this.props.saveWikiConfig(config);
}; };
@@ -164,12 +173,13 @@ class SidePanel extends Component {
const { config } = this.props; const { config } = this.props;
const { navigation, pages } = config; const { navigation, pages } = config;
PageUtils.deleteFolder(navigation, pages, page_folder_id); PageUtils.deleteFolder(navigation, pages, page_folder_id);
// TODO: delete all pages inside the folder, A new API is required
config.navigation = navigation; config.navigation = navigation;
this.props.saveWikiConfig(config); this.props.saveWikiConfig(config);
}; };
// Drag a folder to the front and back of another folder // 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 { config } = this.props;
const { navigation } = config; const { navigation } = config;
let updatedNavigation = deepCopy(navigation); let updatedNavigation = deepCopy(navigation);
@@ -196,11 +206,11 @@ class SidePanel extends Component {
indexOffset++; indexOffset++;
} }
// Get the location of the release // 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) { if (target_folder_index === -1) {
updatedNavigation.forEach(item => { updatedNavigation.forEach(item => {
if (item.type === FOLDER) { 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) { if (target_folder_index > -1) {
item.children.splice(target_folder_index + indexOffset, 0, moved_folder); 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 // 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 { config } = this.props;
let { navigation } = config; let { navigation } = config;
// Find the folder and move it to this new folder // 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) { if (!target_folder) {
toaster.danger('Only_support_two_level_folders'); toaster.danger('Only_support_two_level_folders');
return; return;
@@ -299,6 +309,7 @@ class SidePanel extends Component {
duplicatePage={this.duplicatePage} duplicatePage={this.duplicatePage}
onSetFolderId={this.onSetFolderId} onSetFolderId={this.onSetFolderId}
currentPageId={this.props.currentPageId} currentPageId={this.props.currentPageId}
addPageInside={this.addPageInside}
/> />
{this.state.isShowNewFolderDialog && {this.state.isShowNewFolderDialog &&
<NewFolderDialog <NewFolderDialog
@@ -310,6 +321,7 @@ class SidePanel extends Component {
<AddNewPageDialog <AddNewPageDialog
toggle={this.closeAddNewPageDialog} toggle={this.closeAddNewPageDialog}
onAddNewPage={this.onAddNewPage} onAddNewPage={this.onAddNewPage}
title={gettext('Add page')}
/> />
} }
</div> </div>
@@ -335,6 +347,7 @@ class SidePanel extends Component {
<AddNewPageDialog <AddNewPageDialog
toggle={this.closeAddNewPageDialog} toggle={this.closeAddNewPageDialog}
onAddNewPage={this.onAddNewPage} onAddNewPage={this.onAddNewPage}
title={gettext('Add page')}
/> />
} }
</div> </div>

View File

@@ -1,31 +1,56 @@
import React from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import NavItemIcon from '../view-structure/nav-item-icon'; import NavItemIcon from '../view-structure/nav-item-icon';
import './index.css'; 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 }) { function WikiTopNav({ config, currentPageId }) {
const { navigation, pages } = config; const { navigation, pages } = config;
const folder = navigation.find(item => { const paths = getPaths(navigation, currentPageId, pages);
return item.type === 'folder' && item.children && item.children.find(item => item.id === currentPageId);
});
const page = pages.find(page => page.id === currentPageId);
return ( return (
<div className="wiki2-top-nav d-flex"> <div className="wiki2-top-nav d-flex">
{folder && {paths.map((item, index) => {
<> return (
<div className='wiki2-top-nav-item d-flex'> <Fragment key={item.id}>
<NavItemIcon symbol={'wiki-folder'} disable={true} /> <div className='wiki2-top-nav-item d-flex'>
{folder.name} <NavItemIcon symbol={item.type === 'folder' ? 'wiki-folder' : 'file'} disable={true} />
</div> {item.name}
<div>/</div> </div>
</> {index !== paths.length - 1 && <div>/</div>}
} </Fragment>
{page && );
<div className='wiki2-top-nav-item d-flex'> })}
<NavItemIcon symbol={'file'} disable={true} />
{page.name}
</div>
}
</div> </div>
); );
} }

View File

@@ -10,6 +10,7 @@ import wikiAPI from '../../../utils/wiki-api';
import '../css/add-new-page-dialog.css'; import '../css/add-new-page-dialog.css';
const propTypes = { const propTypes = {
title: PropTypes.node,
toggle: PropTypes.func.isRequired, toggle: PropTypes.func.isRequired,
onAddNewPage: PropTypes.func, onAddNewPage: PropTypes.func,
}; };
@@ -95,9 +96,10 @@ class AddNewPageDialog extends React.Component {
}; };
render() { render() {
const { title } = this.props;
return ( return (
<Modal isOpen={true} toggle={this.toggle} autoFocus={false} className='add-new-page-dialog'> <Modal isOpen={true} toggle={this.toggle} autoFocus={false} className='add-new-page-dialog'>
<ModalHeader toggle={this.toggle}>{gettext('Add page')}</ModalHeader> <ModalHeader toggle={this.toggle}>{title}</ModalHeader>
<ModalBody className='pr-4'> <ModalBody className='pr-4'>
<Label>{gettext('Page name')}</Label> <Label>{gettext('Page name')}</Label>
<Input <Input

View File

@@ -1,2 +1,2 @@
export const DRAGGED_FOLDER_MODE = 'view-folder'; export const DRAGGED_FOLDER_MODE = 'wiki-folder';
export const DRAGGED_VIEW_MODE = 'view'; export const DRAGGED_PAGE_MODE = 'wiki-page';

View File

@@ -1,5 +1,5 @@
import { DragSource, DropTarget } from 'react-dnd'; import { DragSource, DropTarget } from 'react-dnd';
import { DRAGGED_FOLDER_MODE, DRAGGED_VIEW_MODE } from '../constant'; import { DRAGGED_FOLDER_MODE, DRAGGED_PAGE_MODE } from '../constant';
import FolderItem from './folder-item'; import FolderItem from './folder-item';
const dragSource = { const dragSource = {
@@ -20,8 +20,8 @@ const dragSource = {
} }
}, },
isDragging(props, monitor) { isDragging(props, monitor) {
const { folderIndex: currentIndex, draggedRow } = props; const { folderIndex: currentIndex, draggedPage } = props;
const { idx } = draggedRow; const { idx } = draggedPage;
return idx > currentIndex; return idx > currentIndex;
}, },
}; };
@@ -43,7 +43,7 @@ const dropTarget = {
let moveInto = className.includes('dragged-view-over'); let moveInto = className.includes('dragged-view-over');
// 1. drag source is page // 1. drag source is page
if (sourceRow.mode === DRAGGED_VIEW_MODE) { if (sourceRow.mode === DRAGGED_PAGE_MODE) {
const sourceFolderId = sourceRow.folderId; const sourceFolderId = sourceRow.folderId;
const draggedViewId = sourceRow.data.id; const draggedViewId = sourceRow.data.id;
// 1.1 move page into folder // 1.1 move page into folder
@@ -93,7 +93,7 @@ const dropCollect = (connect, monitor) => ({
connectDropTarget: connect.dropTarget(), connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(), isOver: monitor.isOver(),
canDrop: monitor.canDrop(), canDrop: monitor.canDrop(),
draggedRow: monitor.getItem(), draggedPage: monitor.getItem(),
connect, connect,
monitor, monitor,
}); });

View File

@@ -2,10 +2,9 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import FolderOperationDropdownMenu from './folder-operation-dropdownmenu'; 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 DraggedFolderItem from './dragged-folder-item';
import ViewEditPopover from '../../view-structure/views/view-edit-popover'; import ViewEditPopover from '../../view-structure/views/view-edit-popover';
import { FOLDER } from '../../constant';
import NavItemIcon from '../nav-item-icon'; import NavItemIcon from '../nav-item-icon';
class FolderItem extends Component { class FolderItem extends Component {
@@ -21,14 +20,9 @@ class FolderItem extends Component {
}; };
} }
onToggleExpandFolder = (e) => { toggleExpand = (e) => {
e.nativeEvent.stopImmediatePropagation(); e.nativeEvent.stopImmediatePropagation();
this.props.onToggleExpandFolder(this.props.folder.id); this.props.toggleExpand(this.props.folder.id);
this.forceUpdate();
};
onToggleExpandSubfolder = (subfolderId) => {
this.props.onToggleExpandFolder(subfolderId);
this.forceUpdate(); this.forceUpdate();
}; };
@@ -66,8 +60,8 @@ class FolderItem extends Component {
// } // }
}; };
renderFolder = (folder, index, tableGridsLength, isOnlyOneView, id_view_map) => { renderFolder = (folder, index, pagesLength, isOnlyOneView, id_view_map) => {
const { isEditMode, views, foldersStr } = this.props; const { isEditMode, views, pathStr } = this.props;
const { id: folderId } = folder; const { id: folderId } = folder;
return ( return (
<DraggedFolderItem <DraggedFolderItem
@@ -75,11 +69,11 @@ class FolderItem extends Component {
isEditMode={isEditMode} isEditMode={isEditMode}
folder={folder} folder={folder}
folderIndex={index} folderIndex={index}
tableGridsLength={tableGridsLength} pagesLength={pagesLength}
isOnlyOneView={isOnlyOneView} isOnlyOneView={isOnlyOneView}
id_view_map={id_view_map} id_view_map={id_view_map}
renderFolderMenuItems={this.props.renderFolderMenuItems} renderFolderMenuItems={this.props.renderFolderMenuItems}
onToggleExpandFolder={this.onToggleExpandSubfolder} toggleExpand={this.props.toggleExpand}
onToggleAddView={this.props.onToggleAddView} onToggleAddView={this.props.onToggleAddView}
onModifyFolder={this.props.onModifyFolder} onModifyFolder={this.props.onModifyFolder}
onDeleteFolder={this.props.onDeleteFolder} onDeleteFolder={this.props.onDeleteFolder}
@@ -93,45 +87,49 @@ class FolderItem extends Component {
onMoveView={this.props.onMoveView} onMoveView={this.props.onMoveView}
moveFolderToFolder={this.props.moveFolderToFolder} moveFolderToFolder={this.props.moveFolderToFolder}
views={views} views={views}
foldersStr={foldersStr + '-' + folderId} pathStr={pathStr + '-' + folderId}
setClassName={this.props.setClassName} setClassName={this.props.setClassName}
getClassName={this.props.getClassName} getClassName={this.props.getClassName}
movePageOut={this.props.movePageOut} movePageOut={this.props.movePageOut}
layerDragProps={this.props.layerDragProps} layerDragProps={this.props.layerDragProps}
getFolderState={this.props.getFolderState} getFoldState={this.props.getFoldState}
currentPageId={this.props.currentPageId} currentPageId={this.props.currentPageId}
addPageInside={this.props.addPageInside}
/> />
); );
}; };
renderView = (view, index, tableGridsLength, isOnlyOneView) => { renderView = (view, index, pagesLength, isOnlyOneView) => {
const { isEditMode, views, folder, foldersStr } = this.props; const { isEditMode, views, folder, pathStr } = this.props;
const id = view.id; const id = view.id;
if (!views.find(item => item.id === id)) return; if (!views.find(item => item.id === id)) return;
return ( return (
<ViewItem <DraggedViewItem
key={id} key={id}
tableGridsLength={tableGridsLength} pagesLength={pagesLength}
isOnlyOneView={isOnlyOneView} isOnlyOneView={isOnlyOneView}
infolder={false} infolder={false}
view={views.find(item => item.id === id)} view={Object.assign({}, views.find(item => item.id === id), view)}
viewIndex={index} viewIndex={index}
folderId={folder.id} folderId={folder.id}
isEditMode={isEditMode} isEditMode={isEditMode}
renderFolderMenuItems={this.props.renderFolderMenuItems} renderFolderMenuItems={this.props.renderFolderMenuItems}
duplicatePage={this.props.duplicatePage} duplicatePage={this.props.duplicatePage}
onSetFolderId={this.props.onSetFolderId} onSetFolderId={this.props.onSetFolderId}
onSelectView={() => this.props.onSelectView(id)} onSelectView={this.props.onSelectView}
onUpdatePage={this.props.onUpdatePage} onUpdatePage={this.props.onUpdatePage}
onDeleteView={this.props.onDeleteView.bind(this, id)} onDeleteView={this.props.onDeleteView}
onMoveViewToFolder={(targetFolderId) => { onMoveViewToFolder={(targetFolderId) => {
this.props.onMoveViewToFolder(folder.id, view.id, targetFolderId); this.props.onMoveViewToFolder(folder.id, view.id, targetFolderId);
}} }}
onMoveView={this.props.onMoveView} onMoveView={this.props.onMoveView}
onMoveFolder={this.props.onMoveFolder} onMoveFolder={this.props.onMoveFolder}
views={views} views={views}
foldersStr={foldersStr} pathStr={pathStr + '-' + view.id}
currentPageId={this.props.currentPageId} 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 = () => { getFolderChildrenHeight = () => {
const { id: folderId, children } = this.props.folder; const folded = this.props.getFoldState(this.props.folder.id);
const folded = this.props.getFolderState(folderId);
if (folded) return 0; if (folded) return 0;
return 'auto';
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;
}; };
onMouseEnter = () => { onMouseEnter = () => {
@@ -189,18 +174,18 @@ class FolderItem extends Component {
render() { render() {
const { const {
connectDropTarget, connectDragPreview, connectDragSource, isOver, canDrop, connectDropTarget, connectDragPreview, connectDragSource, isOver, canDrop,
isEditMode, folder, tableGridsLength, id_view_map, isOnlyOneView, layerDragProps, isEditMode, folder, pagesLength, id_view_map, isOnlyOneView, layerDragProps,
} = this.props; } = this.props;
const { isEditing } = this.state; const { isEditing } = this.state;
const { id: folderId, name, children } = folder; const { id: folderId, name, children } = folder;
const folded = this.props.getFolderState(folderId); const folded = this.props.getFoldState(folderId);
let viewEditorId = `folder-item-${folderId}`; let viewEditorId = `folder-item-${folderId}`;
let fn = isEditMode ? connectDragSource : (argu) => {argu;}; let fn = isEditMode ? connectDragSource : (argu) => {argu;};
return ( return (
<div <div
className={classnames('view-folder', { 'readonly': !isEditMode })} className={classnames('view-folder', { 'readonly': !isEditMode })}
ref={ref => this.foldRef = ref} ref={ref => this.foldRef = ref}
onClick={this.onToggleExpandFolder} onClick={this.toggleExpand}
> >
{fn(connectDropTarget( {fn(connectDropTarget(
connectDragPreview( connectDragPreview(
@@ -213,7 +198,7 @@ class FolderItem extends Component {
<div className='folder-main'> <div className='folder-main'>
<div <div
className='folder-content' className='folder-content'
style={{ marginLeft: `${(this.props.foldersStr.split('-').length - 1) * 16}px` }} style={{ marginLeft: `${(this.props.pathStr.split('-').length - 1) * 16}px` }}
id={viewEditorId} id={viewEditorId}
> >
{this.state.isMouseEnter ? {this.state.isMouseEnter ?
@@ -254,7 +239,7 @@ class FolderItem extends Component {
> >
{!folded && children && {!folded && children &&
children.map((item, index) => { 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);
}) })
} }
</div> </div>
@@ -267,19 +252,18 @@ FolderItem.propTypes = {
isEditMode: PropTypes.bool, isEditMode: PropTypes.bool,
folder: PropTypes.object, folder: PropTypes.object,
folderIndex: PropTypes.number, folderIndex: PropTypes.number,
tableGridsLength: PropTypes.number, pagesLength: PropTypes.number,
id_view_map: PropTypes.object, id_view_map: PropTypes.object,
isOver: PropTypes.bool, isOver: PropTypes.bool,
canDrop: PropTypes.bool, canDrop: PropTypes.bool,
isDragging: PropTypes.bool, isDragging: PropTypes.bool,
draggedRow: PropTypes.object,
connectDropTarget: PropTypes.func, connectDropTarget: PropTypes.func,
connectDragPreview: PropTypes.func, connectDragPreview: PropTypes.func,
connectDragSource: PropTypes.func, connectDragSource: PropTypes.func,
renderFolderMenuItems: PropTypes.func, renderFolderMenuItems: PropTypes.func,
duplicatePage: PropTypes.func, duplicatePage: PropTypes.func,
onSetFolderId: PropTypes.func, onSetFolderId: PropTypes.func,
onToggleExpandFolder: PropTypes.func, toggleExpand: PropTypes.func,
onToggleAddView: PropTypes.func, onToggleAddView: PropTypes.func,
onModifyFolder: PropTypes.func, onModifyFolder: PropTypes.func,
onDeleteFolder: PropTypes.func, onDeleteFolder: PropTypes.func,
@@ -292,13 +276,14 @@ FolderItem.propTypes = {
views: PropTypes.array, views: PropTypes.array,
onMoveFolder: PropTypes.func, onMoveFolder: PropTypes.func,
moveFolderToFolder: PropTypes.func, moveFolderToFolder: PropTypes.func,
foldersStr: PropTypes.string, pathStr: PropTypes.string,
setClassName: PropTypes.func, setClassName: PropTypes.func,
getClassName: PropTypes.func, getClassName: PropTypes.func,
movePageOut: PropTypes.func, movePageOut: PropTypes.func,
layerDragProps: PropTypes.object, layerDragProps: PropTypes.object,
getFolderState: PropTypes.func, getFoldState: PropTypes.func,
currentPageId: PropTypes.string, currentPageId: PropTypes.string,
addPageInside: PropTypes.func,
}; };
export default FolderItem; export default FolderItem;

View File

@@ -4,9 +4,9 @@ import Icon from '../../../components/icon';
import classNames from 'classnames'; import classNames from 'classnames';
import './nav-item-icon.css'; import './nav-item-icon.css';
function NavItemIcon({ symbol, className, disable }) { function NavItemIcon({ symbol, className, disable, onClick }) {
return ( return (
<div className={classNames('nav-item-icon', {'nav-item-icon-disable': disable})}> <div onClick={onClick} className={classNames('nav-item-icon', {'nav-item-icon-disable': disable})}>
<Icon symbol={symbol} className={className} /> <Icon symbol={symbol} className={className} />
</div> </div>
); );
@@ -16,6 +16,7 @@ NavItemIcon.propTypes = {
symbol: PropTypes.string.isRequired, symbol: PropTypes.string.isRequired,
className: PropTypes.string, className: PropTypes.string,
disable: PropTypes.bool, disable: PropTypes.bool,
onClick: PropTypes.func,
}; };
export default NavItemIcon; export default NavItemIcon;

View File

@@ -2,34 +2,57 @@ import { FOLDER, PAGE } from '../constant';
export default class PageUtils { 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) => { static getPageById = (pages, page_id) => {
if (!page_id || !Array.isArray(pages)) return null; if (!page_id || !Array.isArray(pages)) return null;
return pages.find((page) => page.id === page_id) || 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) => { static getPageIndexById = (pageId, pages) => {
return pages.findIndex(page => page.id === pageId); return pages.findIndex(page => page.id === pageId);
}; };
@@ -102,39 +125,12 @@ export default class PageUtils {
}); });
} }
static addPage(navigation, page_id, target_folder_id) { static insertPage(navigation, page_id, target_page_id, target_id, move_position) {
// 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) {
// 1. No folder, insert page in root directory // 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; let insertIndex = target_page_id ? navigation.findIndex(item => item.id === target_page_id) : -1;
if (insertIndex < 0) { if (insertIndex < 0) {
this.addPage(navigation, page_id, folder_id); this.addPage(navigation, page_id, target_id);
return true; return true;
} }
if (move_position === 'move_below') { if (move_position === 'move_below') {
@@ -146,13 +142,13 @@ export default class PageUtils {
// 2. If there is a folder, find it and insert it // 2. If there is a folder, find it and insert it
navigation.forEach(item => { navigation.forEach(item => {
if (item.type === FOLDER) { 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) { static _insertPageIntoFolder(folder, page_id, target_page_id, target_id, move_position) {
if (folder.id === folder_id) { if (folder.id === target_id) {
let insertIndex = target_page_id ? folder.children.findIndex(item => item.id === target_page_id) : -1; let insertIndex = target_page_id ? folder.children.findIndex(item => item.id === target_page_id) : -1;
if (move_position === 'move_below') { if (move_position === 'move_below') {
insertIndex++; insertIndex++;
@@ -162,70 +158,118 @@ export default class PageUtils {
} }
folder.children.forEach(item => { folder.children.forEach(item => {
if (item.type === FOLDER) { 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 // move page into folder or page(已解决)
static insertPageOut(navigation, page_id, folder_id, move_position) { static movePage(navigation, moved_page_id, target_page_id, source_id, target_id, move_position) {
let indexOffset = 0; let movedPage = null;
if (move_position === 'move_below') { function _cutPageRecursion(item, page_id) {
indexOffset++; 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 }; function _cutPage(navigation, page_id) {
let folder_index = this.getFolderIndexById(navigation, folder_id); const pageIndex = navigation.findIndex(item => item.id === page_id);
if (folder_index > -1) { if (pageIndex > -1) {
navigation.splice(folder_index + indexOffset, 0, page); movedPage = navigation.splice(pageIndex, 1)[0];
} else { } else {
navigation.forEach((item) => { navigation.forEach(item => {
if (item.type === FOLDER) { _cutPageRecursion(item, page_id);
let folder_index = this.getFolderIndexById(item.children, folder_id); });
if (folder_index > -1) { }
item.children.splice(folder_index + indexOffset, 0, page); }
} 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);
}); });
} }
} function _insertPage(navigation, page_id, target_page_id, target_id, move_position) {
if (!target_id) {
static deletePage(navigation, page_id) { let insertIndex = target_page_id ? navigation.findIndex(item => item.id === target_page_id) : -1;
// 1. Delete pages directly under the root directory if (insertIndex < 0) {
const pageIndex = navigation.findIndex(item => item.id === page_id); navigation.splice(0, 0, movedPage);
if (pageIndex > -1) { return;
navigation.splice(pageIndex, 1); }
return true; if (move_position === 'move_below') {
} insertIndex++;
// 2. Delete Page in Folder }
navigation.forEach(item => { navigation.splice(insertIndex, 0, movedPage);
if (item.type === FOLDER) { return;
this._deletePageInFolder(item, page_id);
} }
}); navigation.forEach(item => {
} _insertPageRecursion(item, page_id, target_page_id, target_id, move_position);
});
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;
} }
folder.children.forEach(item => { _cutPage(navigation, moved_page_id);
if (item.type === FOLDER) { _insertPage(navigation, moved_page_id, target_page_id, target_id, move_position);
this._deletePageInFolder(item, page_id); }
// 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);
// movePageintoFolder } else {
static movePage(navigation, moved_page_id, target_page_id, source_folder_id, target_folder_id, move_position) { navigation.forEach((item) => {
this.deletePage(navigation, moved_page_id, source_folder_id); if (item.type === FOLDER) {
this.insertPage(navigation, moved_page_id, target_page_id, target_folder_id, move_position); let folder_index = getFolderIndexById(item.children, target_id);
} if (folder_index > -1) {
item.children.splice(folder_index + indexOffset, 0, movedPage);
// 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); }
}
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);
} }
} }

View File

@@ -1,11 +1,10 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames';
import { DropdownItem } from 'reactstrap'; import { DropdownItem } from 'reactstrap';
import { DropTarget, DragLayer } from 'react-dnd'; import { DropTarget, DragLayer } from 'react-dnd';
import html5DragDropContext from './html5DragDropContext'; import html5DragDropContext from './html5DragDropContext';
import DraggedFolderItem from './folders/dragged-folder-item'; 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 ViewStructureFooter from './view-structure-footer';
import { repoID } from '../../../utils/constants'; import { repoID } from '../../../utils/constants';
@@ -32,35 +31,36 @@ class ViewStructure extends Component {
duplicatePage: PropTypes.func, duplicatePage: PropTypes.func,
onSetFolderId: PropTypes.func, onSetFolderId: PropTypes.func,
currentPageId: PropTypes.string, currentPageId: PropTypes.string,
addPageInside: PropTypes.func,
}; };
constructor(props) { constructor(props) {
super(props); super(props);
this.folderClassNameCache = ''; this.folderClassNameCache = '';
this.idFoldedStatusMap = this.getFoldedFoldersFromBase(); this.idFoldedStatusMap = this.getFoldedFromLocal();
} }
getFoldedFoldersFromBase = () => { getFoldedFromLocal = () => {
const foldedFolders = window.localStorage.getItem(`wiki-folded-folders-${repoID}`); const items = window.localStorage.getItem(`wiki-folded-${repoID}`);
return foldedFolders ? JSON.parse(foldedFolders) : {}; return items ? JSON.parse(items) : {};
}; };
setFoldedFolders = (foldedFolders) => { saveFoldedToLocal = (items) => {
window.localStorage.setItem(`wiki-folded-folders-${repoID}`, JSON.stringify(foldedFolders)); window.localStorage.setItem(`wiki-folded-${repoID}`, JSON.stringify(items));
}; };
getFolderState = (folderId) => { getFoldState = (folderId) => {
return this.idFoldedStatusMap[folderId]; return this.idFoldedStatusMap[folderId];
}; };
onToggleExpandFolder = (folderId) => { toggleExpand = (folderId) => {
const idFoldedStatusMap = this.getFoldedFoldersFromBase(); const idFoldedStatusMap = this.getFoldedFromLocal();
if (idFoldedStatusMap[folderId]) { if (idFoldedStatusMap[folderId]) {
delete idFoldedStatusMap[folderId]; delete idFoldedStatusMap[folderId];
} else { } else {
idFoldedStatusMap[folderId] = true; idFoldedStatusMap[folderId] = true;
} }
this.setFoldedFolders(idFoldedStatusMap); this.saveFoldedToLocal(idFoldedStatusMap);
this.idFoldedStatusMap = idFoldedStatusMap; this.idFoldedStatusMap = idFoldedStatusMap;
}; };
@@ -96,7 +96,7 @@ class ViewStructure extends Component {
return this.folderClassNameCache; 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 { isEditMode, views } = this.props;
const folderId = folder.id; const folderId = folder.id;
return ( return (
@@ -105,11 +105,11 @@ class ViewStructure extends Component {
isEditMode={isEditMode} isEditMode={isEditMode}
folder={folder} folder={folder}
folderIndex={index} folderIndex={index}
tableGridsLength={tableGridsLength} pagesLength={pagesLength}
isOnlyOneView={isOnlyOneView} isOnlyOneView={isOnlyOneView}
id_view_map={id_view_map} id_view_map={id_view_map}
renderFolderMenuItems={this.renderFolderMenuItems} renderFolderMenuItems={this.renderFolderMenuItems}
onToggleExpandFolder={this.onToggleExpandFolder} toggleExpand={this.toggleExpand}
onToggleAddView={this.props.onToggleAddView} onToggleAddView={this.props.onToggleAddView}
onDeleteFolder={this.props.onDeleteFolder} onDeleteFolder={this.props.onDeleteFolder}
onMoveFolder={this.props.onMoveFolder} onMoveFolder={this.props.onMoveFolder}
@@ -122,30 +122,31 @@ class ViewStructure extends Component {
onMoveView={this.props.onMoveView} onMoveView={this.props.onMoveView}
views={views} views={views}
moveFolderToFolder={this.props.moveFolderToFolder} moveFolderToFolder={this.props.moveFolderToFolder}
foldersStr={folderId} pathStr={folderId}
layerDragProps={layerDragProps} layerDragProps={layerDragProps}
setClassName={this.setClassName} setClassName={this.setClassName}
getClassName={this.getClassName} getClassName={this.getClassName}
movePageOut={this.props.movePageOut} movePageOut={this.props.movePageOut}
onModifyFolder={this.props.onModifyFolder} onModifyFolder={this.props.onModifyFolder}
getFolderState={this.getFolderState} getFoldState={this.getFoldState}
currentPageId={this.props.currentPageId} 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 { isEditMode, views } = this.props;
const id = view.id; const id = view.id;
if (!views.find(item => item.id === id)) return; if (!views.find(item => item.id === id)) return;
const folderId = null; // Pages in the root directory, no folders, use null const folderId = null; // Pages in the root directory, no folders, use null
return ( return (
<ViewItem <DraggedViewItem
key={id} key={id}
tableGridsLength={tableGridsLength} pagesLength={pagesLength}
isOnlyOneView={isOnlyOneView} isOnlyOneView={isOnlyOneView}
infolder={false} infolder={false}
view={views.find(item => item.id === id)} view={Object.assign({}, views.find(item => item.id === id), view)}
views={views} views={views}
viewIndex={index} viewIndex={index}
folderId={folderId} folderId={folderId}
@@ -153,16 +154,19 @@ class ViewStructure extends Component {
renderFolderMenuItems={this.renderFolderMenuItems} renderFolderMenuItems={this.renderFolderMenuItems}
duplicatePage={this.props.duplicatePage} duplicatePage={this.props.duplicatePage}
onSetFolderId={this.props.onSetFolderId} onSetFolderId={this.props.onSetFolderId}
onSelectView={() => this.props.onSelectView(id)} onSelectView={this.props.onSelectView}
onUpdatePage={this.props.onUpdatePage} onUpdatePage={this.props.onUpdatePage}
onDeleteView={this.props.onDeleteView.bind(this, id)} onDeleteView={this.props.onDeleteView}
onMoveViewToFolder={(targetFolderId) => { onMoveViewToFolder={(targetFolderId) => {
this.onMoveViewToFolder(folderId, view.id, targetFolderId); this.onMoveViewToFolder(folderId, view.id, targetFolderId);
}} }}
onMoveView={this.props.onMoveView} onMoveView={this.props.onMoveView}
onMoveFolder={this.props.onMoveFolder} onMoveFolder={this.props.onMoveFolder}
foldersStr={''} pathStr={view.id}
currentPageId={this.props.currentPageId} 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) { if (views.length === 1) {
isOnlyOneView = true; isOnlyOneView = true;
} }
const tableGridsLength = views.length; const pagesLength = views.length;
let id_view_map = {}; let id_view_map = {};
views.forEach(view => id_view_map[view.id] = view); views.forEach(view => id_view_map[view.id] = view);
const style = { maxHeight: isEditMode ? 'calc(100% - 40px)' : '100%' }; const style = { maxHeight: isEditMode ? 'calc(100% - 40px)' : '100%' };
@@ -182,8 +186,8 @@ class ViewStructure extends Component {
<div className='view-structure-body' style={style}> <div className='view-structure-body' style={style}>
{navigation.map((item, index) => { {navigation.map((item, index) => {
return item.type === 'folder' ? return item.type === 'folder' ?
this.renderFolder(item, index, tableGridsLength, isOnlyOneView, id_view_map, layerDragProps) : this.renderFolder(item, index, pagesLength, isOnlyOneView, id_view_map, layerDragProps) :
this.renderView(item, index, tableGridsLength, isOnlyOneView, id_view_map); this.renderView(item, index, pagesLength, isOnlyOneView, id_view_map);
})} })}
</div> </div>
); );
@@ -204,15 +208,10 @@ class ViewStructure extends Component {
connectDropTarget: connect.dropTarget() connectDropTarget: connect.dropTarget()
}))(DragLayer(this.collect)(this.renderStructureBody)) }))(DragLayer(this.collect)(this.renderStructureBody))
); );
const isSpecialInstance = false;
const isDarkMode = false;
return ( return (
<div className={classnames('view-structure', <div className='view-structure view-structure-light'>
{ 'view-structure-dark': isDarkMode },
{ 'view-structure-light': !isDarkMode },
)}>
<StructureBody /> <StructureBody />
{(this.props.isEditMode && !isSpecialInstance) && {(this.props.isEditMode) &&
<ViewStructureFooter <ViewStructureFooter
onToggleAddView={this.props.onToggleAddView} onToggleAddView={this.props.onToggleAddView}
onToggleAddFolder={this.props.onToggleAddFolder} onToggleAddFolder={this.props.onToggleAddFolder}

View File

@@ -0,0 +1,91 @@
import { DragSource, DropTarget } from 'react-dnd';
import { DRAGGED_FOLDER_MODE, DRAGGED_PAGE_MODE } from '../constant';
import ViewItem from './view-item';
const dragSource = {
beginDrag: props => {
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)
);

View File

@@ -8,15 +8,15 @@ const DropTargetTopView = (Placeholder) => class extends React.Component {
connectDropTarget: PropTypes.func.isRequired, connectDropTarget: PropTypes.func.isRequired,
isOver: PropTypes.bool, isOver: PropTypes.bool,
canDrop: PropTypes.bool, canDrop: PropTypes.bool,
draggedRow: PropTypes.object, draggedPage: PropTypes.object,
targetFolderId: PropTypes.string, targetFolderId: PropTypes.string,
targetViewId: PropTypes.string, targetViewId: PropTypes.string,
onMoveView: PropTypes.func, onMoveView: PropTypes.func,
}; };
render() { render() {
const { connectDropTarget, isOver, canDrop, draggedRow } = this.props; const { connectDropTarget, isOver, canDrop, draggedPage } = this.props;
const { mode } = draggedRow || {}; const { mode } = draggedPage || {};
if (mode !== 'view') { if (mode !== 'view') {
return null; return null;
} }
@@ -61,7 +61,7 @@ function collect(connect, monitor) {
connectDropTarget: connect.dropTarget(), connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(), isOver: monitor.isOver(),
canDrop: monitor.canDrop(), canDrop: monitor.canDrop(),
draggedRow: monitor.getItem(), draggedPage: monitor.getItem(),
}; };
} }

View File

@@ -10,7 +10,7 @@ export default class PageDropdownMenu extends Component {
static propTypes = { static propTypes = {
view: PropTypes.object.isRequired, view: PropTypes.object.isRequired,
views: PropTypes.array, views: PropTypes.array,
tableGridsLength: PropTypes.number, pagesLength: PropTypes.number,
folderId: PropTypes.string, folderId: PropTypes.string,
canDelete: PropTypes.bool, canDelete: PropTypes.bool,
canDuplicate: PropTypes.bool, canDuplicate: PropTypes.bool,
@@ -105,7 +105,7 @@ export default class PageDropdownMenu extends Component {
render() { render() {
const { const {
folderId, canDelete, canDuplicate, renderFolderMenuItems, tableGridsLength, isOnlyOneView, folderId, canDelete, canDuplicate, renderFolderMenuItems, pagesLength, isOnlyOneView,
} = this.props; } = this.props;
const folderMenuItems = renderFolderMenuItems && renderFolderMenuItems({ currentFolderId: folderId, onMoveViewToFolder: this.onMoveViewToFolder }); const folderMenuItems = renderFolderMenuItems && renderFolderMenuItems({ currentFolderId: folderId, onMoveViewToFolder: this.onMoveViewToFolder });
return ( return (
@@ -132,7 +132,7 @@ export default class PageDropdownMenu extends Component {
<span className="item-text">{gettext('Duplicate page')}</span> <span className="item-text">{gettext('Duplicate page')}</span>
</DropdownItem> </DropdownItem>
} }
{(isOnlyOneView || tableGridsLength === 1 || !canDelete) ? '' : ( {(isOnlyOneView || pagesLength === 1 || !canDelete) ? '' : (
<DropdownItem onClick={this.onDeleteView}> <DropdownItem onClick={this.onDeleteView}>
<Icon symbol={'delete'}/> <Icon symbol={'delete'}/>
<span className="item-text">{gettext('Delete page')}</span> <span className="item-text">{gettext('Delete page')}</span>

View File

@@ -1,100 +1,14 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import { DragSource, DropTarget } from 'react-dnd';
import ViewEditPopover from './view-edit-popover'; import ViewEditPopover from './view-edit-popover';
import PageDropdownMenu from './page-dropdownmenu'; import PageDropdownMenu from './page-dropdownmenu';
import DeleteDialog from './delete-dialog'; 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 Icon from '../../../../components/icon';
import NavItemIcon from '../nav-item-icon'; import NavItemIcon from '../nav-item-icon';
import DraggedViewItem from '../views/dragged-view-item';
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()
});
class ViewItem extends Component { class ViewItem extends Component {
@@ -104,18 +18,26 @@ class ViewItem extends Component {
isShowViewEditor: false, isShowViewEditor: false,
isShowViewOperationDropdown: false, isShowViewOperationDropdown: false,
isShowDeleteDialog: false, isShowDeleteDialog: false,
isShowInsertPage: false,
viewName: props.view.name || '', viewName: props.view.name || '',
viewIcon: props.view.icon, viewIcon: props.view.icon,
isSelected: props.currentPageId === props.view.id, isSelected: props.currentPageId === props.view.id,
isMouseEnter: false,
}; };
this.viewItemRef = React.createRef(); this.viewItemRef = React.createRef();
} }
onMouseEnter = () => { onMouseEnter = () => {
this.setState({ isMouseEnter: true });
if (this.state.isSelected) return; if (this.state.isSelected) return;
}; };
onMouseMove = () => {
if (!this.state.isMouseEnter) this.setState({ isMouseEnter: true });
};
onMouseLeave = () => { onMouseLeave = () => {
this.setState({ isMouseEnter: false });
if (this.state.isSelected) return; if (this.state.isSelected) return;
}; };
@@ -137,6 +59,10 @@ class ViewItem extends Component {
}); });
}; };
toggleInsertPage = () => {
this.setState({ isShowInsertPage: !this.state.isShowInsertPage });
};
saveViewProperties = () => { saveViewProperties = () => {
const { name, icon, id } = this.props.view; const { name, icon, id } = this.props.view;
const { viewIcon } = this.state; const { viewIcon } = this.state;
@@ -198,15 +124,71 @@ class ViewItem extends Component {
window.seafile['docUuid'] = docUuid; 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 (
<DraggedViewItem
key={id}
pagesLength={pagesLength}
isOnlyOneView={isOnlyOneView}
infolder={false}
view={Object.assign({}, views.find(item => 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() { render() {
const { const {
connectDragSource, connectDragPreview, connectDropTarget, isOver, canDrop, isDragging, connectDragSource, connectDragPreview, connectDropTarget, isOver, canDrop, isDragging,
infolder, view, tableGridsLength, isEditMode, folderId, isOnlyOneView, foldersStr, infolder, view, pagesLength, isEditMode, folderId, isOnlyOneView, pathStr,
} = this.props; } = this.props;
const { isShowViewEditor, viewName, viewIcon, isSelected } = this.state; const { isShowViewEditor, viewName, viewIcon, isSelected } = this.state;
const isOverView = isOver && canDrop; const isOverView = isOver && canDrop;
if (isSelected) this.setDocUuid(view.docUuid); if (isSelected) this.setDocUuid(view.docUuid);
const isSpecialInstance = false;
let viewCanDropTop; let viewCanDropTop;
let viewCanDrop; let viewCanDrop;
@@ -219,72 +201,116 @@ class ViewItem extends Component {
} }
let viewEditorId = `view-editor-${view.id}`; let viewEditorId = `view-editor-${view.id}`;
let fn = isEditMode ? connectDragSource : (argu) => {argu;}; let fn = isEditMode ? connectDragSource : (argu) => {argu;};
let childNumber = Array.isArray(view.children) ? view.children.length : 0;
return fn(connectDropTarget( const folded = this.props.getFoldState(view.id);
connectDragPreview( return (
<div <div>
className={classnames('view-item', 'view', {
{ 'selected-view': isSelected }, fn(connectDropTarget(
{ 'view-can-drop-top': viewCanDropTop }, connectDragPreview(
{ 'view-can-drop': viewCanDrop }, <div
{ 'readonly': !isEditMode }, className={classnames('view-item', 'view',
)} { 'selected-view': isSelected },
ref={ref => this.viewItemRef = ref} { 'view-can-drop-top': viewCanDropTop },
onMouseEnter={this.onMouseEnter} { 'view-can-drop': viewCanDrop },
onMouseLeave={this.onMouseLeave} { 'readonly': !isEditMode },
id={viewEditorId} )}
> ref={ref => this.viewItemRef = ref}
<div className="view-item-main" onClick={isShowViewEditor ? () => {} : this.props.onSelectView}> onMouseEnter={this.onMouseEnter}
<div className='view-content' style={foldersStr ? { marginLeft: `${(foldersStr.split('-').length) * 24}px` } : {}}> onMouseMove={this.onMouseMove}
<NavItemIcon symbol={'file'} disable={true} /> onMouseLeave={this.onMouseLeave}
{/* {this.renderIcon(view.icon)} */} id={viewEditorId}
<span className="view-title text-truncate" title={view.name}>{view.name}</span> >
{isShowViewEditor && ( <div className="view-item-main" onClick={isShowViewEditor ? () => {} : (e) => this.props.onSelectView(view.id)}>
<ViewEditPopover <div className='view-content' style={pathStr ? { marginLeft: `${(pathStr.split('-').length - 1) * 24}px` } : {}}>
viewName={viewName} {childNumber === 0 &&
viewIcon={viewIcon} <NavItemIcon symbol={'file'} disable={true} />
viewEditorId={viewEditorId} }
onChangeName={this.onChangeName} {(!this.state.isMouseEnter && childNumber > 0) &&
onChangeIcon={this.onChangeIcon} <NavItemIcon symbol={'files'} disable={true} />
toggleViewEditor={this.toggleViewEditor} }
/> {(this.state.isMouseEnter && childNumber > 0) &&
)} <NavItemIcon
</div> className="icon-expand-folder"
</div> symbol={folded ? 'right-slide' : 'drop-down'}
<div className="d-flex"> onClick={this.toggleExpand}
{isEditMode && />
<div className="more-view-operation" onClick={this.onViewOperationDropdownToggle}> }
<Icon symbol={'more-level'}/> {/* {this.renderIcon(view.icon)} */}
{this.state.isShowViewOperationDropdown && <span className="view-title text-truncate" title={view.name}>{view.name}</span>
<PageDropdownMenu {isShowViewEditor && (
view={view} <ViewEditPopover
views={this.props.views} viewName={viewName}
tableGridsLength={tableGridsLength} viewIcon={viewIcon}
isOnlyOneView={isOnlyOneView} viewEditorId={viewEditorId}
folderId={folderId} onChangeName={this.onChangeName}
canDelete={!isSpecialInstance} onChangeIcon={this.onChangeIcon}
canDuplicate={!isSpecialInstance} toggleViewEditor={this.toggleViewEditor}
toggle={this.onViewOperationDropdownToggle} />
renderFolderMenuItems={this.props.renderFolderMenuItems} )}
toggleViewEditor={this.toggleViewEditor} </div>
duplicatePage={this.props.duplicatePage} </div>
onSetFolderId={this.props.onSetFolderId} <div className="d-flex">
onDeleteView={this.openDeleteDialog} {isEditMode &&
onMoveViewToFolder={this.props.onMoveViewToFolder} <>
<div className="more-view-operation" onClick={this.onViewOperationDropdownToggle}>
<Icon symbol={'more-level'}/>
{this.state.isShowViewOperationDropdown &&
<PageDropdownMenu
view={view}
views={this.props.views}
pagesLength={pagesLength}
isOnlyOneView={isOnlyOneView}
folderId={folderId}
canDelete={true}
canDuplicate={true}
toggle={this.onViewOperationDropdownToggle}
renderFolderMenuItems={this.props.renderFolderMenuItems}
toggleViewEditor={this.toggleViewEditor}
duplicatePage={this.props.duplicatePage}
onSetFolderId={this.props.onSetFolderId}
onDeleteView={this.openDeleteDialog}
onMoveViewToFolder={this.props.onMoveViewToFolder}
/>
}
</div>
<div className="ml-2" onClick={this.toggleInsertPage}>
<span className='fas fa-plus'></span>
</div>
</>
}
</div>
{this.state.isShowDeleteDialog &&
<DeleteDialog
closeDeleteDialog={this.closeDeleteDialog}
handleSubmit={this.props.onDeleteView.bind(this, view.id)}
/>
}
{this.state.isShowInsertPage &&
<AddNewPageDialog
toggle={this.toggleInsertPage}
onAddNewPage={this.onAddNewPage}
title={gettext('Add page inside')}
/> />
} }
</div> </div>
} )
</div> ))
{this.state.isShowDeleteDialog && }
<DeleteDialog <div
closeDeleteDialog={this.closeDeleteDialog} className="view-folder-children"
handleSubmit={this.props.onDeleteView} style={{ height: this.getFolderChildrenHeight() }}
/> onClick={this.onClickFolderChildren}
>
{view.children &&
view.children.map((item, index) => {
return this.renderView(item, index, pagesLength, isOnlyOneView);
})
} }
</div> </div>
) </div>
)); );
} }
} }
@@ -292,14 +318,15 @@ ViewItem.propTypes = {
isOver: PropTypes.bool, isOver: PropTypes.bool,
canDrop: PropTypes.bool, canDrop: PropTypes.bool,
isDragging: PropTypes.bool, isDragging: PropTypes.bool,
draggedRow: PropTypes.object, draggedPage: PropTypes.object,
isEditMode: PropTypes.bool, isEditMode: PropTypes.bool,
infolder: PropTypes.bool, infolder: PropTypes.bool,
view: PropTypes.object, view: PropTypes.object,
folder: PropTypes.object,
views: PropTypes.array, views: PropTypes.array,
viewIndex: PropTypes.number, viewIndex: PropTypes.number,
folderId: PropTypes.string, folderId: PropTypes.string,
tableGridsLength: PropTypes.number, pagesLength: PropTypes.number,
connectDragSource: PropTypes.func, connectDragSource: PropTypes.func,
connectDragPreview: PropTypes.func, connectDragPreview: PropTypes.func,
connectDropTarget: PropTypes.func, connectDropTarget: PropTypes.func,
@@ -313,10 +340,11 @@ ViewItem.propTypes = {
onMoveView: PropTypes.func, onMoveView: PropTypes.func,
isOnlyOneView: PropTypes.bool, isOnlyOneView: PropTypes.bool,
onMoveFolder: PropTypes.func, onMoveFolder: PropTypes.func,
foldersStr: PropTypes.string, pathStr: PropTypes.string,
currentPageId: PropTypes.string, currentPageId: PropTypes.string,
addPageInside: PropTypes.func,
getFoldState: PropTypes.func,
toggleExpand: PropTypes.func,
}; };
export default DropTarget('ViewStructure', dropTarget, dropCollect)( export default ViewItem;
DragSource('ViewStructure', dragSource, dragCollect)(ViewItem)
);

View File

@@ -55,10 +55,6 @@ class Wikis extends Component {
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403 errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
}); });
}); });
this.setState({
loading: false,
wikis: wikis
});
}).catch((error) => { }).catch((error) => {
this.setState({ this.setState({
loading: false, loading: false,