diff --git a/frontend/src/components/files-sub-nav.js b/frontend/src/components/files-sub-nav.js new file mode 100644 index 0000000000..3e7c510c0f --- /dev/null +++ b/frontend/src/components/files-sub-nav.js @@ -0,0 +1,83 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Link } from '@gatsbyjs/reach-router'; +import { + gettext, siteRoot, canAddRepo, canViewOrg +} from '../utils/constants'; + +const propTypes = { + currentTab: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + tabItemClick: PropTypes.func.isRequired, +}; + +class FilesSubNav extends React.Component { + constructor(props) { + super(props); + this.state = { + groupItems: [] + }; + } + + tabItemClick = (e, param, id) => { + this.props.tabItemClick(e, param, id); + }; + + getActiveClass = (tab) => { + return this.props.currentTab === tab ? 'active' : ''; + }; + + renderSharedGroups() { + return ( + <> + {this.props.groupItems.map(item => { + return ( +
  • + this.tabItemClick(e, item.name, item.id)} + > + + {item.name} + +
  • + ); + })} + + ); + } + + render() { + return ( + <> + {canAddRepo && ( +
  • + this.tabItemClick(e, 'my-libs')}> + + {gettext('My Libraries')} + +
  • + )} +
  • + this.tabItemClick(e, 'shared-libs')}> + + {gettext('Shared with me')} + +
  • + {canViewOrg && +
  • this.tabItemClick(e, 'org')}> + + + {gettext('Shared with all')} + +
  • + } + {this.renderSharedGroups()} + + ); + } +} + +FilesSubNav.propTypes = propTypes; + +export default FilesSubNav; diff --git a/frontend/src/components/main-side-nav-folded.js b/frontend/src/components/main-side-nav-folded.js index 0c0a13f851..eedb1183c3 100644 --- a/frontend/src/components/main-side-nav-folded.js +++ b/frontend/src/components/main-side-nav-folded.js @@ -3,7 +3,14 @@ import PropTypes from 'prop-types'; import { Link } from '@gatsbyjs/reach-router'; import { gettext, siteRoot, canInvitePeople, enableTC, sideNavFooterCustomHtml, additionalAppBottomLinks, isDocs, isPro, isDBSqlite3, customNavItems, mediaUrl } from '../utils/constants'; +import { SIDE_PANEL_FOLDED_WIDTH, SUB_NAV_ITEM_HEIGHT } from '../constants'; import Tip from './side-nav-icon-tip'; +import FilesSubNav from '../components/files-sub-nav'; +import { seafileAPI } from '../utils/seafile-api'; +import { Utils } from '../utils/utils'; +import Group from '../models/group'; +import toaster from './toast'; + import '../css/main-side-nav-folded.css'; @@ -15,6 +22,39 @@ const propTypes = { class MainSideNavFolded extends React.Component { + constructor(props) { + super(props); + this.state = { + groupItems: [], + isFilesSubNavShown: false + }; + } + + componentDidMount() { + document.addEventListener('click', this.handleOutsideClick); + } + + componentWillUnmount() { + document.removeEventListener('click', this.handleOutsideClick); + } + + handleOutsideClick = (e) => { + const { isFilesSubNavShown } = this.state; + if (isFilesSubNavShown && !this.filesSubNav.contains(e.target)) { + this.toggleSubNav(); + } + }; + + toggleSubNav = () => { + this.setState({ + isFilesSubNavShown: !this.state.isFilesSubNavShown + }, () => { + if (this.state.isFilesSubNavShown) { + this.loadGroups(); + } + }); + }; + tabItemClick = (e, param, id) => { if (window.uploader && window.uploader.isUploadProgressDialogShow && @@ -26,24 +66,69 @@ class MainSideNavFolded extends React.Component { window.uploader.isUploadProgressDialogShow = false; } this.props.tabItemClick(param, id); + + if (this.props.currentTab == 'libraries' && param == 'libraries') { + e.stopPropagation(); + this.toggleSubNav(); + } else { + this.setState({ + isFilesSubNavShown: false + }); + } }; getActiveClass = (tab) => { return this.props.currentTab === tab ? 'active' : ''; }; + loadGroups = () => { + seafileAPI.listGroups().then(res => { + let groupList = res.data.map(item => { + let group = new Group(item); + return group; + }); + + this.setState({ + groupItems: groupList.sort((a, b) => { + return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; + }) + }); + }).catch(error => { + let errMessage = Utils.getErrorMsg(error); + toaster.danger(errMessage); + }); + }; + render() { let showActivity = isDocs || isPro || !isDBSqlite3; + const { groupItems, isFilesSubNavShown } = this.state; return (