mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 07:27:04 +00:00
Add option to only show folder in nav side panel (#6541)
* fix conflict * remove redundant code * add space at the end of css * update ui
This commit is contained in:
@@ -58,6 +58,7 @@ class DirColumnNav extends React.Component {
|
||||
isMoveDialogShow: false,
|
||||
isMultipleOperation: false,
|
||||
operationList: [],
|
||||
isDisplayFiles: false,
|
||||
};
|
||||
this.isNodeMenuShow = true;
|
||||
}
|
||||
@@ -75,6 +76,7 @@ class DirColumnNav extends React.Component {
|
||||
let menuList = [];
|
||||
menuList.push(TextTranslation.NEW_FOLDER);
|
||||
menuList.push(TextTranslation.NEW_FILE);
|
||||
menuList.push(TextTranslation.DISPLAY_FILES);
|
||||
return menuList;
|
||||
};
|
||||
|
||||
@@ -127,6 +129,9 @@ class DirColumnNav extends React.Component {
|
||||
case 'Open in New Tab':
|
||||
this.onOpenFile(node);
|
||||
break;
|
||||
case 'Display files':
|
||||
this.onDisplayFilesToggle();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -186,6 +191,10 @@ class DirColumnNav extends React.Component {
|
||||
window.open(newUrl, '_blank');
|
||||
};
|
||||
|
||||
onDisplayFilesToggle = () => {
|
||||
this.setState({ isDisplayFiles: !this.state.isDisplayFiles });
|
||||
};
|
||||
|
||||
checkDuplicatedName = (newName) => {
|
||||
let node = this.state.opNode;
|
||||
// root node to new node conditions: parentNode is null,
|
||||
@@ -292,7 +301,7 @@ class DirColumnNav extends React.Component {
|
||||
<Loading />
|
||||
) : (
|
||||
<>
|
||||
<TreeSection title={gettext('Files')} moreKey={{ name: 'files' }} moreOperations={this.state.operationList} moreOperationClick={this.onMoreOperationClick}>
|
||||
<TreeSection title={gettext('Files')} moreKey={{ name: 'files' }} moreOperations={this.state.operationList} moreOperationClick={this.onMoreOperationClick} isDisplayFiles={this.state.isDisplayFiles}>
|
||||
<TreeView
|
||||
userPerm={userPerm}
|
||||
isNodeMenuShow={this.isNodeMenuShow}
|
||||
@@ -310,6 +319,7 @@ class DirColumnNav extends React.Component {
|
||||
onItemsMove={onItemsMove}
|
||||
repoID={repoID}
|
||||
getMenuContainerSize={getMenuContainerSize}
|
||||
isDisplayFiles={this.state.isDisplayFiles}
|
||||
/>
|
||||
</TreeSection>
|
||||
<DirViews repoID={repoID} currentPath={currentPath} userPerm={userPerm} />
|
||||
|
@@ -6,6 +6,8 @@ import { gettext } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import ModalPortal from '../modal-portal';
|
||||
|
||||
import '../../css/item-dropdown-menu.css';
|
||||
|
||||
const propTypes = {
|
||||
tagName: PropTypes.string,
|
||||
item: PropTypes.object.isRequired,
|
||||
@@ -17,6 +19,7 @@ const propTypes = {
|
||||
freezeItem: PropTypes.func,
|
||||
unfreezeItem: PropTypes.func,
|
||||
menuStyle: PropTypes.object,
|
||||
isDisplayFiles: PropTypes.bool,
|
||||
};
|
||||
|
||||
class ItemDropdownMenu extends React.Component {
|
||||
@@ -104,7 +107,7 @@ class ItemDropdownMenu extends React.Component {
|
||||
};
|
||||
|
||||
onMenuItemClick = (event) => {
|
||||
let operation = Utils.getEventData(event, 'toggle');
|
||||
let operation = Utils.getEventData(event, 'toggle') ?? event.currentTarget.getAttribute('data-toggle');
|
||||
let item = this.props.item;
|
||||
this.props.onMenuItemClick(operation, event, item);
|
||||
};
|
||||
@@ -168,7 +171,16 @@ class ItemDropdownMenu extends React.Component {
|
||||
return <DropdownItem key={index} divider />;
|
||||
} else {
|
||||
return (
|
||||
<DropdownItem key={index} data-toggle={menuItem.key} onClick={this.onMenuItemClick} onKeyDown={this.onMenuItemKeyDown}>{menuItem.value}</DropdownItem>
|
||||
<DropdownItem className='p-0' key={index} data-toggle={menuItem.key} onClick={this.onMenuItemClick} onKeyDown={this.onMenuItemKeyDown}>
|
||||
<div className='dropdown-item-wrapper'>
|
||||
<span className='dropdown-item-tick'>
|
||||
{menuItem.value === 'Display files' && this.props.isDisplayFiles && (
|
||||
<i className="sf2-icon-tick"></i>
|
||||
)}
|
||||
</span>
|
||||
<span className='dropdown-item-content'>{menuItem.value}</span>
|
||||
</div>
|
||||
</DropdownItem>
|
||||
);
|
||||
}
|
||||
})}
|
||||
|
@@ -6,7 +6,7 @@ import { isMobile } from '../../utils/utils';
|
||||
|
||||
import './index.css';
|
||||
|
||||
const TreeSection = ({ title, children, moreKey, moreOperations, moreOperationClick, className }) => {
|
||||
const TreeSection = ({ title, children, moreKey, moreOperations, moreOperationClick, className, isDisplayFiles }) => {
|
||||
const [showChildren, setShowChildren] = useState(true);
|
||||
const [highlight, setHighlight] = useState(false);
|
||||
const [freeze, setFreeze] = useState(false);
|
||||
@@ -65,6 +65,7 @@ const TreeSection = ({ title, children, moreKey, moreOperations, moreOperationCl
|
||||
getMenuList={() => validMoreOperations}
|
||||
onMenuItemClick={moreOperationClick}
|
||||
menuStyle={isMobile ? { zIndex: 1050 } : {}}
|
||||
isDisplayFiles={isDisplayFiles}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
@@ -90,6 +91,7 @@ TreeSection.propTypes = {
|
||||
moreKey: PropTypes.object,
|
||||
moreOperationClick: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
isDisplayFiles: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default TreeSection;
|
||||
|
@@ -26,6 +26,7 @@ const propTypes = {
|
||||
handleContextClick: PropTypes.func.isRequired,
|
||||
onNodeDragEnter: PropTypes.func.isRequired,
|
||||
onNodeDragLeave: PropTypes.func.isRequired,
|
||||
isDisplayFiles: PropTypes.bool,
|
||||
};
|
||||
|
||||
class TreeNodeView extends React.Component {
|
||||
@@ -264,6 +265,7 @@ class TreeNodeView extends React.Component {
|
||||
onNodeDragEnter={this.props.onNodeDragEnter}
|
||||
onNodeDragLeave={this.props.onNodeDragLeave}
|
||||
handleContextClick={this.props.handleContextClick}
|
||||
isDisplayFiles={this.props.isDisplayFiles}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -279,6 +281,10 @@ class TreeNodeView extends React.Component {
|
||||
hlClass = 'tree-node-hight-light';
|
||||
}
|
||||
|
||||
if (node.path !== '/' && type !== 'dir' && !this.props.isDisplayFiles) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const { isCustomPermission } = Utils.getUserPermission(userPerm);
|
||||
return (
|
||||
<div className="tree-node">
|
||||
|
@@ -23,6 +23,7 @@ const propTypes = {
|
||||
posX: PropTypes.number,
|
||||
posY: PropTypes.number,
|
||||
getMenuContainerSize: PropTypes.func,
|
||||
isDisplayFiles: PropTypes.bool,
|
||||
};
|
||||
|
||||
const LEFT_INDENT = 20;
|
||||
@@ -343,6 +344,7 @@ class TreeView extends React.Component {
|
||||
onNodeDragEnter={this.onNodeDragEnter}
|
||||
onNodeDragLeave={this.onNodeDragLeave}
|
||||
handleContextClick={this.handleContextClick}
|
||||
isDisplayFiles={this.props.isDisplayFiles}
|
||||
/>
|
||||
<ContextMenu
|
||||
id={'tree-node-contextmenu'}
|
||||
|
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
|
||||
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
|
||||
import { gettext } from '../utils/constants';
|
||||
|
||||
import '../css/view-modes.css';
|
||||
|
||||
const propTypes = {
|
||||
currentViewMode: PropTypes.string.isRequired,
|
||||
switchViewMode: PropTypes.func.isRequired
|
||||
@@ -51,15 +53,15 @@ class ViewModes extends React.Component {
|
||||
<DropdownMenu right={true} className="mt-1">
|
||||
{options.map((item, index) => {
|
||||
return (
|
||||
<DropdownItem key={index} onClick={this.props.switchViewMode.bind(this, item.value)}>
|
||||
<div className="d-flex justify-content-between align-items-center">
|
||||
<span className="mr-8 d-flex justify-content-between align-items-center">
|
||||
<DropdownItem className='p-0' key={index} onClick={this.props.switchViewMode.bind(this, item.value)}>
|
||||
<div className="view-modes-dropdown-wrapper">
|
||||
<span className='view-modes-dropdown-tick'>
|
||||
{currentViewMode === item.value && <i className="sf2-icon-tick"></i>}
|
||||
</span>
|
||||
<span className="view-modes-dropdown-content">
|
||||
<span className={`sf3-font-${item.icon} sf3-font mr-2`}></span>
|
||||
<span>{item.text}</span>
|
||||
</span>
|
||||
<span>
|
||||
{currentViewMode === item.value && <i className="sf2-icon-tick"></i>}
|
||||
</span>
|
||||
</div>
|
||||
</DropdownItem>
|
||||
);
|
||||
|
25
frontend/src/css/item-dropdown-menu.css
Normal file
25
frontend/src/css/item-dropdown-menu.css
Normal file
@@ -0,0 +1,25 @@
|
||||
.dropdown-item-wrapper {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.dropdown-item-wrapper .dropdown-item-tick {
|
||||
width: 1.5rem;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.dropdown-item:hover .dropdown-item-tick {
|
||||
color: #fff;
|
||||
}
|
25
frontend/src/css/view-modes.css
Normal file
25
frontend/src/css/view-modes.css
Normal file
@@ -0,0 +1,25 @@
|
||||
.view-modes-dropdown-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.view-modes-dropdown-tick {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.view-modes-dropdown-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
@@ -35,6 +35,7 @@ const TextTranslation = {
|
||||
'TAGS': { key: 'Tags', value: gettext('Tags') },
|
||||
'TRASH': { key: 'Trash', value: gettext('Trash') },
|
||||
'ONLYOFFICE_CONVERT': { key: 'Convert with ONLYOFFICE', value: gettext('Convert with ONLYOFFICE') },
|
||||
'DISPLAY_FILES': { key: 'Display files', value: gettext('Display files') },
|
||||
};
|
||||
|
||||
export default TextTranslation;
|
||||
|
Reference in New Issue
Block a user