mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-06 17:33:18 +00:00
['Files' page] 'New Library': added 'New Library' dropdown menu to some headings('My Libraries' & departments) (#6169)
This commit is contained in:
70
frontend/src/components/toolbar/single-dropdown-toolbar.js
Normal file
70
frontend/src/components/toolbar/single-dropdown-toolbar.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
opList: PropTypes.array.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
class SingleDropdownToolbar extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
isDropdownMenuOpen: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleDropdownMenu = () => {
|
||||||
|
this.setState({isDropdownMenuOpen: !this.state.isDropdownMenuOpen});
|
||||||
|
};
|
||||||
|
|
||||||
|
onDropdownToggleKeyDown = (e) => {
|
||||||
|
if (e.key == 'Enter' || e.key == 'Space') {
|
||||||
|
this.toggleDropdownMenu();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMenuItemKeyDown = (item, e) => {
|
||||||
|
if (e.key == 'Enter' || e.key == 'Space') {
|
||||||
|
item.onClick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { opList } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<Dropdown isOpen={this.state.isDropdownMenuOpen} toggle={this.toggleDropdownMenu}>
|
||||||
|
<DropdownToggle
|
||||||
|
tag="i"
|
||||||
|
role="button"
|
||||||
|
className="sf3-font-drop-down sf3-font ml-1 sf-dropdown-toggle"
|
||||||
|
onClick={this.toggleDropdownMenu}
|
||||||
|
onKeyDown={this.onDropdownToggleKeyDown}
|
||||||
|
data-toggle="dropdown"
|
||||||
|
>
|
||||||
|
</DropdownToggle>
|
||||||
|
<DropdownMenu style={{'width': '200px'}}>
|
||||||
|
{opList.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>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleDropdownToolbar.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default SingleDropdownToolbar;
|
@@ -1,10 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { gettext, siteRoot } from '../../utils/constants';
|
import { gettext, siteRoot, username } from '../../utils/constants';
|
||||||
import { seafileAPI } from '../../utils/seafile-api';
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
import { Utils } from '../../utils/utils';
|
import { Utils } from '../../utils/utils';
|
||||||
import toaster from '../../components/toast';
|
import toaster from '../../components/toast';
|
||||||
import SharedRepoListView from '../../components/shared-repo-list-view/shared-repo-list-view';
|
import SharedRepoListView from '../../components/shared-repo-list-view/shared-repo-list-view';
|
||||||
|
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
|
||||||
|
import CreateRepoDialog from '../../components/dialog/create-repo-dialog';
|
||||||
|
import Repo from '../../models/repo';
|
||||||
|
|
||||||
import '../../css/groups.css';
|
import '../../css/groups.css';
|
||||||
|
|
||||||
@@ -18,6 +21,9 @@ class GroupItem extends React.Component {
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
isCreateRepoDialogOpen: false
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemUnshare = (repo) => {
|
onItemUnshare = (repo) => {
|
||||||
@@ -69,15 +75,54 @@ class GroupItem extends React.Component {
|
|||||||
this.props.updateGroup(group);
|
this.props.updateGroup(group);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
toggleCreateRepoDialog = () => {
|
||||||
|
this.setState({
|
||||||
|
isCreateRepoDialogOpen: !this.state.isCreateRepoDialogOpen
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onCreateRepo = (repo) => {
|
||||||
|
const { group } = this.props;
|
||||||
|
const { id: groupId, repos } = group;
|
||||||
|
seafileAPI.createGroupOwnedLibrary(groupId, repo).then(res => {
|
||||||
|
let object = {
|
||||||
|
repo_id: res.data.id,
|
||||||
|
repo_name: res.data.name,
|
||||||
|
owner_name: res.data.group_name,
|
||||||
|
owner_email: res.data.owner,
|
||||||
|
permission: res.data.permission,
|
||||||
|
mtime: res.data.mtime,
|
||||||
|
size: res.data.size,
|
||||||
|
encrypted: res.data.encrypted,
|
||||||
|
};
|
||||||
|
const newRepo = new Repo(object);
|
||||||
|
repos.unshift(newRepo);
|
||||||
|
this.props.updateGroup(group);
|
||||||
|
}).catch(error => {
|
||||||
|
let errMessage = Utils.getErrorMsg(error);
|
||||||
|
toaster.danger(errMessage);
|
||||||
|
});
|
||||||
|
this.toggleCreateRepoDialog();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { group } = this.props;
|
const { group } = this.props;
|
||||||
|
const { parent_group_id, admins } = group;
|
||||||
const emptyTip = <p className="group-item-empty-tip">{gettext('No libraries')}</p>;
|
const emptyTip = <p className="group-item-empty-tip">{gettext('No libraries')}</p>;
|
||||||
|
|
||||||
|
const isDeptAdmin = parent_group_id != 0 && admins.indexOf(username) > -1;
|
||||||
return (
|
return (
|
||||||
<div className="pb-3">
|
<div className="pb-3">
|
||||||
<div className="d-flex justify-content-between mt-3 py-1 sf-border-bottom">
|
<div className="d-flex justify-content-between mt-3 py-1 sf-border-bottom">
|
||||||
<h4 className="sf-heading m-0 ellipsis">
|
<h4 className="sf-heading m-0 d-flex align-items-center">
|
||||||
<span className={`${group.parent_group_id == 0 ? 'sf3-font-group' : 'sf3-font-department'} sf3-font nav-icon`} aria-hidden="true"></span>
|
<span className={`${group.parent_group_id == 0 ? 'sf3-font-group' : 'sf3-font-department'} sf3-font nav-icon`} aria-hidden="true"></span>
|
||||||
<a href={`${siteRoot}group/${group.id}/`} title={group.name}>{group.name}</a>
|
<a href={`${siteRoot}group/${group.id}/`} title={group.name} className="ellipsis">{group.name}</a>
|
||||||
|
{isDeptAdmin && (
|
||||||
|
<SingleDropdownToolbar
|
||||||
|
opList={[{'text': gettext('New Library'), 'onClick': this.toggleCreateRepoDialog}]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
{group.repos.length === 0 ?
|
{group.repos.length === 0 ?
|
||||||
@@ -93,6 +138,13 @@ class GroupItem extends React.Component {
|
|||||||
onMonitorRepo={this.onMonitorRepo}
|
onMonitorRepo={this.onMonitorRepo}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
{this.state.isCreateRepoDialogOpen &&
|
||||||
|
<CreateRepoDialog
|
||||||
|
onCreateToggle={this.toggleCreateRepoDialog}
|
||||||
|
onCreateRepo={this.onCreateRepo}
|
||||||
|
libraryType='department'
|
||||||
|
/>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -9,9 +9,10 @@ import Repo from '../../models/repo';
|
|||||||
import Group from '../../models/group';
|
import Group from '../../models/group';
|
||||||
import Loading from '../../components/loading';
|
import Loading from '../../components/loading';
|
||||||
import TopToolbar from '../../components/toolbar/top-toolbar';
|
import TopToolbar from '../../components/toolbar/top-toolbar';
|
||||||
import MyLibsToolbar from '../../components/toolbar/my-libs-toolbar';
|
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
|
||||||
import SortOptionsDialog from '../../components/dialog/sort-options';
|
import SortOptionsDialog from '../../components/dialog/sort-options';
|
||||||
import GuideForNewDialog from '../../components/dialog/guide-for-new-dialog';
|
import GuideForNewDialog from '../../components/dialog/guide-for-new-dialog';
|
||||||
|
import CreateRepoDialog from '../../components/dialog/create-repo-dialog';
|
||||||
import MylibRepoListView from '../../pages/my-libs/mylib-repo-list-view';
|
import MylibRepoListView from '../../pages/my-libs/mylib-repo-list-view';
|
||||||
import SharedLibs from '../../pages/shared-libs/shared-libs.js';
|
import SharedLibs from '../../pages/shared-libs/shared-libs.js';
|
||||||
import SharedWithAll from '../../pages/shared-with-all';
|
import SharedWithAll from '../../pages/shared-with-all';
|
||||||
@@ -39,6 +40,7 @@ class Libraries extends Component {
|
|||||||
groupList: [],
|
groupList: [],
|
||||||
sharedRepoList:[],
|
sharedRepoList:[],
|
||||||
publicRepoList: [],
|
publicRepoList: [],
|
||||||
|
isCreateRepoDialogOpen: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +80,7 @@ class Libraries extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onCreateRepo = (repo) => {
|
onCreateRepo = (repo) => {
|
||||||
|
this.toggleCreateRepoDialog();
|
||||||
seafileAPI.createMineRepo(repo).then((res) => {
|
seafileAPI.createMineRepo(repo).then((res) => {
|
||||||
const newRepo = new Repo({
|
const newRepo = new Repo({
|
||||||
repo_id: res.data.repo_id,
|
repo_id: res.data.repo_id,
|
||||||
@@ -172,6 +175,12 @@ class Libraries extends Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
toggleCreateRepoDialog = () => {
|
||||||
|
this.setState({
|
||||||
|
isCreateRepoDialogOpen: !this.state.isCreateRepoDialogOpen
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isLoading } = this.state;
|
const { isLoading } = this.state;
|
||||||
return (
|
return (
|
||||||
@@ -180,9 +189,6 @@ class Libraries extends Component {
|
|||||||
onShowSidePanel={this.props.onShowSidePanel}
|
onShowSidePanel={this.props.onShowSidePanel}
|
||||||
onSearchedClick={this.props.onSearchedClick}
|
onSearchedClick={this.props.onSearchedClick}
|
||||||
>
|
>
|
||||||
<>
|
|
||||||
{canAddRepo && <MyLibsToolbar onCreateRepo={this.onCreateRepo} />}
|
|
||||||
</>
|
|
||||||
</TopToolbar>
|
</TopToolbar>
|
||||||
<div className="main-panel-center flex-row">
|
<div className="main-panel-center flex-row">
|
||||||
<div className="cur-view-container">
|
<div className="cur-view-container">
|
||||||
@@ -210,9 +216,12 @@ class Libraries extends Component {
|
|||||||
{canAddRepo && (
|
{canAddRepo && (
|
||||||
<div className="pb-3">
|
<div className="pb-3">
|
||||||
<div className="d-flex justify-content-between mt-3 py-1 sf-border-bottom">
|
<div className="d-flex justify-content-between mt-3 py-1 sf-border-bottom">
|
||||||
<h4 className="sf-heading m-0">
|
<h4 className="sf-heading m-0 d-flex align-items-center">
|
||||||
<span className="sf3-font-mine sf3-font nav-icon" aria-hidden="true"></span>
|
<span className="sf3-font-mine sf3-font nav-icon" aria-hidden="true"></span>
|
||||||
{gettext('My Libraries')}
|
{gettext('My Libraries')}
|
||||||
|
<SingleDropdownToolbar
|
||||||
|
opList={[{'text': gettext('New Library'), 'onClick': this.toggleCreateRepoDialog}]}
|
||||||
|
/>
|
||||||
</h4>
|
</h4>
|
||||||
{(!Utils.isDesktop() && this.state.repoList.length > 0) &&
|
{(!Utils.isDesktop() && this.state.repoList.length > 0) &&
|
||||||
<span className="sf3-font sf3-font-sort action-icon" onClick={this.toggleSortOptionsDialog}></span>
|
<span className="sf3-font sf3-font-sort action-icon" onClick={this.toggleSortOptionsDialog}></span>
|
||||||
@@ -275,6 +284,13 @@ class Libraries extends Component {
|
|||||||
sortItems={this.sortRepoList}
|
sortItems={this.sortRepoList}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
{this.state.isCreateRepoDialogOpen && (
|
||||||
|
<CreateRepoDialog
|
||||||
|
libraryType='mine'
|
||||||
|
onCreateRepo={this.onCreateRepo}
|
||||||
|
onCreateToggle={this.toggleCreateRepoDialog}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@@ -158,6 +158,10 @@ a, a:hover { color: #ec8000; }
|
|||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sf-heading .sf-dropdown-toggle {
|
||||||
|
font-size: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.sf-link {
|
.sf-link {
|
||||||
color: #ee8204 !important;
|
color: #ee8204 !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
Reference in New Issue
Block a user