2020-09-24 02:57:45 +00:00
|
|
|
import React, { Fragment } from 'react';
|
2020-12-14 03:47:36 +00:00
|
|
|
import Select from 'react-select';
|
2020-09-24 02:57:45 +00:00
|
|
|
import PropTypes from 'prop-types';
|
2020-12-14 03:47:36 +00:00
|
|
|
import { gettext, ocmRemoteServers } from '../../utils/constants';
|
2020-09-24 02:57:45 +00:00
|
|
|
import { Input } from 'reactstrap';
|
|
|
|
import { Button } from 'reactstrap';
|
|
|
|
import { seafileAPI } from '../../utils/seafile-api.js';
|
|
|
|
import { Utils } from '../../utils/utils';
|
|
|
|
import toaster from '../toast';
|
2021-10-11 10:15:50 +00:00
|
|
|
import OpIcon from '../op-icon';
|
2020-09-24 02:57:45 +00:00
|
|
|
import SharePermissionEditor from '../select-editor/share-permission-editor';
|
|
|
|
|
|
|
|
class ShareItem extends React.Component {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
2020-12-17 07:17:18 +00:00
|
|
|
isOperationShow: false,
|
|
|
|
isOpFrozen: false
|
2020-09-24 02:57:45 +00:00
|
|
|
};
|
|
|
|
}
|
2020-11-02 05:56:35 +00:00
|
|
|
|
2020-09-24 02:57:45 +00:00
|
|
|
onMouseEnter = () => {
|
|
|
|
this.setState({isOperationShow: true});
|
|
|
|
}
|
|
|
|
|
|
|
|
onMouseLeave = () => {
|
|
|
|
this.setState({isOperationShow: false});
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteShareItem = () => {
|
2020-12-17 07:17:18 +00:00
|
|
|
this.setState({
|
|
|
|
// the 'delete' takes time,
|
|
|
|
// so 'lock' the op icon here to avoid multiple click on it
|
|
|
|
// avoid repeated requests
|
|
|
|
isOpFrozen: true
|
|
|
|
});
|
2020-09-24 02:57:45 +00:00
|
|
|
let item = this.props.item;
|
|
|
|
this.props.deleteShareItem(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
let item = this.props.item;
|
2020-12-17 07:17:18 +00:00
|
|
|
const { isOperationShow, isOpFrozen } = this.state;
|
2020-09-24 02:57:45 +00:00
|
|
|
return (
|
2021-10-11 10:15:50 +00:00
|
|
|
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onFocus={this.onMouseEnter}>
|
2020-12-14 03:47:36 +00:00
|
|
|
<td><a href={item.to_server_url} target="_blank">{item.to_server_name}</a></td>
|
2020-12-17 07:17:18 +00:00
|
|
|
<td>{item.to_user}</td>
|
2020-09-24 02:57:45 +00:00
|
|
|
<td>{Utils.sharePerms(item.permission)}</td>
|
|
|
|
{/* <td>
|
2020-11-02 05:56:35 +00:00
|
|
|
<SharePermissionEditor
|
2020-09-24 02:57:45 +00:00
|
|
|
isTextMode={true}
|
|
|
|
isEditIconShow={this.state.isOperationShow}
|
|
|
|
currentPermission={currentPermission}
|
|
|
|
permissions={this.props.permissions}
|
|
|
|
onPermissionChanged={this.onChangeUserPermission}
|
|
|
|
/>
|
|
|
|
</td> */}
|
|
|
|
<td>
|
2021-10-11 10:15:50 +00:00
|
|
|
<OpIcon
|
2020-12-17 07:17:18 +00:00
|
|
|
className={`sf2-icon-x3 action-icon ${isOperationShow && !isOpFrozen ? '' : 'hide'}`}
|
2021-10-11 10:15:50 +00:00
|
|
|
op={this.deleteShareItem}
|
2020-09-24 02:57:45 +00:00
|
|
|
title={gettext('Delete')}
|
2021-10-11 10:15:50 +00:00
|
|
|
/>
|
2020-09-24 02:57:45 +00:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class ShareList extends React.Component {
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<div className="share-list-container">
|
|
|
|
<table className="table-thead-hidden">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
2020-12-14 03:47:36 +00:00
|
|
|
<th width="30%">{gettext('Server')}</th>
|
2020-09-24 02:57:45 +00:00
|
|
|
<th width="25%">{gettext('User Email')}</th>
|
2020-12-14 03:47:36 +00:00
|
|
|
<th width="30%">{gettext('Permission')}</th>
|
2020-09-24 02:57:45 +00:00
|
|
|
<th width="15%"></th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{this.props.items.map((item, index) => {
|
|
|
|
return (
|
|
|
|
<ShareItem
|
|
|
|
key={index}
|
|
|
|
item={item}
|
|
|
|
deleteShareItem={this.props.deleteShareItem}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const propTypes = {
|
|
|
|
isGroupOwnedRepo: PropTypes.bool,
|
|
|
|
itemPath: PropTypes.string.isRequired,
|
|
|
|
itemType: PropTypes.string.isRequired,
|
|
|
|
repoID: PropTypes.string.isRequired,
|
|
|
|
isRepoOwner: PropTypes.bool.isRequired,
|
|
|
|
};
|
|
|
|
|
|
|
|
class ShareToOtherServer extends React.Component {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
2020-12-17 07:17:18 +00:00
|
|
|
selectedServer: null,
|
2020-09-24 02:57:45 +00:00
|
|
|
toUser: '',
|
2020-12-17 07:17:18 +00:00
|
|
|
permission: 'rw',
|
|
|
|
btnDisabled: true,
|
|
|
|
isSubmitting: false,
|
|
|
|
ocmShares: []
|
2020-09-24 02:57:45 +00:00
|
|
|
};
|
|
|
|
this.permissions = ['rw', 'r'];
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
seafileAPI.listOCMSharesPrepare(this.props.repoID).then((res) => {
|
|
|
|
this.setState({ocmShares: res.data.ocm_share_list});
|
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
2020-12-17 07:17:18 +00:00
|
|
|
this.setState({
|
|
|
|
errorMsg: errMessage
|
|
|
|
});
|
2020-09-24 02:57:45 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-12-17 07:17:18 +00:00
|
|
|
OCMShare = () => {
|
|
|
|
const { repoID, itemPath } = this.props;
|
|
|
|
const { selectedServer, toUser, permission } = this.state;
|
|
|
|
let toServerURL = selectedServer.value;
|
2020-09-24 02:57:45 +00:00
|
|
|
if (!toServerURL.endsWith('/')) {
|
|
|
|
toServerURL += '/';
|
|
|
|
}
|
2020-12-17 07:17:18 +00:00
|
|
|
this.setState({
|
|
|
|
btnDisabled: true,
|
|
|
|
isSubmitting: true
|
|
|
|
});
|
2020-09-24 02:57:45 +00:00
|
|
|
seafileAPI.addOCMSharePrepare(toUser, toServerURL, repoID, itemPath, permission).then((res) => {
|
|
|
|
let ocmShares = this.state.ocmShares;
|
2020-12-17 07:17:18 +00:00
|
|
|
ocmShares.unshift(res.data);
|
|
|
|
this.setState({
|
|
|
|
ocmShares: ocmShares,
|
|
|
|
selectedServer: null,
|
|
|
|
toUser: '',
|
|
|
|
permission: 'rw',
|
|
|
|
isSubmitting: false
|
|
|
|
});
|
2020-09-24 02:57:45 +00:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
2020-12-17 07:17:18 +00:00
|
|
|
this.setState({
|
|
|
|
btnDisabled: false,
|
|
|
|
isSubmitting: false
|
|
|
|
});
|
2020-09-24 02:57:45 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
handleToUserChange = (e) => {
|
2020-12-17 07:17:18 +00:00
|
|
|
const toUser = e.target.value;
|
2020-09-24 02:57:45 +00:00
|
|
|
this.setState({
|
2020-12-17 07:17:18 +00:00
|
|
|
toUser: toUser,
|
|
|
|
btnDisabled: !this.state.selectedServer || !toUser.trim()
|
2020-09-24 02:57:45 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-12-17 07:17:18 +00:00
|
|
|
handleServerChange = (selectedServer) => {
|
2020-09-24 02:57:45 +00:00
|
|
|
this.setState({
|
2020-12-17 07:17:18 +00:00
|
|
|
selectedServer,
|
|
|
|
btnDisabled: !this.state.toUser.trim()
|
2020-09-24 02:57:45 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteShareItem = (deletedItem) => {
|
2020-12-17 07:17:18 +00:00
|
|
|
const { id } = deletedItem;
|
|
|
|
toaster.notify(gettext('It may take some time, please wait.'));
|
2020-09-24 02:57:45 +00:00
|
|
|
seafileAPI.deleteOCMSharePrepare(id).then((res) => {
|
|
|
|
let ocmShares = this.state.ocmShares.filter(item => {
|
|
|
|
return item.id != id;
|
|
|
|
});
|
|
|
|
this.setState({ocmShares: ocmShares});
|
2020-12-17 07:17:18 +00:00
|
|
|
toaster.success(gettext('Successfully deleted 1 item.'));
|
2020-09-24 02:57:45 +00:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
setPermission = (permission) => {
|
|
|
|
this.setState({permission: permission});
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2020-12-17 07:17:18 +00:00
|
|
|
const {
|
|
|
|
errorMsg, ocmShares,
|
|
|
|
toUser, selectedServer, permission,
|
|
|
|
btnDisabled, isSubmitting
|
|
|
|
} = this.state;
|
2020-09-24 02:57:45 +00:00
|
|
|
return (
|
|
|
|
<Fragment>
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
2020-12-14 03:47:36 +00:00
|
|
|
<th width="30%">{gettext('Server')}</th>
|
2020-09-24 02:57:45 +00:00
|
|
|
<th width="25%">{gettext('User Email')}</th>
|
2020-12-14 03:47:36 +00:00
|
|
|
<th width="30%">{gettext('Permission')}</th>
|
2020-09-24 02:57:45 +00:00
|
|
|
<th width="15%"></th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<tr>
|
|
|
|
<td>
|
2020-12-14 03:47:36 +00:00
|
|
|
<Select
|
2020-12-17 07:17:18 +00:00
|
|
|
placeholder={gettext('Select a server...')}
|
|
|
|
value={selectedServer}
|
2020-12-14 03:47:36 +00:00
|
|
|
options={ocmRemoteServers}
|
2020-12-17 07:17:18 +00:00
|
|
|
onChange={this.handleServerChange}
|
2020-09-24 02:57:45 +00:00
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<Input
|
|
|
|
value={toUser}
|
|
|
|
onChange={this.handleToUserChange}
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<SharePermissionEditor
|
|
|
|
isTextMode={false}
|
|
|
|
isEditIconShow={false}
|
|
|
|
currentPermission={permission}
|
|
|
|
permissions={this.permissions}
|
|
|
|
onPermissionChanged={this.setPermission}
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
<td>
|
2020-12-17 07:17:18 +00:00
|
|
|
<Button
|
|
|
|
onClick={this.OCMShare}
|
|
|
|
disabled={btnDisabled}
|
|
|
|
className={isSubmitting ? 'btn-loading' : ''}>
|
|
|
|
{gettext('Submit')}
|
|
|
|
</Button>
|
2020-09-24 02:57:45 +00:00
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
2020-12-17 07:17:18 +00:00
|
|
|
{errorMsg ?
|
|
|
|
<p className="error text-center mt-4">{errorMsg}</p> :
|
|
|
|
<ShareList
|
|
|
|
items={ocmShares}
|
|
|
|
deleteShareItem={this.deleteShareItem}
|
|
|
|
/>
|
|
|
|
}
|
2020-09-24 02:57:45 +00:00
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ShareToOtherServer.propTypes = propTypes;
|
|
|
|
|
|
|
|
export default ShareToOtherServer;
|