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:
@@ -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 |
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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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>
|
||||||
|
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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';
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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}
|
||||||
|
@@ -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,
|
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(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
|
@@ -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)
|
|
||||||
);
|
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user