mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-04 16:31:13 +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:
@@ -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"
|
||||
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#949494;}
|
||||
.st0{fill:#999999;}
|
||||
</style>
|
||||
<title>file1</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="file1">
|
||||
<g id="编组-5">
|
||||
<g id="文件" transform="translate(3.000000, 0.000000)">
|
||||
<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
|
||||
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
|
||||
c0,1.8,0.8,2.7,2.9,2.7H23v18H22.8z"/>
|
||||
</g>
|
||||
<title>file</title>
|
||||
<g id="file">
|
||||
<g 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"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 866 B After Width: | Height: | Size: 941 B |
22
frontend/src/assets/icons/files.svg
Normal file
22
frontend/src/assets/icons/files.svg
Normal 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 |
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -11,6 +11,7 @@ export default class WikiConfig {
|
||||
return {
|
||||
id: item.id,
|
||||
type: item.type,
|
||||
children: item.children || [],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
|
@@ -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 &&
|
||||
<NewFolderDialog
|
||||
@@ -310,6 +321,7 @@ class SidePanel extends Component {
|
||||
<AddNewPageDialog
|
||||
toggle={this.closeAddNewPageDialog}
|
||||
onAddNewPage={this.onAddNewPage}
|
||||
title={gettext('Add page')}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
@@ -335,6 +347,7 @@ class SidePanel extends Component {
|
||||
<AddNewPageDialog
|
||||
toggle={this.closeAddNewPageDialog}
|
||||
onAddNewPage={this.onAddNewPage}
|
||||
title={gettext('Add page')}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
@@ -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 (
|
||||
<div className="wiki2-top-nav d-flex">
|
||||
{folder &&
|
||||
<>
|
||||
<div className='wiki2-top-nav-item d-flex'>
|
||||
<NavItemIcon symbol={'wiki-folder'} disable={true} />
|
||||
{folder.name}
|
||||
</div>
|
||||
<div>/</div>
|
||||
</>
|
||||
}
|
||||
{page &&
|
||||
<div className='wiki2-top-nav-item d-flex'>
|
||||
<NavItemIcon symbol={'file'} disable={true} />
|
||||
{page.name}
|
||||
</div>
|
||||
}
|
||||
{paths.map((item, index) => {
|
||||
return (
|
||||
<Fragment key={item.id}>
|
||||
<div className='wiki2-top-nav-item d-flex'>
|
||||
<NavItemIcon symbol={item.type === 'folder' ? 'wiki-folder' : 'file'} disable={true} />
|
||||
{item.name}
|
||||
</div>
|
||||
{index !== paths.length - 1 && <div>/</div>}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -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 (
|
||||
<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'>
|
||||
<Label>{gettext('Page name')}</Label>
|
||||
<Input
|
||||
|
@@ -1,2 +1,2 @@
|
||||
export const DRAGGED_FOLDER_MODE = 'view-folder';
|
||||
export const DRAGGED_VIEW_MODE = 'view';
|
||||
export const DRAGGED_FOLDER_MODE = 'wiki-folder';
|
||||
export const DRAGGED_PAGE_MODE = 'wiki-page';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
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';
|
||||
|
||||
const dragSource = {
|
||||
@@ -20,8 +20,8 @@ const dragSource = {
|
||||
}
|
||||
},
|
||||
isDragging(props, monitor) {
|
||||
const { folderIndex: currentIndex, draggedRow } = props;
|
||||
const { idx } = draggedRow;
|
||||
const { folderIndex: currentIndex, draggedPage } = props;
|
||||
const { idx } = draggedPage;
|
||||
return idx > 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,
|
||||
});
|
||||
|
@@ -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 (
|
||||
<DraggedFolderItem
|
||||
@@ -75,11 +69,11 @@ class FolderItem extends Component {
|
||||
isEditMode={isEditMode}
|
||||
folder={folder}
|
||||
folderIndex={index}
|
||||
tableGridsLength={tableGridsLength}
|
||||
pagesLength={pagesLength}
|
||||
isOnlyOneView={isOnlyOneView}
|
||||
id_view_map={id_view_map}
|
||||
renderFolderMenuItems={this.props.renderFolderMenuItems}
|
||||
onToggleExpandFolder={this.onToggleExpandSubfolder}
|
||||
toggleExpand={this.props.toggleExpand}
|
||||
onToggleAddView={this.props.onToggleAddView}
|
||||
onModifyFolder={this.props.onModifyFolder}
|
||||
onDeleteFolder={this.props.onDeleteFolder}
|
||||
@@ -93,45 +87,49 @@ class FolderItem extends Component {
|
||||
onMoveView={this.props.onMoveView}
|
||||
moveFolderToFolder={this.props.moveFolderToFolder}
|
||||
views={views}
|
||||
foldersStr={foldersStr + '-' + folderId}
|
||||
pathStr={pathStr + '-' + folderId}
|
||||
setClassName={this.props.setClassName}
|
||||
getClassName={this.props.getClassName}
|
||||
movePageOut={this.props.movePageOut}
|
||||
layerDragProps={this.props.layerDragProps}
|
||||
getFolderState={this.props.getFolderState}
|
||||
getFoldState={this.props.getFoldState}
|
||||
currentPageId={this.props.currentPageId}
|
||||
addPageInside={this.props.addPageInside}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<ViewItem
|
||||
<DraggedViewItem
|
||||
key={id}
|
||||
tableGridsLength={tableGridsLength}
|
||||
pagesLength={pagesLength}
|
||||
isOnlyOneView={isOnlyOneView}
|
||||
infolder={false}
|
||||
view={views.find(item => 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 (
|
||||
<div
|
||||
className={classnames('view-folder', { 'readonly': !isEditMode })}
|
||||
ref={ref => this.foldRef = ref}
|
||||
onClick={this.onToggleExpandFolder}
|
||||
onClick={this.toggleExpand}
|
||||
>
|
||||
{fn(connectDropTarget(
|
||||
connectDragPreview(
|
||||
@@ -213,7 +198,7 @@ class FolderItem extends Component {
|
||||
<div className='folder-main'>
|
||||
<div
|
||||
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}
|
||||
>
|
||||
{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);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
@@ -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;
|
||||
|
@@ -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 (
|
||||
<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} />
|
||||
</div>
|
||||
);
|
||||
@@ -16,6 +16,7 @@ NavItemIcon.propTypes = {
|
||||
symbol: PropTypes.string.isRequired,
|
||||
className: PropTypes.string,
|
||||
disable: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default NavItemIcon;
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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 (
|
||||
<ViewItem
|
||||
<DraggedViewItem
|
||||
key={id}
|
||||
tableGridsLength={tableGridsLength}
|
||||
pagesLength={pagesLength}
|
||||
isOnlyOneView={isOnlyOneView}
|
||||
infolder={false}
|
||||
view={views.find(item => 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 {
|
||||
<div className='view-structure-body' style={style}>
|
||||
{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);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
@@ -204,15 +208,10 @@ class ViewStructure extends Component {
|
||||
connectDropTarget: connect.dropTarget()
|
||||
}))(DragLayer(this.collect)(this.renderStructureBody))
|
||||
);
|
||||
const isSpecialInstance = false;
|
||||
const isDarkMode = false;
|
||||
return (
|
||||
<div className={classnames('view-structure',
|
||||
{ 'view-structure-dark': isDarkMode },
|
||||
{ 'view-structure-light': !isDarkMode },
|
||||
)}>
|
||||
<div className='view-structure view-structure-light'>
|
||||
<StructureBody />
|
||||
{(this.props.isEditMode && !isSpecialInstance) &&
|
||||
{(this.props.isEditMode) &&
|
||||
<ViewStructureFooter
|
||||
onToggleAddView={this.props.onToggleAddView}
|
||||
onToggleAddFolder={this.props.onToggleAddFolder}
|
||||
|
@@ -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)
|
||||
);
|
@@ -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(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -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 {
|
||||
<span className="item-text">{gettext('Duplicate page')}</span>
|
||||
</DropdownItem>
|
||||
}
|
||||
{(isOnlyOneView || tableGridsLength === 1 || !canDelete) ? '' : (
|
||||
{(isOnlyOneView || pagesLength === 1 || !canDelete) ? '' : (
|
||||
<DropdownItem onClick={this.onDeleteView}>
|
||||
<Icon symbol={'delete'}/>
|
||||
<span className="item-text">{gettext('Delete page')}</span>
|
||||
|
@@ -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 (
|
||||
<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() {
|
||||
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(
|
||||
<div
|
||||
className={classnames('view-item', 'view',
|
||||
{ 'selected-view': isSelected },
|
||||
{ 'view-can-drop-top': viewCanDropTop },
|
||||
{ 'view-can-drop': viewCanDrop },
|
||||
{ 'readonly': !isEditMode },
|
||||
)}
|
||||
ref={ref => this.viewItemRef = ref}
|
||||
onMouseEnter={this.onMouseEnter}
|
||||
onMouseLeave={this.onMouseLeave}
|
||||
id={viewEditorId}
|
||||
>
|
||||
<div className="view-item-main" onClick={isShowViewEditor ? () => {} : this.props.onSelectView}>
|
||||
<div className='view-content' style={foldersStr ? { marginLeft: `${(foldersStr.split('-').length) * 24}px` } : {}}>
|
||||
<NavItemIcon symbol={'file'} disable={true} />
|
||||
{/* {this.renderIcon(view.icon)} */}
|
||||
<span className="view-title text-truncate" title={view.name}>{view.name}</span>
|
||||
{isShowViewEditor && (
|
||||
<ViewEditPopover
|
||||
viewName={viewName}
|
||||
viewIcon={viewIcon}
|
||||
viewEditorId={viewEditorId}
|
||||
onChangeName={this.onChangeName}
|
||||
onChangeIcon={this.onChangeIcon}
|
||||
toggleViewEditor={this.toggleViewEditor}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
{isEditMode &&
|
||||
<div className="more-view-operation" onClick={this.onViewOperationDropdownToggle}>
|
||||
<Icon symbol={'more-level'}/>
|
||||
{this.state.isShowViewOperationDropdown &&
|
||||
<PageDropdownMenu
|
||||
view={view}
|
||||
views={this.props.views}
|
||||
tableGridsLength={tableGridsLength}
|
||||
isOnlyOneView={isOnlyOneView}
|
||||
folderId={folderId}
|
||||
canDelete={!isSpecialInstance}
|
||||
canDuplicate={!isSpecialInstance}
|
||||
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}
|
||||
const folded = this.props.getFoldState(view.id);
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
fn(connectDropTarget(
|
||||
connectDragPreview(
|
||||
<div
|
||||
className={classnames('view-item', 'view',
|
||||
{ 'selected-view': isSelected },
|
||||
{ 'view-can-drop-top': viewCanDropTop },
|
||||
{ 'view-can-drop': viewCanDrop },
|
||||
{ 'readonly': !isEditMode },
|
||||
)}
|
||||
ref={ref => this.viewItemRef = ref}
|
||||
onMouseEnter={this.onMouseEnter}
|
||||
onMouseMove={this.onMouseMove}
|
||||
onMouseLeave={this.onMouseLeave}
|
||||
id={viewEditorId}
|
||||
>
|
||||
<div className="view-item-main" onClick={isShowViewEditor ? () => {} : (e) => this.props.onSelectView(view.id)}>
|
||||
<div className='view-content' style={pathStr ? { marginLeft: `${(pathStr.split('-').length - 1) * 24}px` } : {}}>
|
||||
{childNumber === 0 &&
|
||||
<NavItemIcon symbol={'file'} disable={true} />
|
||||
}
|
||||
{(!this.state.isMouseEnter && childNumber > 0) &&
|
||||
<NavItemIcon symbol={'files'} disable={true} />
|
||||
}
|
||||
{(this.state.isMouseEnter && childNumber > 0) &&
|
||||
<NavItemIcon
|
||||
className="icon-expand-folder"
|
||||
symbol={folded ? 'right-slide' : 'drop-down'}
|
||||
onClick={this.toggleExpand}
|
||||
/>
|
||||
}
|
||||
{/* {this.renderIcon(view.icon)} */}
|
||||
<span className="view-title text-truncate" title={view.name}>{view.name}</span>
|
||||
{isShowViewEditor && (
|
||||
<ViewEditPopover
|
||||
viewName={viewName}
|
||||
viewIcon={viewIcon}
|
||||
viewEditorId={viewEditorId}
|
||||
onChangeName={this.onChangeName}
|
||||
onChangeIcon={this.onChangeIcon}
|
||||
toggleViewEditor={this.toggleViewEditor}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
{isEditMode &&
|
||||
<>
|
||||
<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>
|
||||
{this.state.isShowDeleteDialog &&
|
||||
<DeleteDialog
|
||||
closeDeleteDialog={this.closeDeleteDialog}
|
||||
handleSubmit={this.props.onDeleteView}
|
||||
/>
|
||||
)
|
||||
))
|
||||
}
|
||||
<div
|
||||
className="view-folder-children"
|
||||
style={{ height: this.getFolderChildrenHeight() }}
|
||||
onClick={this.onClickFolderChildren}
|
||||
>
|
||||
{view.children &&
|
||||
view.children.map((item, index) => {
|
||||
return this.renderView(item, index, pagesLength, isOnlyOneView);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
));
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user