1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-02 07:27:04 +00:00
Files
seahub/frontend/src/pages/groups/group-view.js

547 lines
20 KiB
JavaScript
Raw Normal View History

2018-12-10 13:44:11 +08:00
import React,{ Fragment } from 'react';
2018-12-19 10:44:23 +08:00
import { Popover } from 'reactstrap';
2018-12-08 08:37:18 +08:00
import PropTypes from 'prop-types';
2019-03-19 10:35:21 +08:00
import cookie from 'react-cookies';
import { gettext, siteRoot, username, loginUrl, canAddRepo } from '../../utils/constants';
2018-12-11 18:05:57 +08:00
import { Link } from '@reach/router';
2018-12-08 08:37:18 +08:00
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
2018-12-10 13:44:11 +08:00
import Loading from '../../components/loading';
2018-12-10 17:59:26 +08:00
import ModalPortal from '../../components/modal-portal';
2018-12-08 08:37:18 +08:00
import Group from '../../models/group';
2018-12-18 17:21:01 +08:00
import Repo from '../../models/repo';
2018-12-10 13:44:11 +08:00
import CommonToolbar from '../../components/toolbar/common-toolbar';
2018-12-10 17:59:26 +08:00
import CreateRepoDialog from '../../components/dialog/create-repo-dialog';
import CreateDepartmentRepoDialog from '../../components/dialog/create-department-repo-dialog';
2018-12-19 10:44:23 +08:00
import DismissGroupDialog from '../../components/dialog/dismiss-group-dialog';
import RenameGroupDialog from '../../components/dialog/rename-group-dialog';
2018-12-24 18:25:12 +08:00
import TransferGroupDialog from '../../components/dialog/transfer-group-dialog';
// import ImportMembersDialog from '../../components/dialog/import-members-dialog';
import ManageMembersDialog from '../../components/dialog/manage-members-dialog';
2018-12-10 18:19:03 +08:00
import SharedRepoListView from '../../components/shared-repo-list-view/shared-repo-list-view';
import LibDetail from '../../components/dirent-detail/lib-details';
2018-12-24 18:25:12 +08:00
import '../../css/group-view.css';
2018-12-08 08:37:18 +08:00
const propTypes = {
2018-12-08 16:35:00 +08:00
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired,
2018-12-19 10:44:23 +08:00
onGroupChanged: PropTypes.func.isRequired,
onTabNavClick: PropTypes.func.isRequired,
2018-12-19 10:44:23 +08:00
groupID: PropTypes.string,
2018-12-08 08:37:18 +08:00
};
class GroupView extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
errMessage: '',
2018-12-08 16:35:00 +08:00
emptyTip: null,
2018-12-08 08:37:18 +08:00
currentGroup: null,
currentRepo: null,
2018-12-08 16:35:00 +08:00
isStaff: false,
2018-12-24 18:25:12 +08:00
isOwner: false,
sortBy: cookie.load('seafile-repo-dir-sort-by') || 'name', // 'name' or 'time'
sortOrder: cookie.load('seafile-repo-dir-sort-order') || 'asc', // 'asc' or 'desc'
2018-12-08 08:37:18 +08:00
repoList: [],
2018-12-10 17:59:26 +08:00
libraryType: 'group',
isCreateRepoDialogShow: false,
isDepartmentGroup: false,
2018-12-19 10:44:23 +08:00
showGroupDropdown: false,
2018-12-24 18:25:12 +08:00
showGroupMembersPopover: false,
2018-12-19 10:44:23 +08:00
showRenameGroupDialog: false,
showDismissGroupDialog: false,
2018-12-24 18:25:12 +08:00
showTransferGroupDialog: false,
// showImportMembersDialog: false,
showManageMembersDialog: false,
groupMembers: [],
isShowDetails: false,
2018-12-19 10:44:23 +08:00
};
2018-12-08 08:37:18 +08:00
}
componentDidMount() {
let groupID = this.props.groupID;
this.loadGroup(groupID);
}
componentWillReceiveProps(nextProps) {
if (nextProps.groupID !== this.props.groupID) {
this.loadGroup(nextProps.groupID);
}
}
loadGroup = (groupID) => {
seafileAPI.getGroup(groupID).then((res) => {
let currentGroup = new Group(res.data);
2018-12-08 16:35:00 +08:00
let emptyTip = this.getEmptyTip(currentGroup);
let isStaff = currentGroup.admins.indexOf(username) > -1; //for item operations
2018-12-24 18:25:12 +08:00
let isOwner = currentGroup.owner === username ? true : false;
let isDepartmentGroup = currentGroup.parent_group_id !== 0;
2018-12-08 16:35:00 +08:00
this.setState({
emptyTip: emptyTip,
currentGroup: currentGroup,
isStaff: isStaff,
2018-12-10 17:59:26 +08:00
isDepartmentGroup: isDepartmentGroup,
2018-12-24 18:25:12 +08:00
isOwner: isOwner,
2018-12-08 16:35:00 +08:00
});
2018-12-08 08:37:18 +08:00
this.loadRepos(groupID);
}).catch((error) => {
if (error.response) {
if (error.response.status == 403) {
this.setState({
isLoading: false,
errMessage: gettext('Permission denied')
2018-12-08 08:37:18 +08:00
});
location.href = `${loginUrl}?next=${encodeURIComponent(location.href)}`;
} else {
this.setState({
isLoading: false,
errMessage: gettext('Error')
2018-12-08 08:37:18 +08:00
});
}
} else {
this.setState({
isLoading: false,
errMessage: gettext('Please check the network.')
2018-12-08 08:37:18 +08:00
});
}
});
}
loadRepos = (groupID) => {
this.setState({isLoading: true});
seafileAPI.listGroupRepos(groupID).then((res) => {
let repoList = res.data.map(item => {
2018-12-18 17:21:01 +08:00
let repo = new Repo(item);
return repo;
2018-12-08 08:37:18 +08:00
});
this.setState({
isLoading: false,
repoList: Utils.sortRepos(repoList, this.state.sortBy, this.state.sortOrder)
2018-12-08 08:37:18 +08:00
});
}).catch((error) => {
if (error.response) {
if (error.response.status == 403) {
this.setState({
isLoading: false,
errMessage: gettext('Permission denied')
2018-12-08 08:37:18 +08:00
});
location.href = `${loginUrl}?next=${encodeURIComponent(location.href)}`;
} else {
this.setState({
isLoading: false,
errMessage: gettext('Error')
2018-12-08 08:37:18 +08:00
});
}
} else {
this.setState({
isLoading: false,
errMessage: gettext('Please check the network.')
2018-12-08 08:37:18 +08:00
});
}
});
}
2018-12-08 16:35:00 +08:00
getEmptyTip = (currentGroup) => {
2018-12-08 08:37:18 +08:00
let emptyTip = null;
if (currentGroup) {
if (currentGroup.parent_group_id === 0) {
emptyTip = (
<div className="empty-tip">
<h2>{gettext('No library is shared to this group')}</h2>
<p>{gettext('You can share libraries by clicking the "New Library" button above or the "Share" icon on your libraries list.')}</p>
<p>{gettext('Libraries shared as writable can be downloaded and synced by other group members. Read only libraries can only be downloaded, updates by others will not be uploaded.')}</p>
</div>
);
} else {
2018-12-08 16:35:00 +08:00
if (currentGroup.admins.indexOf(username) == -1) { // is a member of this group
2018-12-08 08:37:18 +08:00
emptyTip = (
<div className="empty-tip">
<h2>{gettext('No libraries')}</h2>
</div>
);
} else {
emptyTip = (
<div className="empty-tip">
<h2>{gettext('No libraries')}</h2>
<p>{gettext('You can create libraries by clicking the "New Library" button above.')}</p>
</div>
);
}
}
}
return emptyTip;
}
2018-12-10 17:59:26 +08:00
onCreateRepoToggle = () => {
this.setState({isCreateRepoDialogShow: !this.state.isCreateRepoDialogShow});
}
2018-12-16 11:17:17 +08:00
onCreateRepo = (repo, groupOwnerType) => {
2018-12-10 13:44:11 +08:00
let groupId = this.props.groupID;
2018-12-16 11:17:17 +08:00
if (groupOwnerType && groupOwnerType === 'department') {
seafileAPI.createGroupOwnedLibrary(groupId, repo).then(res => { //need modify endpoint api
let object = {
repo_id: res.data.id,
repo_name: res.data.name,
2018-12-17 15:12:10 +08:00
owner_name: res.data.group_name,
2018-12-16 11:17:17 +08:00
owner_email: res.data.owner,
permission: res.data.permission,
mtime: res.data.mtime,
size: res.data.size,
encrypted: res.data.encrypted,
};
2018-12-18 17:21:01 +08:00
let repo = new Repo(object);
2018-12-16 11:17:17 +08:00
let repoList = this.addRepoItem(repo);
this.setState({repoList: repoList});
}).then(() => {
//todo
});
} else {
seafileAPI.createGroupRepo(groupId, repo).then(res => {
2018-12-18 17:21:01 +08:00
let repo = new Repo(res.data);
2018-12-16 11:17:17 +08:00
let repoList = this.addRepoItem(repo);
this.setState({repoList: repoList});
}).catch(() => {
//todo
});
}
this.onCreateRepoToggle();
}
onItemDelete = (repo) => {
let groupID = this.props.groupID;
seafileAPI.deleteGroupOwnedLibrary(groupID, repo.repo_id).then(() => {
let repoList = this.state.repoList.filter(item => {
return item.repo_id !== repo.repo_id;
});
2018-12-10 13:44:11 +08:00
this.setState({repoList: repoList});
}).catch(() => {
2018-12-16 11:17:17 +08:00
// todo;
2018-12-10 13:44:11 +08:00
});
}
addRepoItem = (repo) => {
let newRepoList = this.state.repoList.map(item => {return item;});
2018-12-22 15:18:53 +08:00
newRepoList.unshift(repo);
2018-12-10 13:44:11 +08:00
return newRepoList;
}
2018-12-10 18:37:59 +08:00
onItemUnshare = (repo) => {
2018-12-10 17:59:26 +08:00
let group = this.state.currentGroup;
seafileAPI.unshareRepo(repo.repo_id, {share_type: 'group', group_id: group.id}).then(() => {
let repoList = this.state.repoList.filter(item => {
return item.repo_id !== repo.repo_id;
});
this.setState({repoList: repoList});
});
}
onItemRename = (repo, newName) => {
seafileAPI.renameGroupOwnedLibrary(this.props.groupID, repo.repo_id, newName).then(res => {
let repoList = this.state.repoList.map(item => {
if (item.repo_id === repo.repo_id) {
item.repo_name = newName;
}
return item;
});
this.setState({repoList: repoList});
}).catch(() => {
// todo
});
}
2018-12-13 14:40:09 +08:00
onTabNavClick = (tabName) => {
this.props.onTabNavClick(tabName);
}
2018-12-19 10:44:23 +08:00
toggleGroupDropdown = () => {
this.setState({
showGroupDropdown: !this.state.showGroupDropdown
});
}
toggleDismissGroupDialog = () => {
this.setState({
showDismissGroupDialog: !this.state.showDismissGroupDialog,
showGroupDropdown: false,
2018-12-19 10:44:23 +08:00
});
}
toggleRenameGroupDialog = () => {
this.setState({
showRenameGroupDialog: !this.state.showRenameGroupDialog,
showGroupDropdown: false,
2018-12-19 10:44:23 +08:00
});
}
2018-12-13 14:40:09 +08:00
2018-12-24 18:25:12 +08:00
toggleTransferGroupDialog = () => {
this.setState({
showTransferGroupDialog: !this.state.showTransferGroupDialog,
showGroupDropdown: false,
2018-12-24 18:25:12 +08:00
});
}
// toggleImportMembersDialog= () => {
// this.setState({
// showImportMembersDialog: !this.state.showImportMembersDialog
// });
// }
toggleManageMembersDialog = () => {
this.setState({
showManageMembersDialog: !this.state.showManageMembersDialog,
showGroupDropdown: false,
2018-12-24 18:25:12 +08:00
});
}
listGroupMembers = () => {
seafileAPI.listGroupMembers(this.props.groupID).then((res) => {
this.setState({
groupMembers: res.data
});
});
}
toggleGroupMembersPopover = (state) => {
if (state === 'open') {
this.listGroupMembers();
this.setState({
showGroupMembersPopover: true
});
} else {
this.setState({
showGroupMembersPopover: false
});
}
}
onItemDetails = (repo) => {
this.setState({
isShowDetails: true,
currentRepo: repo,
});
}
closeDetails = () => {
this.setState({isShowDetails: false});
}
sortItems = (sortBy, sortOrder) => {
cookie.save('seafile-repo-dir-sort-by', sortBy);
cookie.save('seafile-repo-dir-sort-order', sortOrder);
this.setState({
sortBy: sortBy,
sortOrder: sortOrder,
repoList: Utils.sortRepos(this.state.repoList, sortBy, sortOrder)
});
}
2019-03-07 16:40:01 +08:00
translateRole = (role) => {
if (role === 'Admin') {
return gettext('Admin');
}
else if (role === 'Member') {
return gettext('Member');
}
else if (role === 'Owner') {
return gettext('Owner');
}
}
2018-12-08 08:37:18 +08:00
render() {
2019-05-05 12:00:41 +08:00
let { errMessage, emptyTip, currentGroup, isDepartmentGroup, isStaff } = this.state;
2018-12-10 18:12:46 +08:00
let isShowSettingIcon = !(currentGroup && currentGroup.parent_group_id !== 0 && currentGroup.admins.indexOf(username) === -1);
2019-03-07 16:40:01 +08:00
let that = this;
2018-12-08 08:37:18 +08:00
return (
2018-12-10 13:44:11 +08:00
<Fragment>
2019-02-20 11:54:25 +08:00
<div className="main-panel-north border-left-show">
<div className="cur-view-toolbar">
2018-12-10 17:59:26 +08:00
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
<div className="operation">
2019-05-05 13:25:02 +08:00
{((!isDepartmentGroup && canAddRepo) || (isDepartmentGroup && isStaff)) && (
<button className="btn btn-secondary operation-item" title={gettext('New Library')} onClick={this.onCreateRepoToggle}>
<i className="fas fa-plus-square text-secondary mr-1"></i>{gettext('New Library')}
</button>
)}
2018-12-10 17:59:26 +08:00
</div>
</div>
2018-12-10 13:44:11 +08:00
<CommonToolbar onSearchedClick={this.props.onSearchedClick} />
</div>
<div className="main-panel-center flex-row">
2018-12-10 13:44:11 +08:00
<div className="cur-view-container">
<div className="cur-view-path">
2019-05-05 13:16:32 +08:00
{currentGroup && (
2018-12-10 18:12:46 +08:00
<Fragment>
<div className="path-container">
<Link to={`${siteRoot}groups/`} onClick={() => this.onTabNavClick('groups')}>{gettext('Groups')}</Link>
2018-12-10 18:12:46 +08:00
<span className="path-split">/</span>
<span>{currentGroup.name}</span>
{currentGroup.parent_group_id !== 0 && (
<span className="department-group-icon fas fa-building" title={gettext('This is a special group representing a department.')}></span>
2018-12-10 18:12:46 +08:00
)}
</div>
<div className="path-tool">
2018-12-24 18:25:12 +08:00
{ (isShowSettingIcon && this.state.isStaff) &&
2018-12-19 10:44:23 +08:00
<React.Fragment>
2018-12-28 11:12:24 +08:00
<a href="#" className="sf2-icon-cog1 action-icon group-top-action-icon" title="Settings" id="settings"
2018-12-19 10:44:23 +08:00
onClick={this.toggleGroupDropdown}></a>
<Popover placement="bottom" isOpen={this.state.showGroupDropdown} target="settings"
toggle={this.toggleGroupDropdown} hideArrow={true} className="sf-popover">
<div className="sf-popover-hd sf-popover-title">
2018-12-24 18:25:12 +08:00
<span>{gettext('Settings')}</span>
2018-12-28 11:12:24 +08:00
<a href="#" className="sf-popover-close js-close sf2-icon-x1 action-icon"
2018-12-19 10:44:23 +08:00
onClick={this.toggleGroupDropdown}></a>
</div>
<div className="sf-popover-con">
<ul className="sf-popover-list">
2018-12-24 18:25:12 +08:00
<li><a href="#" className="sf-popover-item" onClick={this.toggleRenameGroupDialog} >{gettext('Rename')}</a></li>
{
this.state.isOwner &&
<li><a href="#" className="sf-popover-item" onClick={this.toggleTransferGroupDialog} >{gettext('Transfer')}</a></li>
}
2018-12-19 10:44:23 +08:00
</ul>
<ul className="sf-popover-list">
2018-12-24 18:25:12 +08:00
{/* <li><a href="#" className="sf-popover-item" onClick={this.toggleImportMembersDialog} >{gettext('Import Members')}</a></li> */}
<li><a href="#" className="sf-popover-item" onClick={this.toggleManageMembersDialog} >{gettext('Manage Members')}</a></li>
2018-12-19 10:44:23 +08:00
</ul>
2018-12-24 18:25:12 +08:00
{
this.state.isOwner &&
<ul className="sf-popover-list">
<li><a href="#" className="sf-popover-item" onClick={this.toggleDismissGroupDialog}>{gettext('Dismiss')}</a></li>
</ul>
}
2018-12-19 10:44:23 +08:00
</div>
</Popover>
</React.Fragment>
}
2018-12-24 18:25:12 +08:00
<a href="#"
2018-12-28 11:12:24 +08:00
className="sf2-icon-user2 action-icon group-top-action-icon"
2018-12-24 18:25:12 +08:00
title={gettext('Members')} id="groupMembers"
onClick={() => this.toggleGroupMembersPopover('open')}>
</a>
<Popover placement="bottom" isOpen={this.state.showGroupMembersPopover} target="groupMembers"
toggle={this.toggleGroupMembersPopover} hideArrow={true} className="sf-popover">
2019-03-07 16:40:01 +08:00
<div className="sf-popover-hd sf-popover-title group-member-list-header">
2018-12-24 18:25:12 +08:00
<span>{gettext('Members')}</span>
2018-12-28 11:12:24 +08:00
<a href="#" className="sf-popover-close js-close sf2-icon-x1 action-icon"
2018-12-24 18:25:12 +08:00
onClick={this.toggleGroupMembersPopover}></a>
</div>
<div className="sf-popover-con">
<ul className="sf-popover-list group-member-list">
{
this.state.groupMembers.map(function(item, index) {
return (
2019-03-07 16:40:01 +08:00
<li key={index}>
<a href="#" className="sf-popover-item user-item">
<img src={item.avatar_url} alt="" className="group-member-avatar avatar"/>
<span className="txt-item ellipsis">
<span className="group-member-name">{item.name}</span>
<span className="group-member-admin">{that.translateRole(item.role)}</span>
</span>
</a>
2018-12-24 18:25:12 +08:00
</li>
);
})
}
</ul>
</div>
</Popover>
2018-12-10 18:12:46 +08:00
</div>
</Fragment>
)}
2018-12-10 13:44:11 +08:00
</div>
<div className="cur-view-content">
{this.state.isLoading && <Loading />}
{(!this.state.isLoading && errMessage) && errMessage}
{(!this.state.isLoading && this.state.repoList.length === 0) && emptyTip}
{(!this.state.isLoading && this.state.repoList.length > 0) &&
2018-12-10 18:19:03 +08:00
<SharedRepoListView
2018-12-10 13:44:11 +08:00
repoList={this.state.repoList}
currentGroup={this.state.currentGroup}
sortBy={this.state.sortBy}
sortOrder={this.state.sortOrder}
sortItems={this.sortItems}
2018-12-10 18:37:59 +08:00
onItemUnshare={this.onItemUnshare}
2018-12-16 11:17:17 +08:00
onItemDelete={this.onItemDelete}
onItemDetails={this.onItemDetails}
onItemRename={this.onItemRename}
2018-12-10 13:44:11 +08:00
/>
}
</div>
</div>
{this.state.isShowDetails && (
<div className="cur-view-detail">
<LibDetail currentRepo={this.state.currentRepo} closeDetails={this.closeDetails}/>
</div>
)}
2018-12-10 13:44:11 +08:00
</div>
2018-12-10 17:59:26 +08:00
{this.state.isCreateRepoDialogShow && !this.state.isDepartmentGroup && (
<ModalPortal>
<CreateRepoDialog
libraryType={this.state.libraryType}
onCreateToggle={this.onCreateRepoToggle}
onCreateRepo={this.onCreateRepo}
/>
</ModalPortal>
)}
{this.state.isCreateRepoDialogShow && this.state.isDepartmentGroup &&
<CreateDepartmentRepoDialog
isAdmin={this.state.isAdmin}
onCreateToggle={this.onCreateRepoToggle}
onCreateRepo={this.onCreateRepo}
/>
}
2018-12-24 18:25:12 +08:00
{this.state.showRenameGroupDialog &&
2018-12-19 10:44:23 +08:00
<RenameGroupDialog
showRenameGroupDialog={this.state.showRenameGroupDialog}
toggleRenameGroupDialog={this.toggleRenameGroupDialog}
loadGroup={this.loadGroup}
groupID={this.props.groupID}
onGroupChanged={this.props.onGroupChanged}
currentGroupName={currentGroup.name}
2018-12-19 10:44:23 +08:00
/>
}
2018-12-24 18:25:12 +08:00
{this.state.showDismissGroupDialog &&
2018-12-19 10:44:23 +08:00
<DismissGroupDialog
showDismissGroupDialog={this.state.showDismissGroupDialog}
toggleDismissGroupDialog={this.toggleDismissGroupDialog}
loadGroup={this.loadGroup}
groupID={this.props.groupID}
onGroupChanged={this.props.onGroupChanged}
/>
}
2018-12-24 18:25:12 +08:00
{this.state.showTransferGroupDialog &&
<TransferGroupDialog
toggleTransferGroupDialog={this.toggleTransferGroupDialog}
groupID={this.props.groupID}
onGroupChanged={this.props.onGroupChanged}
/>
}
{/* this.state.showImportMembersDialog &&
<ImportMembersDialog
toggleImportMembersDialog={this.toggleImportMembersDialog}
groupID={this.props.groupID}
onGroupChanged={this.props.onGroupChanged}
/>
*/}
{this.state.showManageMembersDialog &&
<ManageMembersDialog
toggleManageMembersDialog={this.toggleManageMembersDialog}
groupID={this.props.groupID}
onGroupChanged={this.props.onGroupChanged}
isOwner={this.state.isOwner}
/>
}
2018-12-10 13:44:11 +08:00
</Fragment>
2018-12-08 08:37:18 +08:00
);
}
}
GroupView.propTypes = propTypes;
export default GroupView;