1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-06-25 14:43:15 +00:00
seahub/frontend/src/components/shared-repo-list-view/shared-repo-list-item.js

385 lines
12 KiB
JavaScript
Raw Normal View History

2018-12-08 03:53:45 +00:00
import React, { Fragment } from 'react';
2018-12-08 00:37:18 +00:00
import PropTypes from 'prop-types';
import moment from 'moment';
2018-12-08 03:53:45 +00:00
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
2018-12-11 09:52:19 +00:00
import { Link } from '@reach/router';
2018-12-08 00:37:18 +00:00
import { Utils } from '../../utils/utils';
2018-12-21 07:40:59 +00:00
import { gettext, siteRoot, isPro, username, folderPermEnabled, isSystemStaff } from '../../utils/constants';
2018-12-14 08:34:10 +00:00
import ModalPotal from '../../components/modal-portal';
import ShareDialog from '../../components/dialog/share-dialog';
2018-12-08 00:37:18 +00:00
const propTypes = {
2018-12-08 08:35:00 +00:00
currentGroup: PropTypes.object,
2018-12-21 07:40:59 +00:00
libraryType: PropTypes.string,
2018-12-08 00:37:18 +00:00
repo: PropTypes.object.isRequired,
isItemFreezed: PropTypes.bool.isRequired,
2018-12-10 01:01:05 +00:00
onFreezedItem: PropTypes.func.isRequired,
2018-12-10 10:37:59 +00:00
onItemUnshare: PropTypes.func.isRequired,
onItmeDetails: PropTypes.func,
2018-12-08 00:37:18 +00:00
};
2018-12-10 03:52:44 +00:00
class SharedRepoListItem extends React.Component {
2018-12-08 00:37:18 +00:00
constructor(props) {
super(props);
this.state = {
highlight: false,
isOperationShow: false,
isItemMenuShow: false,
2018-12-14 08:34:10 +00:00
isShowSharedDialog: false,
2018-12-08 00:37:18 +00:00
};
2018-12-10 01:01:05 +00:00
this.isDeparementOnwerGroupMember = false;
2018-12-08 00:37:18 +00:00
}
onMouseEnter = () => {
2018-12-10 01:01:05 +00:00
if (!this.props.isItemFreezed) {
this.setState({
highlight: true,
isOperationShow: true,
});
}
2018-12-08 00:37:18 +00:00
}
2018-12-10 09:59:26 +00:00
onMouseOver = () => {
if (!this.props.isItemFreezed) {
this.setState({
highlight: true,
isOperationShow: true,
});
}
}
2018-12-08 00:37:18 +00:00
onMouseLeave = () => {
2018-12-10 01:01:05 +00:00
if (!this.props.isItemFreezed) {
this.setState({
highlight: false,
isOperationShow: false,
});
}
}
clickOperationMenuToggle = (e) => {
e.preventDefault();
this.toggleOperationMenu();
2018-12-08 03:53:45 +00:00
}
toggleOperationMenu = () => {
2018-12-10 01:01:05 +00:00
if (this.props.isItemFreezed) {
this.setState({
highlight: false,
isOperationShow: false,
isItemMenuShow: !this.state.isItemMenuShow
});
} else {
this.setState({
isItemMenuShow: !this.state.isItemMenuShow
});
}
this.props.onFreezedItem();
2018-12-08 00:37:18 +00:00
}
getRepoComputeParams = () => {
let repo = this.props.repo;
let iconUrl = Utils.getLibIconUrl(repo);
let iconTitle = Utils.getLibIconTitle(repo);
2018-12-13 03:05:47 +00:00
let libPath = `${siteRoot}library/${repo.repo_id}/${Utils.encodePath(repo.repo_name)}/`;
2018-12-08 00:37:18 +00:00
return { iconUrl, iconTitle, libPath };
}
2018-12-10 01:01:05 +00:00
onMenuItemClick = (e) => {
let operation = e.target.dataset.toggle;
switch(operation) {
case 'Rename':
this.onItemRename();
break;
case 'Folder Permission':
this.onItemPermisionChanged();
break;
case 'Details':
this.onItemDetails();
break;
case 'Share':
2018-12-14 08:34:10 +00:00
this.onItemShare();
2018-12-10 01:01:05 +00:00
break;
case 'Unshare':
2018-12-10 10:37:59 +00:00
this.onItemUnshare();
2018-12-10 01:01:05 +00:00
break;
default:
break;
2018-12-08 03:53:45 +00:00
}
2018-12-10 01:01:05 +00:00
}
2018-12-08 03:53:45 +00:00
2018-12-10 01:01:05 +00:00
onItemRename = () => {
// todo
}
2018-12-08 03:53:45 +00:00
2018-12-10 01:01:05 +00:00
onItemPermisionChanged = () => {
// todo
}
onItemDetails = () => {
this.props.onItemDetails(this.props.repo);
2018-12-10 01:01:05 +00:00
}
2018-12-08 03:53:45 +00:00
2018-12-10 10:37:59 +00:00
onItemShare = () => {
2018-12-14 08:34:10 +00:00
this.setState({isShowSharedDialog: true});
2018-12-10 01:01:05 +00:00
}
2018-12-10 10:37:59 +00:00
onItemUnshare = () => {
this.props.onItemUnshare(this.props.repo);
2018-12-10 01:01:05 +00:00
}
2018-12-08 03:53:45 +00:00
2018-12-10 01:01:05 +00:00
onItemDelete = () => {
2018-12-16 03:17:17 +00:00
this.props.onItemDelete(this.props.repo);
2018-12-10 01:01:05 +00:00
}
2018-12-08 03:53:45 +00:00
2018-12-14 08:34:10 +00:00
toggleShareDialog = () => {
this.setState({isShowSharedDialog: false});
}
translateMenuItem = (menuItem) => {
let translateResult = '';
switch(menuItem) {
case 'Rename':
translateResult = gettext('Rename');
break;
case 'Folder Permission':
translateResult = gettext('Folder Premission');
break;
case 'Details':
translateResult = gettext('Details');
break;
case 'Unshare':
translateResult = gettext('Unshare');
break;
case 'Share':
translateResult = gettext('Share');
break;
default:
break;
}
return translateResult;
}
2018-12-10 01:01:05 +00:00
generatorOperations = () => {
let { repo, currentGroup } = this.props;
2018-12-10 03:52:44 +00:00
//todo this have a bug; use current api is not return admins param;
2018-12-21 07:40:59 +00:00
let isStaff = currentGroup && currentGroup.admins && currentGroup.admins.indexOf(username) > -1; //for group repolist;
2018-12-10 01:01:05 +00:00
let isRepoOwner = repo.owner_email === username;
let isAdmin = repo.is_admin;
let operations = [];
// todo ,shared width me shared width all;
2018-12-08 03:53:45 +00:00
if (isPro) {
2018-12-10 01:01:05 +00:00
if (repo.owner_email.indexOf('@seafile_group') != -1) { //current repo is belong to a group;
if (isStaff && repo.owner_email == currentGroup.id + '@seafile_group') { //is a member of this current group,
this.isDeparementOnwerGroupMember = true;
if (folderPermEnabled) {
operations = ['Rename', 'Folder Permission', 'Details'];
2018-12-08 03:53:45 +00:00
} else {
operations = ['Rename', 'Details'];
2018-12-08 03:53:45 +00:00
}
2018-12-10 01:01:05 +00:00
} else {
operations.push('Unshare');
2018-12-08 03:53:45 +00:00
}
} else {
2018-12-10 01:01:05 +00:00
if (isRepoOwner || isAdmin) {
operations.push('Share');
}
if (isStaff || isRepoOwner || isAdmin) {
operations.push('Unshare');
}
2018-12-08 03:53:45 +00:00
}
} else {
2018-12-10 01:01:05 +00:00
if (isRepoOwner) {
operations.push('Share');
2018-12-10 01:01:05 +00:00
}
if (isStaff || isRepoOwner) {
operations.push('Unshare');
}
2018-12-08 03:53:45 +00:00
}
2018-12-10 01:01:05 +00:00
return operations;
}
2018-12-08 03:53:45 +00:00
2018-12-10 01:01:05 +00:00
generatorMobileMenu = () => {
2018-12-21 07:40:59 +00:00
let operations = [];
if (this.props.libraryType && this.props.libraryType === 'public') {
let isRepoOwner = this.props.repo.owner_email === username;
if (isSystemStaff || isRepoOwner) {
operations.push('Unshare');
2018-12-21 07:40:59 +00:00
}
} else {
operations = this.generatorOperations();
if (this.isDeparementOnwerGroupMember) {
operations.unshift('Unshare');
operations.unshift('Share');
2018-12-21 07:40:59 +00:00
}
2018-12-10 01:01:05 +00:00
}
return (
2018-12-08 04:12:05 +00:00
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
2018-12-10 01:01:05 +00:00
<DropdownToggle
2018-12-28 03:12:24 +00:00
tag="i"
className="sf-dropdown-toggle sf2-icon-caret-down"
2018-12-10 01:01:05 +00:00
title={gettext('More Operations')}
data-toggle="dropdown"
aria-expanded={this.state.isItemMenuShow}
onClick={this.clickOperationMenuToggle}
/>
2018-12-08 03:53:45 +00:00
<div className={`${this.state.isItemMenuShow?'':'d-none'}`} onClick={this.toggleOperationMenu}>
<div className="mobile-operation-menu-bg-layer"></div>
<div className="mobile-operation-menu">
2018-12-10 01:01:05 +00:00
{operations.map((item, index) => {
return (
<DropdownItem key={index} data-toggle={item} onClick={this.onMenuItemClick}>{this.translateMenuItem(item)}</DropdownItem>
2018-12-10 01:01:05 +00:00
);
})}
2018-12-08 03:53:45 +00:00
</div>
</div>
</Dropdown>
);
2018-12-10 01:01:05 +00:00
}
generatorPCMenu = () => {
2018-12-21 07:40:59 +00:00
let operations = [];
if (this.props.libraryType && this.props.libraryType === 'public') {
let isRepoOwner = this.props.repo.owner_email === username;
if (isSystemStaff || isRepoOwner) {
operations.push('unshare');
}
} else {
// scene one: (share, delete, itemToggle and other operations);
// scene two: (share, unshare), (share), (unshare)
operations = this.generatorOperations();
}
const shareOperation = <a href="#" className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></a>;
const unshareOperation = <a href="#" className="op-icon sf2-icon-x3" title={gettext('Unshare')} onClick={this.onItemUnshare}></a>;
2018-12-28 03:12:24 +00:00
const deleteOperation = <a href="#" className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></a>;
2018-12-10 01:01:05 +00:00
if (this.isDeparementOnwerGroupMember) {
return (
<Fragment>
{shareOperation}
{deleteOperation}
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
<DropdownToggle
2018-12-28 03:12:24 +00:00
tag="i"
className="sf-dropdown-toggle sf2-icon-caret-down"
2018-12-10 01:01:05 +00:00
title={gettext('More Operations')}
data-toggle="dropdown"
aria-expanded={this.state.isItemMenuShow}
onClick={this.clickOperationMenuToggle}
/>
<DropdownMenu>
{operations.map((item, index) => {
return <DropdownItem key={index} data-toggle={item} onClick={this.onMenuItemClick}>{this.translateMenuItem(item)}</DropdownItem>;
2018-12-10 01:01:05 +00:00
})}
</DropdownMenu>
</Dropdown>
</Fragment>
);
} else {
if (operations.length == 2) {
return (
<Fragment>
{shareOperation}
{unshareOperation}
</Fragment>
);
}
if (operations.length == 1 && operations[0] === 'share') {
return shareOperation;
}
2018-12-08 03:53:45 +00:00
2018-12-10 01:01:05 +00:00
if (operations.length == 1 && operations[0] === 'unshare') {
return unshareOperation;
}
}
return null;
2018-12-08 00:37:18 +00:00
}
renderPCUI = () => {
let { iconUrl, iconTitle, libPath } = this.getRepoComputeParams();
2018-12-10 09:59:26 +00:00
let { repo } = this.props;
2019-01-29 02:06:26 +00:00
// TODO: enableDirPrivateShare, isGroupOwnedRepo
2018-12-14 13:39:17 +00:00
let isGroupOwnedRepo = repo.owner_email.indexOf('@seafile_group') > -1;
2018-12-08 00:37:18 +00:00
return (
2018-12-14 08:34:10 +00:00
<Fragment>
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave}>
<td><img src={iconUrl} title={repo.iconTitle} alt={iconTitle} width="24" /></td>
2018-12-14 08:34:10 +00:00
<td><Link to={libPath}>{repo.repo_name}</Link></td>
<td>{this.state.isOperationShow && this.generatorPCMenu()}</td>
<td>{repo.size}</td>
<td title={moment(repo.last_modified).format('llll')}>{moment(repo.last_modified).fromNow()}</td>
<td title={repo.owner_contact_email}>{repo.owner_name}</td>
</tr>
{this.state.isShowSharedDialog && (
<ModalPotal>
<ShareDialog
itemType={'library'}
itemName={repo.repo_name}
itemPath={'/'}
repoID={repo.repo_id}
2019-01-29 02:06:26 +00:00
repoEncrypted={repo.encrypted}
enableDirPrivateShare={true}
userPerm={repo.permission}
isAdmin={repo.is_admin}
2018-12-14 13:39:17 +00:00
isGroupOwnedRepo={isGroupOwnedRepo}
2018-12-14 08:34:10 +00:00
toggleDialog={this.toggleShareDialog}
/>
</ModalPotal>
)}
</Fragment>
2018-12-08 00:37:18 +00:00
);
}
renderMobileUI = () => {
let { iconUrl, iconTitle, libPath } = this.getRepoComputeParams();
2018-12-10 09:59:26 +00:00
let { repo } = this.props;
2018-12-14 13:39:17 +00:00
let isGroupOwnedRepo = repo.owner_email.indexOf('@seafile_group') > -1;
2018-12-08 00:37:18 +00:00
return (
2018-12-14 08:34:10 +00:00
<Fragment>
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave}>
<td><img src={iconUrl} title={iconTitle} width="24" alt={iconTitle}/></td>
2018-12-14 08:34:10 +00:00
<td>
<Link to={libPath}>{repo.repo_name}</Link><br />
<span className="item-meta-info" title={repo.owner_contact_email}>{repo.owner_name}</span>
<span className="item-meta-info">{repo.size}</span>
<span className="item-meta-info" title={moment(repo.last_modified).format('llll')}>{moment(repo.last_modified).fromNow()}</span>
</td>
<td>{this.generatorMobileMenu()}</td>
</tr>
{this.state.isShowSharedDialog && (
<ModalPotal>
<ShareDialog
itemType={'library'}
itemName={repo.repo_name}
itemPath={'/'}
repoID={repo.repo_id}
2019-01-29 02:06:26 +00:00
repoEncrypted={repo.encrypted}
enableDirPrivateShare={true}
userPerm={repo.permission}
isAdmin={repo.is_admin}
2018-12-14 13:39:17 +00:00
isGroupOwnedRepo={isGroupOwnedRepo}
2018-12-14 08:34:10 +00:00
toggleDialog={this.toggleShareDialog}
/>
</ModalPotal>
)}
</Fragment>
2018-12-08 00:37:18 +00:00
);
}
render() {
if (window.innerWidth >= 768) {
return this.renderPCUI();
} else {
return this.renderMobileUI();
}
}
}
2018-12-10 03:52:44 +00:00
SharedRepoListItem.propTypes = propTypes;
2018-12-08 00:37:18 +00:00
2018-12-10 03:52:44 +00:00
export default SharedRepoListItem;