1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-31 22:54:11 +00:00

[dir view] redesigned the toolbar for the current folder (#6117)

* [dir view] redesigned the toolbar for the current folder

* [dir view] toolbar for the current folder: code cleanup

* [dir view] toolbar for the current folder: updated the 'upload' icon; modified UI details
This commit is contained in:
llj
2024-05-27 16:47:19 +08:00
committed by GitHub
parent d24d71420e
commit 69011567a3
15 changed files with 257 additions and 116 deletions

View File

@@ -22,8 +22,7 @@ const propTypes = {
onUploadFile: PropTypes.func.isRequired,
onUploadFolder: PropTypes.func.isRequired,
direntList: PropTypes.array.isRequired,
currentMode: PropTypes.string.isRequired,
switchViewMode: PropTypes.func.isRequired,
children: PropTypes.object
};
class DirOperationToolbar extends React.Component {
@@ -34,68 +33,29 @@ class DirOperationToolbar extends React.Component {
fileType: '.md',
isCreateFileDialogShow: false,
isCreateFolderDialogShow: false,
isUploadMenuShow: false,
isCreateMenuShow: false,
isShareDialogShow: false,
operationMenuStyle: '',
isDesktopMenuOpen: false,
isMobileOpMenuOpen: false
};
}
componentDidMount() {
document.addEventListener('click', this.hideOperationMenu);
}
componentWillUnmount() {
document.removeEventListener('click', this.hideOperationMenu);
}
toggleDesktopOpMenu = () => {
this.setState({isDesktopMenuOpen: !this.state.isDesktopMenuOpen});
};
toggleMobileOpMenu = () => {
this.setState({isMobileOpMenuOpen: !this.state.isMobileOpMenuOpen});
};
hideOperationMenu = () => {
this.setState({
isUploadMenuShow: false,
isCreateMenuShow: false,
});
};
toggleOperationMenu = (e) => {
e.nativeEvent.stopImmediatePropagation();
let targetRect = e.target.getBoundingClientRect();
let left = targetRect.left;
let top = targetRect.bottom;
let style = {position: 'fixed', display: 'block', left: left, top: top};
this.setState({operationMenuStyle: style});
};
onUploadClick = (e) => {
this.toggleOperationMenu(e);
this.setState({
isUploadMenuShow: !this.state.isUploadMenuShow,
isCreateMenuShow: false,
});
};
onUploadFile = (e) => {
this.setState({isUploadMenuShow: false});
this.props.onUploadFile(e);
};
onUploadFolder = (e) => {
this.setState({isUploadMenuShow: false});
this.props.onUploadFolder(e);
};
onCreateClick = (e) => {
this.toggleOperationMenu(e);
this.setState({
isCreateMenuShow: !this.state.isCreateMenuShow,
isUploadMenuShow: false,
});
};
onShareClick = () => {
this.setState({
isShareDialogShow: !this.state.isShareDialogShow
@@ -161,6 +121,41 @@ class DirOperationToolbar extends React.Component {
return isDuplicated;
};
onDropdownToggleKeyDown = (e) => {
if (e.key == 'Enter' || e.key == 'Space') {
this.toggleDesktopOpMenu();
}
};
onDropDownMouseMove = (e) => {
if (this.state.isSubMenuShown && e.target && e.target.className === 'dropdown-item') {
this.setState({
isSubMenuShown: false
});
}
};
toggleSubMenu = (e) => {
e.stopPropagation();
this.setState({
isSubMenuShown: !this.state.isSubMenuShown}, () => {
this.toggleDesktopOpMenu();
});
};
toggleSubMenuShown = (item) => {
this.setState({
isSubMenuShown: true,
currentItem: item.text
});
};
onMenuItemKeyDown = (item, e) => {
if (e.key == 'Enter' || e.key == 'Space') {
item.onClick();
}
};
render() {
let { path, repoName, userPerm } = this.props;
@@ -179,42 +174,108 @@ class DirOperationToolbar extends React.Component {
let content = null;
if (Utils.isDesktop()) {
const { showShareBtn, repoEncrypted } = this.props;
let opList = [];
if (canUpload) {
if (Utils.isSupportUploadFolder()) {
opList.push({
'icon': 'upload-files',
'text': gettext('Upload'),
subOpList: [
{'text': gettext('Upload Files'), 'onClick': this.onUploadFile},
{'text': gettext('Upload Folder'), 'onClick': this.onUploadFolder}
]
});
} else {
opList.push({'text': gettext('Upload'), 'onClick': this.onUploadFile});
}
}
if (canCreate) {
let newSubOpList = [
{'text': gettext('New Folder'), 'onClick': this.onCreateFolderToggle},
{'text': gettext('New File'), 'onClick': this.onCreateFileToggle},
'Divider',
{'text': gettext('New Markdown File'), 'onClick': this.onCreateMarkdownToggle},
{'text': gettext('New Excel File'), 'onClick': this.onCreateExcelToggle},
{'text': gettext('New PowerPoint File'), 'onClick': this.onCreatePPTToggle},
{'text': gettext('New Word File'), 'onClick': this.onCreateWordToggle}
];
if (enableSeadoc && !repoEncrypted) {
newSubOpList.push({'text': gettext('New SeaDoc File'), 'onClick': this.onCreateSeaDocToggle});
}
opList.push({
'icon': 'new',
'text': gettext('New'),
subOpList: newSubOpList
});
}
if (showShareBtn) {
opList.push({
'icon': 'share',
'text': gettext('Share'),
'onClick': this.onShareClick
});
}
content = (
<Fragment>
{canUpload && (
<Fragment>
{Utils.isSupportUploadFolder() ?
<Fragment>
<button className="btn btn-secondary operation-item" onClick={this.onUploadClick} aria-haspopup="true" aria-expanded={this.state.isUploadMenuShow} aria-controls="upload-menu">{gettext('Upload')}</button>
{this.state.isUploadMenuShow && (
<div className="menu dropdown-menu" style={this.state.operationMenuStyle} role="menu" id="upload-menu">
<button type="button" className="dropdown-item" onClick={this.onUploadFile} role="menuitem">{gettext('Upload Files')}</button>
<button type="button" className="dropdown-item" onClick={this.onUploadFolder} role="menuitem">{gettext('Upload Folder')}</button>
</div>
)}
</Fragment>
:
<button className="btn btn-secondary operation-item" title={gettext('Upload')} onClick={this.onUploadFile}>{gettext('Upload')}</button>}
</Fragment>
)}
{canCreate &&
<Fragment>
<button className="btn btn-secondary operation-item" onClick={this.onCreateClick} aria-haspopup="true" aria-expanded={this.state.isUploadMenuShow} aria-controls="new-menu">{gettext('New')}</button>
{this.state.isCreateMenuShow && (
<div className="menu dropdown-menu" style={this.state.operationMenuStyle} role="menu" id="new-menu">
<button className="dropdown-item" onClick={this.onCreateFolderToggle} role="menuitem">{gettext('New Folder')}</button>
<button className="dropdown-item" onClick={this.onCreateFileToggle}>{gettext('New File')}</button>
<div className="dropdown-divider"></div>
<button className="dropdown-item" onClick={this.onCreateMarkdownToggle} role="menuitem">{gettext('New Markdown File')}</button>
<button className="dropdown-item" onClick={this.onCreateExcelToggle} role="menuitem">{gettext('New Excel File')}</button>
<button className="dropdown-item" onClick={this.onCreatePPTToggle} role="menuitem">{gettext('New PowerPoint File')}</button>
<button className="dropdown-item" onClick={this.onCreateWordToggle} role="menuitem">{gettext('New Word File')}</button>
{enableSeadoc && !repoEncrypted && <button className="dropdown-item" onClick={this.onCreateSeaDocToggle} role="menuitem">{gettext('New SeaDoc File')} (beta)</button>}
</div>
)}
</Fragment>
}
{showShareBtn && <button className="btn btn-secondary operation-item" title={gettext('Share')} onClick={this.onShareClick}>{gettext('Share')}</button>}
<Dropdown isOpen={this.state.isDesktopMenuOpen} toggle={this.toggleDesktopOpMenu}>
<DropdownToggle
tag="div"
role="button"
className="path-item"
title={gettext('More operations')}
aria-label={gettext('More operations')}
onClick={this.toggleDesktopOpMenu}
onKeyDown={this.onDropdownToggleKeyDown}
data-toggle="dropdown"
>
{this.props.children}
<i className="sf3-font-drop-down sf3-font ml-1 path-item-dropdown-toggle"></i>
</DropdownToggle>
<DropdownMenu onMouseMove={this.onDropDownMouseMove} style={{'width': '200px'}}>
{opList.map((item, index)=> {
if (item == 'Divider') {
return <DropdownItem key={index} divider />;
} else if (item.subOpList) {
return (
<Dropdown
key={index}
direction="right"
className="w-100"
isOpen={this.state.isSubMenuShown && this.state.currentItem == item.text}
toggle={this.toggleSubMenu}
onMouseMove={(e) => {e.stopPropagation();}}
>
<DropdownToggle
caret
className="dropdown-item font-weight-normal rounded-0 d-flex align-items-center pr-2"
onMouseEnter={this.toggleSubMenuShown.bind(this, item)}
>
<i className={`sf3-font-${item.icon} sf3-font mr-2 dropdown-item-icon`}></i>
<span className="mr-auto">{item.text}</span>
</DropdownToggle>
<DropdownMenu>
{item.subOpList.map((item, index)=> {
if (item == 'Divider') {
return <DropdownItem key={index} divider />;
} else {
return (<DropdownItem key={index} onClick={item.onClick} onKeyDown={this.onMenuItemKeyDown.bind(this, item)}>{item.text}</DropdownItem>);
}
})}
</DropdownMenu>
</Dropdown>
);
} else {
return (<DropdownItem key={index} onClick={item.onClick} onKeyDown={this.onMenuItemKeyDown.bind(this, item)}>
<i className={`sf3-font-${item.icon} sf3-font mr-2 dropdown-item-icon`}></i>
{item.text}
</DropdownItem>);
}
})}
</DropdownMenu>
</Dropdown>
</Fragment>
);
} else {