mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 07:27:04 +00:00
Monitor shared repos (#5375)
* [shared with me] added 'watch/unwatch file changes' for libraries * [groups, group] added 'watch/unwatch file changes' for libraries * [shared with me] only libraries shared with 'r', 'rw' permissions can be monitored * [groups, group] only libraries shared with 'r', 'rw' permissions can be monitored * [shared with me] improved the interaction for library items * [groups, group] cleaned up the code
This commit is contained in:
@@ -17,6 +17,7 @@ import LibHistorySettingDialog from '../dialog/lib-history-setting-dialog';
|
||||
import toaster from '../toast';
|
||||
import RepoAPITokenDialog from '../dialog/repo-api-token-dialog';
|
||||
import RepoShareUploadLinksDialog from '../dialog/repo-share-upload-links-dialog';
|
||||
import RepoMonitoredIcon from '../../components/repo-monitored-icon';
|
||||
|
||||
const propTypes = {
|
||||
currentGroup: PropTypes.object,
|
||||
@@ -29,6 +30,7 @@ const propTypes = {
|
||||
onItemDetails: PropTypes.func,
|
||||
onItemRename: PropTypes.func,
|
||||
onItemDelete: PropTypes.func,
|
||||
onMonitorRepo: PropTypes.func
|
||||
};
|
||||
|
||||
class SharedRepoListItem extends React.Component {
|
||||
@@ -163,11 +165,36 @@ class SharedRepoListItem extends React.Component {
|
||||
case 'Reset Password':
|
||||
this.onResetPasswordToggle();
|
||||
break;
|
||||
default:
|
||||
case 'Watch File Changes':
|
||||
this.watchFileChanges();
|
||||
break;
|
||||
case 'Unwatch File Changes':
|
||||
this.unwatchFileChanges();
|
||||
break;
|
||||
// no default
|
||||
}
|
||||
}
|
||||
|
||||
watchFileChanges = () => {
|
||||
const { repo } = this.props;
|
||||
seafileAPI.monitorRepo(repo.repo_id).then(() => {
|
||||
this.props.onMonitorRepo(repo, true);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
unwatchFileChanges = () => {
|
||||
const { repo } = this.props;
|
||||
seafileAPI.unMonitorRepo(repo.repo_id).then(() => {
|
||||
this.props.onMonitorRepo(repo, false);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
onItemRenameToggle = () => {
|
||||
this.props.onFreezedItem();
|
||||
this.setState({
|
||||
@@ -294,6 +321,12 @@ class SharedRepoListItem extends React.Component {
|
||||
case 'Reset Password':
|
||||
translateResult = gettext('Reset Password');
|
||||
break;
|
||||
case 'Watch File Changes':
|
||||
translateResult = gettext('Watch File Changes');
|
||||
break;
|
||||
case 'Unwatch File Changes':
|
||||
translateResult = gettext('Unwatch File Changes');
|
||||
break;
|
||||
case 'API Token':
|
||||
translateResult = 'API Token'; // translation is not needed here
|
||||
break;
|
||||
@@ -339,6 +372,10 @@ class SharedRepoListItem extends React.Component {
|
||||
operations.push('Unshare');
|
||||
}
|
||||
}
|
||||
if (repo.permission == 'r' || repo.permission == 'rw') {
|
||||
const monitorOp = repo.monitored ? 'Unwatch File Changes' : 'Watch File Changes';
|
||||
operations.push(monitorOp);
|
||||
}
|
||||
} else {
|
||||
if (isRepoOwner) {
|
||||
operations.push('Share');
|
||||
@@ -400,8 +437,6 @@ class SharedRepoListItem extends React.Component {
|
||||
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')} role="button" aria-label={gettext('Share')} onClick={this.onItemShare}></a>;
|
||||
@@ -433,23 +468,41 @@ class SharedRepoListItem extends React.Component {
|
||||
</Fragment>
|
||||
);
|
||||
} else {
|
||||
if (operations.length == 2) {
|
||||
return (
|
||||
<Fragment>
|
||||
{shareOperation}
|
||||
{unshareOperation}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
if (operations.length == 1 && operations[0] === 'Share') {
|
||||
return shareOperation;
|
||||
}
|
||||
|
||||
if (operations.length == 1 && operations[0] === 'Unshare') {
|
||||
return unshareOperation;
|
||||
}
|
||||
return (
|
||||
<Fragment>
|
||||
{operations.map(item => {
|
||||
switch (item) {
|
||||
case 'Share':
|
||||
return <Fragment key={item}>{shareOperation}</Fragment>;
|
||||
case 'Unshare':
|
||||
return <Fragment key={item}>{unshareOperation}</Fragment>;
|
||||
case 'Watch File Changes':
|
||||
case 'Unwatch File Changes':
|
||||
return (
|
||||
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu} key={item}>
|
||||
<DropdownToggle
|
||||
className="sf-dropdown-toggle sf2-icon-caret-down border-0 p-0"
|
||||
title={gettext('More Operations')}
|
||||
data-toggle="dropdown"
|
||||
aria-expanded={this.state.isItemMenuShow}
|
||||
aria-haspopup={true}
|
||||
style={{'minWidth': '0'}}
|
||||
onClick={this.clickOperationMenuToggle}
|
||||
onKeyDown={this.onDropdownToggleKeyDown}
|
||||
/>
|
||||
<DropdownMenu>
|
||||
{[item].map((item, index) => {
|
||||
return <DropdownItem key={index} data-toggle={item} onClick={this.onMenuItemClick} onKeyDown={this.onMenuItemKeyDown}>{this.translateMenuItem(item)}</DropdownItem>;
|
||||
})}
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
);
|
||||
// no default
|
||||
}
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
onToggleStarRepo = (e) => {
|
||||
@@ -485,15 +538,18 @@ class SharedRepoListItem extends React.Component {
|
||||
<Fragment>
|
||||
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave} onFocus={this.onMouseEnter}>
|
||||
<td className="text-center">
|
||||
<a href="#" role="button" aria-label={this.state.isStarred ? gettext('Unstar') : gettext('Star')} onClick={this.onToggleStarRepo}>
|
||||
<i className={`fa-star ${this.state.isStarred ? 'fas' : 'far star-empty'}`}></i>
|
||||
</a>
|
||||
<a href="#" role="button" aria-label={this.state.isStarred ? gettext('Unstar') : gettext('Star')} onClick={this.onToggleStarRepo}>
|
||||
<i className={`fa-star ${this.state.isStarred ? 'fas' : 'far star-empty'}`}></i>
|
||||
</a>
|
||||
</td>
|
||||
<td><img src={iconUrl} title={iconTitle} alt={iconTitle} width="24" /></td>
|
||||
<td>
|
||||
{this.state.isRenaming ?
|
||||
<Rename name={repo.repo_name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel}/> :
|
||||
<Link to={libPath}>{repo.repo_name}</Link>
|
||||
<Fragment>
|
||||
<Link to={libPath}>{repo.repo_name}</Link>
|
||||
{repo.monitored && <RepoMonitoredIcon repoID={repo.repo_id} />}
|
||||
</Fragment>
|
||||
}
|
||||
</td>
|
||||
<td>{this.state.isOperationShow && this.generatorPCMenu()}</td>
|
||||
@@ -510,7 +566,7 @@ class SharedRepoListItem extends React.Component {
|
||||
navigate(this.repoURL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
renderMobileUI = () => {
|
||||
let { iconUrl, iconTitle, libPath } = this.getRepoComputeParams();
|
||||
let { repo } = this.props;
|
||||
@@ -522,7 +578,10 @@ class SharedRepoListItem extends React.Component {
|
||||
<td onClick={this.visitRepo}>
|
||||
{this.state.isRenaming ?
|
||||
<Rename name={repo.repo_name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel} /> :
|
||||
<Link to={libPath}>{repo.repo_name}</Link>
|
||||
<Fragment>
|
||||
<Link to={libPath}>{repo.repo_name}</Link>
|
||||
{repo.monitored && <RepoMonitoredIcon repoID={repo.repo_id} />}
|
||||
</Fragment>
|
||||
}
|
||||
<br />
|
||||
<span className="item-meta-info" title={repo.owner_contact_email}>{repo.owner_name}</span>
|
||||
|
@@ -99,6 +99,7 @@ class SharedRepoListView extends React.Component {
|
||||
onItemDelete={this.props.onItemDelete}
|
||||
onItemDetails={this.props.onItemDetails}
|
||||
onItemRename={this.props.onItemRename}
|
||||
onMonitorRepo={this.props.onMonitorRepo}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
Reference in New Issue
Block a user