2019-05-15 00:01:48 +00:00
|
|
|
import React, { Fragment } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap';
|
|
|
|
import Select from 'react-select';
|
|
|
|
import { gettext, isPro, siteRoot } from '../../utils/constants';
|
2023-09-04 01:50:14 +00:00
|
|
|
import { seafileAPI } from '../../utils/seafile-api';
|
|
|
|
import { Utils } from '../../utils/utils';
|
2019-05-15 00:01:48 +00:00
|
|
|
import SharePermissionEditor from '../select-editor/share-permission-editor';
|
|
|
|
import FileChooser from '../file-chooser/file-chooser';
|
|
|
|
|
|
|
|
class GroupItem extends React.Component {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
isOperationShow: false
|
|
|
|
};
|
|
|
|
}
|
2020-11-02 05:56:35 +00:00
|
|
|
|
2019-05-15 00:01:48 +00:00
|
|
|
onMouseEnter = () => {
|
|
|
|
this.setState({isOperationShow: true});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
onMouseLeave = () => {
|
|
|
|
this.setState({isOperationShow: false});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
deleteGroupPermissionItem = () => {
|
|
|
|
let item = this.props.item;
|
|
|
|
this.props.deleteGroupPermissionItem(item);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
onChangeGroupPermission = (permission) => {
|
|
|
|
let item = this.props.item;
|
|
|
|
this.props.onChangeGroupPermission(item, permission);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
render() {
|
|
|
|
let item = this.props.item;
|
|
|
|
return (
|
2021-10-08 08:52:17 +00:00
|
|
|
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onFocus={this.onMouseEnter}>
|
2019-05-15 00:01:48 +00:00
|
|
|
<td>
|
2023-09-13 00:40:50 +00:00
|
|
|
<a href={`${siteRoot}group/${item.group_id}/`} target="_blank" rel="noreferrer">{item.group_name}</a>
|
2019-05-15 00:01:48 +00:00
|
|
|
</td>
|
|
|
|
{this.props.showPath &&
|
|
|
|
<td>
|
|
|
|
<a href={`${siteRoot}library/${item.repo_id}/${Utils.encodePath(this.props.repoName + item.folder_path)}`}>{item.folder_name}</a>
|
|
|
|
</td>
|
|
|
|
}
|
|
|
|
<td>
|
2020-11-02 05:56:35 +00:00
|
|
|
<SharePermissionEditor
|
2019-05-15 00:01:48 +00:00
|
|
|
isTextMode={true}
|
2023-08-24 04:10:05 +00:00
|
|
|
autoFocus={true}
|
2019-05-15 00:01:48 +00:00
|
|
|
isEditIconShow={this.state.isOperationShow}
|
|
|
|
currentPermission={item.permission}
|
|
|
|
permissions={this.props.permissions}
|
|
|
|
onPermissionChanged={this.onChangeGroupPermission}
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<span
|
2021-10-08 08:52:17 +00:00
|
|
|
tabIndex="0"
|
|
|
|
role="button"
|
2019-05-15 00:01:48 +00:00
|
|
|
className={`sf2-icon-x3 action-icon ${this.state.isOperationShow ? '' : 'hide'}`}
|
2020-11-02 05:56:35 +00:00
|
|
|
onClick={this.deleteGroupPermissionItem}
|
2021-10-08 08:52:17 +00:00
|
|
|
onKeyDown={Utils.onKeyDown}
|
2019-05-15 00:01:48 +00:00
|
|
|
title={gettext('Delete')}
|
2021-10-08 08:52:17 +00:00
|
|
|
aria-label={gettext('Delete')}
|
2019-05-15 00:01:48 +00:00
|
|
|
>
|
|
|
|
</span>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-13 00:40:50 +00:00
|
|
|
GroupItem.propTypes = {
|
|
|
|
item: PropTypes.object.isRequired,
|
|
|
|
permissions: PropTypes.array.isRequired,
|
|
|
|
deleteUserFolderPermission: PropTypes.func.isRequired,
|
|
|
|
onChangeUserFolderPerm: PropTypes.func.isRequired,
|
|
|
|
showPath: PropTypes.bool.isRequired,
|
|
|
|
repoName: PropTypes.string.isRequired,
|
|
|
|
handleChange: PropTypes.func.isRequired,
|
|
|
|
deleteGroupPermissionItem: PropTypes.func.isRequired,
|
|
|
|
onChangeGroupPermission: PropTypes.func.isRequired,
|
|
|
|
};
|
|
|
|
|
2019-05-15 00:01:48 +00:00
|
|
|
const propTypes = {
|
2019-05-16 09:28:04 +00:00
|
|
|
repoID: PropTypes.string.isRequired,
|
2023-09-13 00:40:50 +00:00
|
|
|
isDepartmentRepo: PropTypes.bool,
|
|
|
|
repoName: PropTypes.string,
|
|
|
|
folderPath: PropTypes.string,
|
2019-05-15 00:01:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const NoOptionsMessage = (props) => {
|
|
|
|
return (
|
|
|
|
<div {...props.innerProps} style={{margin: '6px 10px', textAlign: 'center', color: 'hsl(0,0%,50%)'}}>{gettext('Group not found')}</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-09-13 00:40:50 +00:00
|
|
|
NoOptionsMessage.propTypes = {
|
|
|
|
innerProps: PropTypes.any.isRequired,
|
|
|
|
};
|
|
|
|
|
2019-05-15 00:01:48 +00:00
|
|
|
class LibSubFolderSerGroupPermissionDialog extends React.Component {
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
selectedOption: null,
|
|
|
|
errorMsg: [],
|
|
|
|
permission: 'rw',
|
|
|
|
groupPermissionItems: [],
|
|
|
|
folderPath: '',
|
|
|
|
showFileChooser: false
|
|
|
|
};
|
|
|
|
this.options = [];
|
|
|
|
if (!isPro) {
|
|
|
|
this.permissions = ['r', 'rw'];
|
|
|
|
} else {
|
2023-08-31 02:09:25 +00:00
|
|
|
this.permissions = ['r', 'rw', 'cloud-edit', 'preview', 'invisible'];
|
2019-05-15 00:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handleSelectChange = (option) => {
|
|
|
|
this.setState({selectedOption: option});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this.loadOptions();
|
|
|
|
this.listGroupPermissionItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
loadOptions = () => {
|
|
|
|
seafileAPI.shareableGroups().then((res) => {
|
|
|
|
this.options = res.data.map((item, index) => {
|
|
|
|
return {
|
|
|
|
id: item.id,
|
|
|
|
label: item.name,
|
|
|
|
value: item.name
|
|
|
|
};
|
|
|
|
});
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
listGroupPermissionItems = () => {
|
2019-05-16 09:28:04 +00:00
|
|
|
const { isDepartmentRepo, repoID, folderPath } = this.props;
|
2019-05-17 01:14:26 +00:00
|
|
|
const request = isDepartmentRepo ?
|
|
|
|
seafileAPI.listDepartmentRepoGroupFolderPerm(repoID, folderPath) :
|
|
|
|
seafileAPI.listGroupFolderPerm(repoID, folderPath);
|
|
|
|
request.then((res) => {
|
2019-05-15 00:01:48 +00:00
|
|
|
if (res.data.length !== 0) {
|
|
|
|
this.setState({
|
|
|
|
groupPermissionItems: res.data
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
setPermission = (permission) => {
|
|
|
|
this.setState({permission: permission});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
addGroupFolderPerm = () => {
|
|
|
|
const { selectedOption } = this.state;
|
|
|
|
const folderPath = this.props.folderPath || this.state.folderPath;
|
|
|
|
if (!selectedOption || !folderPath) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:14:26 +00:00
|
|
|
const request = this.props.isDepartmentRepo ?
|
|
|
|
seafileAPI.addDepartmentRepoGroupFolderPerm(this.props.repoID, this.state.permission, folderPath, selectedOption.id) :
|
2019-06-24 07:44:22 +00:00
|
|
|
seafileAPI.addGroupFolderPerm(this.props.repoID, this.state.permission, folderPath, selectedOption.id);
|
2019-05-17 01:14:26 +00:00
|
|
|
request.then(res => {
|
2019-05-15 00:01:48 +00:00
|
|
|
let errorMsg = [];
|
|
|
|
if (res.data.failed.length > 0) {
|
|
|
|
for (let i = 0; i < res.data.failed.length; i++) {
|
|
|
|
errorMsg[i] = res.data.failed[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
errorMsg: errorMsg,
|
|
|
|
groupPermissionItems: this.state.groupPermissionItems.concat(res.data.success),
|
|
|
|
selectedOption: null,
|
|
|
|
permission: 'rw',
|
|
|
|
folderPath: ''
|
|
|
|
});
|
|
|
|
}).catch((error) => {
|
2020-11-02 05:56:35 +00:00
|
|
|
let errorMsg = '';
|
2019-05-15 00:01:48 +00:00
|
|
|
if (error.response) {
|
|
|
|
if (error.response.data && error.response.data['error_msg']) {
|
|
|
|
errorMsg = error.response.data['error_msg'];
|
|
|
|
} else {
|
|
|
|
errorMsg = gettext('Error');
|
2020-11-02 05:56:35 +00:00
|
|
|
}
|
2019-05-15 00:01:48 +00:00
|
|
|
} else {
|
|
|
|
errorMsg = gettext('Please check the network.');
|
2020-11-02 05:56:35 +00:00
|
|
|
}
|
2019-05-15 00:01:48 +00:00
|
|
|
this.setState({
|
|
|
|
errorMsg: [errorMsg]
|
2020-11-02 05:56:35 +00:00
|
|
|
});
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
deleteGroupPermissionItem = (item) => {
|
2019-05-17 01:14:26 +00:00
|
|
|
const request = this.props.isDepartmentRepo ?
|
|
|
|
seafileAPI.deleteDepartmentRepoGroupFolderPerm(item.repo_id, item.permission, item.folder_path, item.group_id) :
|
2019-06-24 07:44:22 +00:00
|
|
|
seafileAPI.deleteGroupFolderPerm(item.repo_id, item.permission, item.folder_path, item.group_id);
|
2019-05-17 01:14:26 +00:00
|
|
|
request.then(() => {
|
2019-05-15 00:01:48 +00:00
|
|
|
this.setState({
|
2020-11-02 05:56:35 +00:00
|
|
|
groupPermissionItems: this.state.groupPermissionItems.filter(deletedItem => { return deletedItem != item; })
|
2019-05-15 00:01:48 +00:00
|
|
|
});
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
onChangeGroupPermission = (item, permission) => {
|
2019-05-17 01:14:26 +00:00
|
|
|
const request = this.props.isDepartmentRepo ?
|
|
|
|
seafileAPI.updateDepartmentRepoGroupFolderPerm(item.repo_id, permission, item.folder_path, item.group_id) :
|
|
|
|
seafileAPI.updateGroupFolderPerm(item.repo_id, permission, item.folder_path, item.group_id);
|
|
|
|
request.then(() => {
|
2019-05-15 00:01:48 +00:00
|
|
|
this.updateGroupPermission(item, permission);
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2020-11-02 05:56:35 +00:00
|
|
|
|
2019-05-15 00:01:48 +00:00
|
|
|
updateGroupPermission = (item, permission) => {
|
|
|
|
let groupID = item.group_id;
|
|
|
|
let groupPermissionItems = this.state.groupPermissionItems.map(sharedItem => {
|
|
|
|
let sharedItemGroupID = sharedItem.group_id;
|
|
|
|
if (groupID === sharedItemGroupID && item.folder_path === sharedItem.folder_path) {
|
|
|
|
sharedItem.permission = permission;
|
|
|
|
}
|
|
|
|
return sharedItem;
|
|
|
|
});
|
|
|
|
this.setState({groupPermissionItems: groupPermissionItems});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
onSetSubFolder = (e) => {
|
|
|
|
this.setState({
|
2020-11-02 05:56:35 +00:00
|
|
|
folderPath: e.target.value
|
2019-05-15 00:01:48 +00:00
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
toggleFileChooser = () => {
|
|
|
|
this.setState({
|
|
|
|
showFileChooser: !this.state.showFileChooser,
|
|
|
|
folderPath: ''
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
toggleSubFolder = (repo, path, item) => {
|
|
|
|
this.setState({
|
|
|
|
folderPath: path,
|
2020-11-02 05:56:35 +00:00
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
handleSubmit = () => {
|
|
|
|
this.setState({
|
|
|
|
showFileChooser: !this.state.showFileChooser
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
onRepoItemClick = () => {
|
|
|
|
this.setState({
|
2020-11-02 05:56:35 +00:00
|
|
|
folderPath: '/'
|
2019-05-15 00:01:48 +00:00
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-05-15 00:01:48 +00:00
|
|
|
|
|
|
|
render() {
|
|
|
|
let showPath = this.props.folderPath ? false : true;
|
|
|
|
|
|
|
|
if (this.state.showFileChooser) {
|
|
|
|
return (
|
|
|
|
<div>
|
2021-12-15 06:55:16 +00:00
|
|
|
<FileChooser
|
|
|
|
repoID={this.props.repoID}
|
2019-05-15 00:01:48 +00:00
|
|
|
mode={'only_current_library'}
|
|
|
|
onDirentItemClick={this.toggleSubFolder}
|
|
|
|
onRepoItemClick={this.onRepoItemClick}
|
|
|
|
/>
|
|
|
|
<div className="modal-footer">
|
|
|
|
<Button color="secondary" onClick={this.toggleFileChooser}>{gettext('Cancel')}</Button>
|
|
|
|
<Button color="primary" onClick={this.handleSubmit}>{gettext('Submit')}</Button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-04-04 06:32:11 +00:00
|
|
|
const thead = (
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th width={showPath ? '32%' : '55%'}>{gettext('Group')}</th>
|
|
|
|
{showPath &&
|
|
|
|
<th width="32%">{gettext('Folder')}</th>
|
|
|
|
}
|
|
|
|
<th width={showPath ? '24%' : '30%'}>{gettext('Permission')}</th>
|
|
|
|
<th width={showPath ? '12%' : '15%'}></th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
);
|
2019-05-15 00:01:48 +00:00
|
|
|
return (
|
|
|
|
<Fragment>
|
2020-04-04 06:32:11 +00:00
|
|
|
<table className="w-xs-250">
|
|
|
|
{thead}
|
2019-05-15 00:01:48 +00:00
|
|
|
<tbody>
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<Select
|
|
|
|
onChange={this.handleSelectChange}
|
|
|
|
options={this.options}
|
|
|
|
placeholder={gettext('Select a group')}
|
|
|
|
maxMenuHeight={200}
|
|
|
|
inputId={'react-select-2-input'}
|
|
|
|
value={this.state.selectedOption}
|
|
|
|
components={{ NoOptionsMessage }}
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
{showPath &&
|
|
|
|
<td>
|
|
|
|
<InputGroup>
|
|
|
|
<Input value={this.state.folderPath} onChange={this.onSetSubFolder} />
|
|
|
|
<InputGroupAddon addonType="append"><Button className="sf2-icon-plus" onClick={this.toggleFileChooser}></Button></InputGroupAddon>
|
|
|
|
</InputGroup>
|
|
|
|
</td>
|
|
|
|
}
|
|
|
|
<td>
|
2020-11-02 05:56:35 +00:00
|
|
|
<SharePermissionEditor
|
2019-05-15 00:01:48 +00:00
|
|
|
isTextMode={false}
|
|
|
|
isEditIconShow={false}
|
|
|
|
currentPermission={this.state.permission}
|
|
|
|
permissions={this.permissions}
|
|
|
|
onPermissionChanged={this.setPermission}
|
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<Button onClick={this.addGroupFolderPerm}>{gettext('Submit')}</Button>
|
|
|
|
</td>
|
|
|
|
</tr>
|
2020-11-02 05:56:35 +00:00
|
|
|
{this.state.errorMsg.length > 0 &&
|
2019-05-15 00:01:48 +00:00
|
|
|
this.state.errorMsg.map((item, index) => {
|
|
|
|
let errMessage = item.group_id + ': ' + item.error_msg;
|
|
|
|
return (
|
|
|
|
<tr key={index}>
|
|
|
|
<td colSpan={3}><p className="error">{errMessage}</p></td>
|
|
|
|
</tr>
|
|
|
|
);
|
2020-11-02 05:56:35 +00:00
|
|
|
})
|
2019-05-15 00:01:48 +00:00
|
|
|
}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
<div className="share-list-container">
|
2020-04-04 06:32:11 +00:00
|
|
|
<table className="table-thead-hidden w-xs-250">
|
|
|
|
{thead}
|
2019-05-15 00:01:48 +00:00
|
|
|
<tbody>
|
|
|
|
{this.state.groupPermissionItems.map((item, index) => {
|
|
|
|
return (
|
2020-11-02 05:56:35 +00:00
|
|
|
<GroupItem
|
|
|
|
key={index}
|
|
|
|
item={item}
|
2019-05-15 00:01:48 +00:00
|
|
|
permissions={this.permissions}
|
|
|
|
deleteGroupPermissionItem={this.deleteGroupPermissionItem}
|
|
|
|
onChangeGroupPermission={this.onChangeGroupPermission}
|
|
|
|
showPath={showPath}
|
|
|
|
repoName={this.props.repoName}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LibSubFolderSerGroupPermissionDialog.propTypes = propTypes;
|
|
|
|
|
|
|
|
export default LibSubFolderSerGroupPermissionDialog;
|