diff --git a/frontend/src/components/cur-dir-path/dir-path.js b/frontend/src/components/cur-dir-path/dir-path.js index bcf1970b25..a2da6aee42 100644 --- a/frontend/src/components/cur-dir-path/dir-path.js +++ b/frontend/src/components/cur-dir-path/dir-path.js @@ -5,6 +5,7 @@ import { UncontrolledTooltip } from 'reactstrap'; import { siteRoot, gettext } from '../../utils/constants'; import { Utils } from '../../utils/utils'; import { InternalLinkOperation } from '../operations'; +import DirOperationToolBar from '../../components/toolbar/dir-operation-toolbar'; const propTypes = { repoName: PropTypes.string.isRequired, @@ -50,7 +51,23 @@ class DirPath extends React.Component { return ( / - {item} + + {item} + ); } else { @@ -58,7 +75,7 @@ class DirPath extends React.Component { return ( / - {item} + {item} ); } @@ -78,31 +95,47 @@ class DirPath extends React.Component { } return ( -
+
{this.props.pathPrefix && this.props.pathPrefix.map((item, index) => { return ( - this.onTabNavClick(e, item.name, item.id)}>{gettext(item.showName)} + this.onTabNavClick(e, item.name, item.id)}>{gettext(item.showName)} / ); })} {this.props.pathPrefix && this.props.pathPrefix.length === 0 && ( - this.onTabNavClick(e, 'libraries')}>{gettext('Files')} + this.onTabNavClick(e, 'libraries')}>{gettext('Files')} / )} {!this.props.pathPrefix && ( - this.onTabNavClick(e, 'libraries')}>{gettext('Files')} + this.onTabNavClick(e, 'libraries')}>{gettext('Files')} / )} {(currentPath === '/' || currentPath === '') ? - {repoName}: - {repoName} + + {repoName} + : + {repoName} } {pathElem} {this.props.isViewFile && ( diff --git a/frontend/src/components/cur-dir-path/index.js b/frontend/src/components/cur-dir-path/index.js index ecd9154eea..b5359238a6 100644 --- a/frontend/src/components/cur-dir-path/index.js +++ b/frontend/src/components/cur-dir-path/index.js @@ -47,15 +47,25 @@ class CurDirPath extends React.Component { return ( {isDesktop && { + 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 = ( - {canUpload && ( - - {Utils.isSupportUploadFolder() ? - - - {this.state.isUploadMenuShow && ( - - )} - - : - } - - )} - {canCreate && - - - {this.state.isCreateMenuShow && ( - - )} - - } - {showShareBtn && } + + + {this.props.children} + + + + {opList.map((item, index)=> { + if (item == 'Divider') { + return ; + } else if (item.subOpList) { + return ( + {e.stopPropagation();}} + > + + + {item.text} + + + {item.subOpList.map((item, index)=> { + if (item == 'Divider') { + return ; + } else { + return ({item.text}); + } + })} + + + ); + } else { + return ( + + {item.text} + ); + } + })} + + ); } else { diff --git a/frontend/src/css/lib-content-view.css b/frontend/src/css/lib-content-view.css index 366d3ab7e3..e7bc8965bf 100644 --- a/frontend/src/css/lib-content-view.css +++ b/frontend/src/css/lib-content-view.css @@ -237,3 +237,25 @@ .op-btn:hover { background: #f5f5f5; } + +.dir-view-path .path-item { + min-width: 0; /* overwrite some styles */ + padding: 0 6px; + font-size: 1rem; + color: inherit; + border-radius: 3px; + text-decoration: none; +} + +.dir-view-path .path-item:hover { + background: #efefef; +} + +.dir-view-path .path-item-dropdown-toggle { + color: #999; + font-size: .6rem; +} + +.dir-view-path .path-split { + padding: 0 2px; +} diff --git a/frontend/src/pages/lib-content-view/lib-content-container.js b/frontend/src/pages/lib-content-view/lib-content-container.js index a1f4dabc6c..4a497ddb2d 100644 --- a/frontend/src/pages/lib-content-view/lib-content-container.js +++ b/frontend/src/pages/lib-content-view/lib-content-container.js @@ -209,6 +209,8 @@ class LibContentContainer extends React.Component { }
diff --git a/frontend/src/pages/lib-content-view/lib-content-toolbar.js b/frontend/src/pages/lib-content-view/lib-content-toolbar.js index 8316a95a2b..b217f3ca51 100644 --- a/frontend/src/pages/lib-content-view/lib-content-toolbar.js +++ b/frontend/src/pages/lib-content-view/lib-content-toolbar.js @@ -2,7 +2,6 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import { gettext } from '../../utils/constants'; import CommonToolbar from '../../components/toolbar/common-toolbar'; -import DirOperationToolBar from '../../components/toolbar/dir-operation-toolbar'; import ViewFileToolbar from '../../components/toolbar/view-file-toolbar'; const propTypes = { @@ -86,25 +85,6 @@ class LibContentToolbar extends React.Component {
- {!this.props.isDirentSelected && - - }
{canUpload && this.state.pathExist && !this.state.isViewFile && ( .btn-secondary.dropdown-toggle.dropdown-item .dropdown-item-icon { + color: #fff; +} + +.dropdown-item:hover .dropdown-item-icon, +.dropdown-item:hover .btn .dropdown-item-icon, +.dropdown-item:focus .dropdown-item-icon, +.dropdown-item:focus .btn .dropdown-item-icon { + color: #fff; +} + /* empty-tip */ .empty-tip { margin: 5.5em 1em; diff --git a/media/css/sf_font3/iconfont.css b/media/css/sf_font3/iconfont.css index 0fdb372694..d60f4f60eb 100644 --- a/media/css/sf_font3/iconfont.css +++ b/media/css/sf_font3/iconfont.css @@ -1,11 +1,11 @@ @font-face { font-family: "sf3-font"; /* Project id 1230969 */ - src: url('iconfont.eot?t=1716614768424'); /* IE9 */ - src: url('iconfont.eot?t=1716614768424#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('iconfont.woff2?t=1716614768424') format('woff2'), - url('iconfont.woff?t=1716614768424') format('woff'), - url('iconfont.ttf?t=1716614768424') format('truetype'), - url('iconfont.svg?t=1716614768424#sf3-font') format('svg'); + src: url('iconfont.eot?t=1716779999367'); /* IE9 */ + src: url('iconfont.eot?t=1716779999367#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('iconfont.woff2?t=1716779999367') format('woff2'), + url('iconfont.woff?t=1716779999367') format('woff'), + url('iconfont.ttf?t=1716779999367') format('truetype'), + url('iconfont.svg?t=1716779999367#sf3-font') format('svg'); } .sf3-font { @@ -16,6 +16,10 @@ -moz-osx-font-smoothing: grayscale; } +.sf3-font-upload-files:before { + content: "\e821"; +} + .sf3-font-share:before { content: "\e820"; } diff --git a/media/css/sf_font3/iconfont.eot b/media/css/sf_font3/iconfont.eot index a366a0a897..1ffbf7357e 100644 Binary files a/media/css/sf_font3/iconfont.eot and b/media/css/sf_font3/iconfont.eot differ diff --git a/media/css/sf_font3/iconfont.js b/media/css/sf_font3/iconfont.js index 2d3b16b868..807191c58f 100644 --- a/media/css/sf_font3/iconfont.js +++ b/media/css/sf_font3/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_1230969='',function(h){var c=(c=document.getElementsByTagName("script"))[c.length-1],l=c.getAttribute("data-injectcss"),c=c.getAttribute("data-disable-injectsvg");if(!c){var s,o,t,v,i,m=function(c,l){l.parentNode.insertBefore(c,l)};if(l&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}s=function(){var c,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_1230969,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(c=document.body).firstChild?m(l,c.firstChild):c.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(s,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),s()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(t=s,v=h.document,i=!1,f(),v.onreadystatechange=function(){"complete"==v.readyState&&(v.onreadystatechange=null,z())})}function z(){i||(i=!0,t())}function f(){try{v.documentElement.doScroll("left")}catch(c){return void setTimeout(f,50)}z()}}(window); \ No newline at end of file +window._iconfont_svg_string_1230969='',function(h){var c=(c=document.getElementsByTagName("script"))[c.length-1],l=c.getAttribute("data-injectcss"),c=c.getAttribute("data-disable-injectsvg");if(!c){var s,o,t,v,i,m=function(c,l){l.parentNode.insertBefore(c,l)};if(l&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}s=function(){var c,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_1230969,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(c=document.body).firstChild?m(l,c.firstChild):c.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(s,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),s()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(t=s,v=h.document,i=!1,f(),v.onreadystatechange=function(){"complete"==v.readyState&&(v.onreadystatechange=null,z())})}function z(){i||(i=!0,t())}function f(){try{v.documentElement.doScroll("left")}catch(c){return void setTimeout(f,50)}z()}}(window); \ No newline at end of file diff --git a/media/css/sf_font3/iconfont.svg b/media/css/sf_font3/iconfont.svg index 621e79afcb..64de3e564c 100644 --- a/media/css/sf_font3/iconfont.svg +++ b/media/css/sf_font3/iconfont.svg @@ -14,6 +14,8 @@ /> + + diff --git a/media/css/sf_font3/iconfont.ttf b/media/css/sf_font3/iconfont.ttf index cf27bfc96f..24db2185bf 100644 Binary files a/media/css/sf_font3/iconfont.ttf and b/media/css/sf_font3/iconfont.ttf differ diff --git a/media/css/sf_font3/iconfont.woff b/media/css/sf_font3/iconfont.woff index a02d378ade..13cbc24a06 100644 Binary files a/media/css/sf_font3/iconfont.woff and b/media/css/sf_font3/iconfont.woff differ diff --git a/media/css/sf_font3/iconfont.woff2 b/media/css/sf_font3/iconfont.woff2 index f64abf9161..c766abc1f1 100644 Binary files a/media/css/sf_font3/iconfont.woff2 and b/media/css/sf_font3/iconfont.woff2 differ