mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-28 16:17:02 +00:00
style: format code
This commit is contained in:
123
frontend/src/pages/wiki2/editor-component/header-icon.jsx
Normal file
123
frontend/src/pages/wiki2/editor-component/header-icon.jsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
|
||||
import { Popover, PopoverBody } from 'reactstrap';
|
||||
import { init } from 'emoji-mart';
|
||||
import Picker from '@emoji-mart/react';
|
||||
import classnames from 'classnames';
|
||||
import data from '@emoji-mart/data';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../../utils/constants';
|
||||
|
||||
// init data for emoji-mart, used in Picker and `getRandomEmoji` method
|
||||
init({ data });
|
||||
|
||||
const HeaderIcon = ({ currentPageConfig, onUpdatePage }, ref) => {
|
||||
const [isShowIconPanel, setIsShowIconPanel] = useState(false);
|
||||
const iconPanelPopoverRef = useRef(null);
|
||||
|
||||
|
||||
const handleSetIcon = useCallback((emoji, cb) => {
|
||||
onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, icon: emoji });
|
||||
cb && cb();
|
||||
}, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]);
|
||||
|
||||
const setRandomEmoji = useCallback(() => {
|
||||
const nativeEmojis = Reflect.ownKeys(data.natives);
|
||||
const emojiCount = nativeEmojis.length;
|
||||
const emoji = nativeEmojis[Math.floor(Math.random() * emojiCount)];
|
||||
handleSetIcon(emoji);
|
||||
}, [handleSetIcon]);
|
||||
|
||||
const handleIconRemove = () => {
|
||||
handleSetIcon('');
|
||||
handleIconPanelDisplayedChange(false);
|
||||
};
|
||||
|
||||
const handleIconPanelDisplayedChange = useCallback((isShowIconPanel) => {
|
||||
setIsShowIconPanel(isShowIconPanel);
|
||||
// setIsShowCoverPanel(false);
|
||||
}, []);
|
||||
|
||||
const handleClickAddIcon = useCallback(() => {
|
||||
setRandomEmoji();
|
||||
handleIconPanelDisplayedChange(false);
|
||||
}, [handleIconPanelDisplayedChange, setRandomEmoji]);
|
||||
|
||||
useImperativeHandle(ref, () => {
|
||||
return { handleClickAddIcon };
|
||||
}, [handleClickAddIcon]);
|
||||
|
||||
const handleIconPanelListener = useCallback((e) => {
|
||||
const isClickInPopover = iconPanelPopoverRef.current.contains(e.target);
|
||||
if (!isClickInPopover) handleIconPanelDisplayedChange(false);
|
||||
}, [handleIconPanelDisplayedChange]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isShowIconPanel) {
|
||||
setTimeout(() => {
|
||||
// Avoid open behavior closing popover
|
||||
addEventListener('click', handleIconPanelListener);
|
||||
}, 0);
|
||||
}
|
||||
if (!isShowIconPanel) removeEventListener('click', handleIconPanelListener);
|
||||
|
||||
return () => {
|
||||
removeEventListener('click', handleIconPanelListener);
|
||||
};
|
||||
}, [handleIconPanelListener, isShowIconPanel]);
|
||||
|
||||
// Update current page favicon
|
||||
useEffect(() => {
|
||||
let faviconUrl = '';
|
||||
if (currentPageConfig.icon) {
|
||||
faviconUrl = `data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>${currentPageConfig.icon}</text></svg>`;
|
||||
} else {
|
||||
const { serviceUrl, mediaUrl, faviconPath } = window.seafile;
|
||||
faviconUrl = `${serviceUrl}${mediaUrl}${faviconPath}`;
|
||||
}
|
||||
document.getElementById('favicon').href = faviconUrl;
|
||||
}, [currentPageConfig.icon]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={classnames('wiki-icon-container', { gap: currentPageConfig.icon && !currentPageConfig.cover_img_url })}>
|
||||
<div className={classnames('wiki-icon-wrapper', { show: currentPageConfig.icon })} id='wiki-icon-wrapper' onClick={handleIconPanelDisplayedChange.bind(null, !isShowIconPanel)}>
|
||||
<span>{currentPageConfig.icon}</span>
|
||||
</div>
|
||||
</div>
|
||||
<Popover
|
||||
flip
|
||||
target="wiki-icon-wrapper"
|
||||
toggle={() => void 0}
|
||||
placement="bottom"
|
||||
isOpen={!!(isShowIconPanel && !!currentPageConfig.icon)}
|
||||
popperClassName='wiki-icon-popover'
|
||||
hideArrow={true}
|
||||
>
|
||||
<div ref={iconPanelPopoverRef}>
|
||||
<div className='wiki-icon-panel-header popover-header'>
|
||||
<span>{gettext('Emojis')}</span>
|
||||
<span onClick={handleIconRemove} className='wiki-remove-icon-btn'>{gettext('Remove')}</span>
|
||||
</div>
|
||||
<PopoverBody className='wiki-icon-panel-body'>
|
||||
<Picker
|
||||
data={data}
|
||||
onEmojiSelect={(emoji) => handleSetIcon(emoji.native, handleIconPanelDisplayedChange.bind(null, false))}
|
||||
previewPosition="none"
|
||||
skinTonePosition="none"
|
||||
locale={window.seafile.lang.slice(0, 2)}
|
||||
maxFrequentRows={2}
|
||||
theme="light"
|
||||
/>
|
||||
</PopoverBody>
|
||||
</div>
|
||||
</Popover>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
HeaderIcon.propTypes = {
|
||||
currentPageConfig: PropTypes.object.isRequired,
|
||||
onUpdatePage: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default forwardRef(HeaderIcon);
|
@@ -1,15 +1,10 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Input, Popover, PopoverBody } from 'reactstrap';
|
||||
import classnames from 'classnames';
|
||||
import data from '@emoji-mart/data';
|
||||
import Picker from '@emoji-mart/react';
|
||||
import { init } from 'emoji-mart';
|
||||
import { Input, Popover, PopoverBody } from 'reactstrap';
|
||||
import { gettext } from '../../../utils/constants';
|
||||
import { WIKI_COVER_LIST } from '../constant';
|
||||
|
||||
// init data for emoji-mart, used in Picker and `getRandomEmoji` method
|
||||
init({ data });
|
||||
import HeaderIcon from './header-icon';
|
||||
|
||||
const propTypes = {
|
||||
currentPageConfig: PropTypes.object.isRequired,
|
||||
@@ -18,12 +13,11 @@ const propTypes = {
|
||||
|
||||
const PageHeader = ({ currentPageConfig, onUpdatePage }) => {
|
||||
const [isShowController, setIsShowController] = useState(false);
|
||||
const [isShowIconPanel, setIsShowIconPanel] = useState(false);
|
||||
const [isShowCoverController, setIsShowCoverController] = useState(false);
|
||||
const [isShowCoverPanel, setIsShowCoverPanel] = useState(false);
|
||||
const iconPanelPopoverRef = useRef(null);
|
||||
const coverPanelPopoverRef = useRef(null);
|
||||
const headerWrapperRef = useRef(null);
|
||||
const headerIconRef = useRef({ handleClickAddIcon: () => void 0 });
|
||||
|
||||
const getCoverImgUrl = useCallback((imageName) => {
|
||||
const { serviceUrl, mediaUrl } = window.seafile;
|
||||
@@ -46,36 +40,8 @@ const PageHeader = ({ currentPageConfig, onUpdatePage }) => {
|
||||
setIsShowController(isShowController);
|
||||
}, [isShowCoverPanel]);
|
||||
|
||||
const handleSetIcon = useCallback((emoji, cb) => {
|
||||
onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, icon: emoji });
|
||||
cb && cb();
|
||||
}, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]);
|
||||
|
||||
const setRandomEmoji = useCallback(() => {
|
||||
const nativeEmojis = Reflect.ownKeys(data.natives);
|
||||
const emojiCount = nativeEmojis.length;
|
||||
const emoji = nativeEmojis[Math.floor(Math.random() * emojiCount)];
|
||||
handleSetIcon(emoji);
|
||||
}, [handleSetIcon]);
|
||||
|
||||
const handleIconPanelDisplayedChange = useCallback((isShowIconPanel) => {
|
||||
setIsShowIconPanel(isShowIconPanel);
|
||||
setIsShowCoverPanel(false);
|
||||
}, []);
|
||||
|
||||
const handleClickAddIcon = useCallback(() => {
|
||||
setRandomEmoji();
|
||||
handleIconPanelDisplayedChange(false);
|
||||
}, [handleIconPanelDisplayedChange, setRandomEmoji]);
|
||||
|
||||
const handleIconPanelListener = useCallback((e) => {
|
||||
const isClickInPopover = iconPanelPopoverRef.current.contains(e.target);
|
||||
if (!isClickInPopover) handleIconPanelDisplayedChange(false);
|
||||
}, [handleIconPanelDisplayedChange]);
|
||||
|
||||
const handleCoverPanelDisplayedChange = useCallback((isShowCoverPanel) => {
|
||||
setIsShowCoverPanel(isShowCoverPanel);
|
||||
setIsShowIconPanel(false);
|
||||
}, []);
|
||||
|
||||
const handleCoverPanelListener = useCallback((e) => {
|
||||
@@ -83,26 +49,7 @@ const PageHeader = ({ currentPageConfig, onUpdatePage }) => {
|
||||
if (!isClickInPopover) handleCoverPanelDisplayedChange(false);
|
||||
}, [handleCoverPanelDisplayedChange]);
|
||||
|
||||
// Update current page favicon
|
||||
useEffect(() => {
|
||||
let faviconUrl = '';
|
||||
if (currentPageConfig.icon) {
|
||||
faviconUrl = `data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>${currentPageConfig.icon}</text></svg>`;
|
||||
} else {
|
||||
const { serviceUrl, mediaUrl, faviconPath } = window.seafile;
|
||||
faviconUrl = `${serviceUrl}${mediaUrl}${faviconPath}`;
|
||||
}
|
||||
document.getElementById('favicon').href = faviconUrl;
|
||||
}, [currentPageConfig.icon]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isShowIconPanel) {
|
||||
setTimeout(() => {
|
||||
// Avoid open behavior closing popover
|
||||
addEventListener('click', handleIconPanelListener);
|
||||
}, 0);
|
||||
}
|
||||
if (!isShowIconPanel) removeEventListener('click', handleIconPanelListener);
|
||||
if (isShowCoverPanel) {
|
||||
setTimeout(() => {
|
||||
// Avoid open behavior closing popover
|
||||
@@ -112,15 +59,9 @@ const PageHeader = ({ currentPageConfig, onUpdatePage }) => {
|
||||
if (!isShowCoverPanel) removeEventListener('click', handleCoverPanelListener);
|
||||
|
||||
return () => {
|
||||
removeEventListener('click', handleIconPanelListener);
|
||||
removeEventListener('click', handleCoverPanelListener);
|
||||
};
|
||||
}, [handleCoverPanelListener, handleIconPanelListener, isShowCoverPanel, isShowIconPanel]);
|
||||
|
||||
const handleIconRemove = () => {
|
||||
handleSetIcon('');
|
||||
handleIconPanelDisplayedChange(false);
|
||||
};
|
||||
}, [handleCoverPanelListener, isShowCoverPanel]);
|
||||
|
||||
const handleAddCover = useCallback(() => {
|
||||
const coverName = WIKI_COVER_LIST[Math.floor(Math.random() * WIKI_COVER_LIST.length)];
|
||||
@@ -196,44 +137,11 @@ const PageHeader = ({ currentPageConfig, onUpdatePage }) => {
|
||||
</div>
|
||||
)}
|
||||
<div className='wiki-page-gap-container'>
|
||||
<div
|
||||
className='wiki-editor-header'
|
||||
>
|
||||
<div className={classnames('wiki-icon-container', { gap: currentPageConfig.icon && !currentPageConfig.cover_img_url })}>
|
||||
<div className={classnames('wiki-icon-wrapper', { show: currentPageConfig.icon })} id='wiki-icon-wrapper' onClick={handleIconPanelDisplayedChange.bind(null, !isShowIconPanel)}>
|
||||
<span>{currentPageConfig.icon}</span>
|
||||
</div>
|
||||
</div>
|
||||
<Popover
|
||||
flip
|
||||
target="wiki-icon-wrapper"
|
||||
toggle={() => void 0}
|
||||
placement="bottom"
|
||||
isOpen={!!(isShowIconPanel && !!currentPageConfig.icon)}
|
||||
popperClassName='wiki-icon-popover'
|
||||
hideArrow={true}
|
||||
>
|
||||
<div ref={iconPanelPopoverRef}>
|
||||
<div className='wiki-icon-panel-header popover-header'>
|
||||
<span>{gettext('Emojis')}</span>
|
||||
<span onClick={handleIconRemove} className='wiki-remove-icon-btn'>{gettext('Remove')}</span>
|
||||
</div>
|
||||
<PopoverBody className='wiki-icon-panel-body'>
|
||||
<Picker
|
||||
data={data}
|
||||
onEmojiSelect={(emoji) => handleSetIcon(emoji.native, handleIconPanelDisplayedChange.bind(null, false))}
|
||||
previewPosition="none"
|
||||
skinTonePosition="none"
|
||||
locale={window.seafile.lang.slice(0, 2)}
|
||||
maxFrequentRows={2}
|
||||
theme="light"
|
||||
/>
|
||||
</PopoverBody>
|
||||
</div>
|
||||
</Popover>
|
||||
<div className='wiki-editor-header'>
|
||||
<HeaderIcon currentPageConfig={currentPageConfig} onUpdatePage={onUpdatePage} ref={headerIconRef} />
|
||||
<div className={classnames('wiki-page-controller', { show: isShowController })}>
|
||||
{!currentPageConfig.icon && (
|
||||
<div className='wiki-page-controller-item' onClick={handleClickAddIcon}>
|
||||
<div className='wiki-page-controller-item' onClick={headerIconRef.current.handleClickAddIcon}>
|
||||
<i className='sf3-font sf3-font-icon'></i>
|
||||
<span className='text'>{gettext('Add icon')}</span>
|
||||
</div>
|
||||
|
@@ -1,6 +1,8 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import NavItemIcon from '../common/nav-item-icon';
|
||||
import CustomIcon from '../custom-icon';
|
||||
|
||||
import './index.css';
|
||||
|
||||
// Find the path array from the root to the leaf based on the currentPageId (leaf)
|
||||
@@ -37,26 +39,17 @@ function getPaths(navigation, currentPageId, pages) {
|
||||
return pathStr.split('-').map(id => idPageMap[id]);
|
||||
}
|
||||
|
||||
function WikiTopNav({ config, currentPageId, currentPageConfig }) {
|
||||
function WikiTopNav({ config, currentPageId }) {
|
||||
const { navigation, pages } = config;
|
||||
const paths = getPaths(navigation, currentPageId, pages);
|
||||
const customIcon = currentPageConfig.icon;
|
||||
|
||||
return (
|
||||
<div className="wiki2-top-nav d-flex">
|
||||
{paths.map((item, index) => {
|
||||
return (
|
||||
<Fragment key={item.id}>
|
||||
<div className='wiki2-top-nav-item d-flex'>
|
||||
{
|
||||
item.type === 'folder' && (<NavItemIcon symbol={'wiki-folder'} disable={true} />)
|
||||
}
|
||||
{
|
||||
item.type !== 'folder' && (
|
||||
customIcon
|
||||
? <span className='nav-item-icon nav-item-icon-disable'>{customIcon}</span>
|
||||
: <NavItemIcon symbol={'file'} disable={true} />
|
||||
)
|
||||
}
|
||||
{item.icon ? <CustomIcon icon={item.icon} /> : <NavItemIcon symbol={'file'} disable={true} />}
|
||||
{item.name}
|
||||
</div>
|
||||
{index !== paths.length - 1 && <div>/</div>}
|
||||
@@ -70,7 +63,6 @@ function WikiTopNav({ config, currentPageId, currentPageConfig }) {
|
||||
WikiTopNav.propTypes = {
|
||||
config: PropTypes.object,
|
||||
currentPageId: PropTypes.string,
|
||||
currentPageConfig: PropTypes.object,
|
||||
};
|
||||
|
||||
export default WikiTopNav;
|
||||
|
@@ -1,352 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ViewEditPopover from './view-edit-popover';
|
||||
import PageDropdownMenu from './page-dropdownmenu';
|
||||
import DeleteDialog from './delete-dialog';
|
||||
import { gettext } from '../../../../utils/constants';
|
||||
import AddNewPageDialog from '../add-new-page-dialog';
|
||||
import Icon from '../../../../components/icon';
|
||||
import NavItemIcon from '../nav-item-icon';
|
||||
import DraggedViewItem from '../views/dragged-view-item';
|
||||
|
||||
class ViewItem extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
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;
|
||||
};
|
||||
|
||||
onCurrentPageChanged = (currentPageId) => {
|
||||
const { isSelected } = this.state;
|
||||
if (currentPageId === this.props.view.id && isSelected === false) {
|
||||
this.setState({ isSelected: true });
|
||||
} else if (currentPageId !== this.props.view.id && isSelected === true) {
|
||||
this.setState({ isSelected: false });
|
||||
}
|
||||
};
|
||||
|
||||
toggleViewEditor = (e) => {
|
||||
if (e) e.stopPropagation();
|
||||
this.setState({ isShowViewEditor: !this.state.isShowViewEditor }, () => {
|
||||
if (!this.state.isShowViewEditor) {
|
||||
this.saveViewProperties();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
toggleInsertPage = () => {
|
||||
this.setState({ isShowInsertPage: !this.state.isShowInsertPage });
|
||||
};
|
||||
|
||||
saveViewProperties = () => {
|
||||
const { name, icon, id } = this.props.view;
|
||||
const { viewIcon } = this.state;
|
||||
let viewName = this.state.viewName.trim();
|
||||
if (viewIcon !== icon || viewName !== name) {
|
||||
let newView = {};
|
||||
if (viewName !== name) {
|
||||
newView.name = viewName;
|
||||
}
|
||||
if (viewIcon !== icon) {
|
||||
newView.icon = viewIcon;
|
||||
}
|
||||
this.props.onUpdatePage(id, newView);
|
||||
}
|
||||
};
|
||||
|
||||
onChangeName = (newViewName) => {
|
||||
this.setState({ viewName: newViewName });
|
||||
};
|
||||
|
||||
onChangeIcon = (newViewIcon) => {
|
||||
this.setState({ viewIcon: newViewIcon });
|
||||
};
|
||||
|
||||
openDeleteDialog = () => {
|
||||
this.setState({ isShowDeleteDialog: true });
|
||||
};
|
||||
|
||||
closeDeleteDialog = () => {
|
||||
this.setState({ isShowDeleteDialog: false });
|
||||
};
|
||||
|
||||
onViewOperationDropdownToggle = () => {
|
||||
const isShowViewOperationDropdown = !this.state.isShowViewOperationDropdown;
|
||||
this.setState({ isShowViewOperationDropdown });
|
||||
this.changeItemFreeze(isShowViewOperationDropdown);
|
||||
};
|
||||
|
||||
changeItemFreeze = (isFreeze) => {
|
||||
if (isFreeze) {
|
||||
this.viewItemRef.classList.add('view-freezed');
|
||||
} else {
|
||||
this.viewItemRef.classList.remove('view-freezed');
|
||||
}
|
||||
};
|
||||
|
||||
renderIcon = (icon) => {
|
||||
if (!icon) {
|
||||
return null;
|
||||
}
|
||||
if (icon.includes('dtable-icon')) {
|
||||
return <span className={`mr-2 dtable-font ${icon}`}></span>;
|
||||
} else {
|
||||
return <Icon className="mr-2" symbol={icon} />;
|
||||
}
|
||||
};
|
||||
|
||||
setDocUuid = (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() {
|
||||
const {
|
||||
connectDragSource, connectDragPreview, connectDropTarget, isOver, canDrop, isDragging,
|
||||
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);
|
||||
|
||||
let viewCanDropTop;
|
||||
let viewCanDrop;
|
||||
if (infolder) {
|
||||
viewCanDropTop = false;
|
||||
viewCanDrop = isOverView;
|
||||
} else {
|
||||
viewCanDropTop = isOverView && isDragging;
|
||||
viewCanDrop = isOverView && !isDragging;
|
||||
}
|
||||
let viewEditorId = `view-editor-${view.id}`;
|
||||
let fn = isEditMode ? connectDragSource : (argu) => { argu; };
|
||||
let childNumber = Array.isArray(view.children) ? view.children.length : 0;
|
||||
|
||||
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 && (
|
||||
view.icon
|
||||
? <span className='nav-item-icon nav-item-icon-disable'>{view.icon}</span>
|
||||
: <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
|
||||
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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ViewItem.propTypes = {
|
||||
isOver: PropTypes.bool,
|
||||
canDrop: PropTypes.bool,
|
||||
isDragging: PropTypes.bool,
|
||||
draggedPage: PropTypes.object,
|
||||
isEditMode: PropTypes.bool,
|
||||
infolder: PropTypes.bool,
|
||||
view: PropTypes.object,
|
||||
folder: PropTypes.object,
|
||||
views: PropTypes.array,
|
||||
viewIndex: PropTypes.number,
|
||||
folderId: PropTypes.string,
|
||||
pagesLength: PropTypes.number,
|
||||
connectDragSource: PropTypes.func,
|
||||
connectDragPreview: PropTypes.func,
|
||||
connectDropTarget: PropTypes.func,
|
||||
renderFolderMenuItems: PropTypes.func,
|
||||
duplicatePage: PropTypes.func,
|
||||
onSetFolderId: PropTypes.func,
|
||||
onSelectView: PropTypes.func,
|
||||
onUpdatePage: PropTypes.func,
|
||||
onDeleteView: PropTypes.func,
|
||||
onMoveViewToFolder: PropTypes.func,
|
||||
onMoveView: PropTypes.func,
|
||||
isOnlyOneView: PropTypes.bool,
|
||||
onMoveFolder: PropTypes.func,
|
||||
pathStr: PropTypes.string,
|
||||
currentPageId: PropTypes.string,
|
||||
addPageInside: PropTypes.func,
|
||||
getFoldState: PropTypes.func,
|
||||
toggleExpand: PropTypes.func,
|
||||
};
|
||||
|
||||
export default ViewItem;
|
Reference in New Issue
Block a user